Compare commits

...

154 Commits

Author SHA1 Message Date
Raphael 062d6419d6 Merge branch 'develop-eduard' into develop 4 months ago
Erik Auerswald 00d6417104 adjust generator limit to allow an IPv4 /15 4 months ago
Erik Auerswald a1509c1b4d fix off-by-one error in generator limit
This commit does not add tests that verify the exact limit,
because pinging 100000 localhost addresses takes over 15
minutes on my PC.  I have tested this fix manually.
4 months ago
Erik Auerswald 54e6f838c3 also apply generator limit to use with CIDR
As described in GH issue #299, the MAX_GENERATE+1 limit is only
applied when using an address range, not when using CIDR.  This
commit changes this to always honor the generator limit.

* refactor target address generation to use the same new function
  for both range and CIDR notation
* check the limit for addresses to generate in the new function
* document the generator limit in "fping --help" output
* document the generator limit in the fping man page
* test that the address generation limit applies when using CIDR
  notation
4 months ago
Erik Auerswald d0ed64bcc7 align functions add_cidr() and add_range()
* call freeaddrinfo() before checking the prefix length in
  add_cidr()
* add a comment to the generator limit check in add_range()
4 months ago
Erik Auerswald ab20b150b8 ci: skip an unreliable test on macOS
Sometimes, this test fails on macOS, at least on the GitHub CI.
It looks as if the fping process is killed before it produces
the required output.  This test works reliably on GNU/Linux, so
keep it, but skip it when running on macOS.
4 months ago
Erik Auerswald 65f00ff013 ci: test timestamp plausibility
Some changes of fping resulted in some systems reporting
implausible timestamps, see, e.g., GH issue #203.  This
commit adds a simplistic plausability check for timestamps
in Unix time format: they need to be greater or equal to
1000000000 (2001-09-09 03:46:40+02:00).
4 months ago
Erik Auerswald a333f95c9d ci: test empty string argument instead of number
Giving an empty string instead of a number as option argument
was not reliably caught, see GH issue #324 and GH PR #323.
4 months ago
German Service Network 94de79153f Fix incorrect return-value check for a scanf like function 4 months ago
German Service Network 118cdc5cc6 configure.ac check required function strftime 5 months ago
German Service Network b39f5a5cef Extended dokumentation for parameter timestamp-format 5 months ago
German Service Network aa724910b8 Test 05 for --timestamp-format extended 5 months ago
German Service Network 85b92d3d21 New parameter timestamp-format for changing the timestamp output 5 months ago
German Service Network 652d319803 Handling optparse long option 5 months ago
German Service Network 2f2ff0bd2c Change to codeql-action-v2 5 months ago
German Service Network 46793cdf80 Debug with Visual Studio Code 5 months ago
Erik Auerswald 97b7484350 test error when binding to wrong local address
Test "fping -S" with both IPv4 and IPv6 addresses not configured
on local interfaces using addresses reserved for documentation.
Check the fping error message, but accept any system generated
additional information.  This additional information differs
between operation systems.
5 months ago
Erik Auerswald 79e274d4b8 test help output during normal option parsing
The existing test for "fping -h" triggers the special code path
for only one option, either -h or --help, that is handled before
normal option parsing.
5 months ago
Eduard Vlad 11a48b4de1 add nonzero flag instead of random data for accessing it 5 months ago
Erik Auerswald 90ad83fbd0 Print cumulative stats with -Q SECS,cumulative
With -Q SECS, fping emits information for the just finished
interval.  This is good for long-running fping processes where
one would like to get an update on recent results, ignoring
missing responses from older intervals.  This seems appropriate
for use with other software like netdata or smokeping.

But for short(er)-running fping processes, e.g., during a change
window, it may be more interesting to get a status update since
the beginning of the change window, i.e., the start of fping.
Adding a comma followed by the keyword "cumulative" to -Q SECS
(i.e., -Q SECS,cumulative) changes the interim reports to output
the current per system overall statistics, unless -N is used, too.

The new syntax is documented in fping.pod and added to fping -h
output.

Four tests are added:

  1. Characters after SECS are ignored as before.
  2. Unknown keywords are ignored as before.
  2. Adding ",cumulative" changes -Q output.
  3. Adding ",cumulative" also affects the additional -o output.

This addresses issue #243.
6 months ago
dwes 0d08321346 Prepare v5.2 release. 7 months ago
German Service Network bd44c9f016 Removes the unnecessary file 18 7 months ago
German Service Network f71e40ab60 Extended configure.ac with --enable-debug and create debug output cpu time use 7 months ago
German Service Network 5a2a23d2af Update Azure Pipline add macOS pipline job 7 months ago
German Service Network 47c0c3d8de Update Azure Pipline linux test based on github pipline with matching exclude 7 months ago
David Schweikert ab05279782 Fix number of tests 7 months ago
David Schweikert d6d9c653eb Remove flaky test for now.
Remove the 'fping -X 2 --generate 8.8.0.0/29' test, because it
is currently failing on the MacOS runner. Also, I am not sure that
it is a good idea to ping the IPs 8.8.0.1 and 8.8.0.2 and rely on
them being up.
7 months ago
German Service Network 94e98acaaa Check if the variable next_value->ping_ts != 0 in seqmap_add() 7 months ago
Erik Auerswald c3a2f2c7cc always output error message in crash_and_burn()
This aligns crash_and_burn() with errno_crash_and_burn()
and addresses issue #300.
9 months ago
Erik Auerswald 4151976986 improve help output for options -c and -C 9 months ago
Erik Auerswald 266eb16568 use function stats_reset_interval()
Git commit bb8d71ef27 from 2020 among many
other things introduced the function stats_reset_interval() to reset the
*_i interval (or split) host statistics, but did not use it.  This commit
replaces the open coded reset of interval stats inside print_host_splits()
and print_netdata() with calling stats_reset_interval().
9 months ago
Erik Auerswald c138b08141 typo fixes pertaining to ICMP for IPv6 sockets
As mentioned in issue #300, error messages pertaining to
socket creation may not be printed.  But they should be
corrected anyway, just as the comments.  Having correct
error messages also makes a fix for issue #300 more
obvious, because the messages itself would not change.
9 months ago
Erik Auerswald ae0bc23804 Document that -c N overrides -a or -u 9 months ago
Erik Auerswald 1443614dad Decouple -a/-u effects from -c
As described in issue #295, the option combinations "-c N -u"
and "-c N -a" inadvertently have the same effect as "-c N -q".
Prevent this by first acting on -c, which includes disabling
either -a or -u, if -c is given, before acting on -a/-u.
9 months ago
Erik Auerswald c122186f70 Move description of -i MSEC to probing options
The -i MSEC, --interval=MSEC option does not directly affect
the output format, but rather the probe generation, i.e., the
minimum time between probes.  Thus it is more fitting to list
it under "probing options" than under "output options".
9 months ago
Erik Auerswald d312a278d5 Test ping to "all IPv6 nodes" multicast address
Any Echo Response packet uses a different source address than
used for the target, because it is not allowed to use a multicast
address as source.  This results in extra output in a specific
format on standard error.

This should work, because IPv6 requires multicast support, and
every IPv6 node is supposed to join the "all nodes" multicast
group, including the node the test runs on.  It at least works
on my Ubuntu 20.04 LTS system.
9 months ago
Erik Auerswald ef74f642d1 Test edge cases of -f and -g
* -f with non-existing file
* -f with input file containing comment and empty line
* -g with non-numeric address in "CIDR" format
* -g with one non-numeric address in start resp. end position
* -g with one IPv6 address in start resp. end position
9 months ago
Erik Auerswald 32b9a55a98 Test -l together with -Q or -t 9 months ago
Erik Auerswald dcda0cc595 Test that -x, -X, -k require numeric argument 9 months ago
Erik Auerswald c5428391a6 Test that negative numbers are not accepted 9 months ago
Erik Auerswald 8ae2babae0 Fix a comment describing a test 9 months ago
Erik Auerswald 290d944b56 Defensive coding: guard against a division by zero
In the function print_per_system_stats(), if packets have been
lost, the number of sent packets is checked to be positive before
dividing by it.  If no packets have been lost, this is not checked.
Either the existing check is not needed, or both code paths need
the check.

The function print_per_system_splits() is quite similar to
print_per_system_stats(), and has the equivalent guards against a
division by zero in both code paths, not just one of them.

In the spirit of defensive coding, I think it is better to be safe
and add the missing guard against a division by zero.
9 months ago
Erik Auerswald e4bae43d66 Update exit status description in man page
With the options -x and -X, fping does not require all hosts to
be reachable for an exit status of 0.

This addresses a comment in issue #99 suggesting such a man page
update.
9 months ago
Erik Auerswald 2a609b856d Test examples from man page
The man page gives two examples combining -C and -q, but
these combinations are not yet tested.  Add tests to help
ensure the documented examples continue to work.
10 months ago
Erik Auerswald 3a527fbc86 Add test for option combination -Q SECS -o
The -o option adds outage duration to the periodic reports.
Each report shows the outage since the last report, not since
the beginning.
10 months ago
Erik Auerswald 4753437b17 Add longer test for -Q SECS
The statistics printed every SECS seconds show the results
since the the last report, not since the beginning.  Also,
every report starts with a timestamp.
10 months ago
Erik Auerswald ccc0cdfdd7 Test that -g does not accept IPv6 10 months ago
Erik Auerswald 2fa4f61079 Test edge case behavior of "fping -g"
* wrong number or kind of arguments fails and prints usage;
* an empty range silently pings nothing and fping returns 1;
* a too large range fails with an error message;
* a zero CIDR prefix length fails with an error message.
10 months ago
deepkv c8e9632150 Add --fwmark/-k option for Linux 10 months ago
German Service Network a3f4c573bf Change obsolete macro from AC_CANONICAL_SYSTEM to AC_CANONICAL_TARGET 1 year ago
German Service Network 7351afdd89 Move the OS detection to configure.ac script to set the use of clock_realtime 1 year ago
German Service Network 163fcdb1ed Fix deprected github action ubuntu-18.04 to ubuntu-22.04 1 year ago
German Service Network b8e413f5ba Checking obsolete macro AC_PROG_CC_STDC as of autoconf-2.70 1 year ago
German Service Network 88091f7c94 Checking obsolete macro AC_GNU_SOURCE as of autoconf-2.62 1 year ago
darless 8601d1ba70 Remove dockerfile from root 1 year ago
darless1 e20939ebfe Move to contrib folder 1 year ago
darless1 55ad83898f Dockerfile for fping 1 year ago
German Service Network 59f32cefb2 Repair the faulty test 15 1 year ago
ilyam8 a6c314516c remove host from netdata chart titles 1 year ago
ilyam8 16108c4fa7 remove www 1 year ago
ilyam8 d95370cbb0 update netdata link 1 year ago
Vincent OLLIVIER 86dedacbe7 Updating documentation regarding root requirements since for --file parameter 1 year ago
Khem Raj c0fbccb977 fping: Initialize msghdr struct in a portable way
Initializing the structure assuming glibc layout results in
compile errors on musl, therefore do partial intialization and then
assigning the members individually.

Signed-off-by: Khem Raj <raj.khem@gmail.com>
1 year ago
German Service Network f94adaf29e Test for fping: add option to exit immediately once N hosts have been found 1 year ago
German Service Network d45438c723 fping: add option to exit immeditely once N hosts have been found 1 year ago
German Service Network e597c48d77 Fixing build warning long int on seqmap.c line 84 1 year ago
German Service Network 9d7731e7a0 OpenBSD is not affected by the "broken alpha headers" bug, too. 1 year ago
German Service Network e8660637cc Fallback to SO_TIMESTAMP if SO_TIMESTAMPNS is not available 1 year ago
David Schweikert 8dc0b7f39a correctly call getnameinfo() 2 years ago
David Schweikert 041ba7acb8 reformat 2 years ago
Thomas Klausner 5d3eee1105 NetBSD/alpha is not affected by the "broken alpha headers" bug. 3 years ago
David Schweikert ab1ed993ba fix socket4 vs socket6 typo (#249, thanks @sfan5) 3 years ago
David Schweikert e975a4339b fix unprivileged ping broken in v5.1 (fixes #248) 3 years ago
David Schweikert 87c9b29d86 update changelog and 5.1 release date 3 years ago
David Schweikert ae49f4d933 Update autotools and fix code coverage issues. 3 years ago
Erik Auerswald c67f6deb51 add missing files to autoclean.sh
At least on my system (Ubuntu GNU/Linux 18.04.6 LTS), autoclean.sh
misses three files: compile, doc/Makefile, and src/Makefile.  Add
them.
3 years ago
German Service Network 948b58ee1f Remove dublicate include time.h entry 3 years ago
David Schweikert 3ecfbb7c1e GH action test 3 years ago
David Schweikert 2d574aa1d1
Create codeql-analysis.yml (#241)
Create codeql-analysis.yml
3 years ago
David Schweikert 052b58be65
Merge pull request #240 from auerswal/doc-fixes
Documentation improvements
3 years ago
Erik Auerswald 36b652b358 Improve -Q documentation
The `-Q, --squiet=SECS` option does not replace the summary
statistics of `-q, --quiets`, but adds interval summary
statistics every SECS seconds to the output.
3 years ago
Erik Auerswald 1452bf362e Improve -d and -n documentation
* Adjust `fping.pod` entries for `-d, --rdns` and `-n, --name`:

  * The code performs reverse DNS lookups on the given targets,
    not on source addresses from ICMP Echo Responses or ICMP
    error messages.  Adjust the `-d` description to reflect this.

  * The sentence describing `-n` seems incomplete, so provide a
    completion in similar spirit to `-d`.

* Add `-d, --rdns` to `-h, --help` output since `-d` and `-n` are
  no longer equivalent.
3 years ago
David Schweikert 477e6776ce
Merge pull request #236 from schweikert/travis-fix
Prepare 5.1 release
3 years ago
David Schweikert cbe7a92c14 prepare 5.1 release 3 years ago
David Schweikert bbaa365526 more travis stability fixes 3 years ago
David Schweikert cf03fa5bdb skip timing test on macos 3 years ago
David Schweikert f1d3615706
Merge pull request #217 from gsnw/bug/203
Fixed wrong timestamp under Free- and OpenBSD and macOS
3 years ago
German Service Network 04af04c839 Fixed wrong timestamp under Free- and OpenBSD and macOS 3 years ago
David Schweikert 749127f525
Merge pull request #227 from aafbsd/patch-1
fix getnameinfo
3 years ago
David Schweikert 03aea81617
Merge pull request #229 from gsnw/bug/219
use formatstring macro PRId64 in print_netdata for output int64_t
3 years ago
David Schweikert df5f072ddd
Merge pull request #235 from schweikert/travis-fix
make travis testing more robust
3 years ago
David Schweikert 7b3cf2593a fix travis build 3 years ago
David Schweikert ca3cf3a347
Merge pull request #232 from zdyxry/spec
Use setcap to specify specific files
3 years ago
Yiran Zhou 029da075e2 Use setcap to specify specific files 3 years ago
David Schweikert 19ddae8fdc
Merge pull request #226 from k0ste/help
Netdata feature: use host instead name as family label
3 years ago
German Service Network ea0eda41f1 use formatstring macro PRId64 in print_netdata for output int64_t 3 years ago
aafbsd bbe847a5d9
Update fping.c
getnameinfo() was not called properly for IPv4 (didn't check v6).
Additionally, one might also want to check the result code, call gai_strerror() and inform the user if s.th. goes wrong
3 years ago
David Schweikert b4aeda17fd
Merge pull request #215 from normanr/develop
Allow -4 option to be given multiple times when IPv6 is enabled.
3 years ago
Konstantin Shalygin b46c161bb3
Netdata feature: use host instead name as family label
Fixes https://github.com/netdata/netdata/issues/11336
3 years ago
David Schweikert d05a7e7bf9
Merge pull request #208 from timgates42/bugfix_typo_permanently
docs: fix simple typo, permanetly -> permanently
3 years ago
Norman Rasmussen e432f46e01 Allow -4 option to be given multiple times when IPv6 is enabled. 4 years ago
Tim Gates 95df9d00f5
docs: fix simple typo, permanetly -> permanently
There is a small typo in src/fping.c.

Should read `permanently` rather than `permanetly`.
4 years ago
David Schweikert eac20347ba
Merge pull request #200 from simetnicbr/for-upstream/privileged-SO_BINDTODEVICE
fping: retain privileges until after privileged setsockopt
4 years ago
David Schweikert 49673f7862
Merge pull request #198 from dinoex/develop
- fix regression introduced in fping 4.3
4 years ago
David Schweikert ce9d6b351e
Merge pull request #197 from gsnw/develop
Update Azure Pipline based on travis-ci tuning
4 years ago
Henrique de Moraes Holschuh 59d83ed402 fping: retain privileges until after privileged setsockopt
On Linux, one needs privileges to setsockopt(SO_BINDTODEVICE), and the
current code would drop setuid root privileges too soon.

Temporarily drop privileges instead, and raise them back to issue the
privileged setsockopt().  Once we know we won't need to do any further
privileged setsockopt(), permanently drop privileges.

For now, assume SO_BINDTODEVICE is the only setsockopt that needs this.
4 years ago
Dirk Meyer 31f76f6071 - fix regression introduced in fping 4.3
bind to source only when option was set.
this allows to work in jails and lxc with custom IPs.
this allows IPv4 only and IPv6 only hosts
4 years ago
German Service Network f2b2cdf620 Update Azure Pipline based on travis-ci tuning 4 years ago
David Schweikert 296de3d7a2 small fixes to changelog 4 years ago
David Schweikert 03bfc48ff4 travis-ci: fix deploy stage 4 years ago
David Schweikert 5f5220939d travis-ci: fix deploy stage 4 years ago
David Schweikert f6e3d7194d prepare 5.0 release 4 years ago
David Schweikert 57d49f2d8e move coverity scan to a script, so that it doesn't run for every job 4 years ago
David Schweikert 2ca8edeaf6 change license field in fping.spec to something that seems better matching, fixes #192 4 years ago
David Schweikert 0d8f3cef2a move coverity scan to a script, so that it doesn't run for every job 4 years ago
David Schweikert aeea60a0e0 move coverity scan to a script, so that it doesn't run for every job 4 years ago
David Schweikert 5a6a61cb32 update coverage badge link 4 years ago
David Schweikert 4f16eea49f use int64_t for time-related variables 4 years ago
David Schweikert 2dbe46f936 remove debug output 4 years ago
David Schweikert 363396c28f use int64_t everywhere, instead of long and 10us values 4 years ago
David Schweikert 88ef7a7b98 Merge branch 'testing-improvements' into develop 4 years ago
David Schweikert 73bfc121c2 more travis-ci improvements 4 years ago
David Schweikert d06b8fcea3
Merge pull request #196 from schweikert/travis-improvements
Travis CI improvements, add macos testing
4 years ago
David Schweikert 5655b7664c travis-ci improvements 4 years ago
David Schweikert 3bb2811139 travis-ci: use xenial autotools instead of building them 4 years ago
David Schweikert 2f71a6a701 travis-ci improvements, add macos testing 4 years ago
David Schweikert 9682f3e49d add a not about unprivileged mode 4 years ago
David Schweikert a136764f8c always exclude IP header in returned size 4 years ago
David Schweikert 43f6e3498e print lost pings in loop and count mode, fixes #175 4 years ago
David Schweikert 130b1d6f9b revert sprint_tm change doing apparent wrong casting 4 years ago
David Schweikert fec099871c fix compiler warning 4 years ago
David Schweikert da27697eb4 small formatting fixes to printed time 4 years ago
David Schweikert fe4388ca3d use int64_t whenever time is stored, fixes #195 4 years ago
David Schweikert eb87a2affd use int64_t instead of struct timespec everywhere
This should be more efficient and is also easier to read.
4 years ago
David Schweikert 5473c7d734 remove unused host_entry fields 4 years ago
David Schweikert ac3eb34ad7 Merge branch 'develop' of github.com:schweikert/fping into develop 4 years ago
David Schweikert 2cb373463f simplify timespec conversions to ns, prepare mocking of receive_packet 4 years ago
David Schweikert 6505832d6a
Merge pull request #194 from Kiskae/portable_signals
Improve portability of signal handling
4 years ago
David van Leusen 254573f241 use sigaction when possible 4 years ago
David van Leusen 69f7277076 implement finish handler through flag instead of direct call in signal handler 4 years ago
David Schweikert 2b5c0e62ec
Merge pull request #193 from schweikert/timeout-events
refactored event loop, now for each ping create both next-ping+timeout events
4 years ago
David Schweikert bb8d71ef27 refactored event loop, now for each ping we create both a ping and a timeout event 4 years ago
Steven Noonan 6600b04152 only use getsockname() for identity with SOCK_DGRAM sockets
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
4 years ago
David Schweikert 8152668607 update CHANGELOG 4 years ago
David Schweikert c7437d8f61
Merge pull request #187 from Polynomial-C/disable-ipv6_build_fix
Fix build with --disable-ipv6
4 years ago
Lars Wendler 54e97d9e39
Fix build with --disable-ipv6
Otherwise build breaks with:

fping.c:399:14: error: ‘ident6’ undeclared (first use in this function); did you mean ‘ident4’?
  399 |     ident4 = ident6 = getpid() & 0xFFFF;
      |              ^~~~~~
      |              ident4

Signed-off-by: Lars Wendler <polynomial-c@gentoo.org>
4 years ago
David Schweikert 08c83453f3 Merge branch 'v4.x' into develop 4 years ago
David Schweikert 9731556633 prepare for version 5.x 4 years ago
David Schweikert c1d3f65694 update changelog 4 years ago
David Schweikert 721af135db
Merge pull request #136 from tycho/high-resolution-clock-sources
Move to 1us resolution for latency measurements
4 years ago
Steven Noonan ad451e7a15
test-05: don't assume -D timestamp is based on UNIX epoch
If CLOCKID != CLOCK_REALTIME, it probably will not have anything to do
with the UNIX epoch, so it could be smaller than 10 digits.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
4 years ago
Steven Noonan 754a21e2bd
move to 1us resolution for latency measurement
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
4 years ago
Steven Noonan 8aa4361118
allow passing hex or decimal arguments to -z (debug) flag
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
4 years ago
Steven Noonan e21b68f62e
main: add missing getopt_long specification for -z debug argument
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
4 years ago

@ -0,0 +1,30 @@
.*.swp
*.tar.gz
*~
src/*.gcno
src/*.gcda
src/*.gcov
src/tags
.deps
Makefile
Makefile.in
aclocal.m4
autom4te.cache
compile
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
missing
src/*.o
src/fping
src/fping6
stamp-h1
doc/fping.8
doc/fping6.8
ci/build

@ -0,0 +1,67 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ develop ]
schedule:
- cron: '38 4 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

@ -0,0 +1,108 @@
name: Test
on: [push, pull_request]
jobs:
Test-Linux:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-22.04]
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install libcap2-bin libtest-command-perl lcov
sudo sysctl net.ipv4.ping_group_range='0 2147483647'
- name: Build
run: |
ci/build-1-autotools.sh
ci/build-4-compile.sh
ci/test-tarball.sh
- name: Test
run: |
set -ex
PATH=`pwd`/src:$PATH
# avoid pinging internet hosts because it doesn't
# work with GitHub Actions being hosted in Azure.
prove $(ls ci/test-*.pl|grep -v internet-hosts)
ci/run-lcov.sh
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: lcov.info
flag-name: ${{ matrix.os }}
parallel: true
Test-Mac:
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install dependencies
run: |
brew install automake lcov
ci/build-2-test-command.sh
ci/build-3-prepare-macos.sh
- name: Build
run: |
ci/build-4-compile.sh
- name: Test
run: |
set -ex
PATH=`pwd`/src:$PATH
export SKIP_IPV6=1
prove $(ls ci/test-*.pl|grep -v internet-hosts)
ci/run-lcov.sh
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: lcov.info
flag-name: macos
parallel: true
Coveralls-Finish:
needs: [Test-Linux, Test-Mac]
runs-on: ubuntu-latest
steps:
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
Release-Tarball:
needs: [Test-Linux, Test-Mac]
if: ${{ github.event_name == 'push' }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install libcap2-bin libtest-command-perl
- name: Build
run: |
ci/build-1-autotools.sh
ci/build-4-compile.sh
ci/test-tarball.sh
- uses: actions/upload-artifact@v2
with:
name: dist
path: fping-*.tar.gz

@ -1,40 +1,98 @@
# travis-ci.org configuration
#
language: generic
sudo: required
dist: trusty
os:
- linux
dist:
- trusty
- xenial
env:
global:
- secure: "CoI8hwHH1yfQoQxIfWGRS0WfTyScox+5aJn0fDDgz2uKrrIxmBvIw/WKX8wcSiV6fLmLuwgNkKqSM3hdO4qaG+JxfWcuEiZZHm+kxSGMkWbGb/fvAI+gHg8ldKyYttcIX71O5rlZiC2QpNKQi2v18S6pI5p8eqnx7DYx4YrmguQ="
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
- secure: "C9ZJ9LYnuowRdF4D66KLfquimvu8GtRGIafwvCcGYKReEy8phlBdFsHlybkMBNYJNTJSM0j6wyo1lKTVGHxmpQDimjR7kmxUtawbhuJ5qOCBtFqNVh9lRQi7hC4+UOhvRsIcbV8HAJM5u/5RxGOfXCePK3a2DtiYv1d2NHToZN8="
global:
- secure: "CoI8hwHH1yfQoQxIfWGRS0WfTyScox+5aJn0fDDgz2uKrrIxmBvIw/WKX8wcSiV6fLmLuwgNkKqSM3hdO4qaG+JxfWcuEiZZHm+kxSGMkWbGb/fvAI+gHg8ldKyYttcIX71O5rlZiC2QpNKQi2v18S6pI5p8eqnx7DYx4YrmguQ="
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
- secure: "C9ZJ9LYnuowRdF4D66KLfquimvu8GtRGIafwvCcGYKReEy8phlBdFsHlybkMBNYJNTJSM0j6wyo1lKTVGHxmpQDimjR7kmxUtawbhuJ5qOCBtFqNVh9lRQi7hC4+UOhvRsIcbV8HAJM5u/5RxGOfXCePK3a2DtiYv1d2NHToZN8="
notifications:
webhooks: https://coveralls.io/webhook
compiler:
- gcc
before_install:
- sudo apt-get update -qq
- sudo apt-get install libcap2-bin
#- sudo apt-get install traceroute
#- traceroute google.com
- echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
install:
- ci/build-1-autotools.sh
- curl -L http://cpanmin.us | perl - --sudo App::cpanminus
- cpanm --sudo Test::Command
- gcc
addons:
apt:
update: true
packages:
- libcap2-bin
- libtest-command-perl
script:
- ci/build-2-install.sh
- env PATH=`pwd`/src:$PATH prove ci/test-*.pl
- ci/test-tarball.sh
- ci/build-4-compile.sh
- ci/run-tests.sh
after_success:
- ci/coveralls.sh
- ci/deploy-bintray.sh
- ci/deploy-coveralls.sh
addons:
coverity_scan:
project:
name: "schweikert/fping"
description: "Build submitted via Travis CI"
notification_email: david@schweikert.ch
#build_command_prepend: "ci/build-2-install.sh"
build_command: "ci/build-2-install.sh"
branch_pattern: coverity_scan
stages:
- test
- name: deploy
if: branch = master OR branch = v4.x
- name: coverity
if: branch = master OR branch = coverity_scan
jobs:
include:
#### STAGE: test
- stage: test
name: test trusty
os: linux
dist: trusty
env:
- SKIP_IPV6=1
install:
- ci/build-1-autotools.sh
- name: test xenial
os: linux
dist: xenial
env:
- SKIP_IPV6=1
- name: test bionic
os: linux
dist: bionic
env:
- SKIP_IPV6=1
- name: test bionic lxd arm64
os: linux
dist: bionic
arch: arm64
- name: test macos
os: osx
install:
- ci/build-2-test-command.sh
- ci/build-3-prepare-macos.sh
env:
- SKIP_IPV6=1
#### STAGE: deploy
- stage: deploy
name: deploy
os: linux
dist: xenial
env:
- SKIP_IPV6=1
after_success:
- ci/deploy-bintray.sh
#### STAGE: coverity
- stage: coverity
name: coverity
os: linux
dist: xenial
after_success:
script:
- ci/deploy-coverity.sh

@ -0,0 +1,35 @@
{
"configurations": [
{
"name": "Debug fping",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/src/fping",
"args": ["127.0.0.1"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"preLaunchTask": "build",
"postDebugTask": "autoclean",
"miDebuggerPath": "/usr/bin/gdb",
"logging": {
"engineLogging": false
}
}
],
"version": "2.0.0"
}

45
.vscode/tasks.json vendored

@ -0,0 +1,45 @@
{
"tasks": [
{
"type": "shell",
"label": "autogen",
"command": "./autogen.sh",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": []
},
{
"type": "shell",
"label": "configure",
"command": "./configure",
"args": ["--enable-debug"],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": ["autogen"],
"problemMatcher": []
},
{
"type": "shell",
"label": "build",
"command": "make",
"args": ["CFLAGS=\"-g -O0\""],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": ["configure"],
"problemMatcher": ["$gcc"]
},
{
"type": "shell",
"label": "autoclean",
"command": "./autoclean.sh",
"problemMatcher": []
}
],
"version": "2.0.0"
}

@ -1,3 +1,112 @@
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)
======================

@ -1,5 +1,5 @@
[![Build Status](https://travis-ci.org/schweikert/fping.svg?branch=develop)](https://travis-ci.org/schweikert/fping)
[![Coverage Status](https://coveralls.io/repos/schweikert/fping/badge.svg?branch=develop&service=github)](https://coveralls.io/github/schweikert/fping?branch=develop)
[![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
@ -28,7 +28,14 @@ If you want to install fping from source, proceed as follows:
(see: `./configure --help`)
2. Run `make; make install`.
3. Make fping either setuid, or, if under Linux:
`sudo setcap cap_net_raw+ep fping`
`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. setuid will not work for --fwmark.
## Usage

@ -4,6 +4,7 @@ rm -f Makefile
rm -f Makefile.in
rm -f aclocal.m4
rm -rf autom4te.cache
rm -f compile
rm -f config.guess
rm -f config.h
rm -f config.h.in
@ -16,7 +17,9 @@ rm -f install-sh
rm -f missing
rm -f mkinstalldirs
rm -f stamp-h1
rm -f doc/Makefile
rm -f doc/Makefile.in
rm -f src/Makefile
rm -f src/Makefile.in
rm -f doc/fping.8
rm -f src/*.gcda

@ -2,25 +2,51 @@ jobs:
- job: linux_build
displayName: Linux Build
pool: Hosted Ubuntu 1604
pool:
name: Azure Pipelines
vmImage: 'ubuntu-latest'
workspace:
clean: all
steps:
- script: |
sudo apt-get update -qq
sudo apt-get install libcap2-bin
echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
sudo apt-get install libcap2-bin libtest-command-perl
displayName: 'before_install'
- script: |
ci/build-1-autotools.sh
curl -L http://cpanmin.us | perl - --sudo App::cpanminus
cpanm --sudo Test::Command
ci/build-4-compile.sh
displayName: install
- script: |
ci/build-2-install.sh
env PATH=`pwd`/src:$PATH prove ci/test-{01..13}*.pl
env PATH=`pwd`/src:$PATH prove ci/test-15*.pl
set -ex
PATH=`pwd`/src:$PATH
prove $(ls ci/test-*.pl|grep -v internet-hosts|grep -v -E "test-13-unknown-host.pl|test-14-ping-internet-hosts.pl")
ci/test-tarball.sh
displayName: 'build_test'
- job: macos_build
displayName: macOS Build
pool:
name: Azure Pipelines
vmImage: 'macos-latest'
workspace:
clean: all
steps:
- script: |
brew install autoconf automake lcov
ci/build-2-test-command.sh
ci/build-3-prepare-macos.sh
displayName: 'before_install'
- script: |
ci/build-4-compile.sh
displayName: install
- script: |
set -ex
PATH=`pwd`/src:$PATH
export SKIP_IPV6=1
prove $(ls ci/test-*.pl|grep -v internet-hosts|grep -v test-10-option-u-x.pl)
ci/run-lcov.sh
displayName: 'build_test'

@ -1,8 +1,15 @@
#!/bin/bash -e
#!/bin/bash
AUTOCONF=http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
AUTOMAKE=http://ftp.gnu.org/gnu/automake/automake-1.14.1.tar.gz
LIBTOOL=http://alpha.gnu.org/gnu/libtool/libtool-2.4.2.418.tar.gz
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

@ -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

@ -11,8 +11,3 @@ if [[ ! `ifconfig lo0` =~ 127\.0\.0\.2 ]]; then
sudo ifconfig lo0 127.0.0.4/8 alias
sudo ifconfig lo0 127.0.0.5/8 alias
fi
if [[ ! $PATH =~ /Users/dws/checkouts/fping/src ]]; then
echo "# WARNING: must set PATH:"
echo PATH=/Users/dws/checkouts/fping/src:\$PATH
fi

@ -1,13 +0,0 @@
#!/bin/sh
set -x
sudo -H pip install cpp-coveralls
cd src
ls -l
gcov *.o
cd ..
coveralls --exclude ci --exclude src/optparse.c --no-gcov

@ -4,18 +4,6 @@
set -e
# do this only for the gcc run
#if [ "$CC" != "gcc" ]; then
# echo "skipped upload because $CC != gcc"
# exit 0
#fi
# do this only for the master and version3 branch
if [ "$TRAVIS_BRANCH" != "master" -a "$TRAVIS_BRANCH" != "version3" ]; then
echo "skipped upload branch $TRAVIS_BRANCH isn't master/version3"
exit 0
fi
VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//')
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
REPO=release

@ -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'

@ -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 "

@ -1,6 +1,6 @@
#!/bin/bash
sudo setcap cap_net_raw+ep src/fping
sudo setcap cap_net_raw,cap_net_admin+ep src/fping
if [[ ! $PATH =~ fping/src ]]; then
PATH=/home/dws/checkouts/fping/src:$PATH

@ -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'

@ -0,0 +1,8 @@
#!/bin/sh
set -ex
PATH=`pwd`/src:$PATH
prove ci/test-*.pl
ci/test-tarball.sh

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 9;
use Test::Command tests => 12;
use Test::More;
# ping 127.0.0.1
@ -14,8 +14,8 @@ use Test::More;
# ping ::1
SKIP: {
#system("/sbin/ifconfig >&2");
if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'No IPv6 on this host', 3;
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping ::1");
$cmd->exit_is_num(0);
@ -23,13 +23,25 @@ SKIP: {
$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\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[2\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
$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});
}

@ -1,11 +1,11 @@
#!/usr/bin/perl -w
use Test::Command tests => 9;
use Test::Command tests => 12;
my $I_HELP = " -I, --iface=IFACE bind to a particular interface\n";
$I_HELP = '' if $^O eq 'darwin';
# fping -h
# 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\.\.\.\]
@ -16,11 +16,21 @@ Probing options:
}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+
fping: comments to david\@schweikert\.ch\n});
$cmd2->stdout_like(qr{fping: Version \S+});
$cmd2->stderr_is_eq("");
# fping with unknown option

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 24;
use Test::Command tests => 36;
# fping -i 0
my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29");
@ -50,9 +50,16 @@ $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 0.9
# 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:});
}

@ -44,8 +44,8 @@ $cmd->stderr_like(qr{^::1:.*(not supported|not known)});
# fping -6
SKIP: {
if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'No IPv6 on this host', 3;
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -6 ::1");
$cmd->exit_is_num(0);
@ -85,14 +85,17 @@ $cmd->stderr_is_eq("");
}
# fping -B
{
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.8);
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);
}

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 12;
use Test::Command tests => 51;
# -c n count of pings to send to each target (default 1)
# -C n same as -c, report results in verbose format
@ -11,10 +11,50 @@ use Test::Command tests => 12;
{
my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{localhost : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
localhost : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
$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 -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+
@ -26,10 +66,10 @@ $cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\
{
my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{localhost : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
localhost : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
$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+
@ -37,18 +77,130 @@ $cmd->stderr_like(qr{localhost : \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 -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{10}\.\d+\] 127\.0\.0\.1 : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
\[\d{10}\.\d+\] 127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
$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");

@ -1,6 +1,7 @@
#!/usr/bin/perl -w
use Test::Command tests => 24;
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)
@ -13,6 +14,10 @@ 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");
@ -37,6 +42,70 @@ $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");
@ -45,6 +114,22 @@ $cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n127.0.0.3 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");
@ -53,7 +138,7 @@ $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)
# 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);
@ -61,6 +146,14 @@ $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");
@ -69,6 +162,66 @@ $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");

@ -1,10 +1,11 @@
#!/usr/bin/perl -w
use Test::Command tests => 9;
use Test::Command tests => 15;
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
@ -19,25 +20,57 @@ $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\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
$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 -k
SKIP: {
if($^O ne 'linux') {
skip '-k option is only supported on Linux', 3;
}
my $cmd = Test::Command->new(cmd => 'sudo env "PATH=$PATH" 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\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[2\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[3\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[4\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
$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: {

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 18;
use Test::Command tests => 36;
# -n show targets by name (-d is equivalent)
# -O n set the type of service (tos) flag on the ICMP packets
@ -31,7 +31,12 @@ $cmd->stderr_is_eq("fping: use either one of -d or -n\n");
{
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("");
$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*$});
}
@ -63,4 +68,81 @@ $cmd->stderr_like(qr{\[\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
});
}

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 21;
use Test::Command tests => 27;
use Test::More;
# -R random bytes
@ -19,8 +19,8 @@ $cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%.*});
}
SKIP: {
if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'No IPv6 on this host', 3;
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);
@ -84,10 +84,18 @@ $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(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'No IPv6 on this host', 3;
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -S ::1 ::1");
$cmd->exit_is_num(0);
@ -95,6 +103,17 @@ SKIP: {
$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");

@ -1,9 +1,11 @@
#!/usr/bin/perl -w
use Test::Command tests => 12;
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
{
@ -17,9 +19,7 @@ $cmd->stderr_is_eq("");
{
my $cmd = Test::Command->new(cmd => "fping -v");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{ping: Version 4\.\d+(-rc\d+)?
fping: comments to david\@schweikert\.ch
});
$cmd->stdout_like(qr{ping: Version [45]\.\d+(-rc\d+)?});
$cmd->stderr_is_eq("");
}
@ -38,3 +38,11 @@ $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("");
}

@ -1,43 +0,0 @@
#!/usr/bin/perl -w
use English;
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_gid_range = get_ping_gid_range();
# Linux test for unprivileged ping support
foreach(@gids) {
if ($_ >= $allowed_gid_range[0] && $_ <= $allowed_gid_range[1]) {
plan skip_all => "Userspace pings are allowed, gid $_ in range [$allowed_gid_range[0], $allowed_gid_range[1]]";
exit 0;
}
}
plan tests => 3;
# run without privileges
my $fping_bin = `which fping`; chomp $fping_bin;
system("cp $fping_bin /tmp/fping.copy; chmod +x /tmp/fping.copy");
# fping
{
my $cmd = Test::Command->new(cmd => "/tmp/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\?\)});
}

@ -0,0 +1,57 @@
#!/usr/bin/perl -w
use English;
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 $fping_bin = `which fping`; chomp $fping_bin;
system("cp $fping_bin /tmp/fping.copy; chmod +x /tmp/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 => 3;
{
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("");
}
}
sub test_privileged_fails {
plan tests => 3;
{
my $cmd = Test::Command->new(cmd => "/tmp/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\?\)});
}
}

@ -1,10 +1,27 @@
#!/usr/bin/perl -w
use Test::Command tests => 33;
use Test::Command tests => 84;
use Test::More;
for my $arg (qw(b B c C H i O p Q r t)) {
my $cmd = Test::Command->new(cmd => "fping -$arg xxx");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{Usage:});
# 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:});
}
}

@ -15,13 +15,12 @@ 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 4.2.2.5 www.france-telecom.fr www.google.com");
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]/3/\d+%, min/avg/max = $re_num/$re_num/$re_num
4\.2\.2\.5\s*: xmt/rcv/%loss = [123]/3/\d+%, min/avg/max = $re_num/$re_num/$re_num
www\.france-telecom\.fr\s*: xmt/rcv/%loss = [123]/3/\d+%, min/avg/max = $re_num/$re_num/$re_num
www\.google\.com\s*: xmt/rcv/%loss = [123]/3/\d+%, min/avg/max = $re_num/$re_num/$re_num
$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
});
}
@ -59,23 +58,23 @@ $cmd->stderr_is_eq("");
# fping -A -n (IPv6)
SKIP: {
if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
skip 'No IPv6 on this host', 3;
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_is_eq("dns.google (2001:4860:4860::8888) is alive\n");
$cmd->stdout_like(qr{^dns.google \(2001:4860:4860::88(44|88)\) is alive\n$});
$cmd->stderr_is_eq("");
}
# fping -m
SKIP: {
if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
skip 'No IPv6 on this host', 3;
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_is_eq("2001:4860:4860::8888 is alive\n8.8.8.8 is alive\n");
$cmd->stdout_like(qr{^.* is alive\n.* is alive\n.* is alive\n.* is alive\n});
$cmd->stderr_is_eq("");
}

@ -9,26 +9,26 @@ plan tests => 3;
{
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 for host 127\.0\.0\.1' packets '127_0_0_1' fping\.packets line 110020 1
$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 for host 127\.0\.0\.1' percentage '127_0_0_1' fping\.quality area 110010 1
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 for host 127\.0\.0\.1' ms '127_0_0_1' fping\.latency area 110000 1
DIMENSION min minimum absolute 10 1000
DIMENSION max maximum absolute 10 1000
DIMENSION avg average absolute 10 1000
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{1,2}
SET avg = \d{1,2}
SET max = \d{1,2}
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+});

@ -6,6 +6,11 @@
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

@ -3,8 +3,25 @@ dnl Process this file with autoconf to produce a configure script.
dnl Minimum Autoconf version required.
AC_PREREQ(2.59)
AC_INIT([fping],[4.3])
AC_GNU_SOURCE
AC_INIT([fping],[5.2])
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],
@ -34,22 +51,27 @@ AM_CONDITIONAL([IPV6], [test "x$have_ipv6" = "xyes"])
AM_COND_IF([IPV6], [AC_DEFINE([IPV6], [1], [IPv6 enabled])])
AC_ARG_ENABLE([timestamp],
AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMP)]))
AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMPNS)]))
AS_IF([test "x$enable_timestamp" != "xno"], [
AC_CHECK_DECL([SO_TIMESTAMP], [AC_DEFINE(HAVE_SO_TIMESTAMP, [1], [SO_TIMESTAMP is defined])], [have_so_timestamp="no"], [#include <sys/types.h>
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_CANONICAL_TARGET
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
@ -59,7 +81,7 @@ dnl Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CC_STDC
m4_version_prereq([2.70],,[AC_PROG_CC_STDC])
AC_PROG_CPP
AC_PROG_INSTALL
@ -73,6 +95,13 @@ 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

@ -0,0 +1,16 @@
FROM ubuntu:20.04
# Base
RUN apt-get update && apt-get install -y \
build-essential \
automake \
m4
# Add source code
COPY ./ /app
# Compile
WORKDIR /app
RUN autoreconf --install
RUN ./configure && make && make install
ENTRYPOINT ["fping"]

@ -2,7 +2,7 @@ Summary: send ICMP echo probes to multiple hosts
Name: fping
Version: 4.2
Release: 1
License: BSD with advertising
License: Freely redistributable without restriction
Group: Applications/System
Source0: http://fping.org/dist/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
@ -54,7 +54,8 @@ rm -rf $RPM_BUILD_ROOT
%post
if [ -x /usr/sbin/setcap ]; then
/bin/chmod 0755 /usr/sbin/fping*
/usr/sbin/setcap cap_net_raw+ep /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

@ -66,7 +66,8 @@ default is 1.5.
Number of request packets to send to each target. In this mode, a line is
displayed for each received response (this can suppressed with B<-q> or B<-Q>).
Also, statistics about responses for each target are displayed when all
requests have been sent (or when interrupted).
requests have been sent (or when interrupted). This option overrides B<-a>
or B<-u>.
=item B<-C>, B<--vcount>=I<N>
@ -77,11 +78,12 @@ designed for automated response-time statistics gathering. For example:
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.
C<-> indicating that no response was received to the fourth request. This
option overrides B<-a> or B<-u>.
=item B<-d>, B<--rdns>
Use DNS to lookup address of return ping packet. This allows you to give fping
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).
@ -91,16 +93,23 @@ hostnames as target (NAME->IP->NAME).
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. This option can only be used by the root
user. Regular users should pipe in the file via stdin:
$ fping < targets_file
Read list of targets from a file.
=item B<-g>, B<--generate> I<addr/mask>
@ -133,6 +142,11 @@ to any target (default is 10, minimum is 1).
Set the interface (requires SO_BINDTODEVICE support).
=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
@ -150,11 +164,11 @@ 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
to print hostnames in the output.
=item B<-N>, B<--netdata>
Format output for netdata (-l -Q are required). See: L<http://my-netdata.io/>
Format output for netdata (-l -Q are required). See: L<https://netdata.cloud/>
=item B<-o>, B<--outage>
@ -176,9 +190,11 @@ an individual target. Default is 1000 and minimum is 10.
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>
=item B<-Q>, B<--squiet>=I<SECS[,cumulative]>
Like B<-q>, but show summary results every n seconds.
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>
@ -231,6 +247,11 @@ Print B<fping> version information.
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
@ -266,12 +287,17 @@ B<fping website: L<http://www.fping.org>>
=head1 DIAGNOSTICS
Exit status is 0 if all the hosts are reachable, 1 if some hosts
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:

@ -1,2 +1,3 @@
BasedOnStyle: WebKit
BreakBeforeBraces: Stroustrup
PointerAlignment: Right

File diff suppressed because it is too large Load Diff

@ -7,19 +7,30 @@
#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;
extern int nonzero_payload_flag;
/* socket.c */
int open_ping_socket_ipv4(int *using_sock_dgram);
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);
#ifdef IPV6
int open_ping_socket_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);

@ -238,12 +238,14 @@ optparse_long(struct optparse *options,
/* 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;

@ -48,6 +48,7 @@ struct optparse {
int permute;
int optind;
int optopt;
char *optlongname;
char *optarg;
char errmsg[64];
int subopt;

@ -39,14 +39,16 @@
#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_S)
* 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
@ -55,7 +57,7 @@
static SEQMAP_VALUE* seqmap_map = NULL;
static unsigned int seqmap_next_id = 0;
#define SEQMAP_TIMEOUT_IN_S 10
#define SEQMAP_TIMEOUT_IN_NS 10000000000
#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
void seqmap_init()
@ -66,7 +68,7 @@ void seqmap_init()
}
}
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval* now)
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t timestamp)
{
unsigned int current_id;
SEQMAP_VALUE* next_value;
@ -79,26 +81,27 @@ unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct ti
/* check if expired (note that unused seqmap values will have fields set to
* 0, so will be seen as expired */
next_value = &seqmap_map[seqmap_next_id];
if (next_value->ping_ts.tv_sec != 0 && (now->tv_sec - next_value->ping_ts.tv_sec) < SEQMAP_TIMEOUT_IN_S) {
fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%d, host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
SEQMAP_TIMEOUT_IN_S, host_nr, ping_count, seqmap_next_id);
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.tv_sec = now->tv_sec;
next_value->ping_ts.tv_usec = now->tv_usec;
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, struct timeval* now)
SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now)
{
SEQMAP_VALUE* value;
@ -109,9 +112,13 @@ SEQMAP_VALUE* seqmap_fetch(unsigned int id, struct timeval* now)
value = &seqmap_map[id];
/* verify that value is not expired */
if (now->tv_sec - value->ping_ts.tv_sec >= SEQMAP_TIMEOUT_IN_S) {
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;
}

@ -2,19 +2,20 @@
#define SEQMAP_H
#include <sys/time.h>
#include <stdint.h>
typedef struct seqmap_value
{
unsigned int host_nr;
unsigned int ping_count;
struct timeval ping_ts;
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, struct timeval *now);
SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now);
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

@ -47,7 +47,7 @@
char* ping_buffer_ipv4 = 0;
size_t ping_pkt_size_ipv4;
int open_ping_socket_ipv4(int *using_sock_dgram)
int open_ping_socket_ipv4(int *socktype)
{
struct protoent* proto;
int s;
@ -56,23 +56,16 @@ int open_ping_socket_ipv4(int *using_sock_dgram)
if ((proto = getprotobyname("icmp")) == NULL)
crash_and_burn("icmp: unknown protocol");
*using_sock_dgram = 0;
/* create raw socket for ICMP calls (ping) */
s = socket(AF_INET, SOCK_RAW, proto->p_proto);
*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) */
s = socket(AF_INET, SOCK_DGRAM, proto->p_proto);
*socktype = SOCK_DGRAM;
s = socket(AF_INET, *socktype, proto->p_proto);
if (s < 0) {
return -1;
}
#ifdef __linux__
/* We only treat SOCK_DGRAM differently on Linux, where the IPv4 header
* structure is missing in the message.
*/
*using_sock_dgram = 1;
#endif
}
/* Make sure that we use non-blocking IO */
@ -109,12 +102,14 @@ void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr, int *ident)
if (bind(s, (struct sockaddr*)&sa, len) < 0)
errno_crash_and_burn("cannot bind source address");
memset(&sa, 0, len);
if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
errno_crash_and_burn("can't get ICMP socket identity");
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;
if (sa.sin_port)
*ident = sa.sin_port;
}
}
unsigned short calcsum(unsigned short* buffer, int length)
@ -138,6 +133,7 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len,
{
struct icmp* icp;
int n;
size_t i;
icp = (struct icmp*)ping_buffer_ipv4;
@ -147,9 +143,12 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len,
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;
if (nonzero_payload_flag) {
// for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) {
// ping_buffer_ipv4[n] = random() & 0xFF;
// }
for(n = (char*) &icp->icmp_data - (char*)icp, i = 0xA; n < ping_pkt_size_ipv4; ++n, i += 1) {
ping_buffer_ipv4[n] = i & 0xFF;
}
}

@ -46,20 +46,22 @@
char* ping_buffer_ipv6 = 0;
size_t ping_pkt_size_ipv6;
int open_ping_socket_ipv6()
int open_ping_socket_ipv6(int *socktype)
{
struct protoent* proto;
int s;
/* confirm that ICMP is available on this machine */
/* confirm that ICMP6 is available on this machine */
if ((proto = getprotobyname("ipv6-icmp")) == NULL)
crash_and_burn("icmp: unknown protocol");
crash_and_burn("ipv6-icmp: unknown protocol");
/* create raw socket for ICMP calls (ping) */
s = socket(AF_INET6, SOCK_RAW, proto->p_proto);
/* create raw socket for ICMP6 calls (ping) */
*socktype = SOCK_RAW;
s = socket(AF_INET6, *socktype, proto->p_proto);
if (s < 0) {
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
s = socket(AF_INET6, SOCK_DGRAM, proto->p_proto);
/* 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;
}
@ -99,18 +101,21 @@ void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident)
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
errno_crash_and_burn("cannot bind source address");
memset(&sa, 0, len);
if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
errno_crash_and_burn("can't get ICMP socket identity");
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;
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;
size_t i;
icp = (struct icmp6_hdr*)ping_buffer_ipv6;
icp->icmp6_type = ICMP6_ECHO_REQUEST;
@ -118,9 +123,9 @@ int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len,
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;
if (nonzero_payload_flag) {
for (n = sizeof(struct icmp6_hdr), i = 0xA; n < ping_pkt_size_ipv6; ++n, i+=1) {
ping_buffer_ipv6[n] = i & 0xFF;
}
}

Loading…
Cancel
Save