Compare commits

..

2 Commits

Author SHA1 Message Date
David Schweikert 9dad469f4a update changelog and 5.1 release date 3 years ago
David Schweikert 06bcaacd78 Update autotools and fix code coverage issues. 3 years ago

@ -1,30 +0,0 @@
.*.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

@ -39,7 +39,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -50,7 +50,7 @@ jobs:
# 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
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -64,4 +64,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v1

@ -5,7 +5,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-22.04]
os: [ubuntu-18.04, ubuntu-20.04]
steps:
- name: Checkout repository
uses: actions/checkout@v2
@ -14,7 +14,6 @@ jobs:
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: |

@ -1,35 +0,0 @@
{
"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

@ -1,45 +0,0 @@
{
"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,43 +1,3 @@
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)
======================

@ -28,14 +28,13 @@ 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,cap_net_admin+ep fping`
`sudo setcap cap_net_raw+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.
fping in rootless / unprivileged containers.
## Usage

@ -4,7 +4,6 @@ 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
@ -17,9 +16,7 @@ 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

@ -20,33 +20,7 @@ jobs:
- script: |
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")
prove ci/test-{01..12}*.pl
prove ci/test-15*.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,6 +1,6 @@
#!/bin/bash
sudo setcap cap_net_raw,cap_net_admin+ep src/fping
sudo setcap cap_net_raw+ep src/fping
if [[ ! $PATH =~ fping/src ]]; then
PATH=/home/dws/checkouts/fping/src:$PATH

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 12;
use Test::Command tests => 9;
use Test::More;
# ping 127.0.0.1
@ -23,18 +23,6 @@ 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");

@ -1,11 +1,11 @@
#!/usr/bin/perl -w
use Test::Command tests => 12;
use Test::Command tests => 9;
my $I_HELP = " -I, --iface=IFACE bind to a particular interface\n";
$I_HELP = '' if $^O eq 'darwin';
# fping -h (special pre-parse code path)
# fping -h
my $cmd1 = Test::Command->new(cmd => "fping -h");
$cmd1->exit_is_num(0);
$cmd1->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\]
@ -16,17 +16,6 @@ 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);

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 36;
use Test::Command tests => 24;
# fping -i 0
my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29");
@ -50,16 +50,9 @@ $cmd9->exit_is_num(1);
$cmd9->stdout_is_eq("");
$cmd9->stderr_is_eq("fping: backoff factor 0.9 not valid, must be between 1.0 and 5.0\n");
# fping -B 5.1
# fping -B 0.9
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:});
}

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 51;
use Test::Command tests => 12;
# -c n count of pings to send to each target (default 1)
# -C n same as -c, report results in verbose format
@ -22,46 +22,6 @@ $cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\
});
}
# fping -c n -q
{
my $cmd = Test::Command->new(cmd => "fping -q -c 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -c n -a (-a is ignored)
{
my $cmd = Test::Command->new(cmd => "fping -a -c 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -c n -u (-u is ignored)
{
my $cmd = Test::Command->new(cmd => "fping -u -c 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -C n
{
my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1");
@ -77,55 +37,6 @@ $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");
@ -138,69 +49,6 @@ $cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \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,7 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 75;
use Test::More;
use Test::Command tests => 24;
use File::Temp;
# -f file read list of targets from a file ( - means stdin) (only if no -g specified)
@ -14,10 +13,6 @@ 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");
@ -42,70 +37,6 @@ $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");
@ -114,22 +45,6 @@ $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");
@ -138,7 +53,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: point-to-point)
# fping -g (cidr - long prefixes)
{
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/31");
$cmd->exit_is_num(0);
@ -146,14 +61,6 @@ $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");
@ -162,66 +69,6 @@ $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,11 +1,10 @@
#!/usr/bin/perl -w
use Test::Command tests => 15;
use Test::Command tests => 9;
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
@ -25,17 +24,6 @@ $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0
});
}
# 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');
@ -50,27 +38,6 @@ $cmd->stderr_like(qr{\[\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 => 36;
use Test::Command tests => 18;
# -n show targets by name (-d is equivalent)
# -O n set the type of service (tos) flag on the ICMP packets
@ -68,81 +68,4 @@ $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 => 27;
use Test::Command tests => 21;
use Test::More;
# -R random bytes
@ -84,14 +84,6 @@ $cmd->stdout_is_eq("127.0.0.1 is alive\n");
$cmd->stderr_is_eq("");
}
# fping -S (wrong source address)
{
my $cmd = Test::Command->new(cmd => "fping -S 192.0.2.47 127.0.0.1");
$cmd->exit_is_num(4);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{fping: cannot bind source address : .+\n});
}
# fping -S
SKIP: {
if($ENV{SKIP_IPV6}) {
@ -103,17 +95,6 @@ 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,11 +1,9 @@
#!/usr/bin/perl -w
use Test::Command tests => 15;
use Test::Command tests => 12;
# -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
{
@ -38,11 +36,3 @@ $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("");
}

@ -0,0 +1,43 @@
#!/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\?\)});
}

@ -1,57 +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 = 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,27 +1,10 @@
#!/usr/bin/perl -w
use Test::Command tests => 84;
use Test::More;
use Test::Command tests => 33;
# 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");
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:});
}
}
# 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:});
}
}

@ -9,19 +9,19 @@ 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' packets '127.0.0.1' fping\.packets line 110020 1
$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
DIMENSION xmt sent absolute 1 1
DIMENSION rcv received absolute 1 1
BEGIN fping\.127_0_0_1_packets
SET xmt = 1
SET rcv = 1
END
CHART fping\.127_0_0_1_quality '' 'FPing Quality' percentage '127.0.0.1' fping\.quality area 110010 1
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
DIMENSION returned '' absolute 1 1
BEGIN fping\.127_0_0_1_quality
SET returned = 100
END
CHART fping\.127_0_0_1_latency '' 'FPing Latency' ms '127.0.0.1' fping\.latency area 110000 1
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 1 1000000
DIMENSION max maximum absolute 1 1000000
DIMENSION avg average absolute 1 1000000

@ -3,25 +3,8 @@ dnl Process this file with autoconf to produce a configure script.
dnl Minimum Autoconf version required.
AC_PREREQ(2.59)
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
AC_INIT([fping],[5.1])
AC_GNU_SOURCE
dnl --disable-ipv4
AC_ARG_ENABLE([ipv4],
@ -60,18 +43,13 @@ dnl Test if --enable-timestamp is explicitely enabled and make an error if this
AS_IF([test "x$enable_timestamp" = "xyes" -a "x$have_so_timestamp" = "xno"], [
AC_MSG_ERROR([--enable-timestamp not supported on this platform])
])
AS_IF([test "x$only_clock_realtime" = "xyes"], [AC_DEFINE(ONLY_CLOCK_REALTIME, [1], [ONLY_CLOCK_REALTIME is defined])])
AC_ARG_ENABLE([safe-limits],
AS_HELP_STRING([--enable-safe-limits], [Restrict timing parameters (-i, -p) within "safe" limits]))
AS_IF([test "x$enable_safe_limits" = "xyes"], [
AC_DEFINE(FPING_SAFE_LIMITS, [1], [safe limits should be enforced])])
AC_ARG_ENABLE([debug],
AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@]), [enable_debug=$enableval], [enable_debug=no])
AS_IF([test "x$enable_debug" = "xyes"], [
AC_DEFINE([DEBUG], [1], [Define if debugging is enabled])])
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AM_MAINTAINER_MODE
@ -81,7 +59,7 @@ dnl Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O
m4_version_prereq([2.70],,[AC_PROG_CC_STDC])
AC_PROG_CC_STDC
AC_PROG_CPP
AC_PROG_INSTALL
@ -100,9 +78,6 @@ if test $ac_cv_func_sigaction = yes; then
AC_DEFINE([USE_SIGACTION],[1],[Define if sigaction is available.])
fi
AC_CHECK_FUNCS([strftime], [],
[AC_MSG_ERROR([strftime function is required but not found])])
AH_TOP([
#ifndef CONFIG_H
#define CONFIG_H

@ -1,16 +0,0 @@
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"]

@ -54,8 +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,cap_net_admin+ep /usr/sbin/fping
/usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping6
/usr/sbin/setcap cap_net_raw+ep /usr/sbin/fping
/usr/sbin/setcap cap_net_raw+ep /usr/sbin/fping6
fi
%changelog

@ -66,8 +66,7 @@ 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). This option overrides B<-a>
or B<-u>.
requests have been sent (or when interrupted).
=item B<-C>, B<--vcount>=I<N>
@ -78,8 +77,7 @@ 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. This
option overrides B<-a> or B<-u>.
C<-> indicating that no response was received to the fourth request.
=item B<-d>, B<--rdns>
@ -93,23 +91,16 @@ 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.
Read list of targets from a file. This option can only be used by the root
user. Regular users should pipe in the file via stdin:
$ fping < targets_file
=item B<-g>, B<--generate> I<addr/mask>
@ -142,11 +133,6 @@ 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
@ -168,7 +154,7 @@ to print hostnames in the output.
=item B<-N>, B<--netdata>
Format output for netdata (-l -Q are required). See: L<https://netdata.cloud/>
Format output for netdata (-l -Q are required). See: L<http://my-netdata.io/>
=item B<-o>, B<--outage>
@ -190,11 +176,10 @@ 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[,cumulative]>
=item B<-Q>, B<--squiet>=I<SECS>
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.
seconds.
=item B<-r>, B<--retry>=I<N>
@ -247,11 +232,6 @@ 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
@ -287,17 +267,12 @@ B<fping website: L<http://www.fping.org>>
=head1 DIAGNOSTICS
Exit status is 0 if all the hosts (or the number of hosts specified with B<-x>
or B<-X>) are reachable, 1 if some (or too many with B<-x> or B<-X>) hosts
Exit status is 0 if all the hosts are reachable, 1 if some hosts
were unreachable, 2 if any IP addresses were not found, 3 for invalid command
line arguments, and 4 for a system call failure.
=head1 RESTRICTIONS
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,3 +1,2 @@
BasedOnStyle: WebKit
BreakBeforeBraces: Stroustrup
PointerAlignment: Right

@ -34,17 +34,17 @@
extern "C" {
#endif /* __cplusplus */
#include "fping.h"
#include "config.h"
#include "fping.h"
#include "options.h"
#include "optparse.h"
#include <errno.h>
#include <inttypes.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include "seqmap.h"
@ -60,6 +60,8 @@ extern "C" {
#include <stddef.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
@ -116,16 +118,15 @@ extern int h_errno;
/*** Constants ***/
/* CLOCK_MONTONIC starts under macOS, OpenBSD and FreeBSD with undefined positive point and can not be use
* see github PR #217
* The configure script detect the predefined operating systems an set CLOCK_REALTIME using over ONLY_CLOCK_REALTIME variable
*/
#if HAVE_SO_TIMESTAMPNS || ONLY_CLOCK_REALTIME
#if HAVE_SO_TIMESTAMPNS
#define CLOCKID CLOCK_REALTIME
#endif
/* CLOCK_MONTONIC starts under macOS, OpenBSD and FreeBSD with undefined positive point and can not be use
* see github PR #217
*/
#if !defined(CLOCKID)
#if defined(CLOCK_MONOTONIC)
#if defined(CLOCK_MONOTONIC) && !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
#define CLOCKID CLOCK_MONOTONIC
#else
#define CLOCKID CLOCK_REALTIME
@ -139,7 +140,7 @@ extern int h_errno;
#define SIZE_ICMP_HDR 8 /* from ip_icmp.h */
#define MAX_PING_DATA (MAX_IP_PACKET - SIZE_IP_HDR - SIZE_ICMP_HDR)
#define MAX_GENERATE 131070 /* maximum number of hosts that -g can generate */
#define MAX_GENERATE 100000 /* maximum number of hosts that -g can generate */
/* sized so as to be like traditional ping */
#define DEFAULT_PING_DATA_SIZE 56
@ -354,19 +355,15 @@ int generate_flag = 0; /* flag for IP list generation */
int verbose_flag, quiet_flag, stats_flag, unreachable_flag, alive_flag;
int elapsed_flag, version_flag, count_flag, loop_flag, netdata_flag;
int per_recv_flag, report_all_rtts_flag, name_flag, addr_flag, backoff_flag, rdns_flag;
int multif_flag, timeout_flag, fast_reachable;
int multif_flag, timeout_flag;
int outage_flag = 0;
int timestamp_flag = 0;
int timestamp_format_flag = 0;
int nonzero_payload_flag = 0;
int cumulative_stats_flag = 0;
int random_data_flag = 0;
#if defined(DEBUG) || defined(_DEBUG)
int randomly_lose_flag, trace_flag, print_per_system_flag;
int lose_factor;
#endif /* DEBUG || _DEBUG */
unsigned int fwmark = 0;
char* filename = NULL; /* file containing hosts to ping */
/*** forward declarations ***/
@ -382,7 +379,6 @@ void usage(int);
int wait_for_reply(int64_t);
void print_per_system_stats(void);
void print_per_system_splits(void);
void stats_reset_interval(HOST_ENTRY *h);
void print_netdata(void);
void print_global_stats(void);
void main_loop();
@ -394,7 +390,6 @@ struct event *ev_dequeue(struct event_queue *queue);
void ev_remove(struct event_queue *queue, struct event *event);
void add_cidr(char*);
void add_range(char*, char*);
void add_addr_range_ipv4(unsigned long, unsigned long);
void print_warning(char* fmt, ...);
int addr_cmp(struct sockaddr* a, struct sockaddr* b);
void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time);
@ -402,7 +397,6 @@ void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time);
struct event *host_get_timeout_event(HOST_ENTRY *h, int index);
void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency);
void update_current_time();
void print_timestamp_format(int64_t current_time_ns, int timestamp_format);
/************************************************************
@ -456,13 +450,6 @@ int p_setsockopt(uid_t p_uid, int sockfd, int level, int optname,
int main(int argc, char** argv)
{
/* Debug: CPU Performance */
#if defined(DEBUG) || defined(_DEBUG)
clock_t perf_cpu_start, perf_cpu_end;
double perf_cpu_time_used;
perf_cpu_start = clock();
#endif /* DEBUG || _DEBUG */
int c;
const uid_t suid = geteuid();
int tos = 0;
@ -525,7 +512,6 @@ int main(int argc, char **argv)
{ "vcount", 'C', OPTPARSE_REQUIRED },
{ "rdns", 'd', OPTPARSE_NONE },
{ "timestamp", 'D', OPTPARSE_NONE },
{ "timestamp-format", '0', OPTPARSE_REQUIRED },
{ "elapsed", 'e', OPTPARSE_NONE },
{ "file", 'f', OPTPARSE_REQUIRED },
{ "generate", 'g', OPTPARSE_NONE },
@ -533,9 +519,6 @@ int main(int argc, char **argv)
{ "ttl", 'H', OPTPARSE_REQUIRED },
{ "interval", 'i', OPTPARSE_REQUIRED },
{ "iface", 'I', OPTPARSE_REQUIRED },
#ifdef SO_MARK
{ "fwmark", 'k', OPTPARSE_REQUIRED },
#endif
{ "loop", 'l', OPTPARSE_NONE },
{ "all", 'm', OPTPARSE_NONE },
{ "dontfrag", 'M', OPTPARSE_NONE },
@ -547,7 +530,7 @@ int main(int argc, char **argv)
{ "quiet", 'q', OPTPARSE_NONE },
{ "squiet", 'Q', OPTPARSE_REQUIRED },
{ "retry", 'r', OPTPARSE_REQUIRED },
{ "nonzero", 'Z', OPTPARSE_NONE },
{ "random", 'R', OPTPARSE_NONE },
{ "stats", 's', OPTPARSE_NONE },
{ "src", 'S', OPTPARSE_REQUIRED },
{ "timeout", 't', OPTPARSE_REQUIRED },
@ -555,7 +538,6 @@ int main(int argc, char **argv)
{ "unreach", 'u', OPTPARSE_NONE },
{ "version", 'v', OPTPARSE_NONE },
{ "reachable", 'x', OPTPARSE_REQUIRED },
{ "fast-reachable", 'X', OPTPARSE_REQUIRED },
#if defined(DEBUG) || defined(_DEBUG)
{ NULL, 'z', OPTPARSE_REQUIRED },
#endif
@ -565,19 +547,6 @@ int main(int argc, char **argv)
float opt_value_float;
while ((c = optparse_long(&optparse_state, longopts, NULL)) != EOF) {
switch (c) {
case '0':
if(strstr(optparse_state.optlongname, "timestamp-format") != NULL) {
if(strcmp(optparse_state.optarg, "ctime") == 0) {
timestamp_format_flag = 1;
}else if(strcmp(optparse_state.optarg, "iso") == 0) {
timestamp_format_flag = 2;
}else if(strcmp(optparse_state.optarg, "rfc3339") == 0) {
timestamp_format_flag = 3;
}else{
usage(1);
}
}
break;
case '4':
#ifdef IPV6
if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) {
@ -622,7 +591,7 @@ int main(int argc, char **argv)
break;
case 't':
if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
if (!sscanf(optparse_state.optarg, "%f", &opt_value_float))
usage(1);
if (opt_value_float < 0) {
usage(1);
@ -632,12 +601,12 @@ int main(int argc, char **argv)
break;
case 'r':
if (sscanf(optparse_state.optarg, "%u", &retry) != 1)
if (!sscanf(optparse_state.optarg, "%u", &retry))
usage(1);
break;
case 'i':
if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
if (!sscanf(optparse_state.optarg, "%f", &opt_value_float))
usage(1);
if (opt_value_float < 0) {
usage(1);
@ -646,7 +615,7 @@ int main(int argc, char **argv)
break;
case 'p':
if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
if (!sscanf(optparse_state.optarg, "%f", &opt_value_float))
usage(1);
if (opt_value_float < 0) {
usage(1);
@ -671,7 +640,7 @@ int main(int argc, char **argv)
break;
case 'b':
if (sscanf(optparse_state.optarg, "%u", &ping_data_size) != 1)
if (!sscanf(optparse_state.optarg, "%u", &ping_data_size))
usage(1);
break;
@ -688,21 +657,13 @@ int main(int argc, char **argv)
case 'Q':
verbose_flag = 0;
quiet_flag = 1;
if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
if (!sscanf(optparse_state.optarg, "%f", &opt_value_float))
usage(1);
if (opt_value_float < 0) {
usage(1);
}
report_interval = opt_value_float * 1e9;
/* recognize keyword(s) after number, ignore everything else */
{
char *comma = strchr(optparse_state.optarg, ',');
if ((comma != NULL) && (strcmp(++comma, "cumulative") == 0)) {
cumulative_stats_flag = 1;
}
}
break;
case 'e':
@ -751,8 +712,8 @@ int main(int argc, char **argv)
timestamp_flag = 1;
break;
case 'Z':
nonzero_payload_flag = 1;
case 'R':
random_data_flag = 1;
break;
case 'l':
@ -791,32 +752,9 @@ int main(int argc, char **argv)
usage(1);
break;
case 'X':
if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg)))
usage(1);
fast_reachable = 1;
break;
case 'f':
filename = optparse_state.optarg;
break;
#ifdef SO_MARK
case 'k':
if (!(fwmark = (unsigned int)atol(optparse_state.optarg)))
usage(1);
if (socket4 >= 0)
if(-1 == setsockopt(socket4, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
perror("fwmark ipv4");
#ifdef IPV6
if (socket6 >= 0)
if(-1 == setsockopt(socket6, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
perror("fwmark ipv6");
#endif
break;
#endif
case 'g':
/* use IP list generation */
@ -866,7 +804,7 @@ int main(int argc, char **argv)
break;
case 'O':
if (sscanf(optparse_state.optarg, "%i", &tos) == 1) {
if (sscanf(optparse_state.optarg, "%i", &tos)) {
if (socket4 >= 0) {
if (setsockopt(socket4, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) {
perror("setting type of service octet IP_TOS");
@ -908,13 +846,11 @@ int main(int argc, char **argv)
#ifndef IPV6
if (socket4 < 0) {
crash_and_burn("can't create socket (must run as root?)");
}
#else
if ((socket4 < 0 && socket6 < 0) || (hints_ai_family == AF_INET6 && socket6 < 0)) {
#endif
crash_and_burn("can't create socket (must run as root?)");
}
#endif
if (ttl > 255) {
fprintf(stderr, "%s: ttl %u out of range\n", prog, ttl);
@ -953,6 +889,9 @@ int main(int argc, char **argv)
exit(1);
}
if (alive_flag || unreachable_flag || min_reachable)
verbose_flag = 0;
if (count_flag) {
if (verbose_flag)
per_recv_flag = 1;
@ -967,9 +906,6 @@ int main(int argc, char **argv)
alive_flag = unreachable_flag = verbose_flag = 0;
}
if (alive_flag || unreachable_flag || min_reachable)
verbose_flag = 0;
trials = (count > retry + 1) ? count : retry + 1;
/* auto-tune default timeout for count/loop modes
@ -1071,17 +1007,13 @@ int main(int argc, char **argv)
int opt = 1;
if (socket4 >= 0) {
if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) {
if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option");
}
perror("setting SO_TIMESTAMPNS option");
}
}
#ifdef IPV6
if (socket6 >= 0) {
if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) {
if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option (IPv6)");
}
perror("setting SO_TIMESTAMPNS option (IPv6)");
}
}
#endif
@ -1174,11 +1106,11 @@ int main(int argc, char **argv)
exit(num_noaddress ? 2 : 1);
}
if (socket4 >= 0 && (src_addr_set || socktype4 == SOCK_DGRAM)) {
if (src_addr_set && socket4 >= 0) {
socket_set_src_addr_ipv4(socket4, &src_addr, (socktype4 == SOCK_DGRAM) ? &ident4 : NULL);
}
#ifdef IPV6
if (socket6 >= 0 && (src_addr6_set || socktype6 == SOCK_DGRAM)) {
if (src_addr6_set && socket6 >= 0) {
socket_set_src_addr_ipv6(socket6, &src_addr6, (socktype6 == SOCK_DGRAM) ? &ident6 : NULL);
}
#endif
@ -1231,13 +1163,6 @@ int main(int argc, char **argv)
/* main loop */
main_loop();
/* Debug: CPU Performance */
#if defined(DEBUG) || defined(_DEBUG)
perf_cpu_end = clock();
perf_cpu_time_used = ((double) (perf_cpu_end - perf_cpu_start)) / CLOCKS_PER_SEC;
printf("[DEBUG] CPU time used: %f sec", perf_cpu_time_used);
#endif /* DEBUG || _DEBUG */
finish();
return 0;
@ -1283,7 +1208,6 @@ void add_cidr(char *addr)
exit(1);
}
net_addr = ntohl(((struct sockaddr_in*)addr_res->ai_addr)->sin_addr.s_addr);
freeaddrinfo(addr_res);
/* check mask */
if (mask < 1 || mask > 32) {
@ -1305,7 +1229,15 @@ void add_cidr(char *addr)
}
/* add all hosts in that network (net_addr and net_last inclusive) */
add_addr_range_ipv4(net_addr, net_last);
for (; net_addr <= net_last; net_addr++) {
struct in_addr in_addr_tmp;
char buffer[20];
in_addr_tmp.s_addr = htonl(net_addr);
inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer));
add_name(buffer);
}
freeaddrinfo(addr_res);
}
void add_range(char* start, char* end)
@ -1349,14 +1281,7 @@ void add_range(char *start, char *end)
end_long = ntohl(((struct sockaddr_in*)addr_res->ai_addr)->sin_addr.s_addr);
freeaddrinfo(addr_res);
/* add IPv4 addresses from closed interval [start_long,end_long] */
add_addr_range_ipv4(start_long, end_long);
}
void add_addr_range_ipv4(unsigned long start_long, unsigned long end_long)
{
/* check if generator limit is exceeded */
if (end_long >= start_long + MAX_GENERATE) {
if (end_long > start_long + MAX_GENERATE) {
fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog);
exit(1);
}
@ -1382,7 +1307,9 @@ void main_loop()
dbg_printf("%s", "# main_loop\n");
/* timeout event ? */
if (event_queue_timeout.first && event_queue_timeout.first->ev_time - current_time_ns <= 0) {
if (event_queue_timeout.first &&
event_queue_timeout.first->ev_time - current_time_ns <= 0)
{
event = ev_dequeue(&event_queue_timeout);
h = event->host;
@ -1392,7 +1319,7 @@ void main_loop()
if (per_recv_flag) {
if (timestamp_flag) {
print_timestamp_format(current_time_ns, timestamp_format_flag);
printf("[%.5f] ", (double)current_time_ns / 1e9);
}
printf("%-*s : [%d], timed out",
max_hostname_len, h->host, event->ping_index);
@ -1431,7 +1358,9 @@ void main_loop()
}
/* ping event ? */
if (event_queue_ping.first && event_queue_ping.first->ev_time - current_time_ns <= 0) {
if (event_queue_ping.first &&
event_queue_ping.first->ev_time - current_time_ns <= 0)
{
/* Make sure that we don't ping more than once every "interval" */
lt = current_time_ns - last_send_time;
if (lt < interval)
@ -1577,6 +1506,7 @@ void update_current_time()
current_time_ns = timespec_ns(&current_time);
}
/************************************************************
Function: finish
@ -1631,8 +1561,7 @@ void finish()
if ((num_hosts-num_unreachable) >= min_reachable) {
printf("Enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts-num_unreachable);
exit(0);
}
else {
} else {
printf("Not enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts-num_unreachable);
exit(1);
}
@ -1696,7 +1625,7 @@ void print_per_system_stats(void)
else {
fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%",
h->num_sent, h->num_recv,
h->num_sent > 0 ? ((h->num_recv * 100) / h->num_sent) : 0);
((h->num_recv * 100) / h->num_sent));
}
if (h->num_recv) {
@ -1736,7 +1665,7 @@ void print_netdata(void)
h = table[i];
if (!sent_charts) {
printf("CHART fping.%s_packets '' 'FPing Packets' packets '%s' fping.packets line 110020 %.0f\n", h->name, h->host, report_interval / 1e9);
printf("CHART fping.%s_packets '' 'FPing Packets for host %s' packets '%s' fping.packets line 110020 %.0f\n", h->name, h->host, h->host, report_interval / 1e9);
printf("DIMENSION xmt sent absolute 1 1\n");
printf("DIMENSION rcv received absolute 1 1\n");
}
@ -1747,7 +1676,7 @@ void print_netdata(void)
printf("END\n");
if (!sent_charts) {
printf("CHART fping.%s_quality '' 'FPing Quality' percentage '%s' fping.quality area 110010 %.0f\n", h->name, h->host, report_interval / 1e9);
printf("CHART fping.%s_quality '' 'FPing Quality for host %s' percentage '%s' fping.quality area 110010 %.0f\n", h->name, h->host, h->host, report_interval / 1e9);
printf("DIMENSION returned '' absolute 1 1\n");
/* printf("DIMENSION lost '' absolute 1 1\n"); */
}
@ -1764,7 +1693,7 @@ void print_netdata(void)
printf("END\n");
if (!sent_charts) {
printf("CHART fping.%s_latency '' 'FPing Latency' ms '%s' fping.latency area 110000 %.0f\n", h->name, h->host, report_interval / 1e9);
printf("CHART fping.%s_latency '' 'FPing Latency for host %s' ms '%s' fping.latency area 110000 %.0f\n", h->name, h->host, h->host, report_interval / 1e9);
printf("DIMENSION min minimum absolute 1 1000000\n");
printf("DIMENSION max maximum absolute 1 1000000\n");
printf("DIMENSION avg average absolute 1 1000000\n");
@ -1779,7 +1708,7 @@ void print_netdata(void)
}
printf("END\n");
stats_reset_interval(h);
h->num_sent_i = h->num_recv_i = h->max_reply_i = h->min_reply_i = h->total_time_i = 0;
}
sent_charts = 1;
@ -1839,9 +1768,7 @@ void print_per_system_splits(void)
}
fprintf(stderr, "\n");
if (!cumulative_stats_flag) {
stats_reset_interval(h);
}
h->num_sent_i = h->num_recv_i = h->max_reply_i = h->min_reply_i = h->total_time_i = 0;
}
}
@ -1981,11 +1908,9 @@ int socket_can_read(struct timeval *timeout)
select_again:
FD_ZERO(&readset);
if (socket4 >= 0)
FD_SET(socket4, &readset);
if(socket4 >= 0) FD_SET(socket4, &readset);
#ifdef IPV6
if (socket6 >= 0)
FD_SET(socket6, &readset);
if(socket6 >= 0) FD_SET(socket6, &readset);
#endif
nfound = select(socketmax + 1, &readset, NULL, NULL, timeout);
@ -2028,13 +1953,15 @@ int receive_packet(int64_t wait_time,
reply_buf,
reply_buf_len
};
struct msghdr recv_msghdr = {0};
recv_msghdr.msg_name = reply_src_addr;
recv_msghdr.msg_namelen = reply_src_addr_len;
recv_msghdr.msg_iov = &msg_iov;
recv_msghdr.msg_iovlen = 1;
recv_msghdr.msg_control = &msg_control;
recv_msghdr.msg_controllen = sizeof(msg_control);
struct msghdr recv_msghdr = {
reply_src_addr,
reply_src_addr_len,
&msg_iov,
1,
&msg_control,
sizeof(msg_control),
0
};
#if HAVE_SO_TIMESTAMPNS
struct cmsghdr* cmsg;
#endif
@ -2064,7 +1991,8 @@ int receive_packet(int64_t wait_time,
struct timespec reply_timestamp_ts;
for (cmsg = CMSG_FIRSTHDR(&recv_msghdr);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) {
cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg))
{
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPNS) {
memcpy(&reply_timestamp_ts, CMSG_DATA(cmsg), sizeof(reply_timestamp_ts));
*reply_timestamp = timespec_ns(&reply_timestamp_ts);
@ -2161,7 +2089,7 @@ int decode_icmp_ipv4(
if (!using_sock_dgram4) {
struct ip* ip = (struct ip*)reply_buf;
#if defined(__alpha__) && __STDC__ && !defined(__GLIBC__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
#if defined(__alpha__) && __STDC__ && !defined(__GLIBC__)
/* The alpha headers are decidedly broken.
* Using an ANSI compiler, it provides ip_vhl instead of ip_hl and
* ip_v. So, to get ip_hl, we mask off the bottom four bits.
@ -2172,11 +2100,12 @@ int decode_icmp_ipv4(
#endif
}
if (reply_buf_len < hlen + ICMP_MINLEN) {
/* too short */
if (verbose_flag) {
char buf[INET6_ADDRSTRLEN];
getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
getnameinfo( response_addr, sizeof( struct sockaddr_in ), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf);
}
return -1;
@ -2209,7 +2138,7 @@ int decode_icmp_ipv4(
return -1;
}
getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
getnameinfo(response_addr, sizeof( struct sockaddr_in ), addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
switch (icp->icmp_type) {
case ICMP_UNREACH:
@ -2268,7 +2197,7 @@ int decode_icmp_ipv6(
if (reply_buf_len < sizeof(struct icmp6_hdr)) {
if (verbose_flag) {
char buf[INET6_ADDRSTRLEN];
getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
getnameinfo((struct sockaddr*)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf);
}
return 0; /* too short */
@ -2375,8 +2304,7 @@ int wait_for_reply(int64_t wait_time)
}
update_current_time();
if (recv_time == 0)
recv_time = current_time_ns;
if(recv_time==0) recv_time = current_time_ns;
/* Process ICMP packet and retrieve id/seq */
if (response_addr.ss_family == AF_INET) {
@ -2480,9 +2408,6 @@ int wait_for_reply(int64_t wait_time)
/* print "is alive" */
if (h->num_recv == 1) {
num_alive++;
if (fast_reachable && num_alive >= min_reachable)
finish_requested = 1;
if (verbose_flag || alive_flag) {
printf("%s", h->host);
@ -2505,7 +2430,7 @@ int wait_for_reply(int64_t wait_time)
/* print received ping (unless --quiet) */
if (per_recv_flag) {
if (timestamp_flag) {
print_timestamp_format(recv_time, timestamp_format_flag);
printf("[%.5f] ", (double)recv_time / 1e9);
}
avg = h->total_time / h->num_recv;
printf("%-*s : [%d], %d bytes, %s ms",
@ -2722,7 +2647,9 @@ void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_
void crash_and_burn(char* message)
{
if (verbose_flag)
fprintf(stderr, "%s: %s\n", prog, message);
exit(4);
}
@ -2858,6 +2785,7 @@ struct event *host_get_timeout_event(HOST_ENTRY *h, int index)
return &h->event_storage_timeout[index % event_storage_count];
}
/************************************************************
Function: ev_enqueue
@ -2956,40 +2884,6 @@ void ev_remove(struct event_queue *queue, struct event *event)
event->ev_next = NULL;
}
/************************************************************
Function: print_human_readable_time from current_time_ns
*************************************************************/
void print_timestamp_format(int64_t current_time_ns, int timestamp_format)
{
char time_buffer[100];
time_t current_time_s;
struct tm *local_time;
current_time_s = current_time_ns / 1000000000;
local_time = localtime(&current_time_s);
switch(timestamp_format) {
case 1:
// timestamp-format ctime
strftime(time_buffer, sizeof(time_buffer), "%c", local_time);
printf("[%s] ", time_buffer);
break;
case 2:
// timestamp-format iso
strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%T%z", local_time);
printf("[%s] ", time_buffer);
break;
case 3:
// timestamp-format rfc3339
strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d %H:%M:%S", local_time);
printf("[%s] ", time_buffer);
break;
default:
printf("[%.5f] ", (double)current_time_ns / 1e9);
}
}
/************************************************************
Function: usage
@ -3012,19 +2906,14 @@ void usage(int is_error)
fprintf(out, " -6, --ipv6 only ping IPv6 addresses\n");
fprintf(out, " -b, --size=BYTES amount of ping data to send, in bytes (default: %d)\n", DEFAULT_PING_DATA_SIZE);
fprintf(out, " -B, --backoff=N set exponential backoff factor to N (default: 1.5)\n");
fprintf(out, " -c, --count=N count mode: send N pings to each target and report stats\n");
fprintf(out, " -c, --count=N count mode: send N pings to each target\n");
fprintf(out, " -f, --file=FILE read list of targets from a file ( - means stdin)\n");
fprintf(out, " -g, --generate generate target list (only if no -f specified),\n");
fprintf(out, " limited to at most %d targets\n", MAX_GENERATE);
fprintf(out, " -g, --generate generate target list (only if no -f specified)\n");
fprintf(out, " (give start and end IP in the target list, or a CIDR address)\n");
fprintf(out, " (ex. %s -g 192.168.1.0 192.168.1.255 or %s -g 192.168.1.0/24)\n", prog, prog);
fprintf(out, " -H, --ttl=N set the IP TTL value (Time To Live hops)\n");
fprintf(out, " -i, --interval=MSEC interval between sending ping packets (default: %.0f ms)\n", interval / 1e6);
#ifdef SO_BINDTODEVICE
fprintf(out, " -I, --iface=IFACE bind to a particular interface\n");
#endif
#ifdef SO_MARK
fprintf(out, " -k, --fwmark=FWMARK set the routing mark\n");
#endif
fprintf(out, " -l, --loop loop mode: send pings forever\n");
fprintf(out, " -m, --all use all IPs of provided hostnames (e.g. IPv4 and IPv6), use with -A\n");
@ -3033,7 +2922,7 @@ void usage(int is_error)
fprintf(out, " -p, --period=MSEC interval between ping packets to one target (in ms)\n");
fprintf(out, " (in loop and count modes, default: %.0f ms)\n", perhost_interval / 1e6);
fprintf(out, " -r, --retry=N number of retries (default: %d)\n", DEFAULT_RETRY);
fprintf(out, " -Z, --nonzero non-zero packet data (same payload as ping 0xA ...)\n");
fprintf(out, " -R, --random random packet data (to foil link data compression)\n");
fprintf(out, " -S, --src=IP set source address\n");
fprintf(out, " -t, --timeout=MSEC individual target initial timeout (default: %.0f ms,\n", timeout / 1e6);
fprintf(out, " except with -l/-c/-C, where it's the -p period up to 2000 ms)\n");
@ -3041,21 +2930,19 @@ void usage(int is_error)
fprintf(out, "Output options:\n");
fprintf(out, " -a, --alive show targets that are alive\n");
fprintf(out, " -A, --addr show targets by address\n");
fprintf(out, " -C, --vcount=N same as -c, report results (not stats) in verbose format\n");
fprintf(out, " -C, --vcount=N same as -c, report results in verbose format\n");
fprintf(out, " -d, --rdns show targets by name (force reverse-DNS lookup)\n");
fprintf(out, " -D, --timestamp print timestamp before each output line\n");
fprintf(out, " --timestamp-format=FORMAT show timestamp in the given format (-D required): ctime|iso|rfc3339\n");
fprintf(out, " -e, --elapsed show elapsed time on return packets\n");
fprintf(out, " -i, --interval=MSEC interval between sending ping packets (default: %.0f ms)\n", interval / 1e6);
fprintf(out, " -n, --name show targets by name (reverse-DNS lookup for target IPs)\n");
fprintf(out, " -N, --netdata output compatible for netdata (-l -Q are required)\n");
fprintf(out, " -o, --outage show the accumulated outage time (lost packets * packet interval)\n");
fprintf(out, " -q, --quiet quiet (don't show per-target/per-ping results)\n");
fprintf(out, " -Q, --squiet=SECS[,cumulative] same as -q, but add interval summary every SECS seconds,\n");
fprintf(out, " with 'cumulative', print stats since beginning\n");
fprintf(out, " -Q, --squiet=SECS same as -q, but add interval summary every SECS seconds\n");
fprintf(out, " -s, --stats print final stats\n");
fprintf(out, " -u, --unreach show targets that are unreachable\n");
fprintf(out, " -v, --version show version\n");
fprintf(out, " -x, --reachable=N shows if >=N hosts are reachable or not\n");
fprintf(out, " -X, --fast-reachable=N exits true immediately when N hosts are found\n");
exit(is_error);
}

@ -22,7 +22,7 @@ extern int trace_flag;
void crash_and_burn( char *message );
void errno_crash_and_burn( char *message );
int in_cksum( unsigned short *p, int n );
extern int nonzero_payload_flag;
extern int random_data_flag;
/* socket.c */
int open_ping_socket_ipv4(int *socktype);

@ -238,14 +238,12 @@ 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,7 +48,6 @@ struct optparse {
int permute;
int optind;
int optopt;
char *optlongname;
char *optarg;
char errmsg[64];
int subopt;

@ -41,7 +41,6 @@
#include "options.h"
#include "fping.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@ -81,8 +80,8 @@ unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t t
/* check if expired (note that unused seqmap values will have fields set to
* 0, so will be seen as expired */
next_value = &seqmap_map[seqmap_next_id];
if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) {
fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
if (timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) {
fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%ld, host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
SEQMAP_TIMEOUT_IN_NS, host_nr, ping_count, seqmap_next_id);
exit(4);
}

@ -133,7 +133,6 @@ 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;
@ -143,12 +142,9 @@ 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 (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;
if (random_data_flag) {
for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) {
ping_buffer_ipv4[n] = random() & 0xFF;
}
}

@ -51,15 +51,15 @@ int open_ping_socket_ipv6(int *socktype)
struct protoent* proto;
int s;
/* confirm that ICMP6 is available on this machine */
/* confirm that ICMP is available on this machine */
if ((proto = getprotobyname("ipv6-icmp")) == NULL)
crash_and_burn("ipv6-icmp: unknown protocol");
crash_and_burn("icmp: unknown protocol");
/* create raw socket for ICMP6 calls (ping) */
/* create raw socket for ICMP calls (ping) */
*socktype = SOCK_RAW;
s = socket(AF_INET6, *socktype, proto->p_proto);
if (s < 0) {
/* try non-privileged icmp6 (works on Mac OSX without privileges, for example) */
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
*socktype = SOCK_DGRAM;
s = socket(AF_INET6, *socktype, proto->p_proto);
if (s < 0) {
@ -104,7 +104,7 @@ void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident)
if (ident) {
memset(&sa, 0, len);
if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
errno_crash_and_burn("can't get ICMP6 socket identity");
errno_crash_and_burn("can't get ICMP socket identity");
if (sa.sin6_port)
*ident = sa.sin6_port;
@ -115,7 +115,6 @@ int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len,
{
struct icmp6_hdr* icp;
int n;
size_t i;
icp = (struct icmp6_hdr*)ping_buffer_ipv6;
icp->icmp6_type = ICMP6_ECHO_REQUEST;
@ -123,9 +122,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 (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;
if (random_data_flag) {
for (n = sizeof(struct icmp6_hdr); n < ping_pkt_size_ipv6; ++n) {
ping_buffer_ipv6[n] = random() & 0xFF;
}
}

Loading…
Cancel
Save