Compare commits

..

3 Commits

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

@ -1,67 +0,0 @@
# 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

@ -1,108 +0,0 @@
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,98 +1,40 @@
# travis-ci.org configuration
#
language: generic language: generic
sudo: required
os: dist: trusty
- linux
dist:
- trusty
- xenial
env: env:
global: global:
- secure: "CoI8hwHH1yfQoQxIfWGRS0WfTyScox+5aJn0fDDgz2uKrrIxmBvIw/WKX8wcSiV6fLmLuwgNkKqSM3hdO4qaG+JxfWcuEiZZHm+kxSGMkWbGb/fvAI+gHg8ldKyYttcIX71O5rlZiC2QpNKQi2v18S6pI5p8eqnx7DYx4YrmguQ=" - secure: "CoI8hwHH1yfQoQxIfWGRS0WfTyScox+5aJn0fDDgz2uKrrIxmBvIw/WKX8wcSiV6fLmLuwgNkKqSM3hdO4qaG+JxfWcuEiZZHm+kxSGMkWbGb/fvAI+gHg8ldKyYttcIX71O5rlZiC2QpNKQi2v18S6pI5p8eqnx7DYx4YrmguQ="
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key # via the "travis encrypt" command using the project repo's public key
- secure: "C9ZJ9LYnuowRdF4D66KLfquimvu8GtRGIafwvCcGYKReEy8phlBdFsHlybkMBNYJNTJSM0j6wyo1lKTVGHxmpQDimjR7kmxUtawbhuJ5qOCBtFqNVh9lRQi7hC4+UOhvRsIcbV8HAJM5u/5RxGOfXCePK3a2DtiYv1d2NHToZN8=" - secure: "C9ZJ9LYnuowRdF4D66KLfquimvu8GtRGIafwvCcGYKReEy8phlBdFsHlybkMBNYJNTJSM0j6wyo1lKTVGHxmpQDimjR7kmxUtawbhuJ5qOCBtFqNVh9lRQi7hC4+UOhvRsIcbV8HAJM5u/5RxGOfXCePK3a2DtiYv1d2NHToZN8="
notifications:
webhooks: https://coveralls.io/webhook
compiler: compiler:
- gcc - gcc
before_install:
addons: - sudo apt-get update -qq
apt: - sudo apt-get install libcap2-bin
update: true #- sudo apt-get install traceroute
packages: #- traceroute google.com
- 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-
- libtest-command-perl install:
- ci/build-1-autotools.sh
- curl -L http://cpanmin.us | perl - --sudo App::cpanminus
- cpanm --sudo Test::Command
script: script:
- ci/build-4-compile.sh - ci/build-2-install.sh
- ci/run-tests.sh - env PATH=`pwd`/src:$PATH prove ci/test-*.pl
- ci/test-tarball.sh
after_success: after_success:
- ci/deploy-coveralls.sh - ci/coveralls.sh
- ci/deploy-bintray.sh
stages: addons:
- test coverity_scan:
- name: deploy project:
if: branch = master OR branch = v4.x name: "schweikert/fping"
- name: coverity description: "Build submitted via Travis CI"
if: branch = master OR branch = coverity_scan notification_email: david@schweikert.ch
#build_command_prepend: "ci/build-2-install.sh"
jobs: build_command: "ci/build-2-install.sh"
include: branch_pattern: coverity_scan
#### 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

@ -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,132 +1,11 @@
fping 5.2 (2024-04-21) UNRELEASED
====================== ==========
## New features
- New option -X / --fast-reachable to exit immediately once N hosts have been
found (#260, thanks @chriscray and @gsnw)
- New option -k / -fwmark to set Linux fwmark mask (#289, thanks @tomangert and
@deepkv)
## Bugfixes and other changes
- Always output fatal error messages (#303, thanks @auerswal)
- Fallback to SO\_TIMESTAMP if SO\_TIMESTAMPNS is not available (#279, thanks
@gsnw)
- Fix "not enough sequence numbers available" error on BSD-like systems (#307,
thanks @cagney, @gsnw)
- Fix running in unprivileged mode (#248, thanks @sfan5)
- Fix build issue for NetBSD/alpha (#255, thanks @0-wiz-0)
- Fix build issue for OpenBSD/alpha (#275, thanks @gsnw)
- Fix build warning for long int usage (#258, thanks @gsnw)
- Fix build error with musl libc (#263, thanks @kraj)
- Fix to guard against division by zero (#293, thanks @auerswal)
- Decouple -a/-u effects from -c (#298, thanks @auerswal)
- Added contrib/Dockerfile (#224, thanks @darless)
- Remove host from Netdata chart titles (#253, thanks @ilyam8)
- Add additional tests (#292, #297, thanks @auerswal)
- Update github action os images (#282, thanks @gsnw)
- Fix Azure pipeline tests (#308, thanks @gsnw)
- Various autoconf fixes (#286, #283, thanks @gsnw)
- Extended configure script with --enable-debug and output cpu usage (#311,
thanks @gsnw)
- Documentation: Update Netdata website link (#257, thanks @ilyam8)
- Documentation: fix description of --file option (#268, thanks @MohGeek)
- Documentation: improve exit status description (#294, thanks @auerswal)
- Documentation: move description of -i MSEC (#298, thanks @auerswal)
- Documentation: improve help output for options -c and -C (#302, #auerswal)
fping 5.1 (2022-02-06)
======================
## Bugfixes and other changes
- Use setcap to specify specific files in fping.spec (#232, thanks @zdyxry)
- Netdata: use host instead name as family label (#226, thanks @k0ste)
- Netdata: use formatstring macro PRId64 (#229, thanks @gsnw)
- Allow -4 option to be given multiple times (#215, thanks @normanr)
- Documentation fix (#208, thanks @timgates42)
- Retain privileges until after privileged setsockopt (#200, thanks @simetnicbr)
- Set bind to source only when option is set (#198, thanks @dinoex)
- Update Azure test pipeline (#197, thanks @gsnw)
- Fix getnameinfo not called properly for IPv4 (#227, thanks @aafbsd)
- Fixed wrong timestamp under Free- and OpenBSD and macOS (#217, thanks @gsnw)
- Documentation updates (#240, thanks @auerswal)
- Updated autotools (autoconf 2.71, automake 1.16.5, libtool 2.4.6)
fping 5.0 (2020-08-05)
======================
## Incompatible Changes
- In non-quiet loop and count mode, a line is printed for every lost packet
(#175, thanks @kbucheli):
```
$ fping -D -c2 8.8.8.8 8.8.8.7
[1596092373.18423] 8.8.8.8 : [0], 64 bytes, 12.8 ms (12.8 avg, 0% loss)
[1596092374.18223] 8.8.8.7 : [0], timed out (NaN avg, 100% loss)
[1596092374.18424] 8.8.8.8 : [1], 64 bytes, 12.3 ms (12.5 avg, 0% loss)
[1596092375.18344] 8.8.8.7 : [1], timed out (NaN avg, 100% loss)
8.8.8.8 : xmt/rcv/%loss = 2/2/0%, min/avg/max = 12.3/12.5/12.8
8.8.8.7 : xmt/rcv/%loss = 2/0/100%
```
- The returned size in bytes now always excludes the IP header, so if before it
reported '84 bytes' e.g. when using 'fping -l', now it reports '64 bytes'.
This is to make the reported size consistent with ping(8) from iputils and
also with fping when pinging a IPv6 host (which never included the IPv6
header size).
## New features
- The number of sent pings is only counted when the pings are received or have
timed out, ensuring that the loss ratio will be always correct. This makes it
possible, for example, to use loop mode (-l) with interval statistics (-Q)
and a timeout larger than period, without having the issue that initially
some pings would be reported as missing (#193)
- Improved precision of measurements from 10us to 1us (#136, thanks @tycho)
## Bugfixes and other changes
- The reported size of received packets is now always correct on Linux even for
packets > 4096 bytes (#180)
- Travis CI automated testing now also macos testing and additional ubuntu
distributions (#196)
fping 4.4 (2020-07-24)
======================
## Bugfixes and other changes
- Fix wrong ident used for normal (non-unprivileged) pings (#191, thanks @tycho)
- Fix build with --disable-ipv6 (#187, thanks Polynomial-C)
fping 4.3 (2020-07-11)
======================
## New features
- Linux unprivileged ping support (#173, thanks @tycho)
- Add SIGQUIT summary support similar to ping (#185, thanks @laddp)
## Bugfixes and other changes ## Bugfixes and other changes
- Corrected long option name of -s to --stats (#148, thanks @wopfel) - Corrected long option name of -s to --stats (#148, thanks @wopfel)
- Do not fail if using fping6 with -6 flag (#149, thanks @stromnet) - Do not fail if using fping6 with -6 flag (#149, thanks @stromnet)
- Fail if interface binding (-I) does not work (#162, thanks @kbucheli) - Fail if interface binding (-I) does not work (#162, by @kbucheli)
- Fix using option -4 when fping is compiled IPv4-only (#154, thanks @pbhenson)
- Add Azure pipeline test build (#153 and #170, thanks @gsnw)
- GCC 10 compatibility fixes (#167 and #168, thanks @cranderson)
- Macos build fix (#174, thanks @tycho)
- Fix xmt stats in Netdata output (#172, thanks @vlvkobal)
- Only increase num_alive if response is not a duplicate (#151, thanks @brownowski)
- Use line buffering for stdout (#179, thanks @bg6cq)
fping 4.2 (2019-02-19) fping 4.2 (2019-02-19)
====================== ======================

@ -1,3 +1,3 @@
SUBDIRS = doc src SUBDIRS = doc src
EXTRA_DIST = CHANGELOG.md contrib README.md ci/*.sh ci/*.pl EXTRA_DIST = CHANGELOG.md

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

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

@ -1,52 +0,0 @@
jobs:
- job: linux_build
displayName: Linux Build
pool:
name: Azure Pipelines
vmImage: 'ubuntu-latest'
workspace:
clean: all
steps:
- script: |
sudo apt-get update -qq
sudo apt-get install libcap2-bin libtest-command-perl
displayName: 'before_install'
- script: |
ci/build-4-compile.sh
displayName: install
- 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")
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,15 +1,8 @@
#!/bin/bash #!/bin/bash -e
set -e AUTOCONF=http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
set -x 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
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 PREFIX=$(pwd)/ci/build
PATH=$(pwd)/ci/build/bin:$PATH PATH=$(pwd)/ci/build/bin:$PATH

@ -1,6 +0,0 @@
#!/bin/sh
set -ex
curl -L http://cpanmin.us | perl - -L $HOME/perl5 App::cpanminus
$HOME/perl5/bin/cpanm --sudo Test::Command

@ -0,0 +1,13 @@
#!/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,6 +4,18 @@
set -e 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$//') VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//')
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
REPO=release REPO=release

@ -1,16 +0,0 @@
#!/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'

@ -1,25 +0,0 @@
#!/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 #!/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 if [[ ! $PATH =~ fping/src ]]; then
PATH=/home/dws/checkouts/fping/src:$PATH PATH=/home/dws/checkouts/fping/src:$PATH

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

@ -1,9 +0,0 @@
#!/bin/sh
lcov -c -no-external \
-d . \
-b src \
-o lcov-all.info
lcov --remove lcov-all.info -o lcov.info \
'*/optparse.c'

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

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

@ -1,11 +1,11 @@
#!/usr/bin/perl -w #!/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"; my $I_HELP = " -I, --iface=IFACE bind to a particular interface\n";
$I_HELP = '' if $^O eq 'darwin'; $I_HELP = '' if $^O eq 'darwin';
# fping -h (special pre-parse code path) # fping -h
my $cmd1 = Test::Command->new(cmd => "fping -h"); my $cmd1 = Test::Command->new(cmd => "fping -h");
$cmd1->exit_is_num(0); $cmd1->exit_is_num(0);
$cmd1->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\] $cmd1->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\]
@ -16,21 +16,11 @@ Probing options:
}s); }s);
$cmd1->stderr_is_eq(""); $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 # fping -v
my $cmd2 = Test::Command->new(cmd => "fping -v"); my $cmd2 = Test::Command->new(cmd => "fping -v");
$cmd2->exit_is_num(0); $cmd2->exit_is_num(0);
$cmd2->stdout_like(qr{fping: Version \S+}); $cmd2->stdout_like(qr{fping: Version \S+
fping: comments to david\@schweikert\.ch\n});
$cmd2->stderr_is_eq(""); $cmd2->stderr_is_eq("");
# fping with unknown option # fping with unknown option

@ -1,6 +1,6 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use Test::Command tests => 36; use Test::Command tests => 24;
# fping -i 0 # fping -i 0
my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29"); 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->stdout_is_eq("");
$cmd9->stderr_is_eq("fping: backoff factor 0.9 not valid, must be between 1.0 and 5.0\n"); $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"); my $cmd10 = Test::Command->new(cmd => "fping -B 5.1 127.0.0.1");
$cmd10->exit_is_num(1); $cmd10->exit_is_num(1);
$cmd10->stdout_is_eq(""); $cmd10->stdout_is_eq("");
$cmd10->stderr_is_eq("fping: backoff factor 5.1 not valid, must be between 1.0 and 5.0\n"); $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 # fping -6
SKIP: { SKIP: {
if($ENV{SKIP_IPV6}) { if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'Skip IPv6 tests', 3; skip 'No IPv6 on this host', 3;
} }
my $cmd = Test::Command->new(cmd => "fping -6 ::1"); my $cmd = Test::Command->new(cmd => "fping -6 ::1");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
@ -85,17 +85,14 @@ $cmd->stderr_is_eq("");
} }
# fping -B # fping -B
SKIP: { {
if($^O eq 'darwin') { my $t0 = [gettimeofday];
skip 'timing test not reliable on macOS', 5; my $cmd = Test::Command->new(cmd => "fping -t 100 -r 3 -B 2 8.8.8.7");
} $cmd->exit_is_num(1);
my $t0 = [gettimeofday]; $cmd->stdout_is_eq("8.8.8.7 is unreachable\n");
my $cmd = Test::Command->new(cmd => "fping -t 100 -r 3 -B 2 8.8.8.7"); $cmd->stderr_like(qr{^(|(8.8.8.7: error while sending ping: No route to host\n)+)$});
$cmd->exit_is_num(1); my $elapsed = tv_interval($t0);
$cmd->stdout_is_eq("8.8.8.7 is unreachable\n"); # 0.1 + 0.2 + 0.4 + 0.8 = 1.5
$cmd->stderr_like(qr{^(|(8.8.8.7: error while sending ping: No route to host\n)+)$}); cmp_ok($elapsed, '>=', 1.5);
my $elapsed = tv_interval($t0); cmp_ok($elapsed, '<', 1.8);
# 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 #!/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 count of pings to send to each target (default 1)
# -C n same as -c, report results in verbose format # -C n same as -c, report results in verbose format
@ -11,50 +11,10 @@ use Test::Command tests => 51;
{ {
my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 localhost 127.0.0.1"); my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) $cmd->stdout_like(qr{localhost : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 64 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\], 64 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\], 64 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->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+ $cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
@ -66,10 +26,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"); my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) $cmd->stdout_like(qr{localhost : \[0\], 84 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 64 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\], 64 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\], 64 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->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ $cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
@ -77,130 +37,18 @@ $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 # fping -D
{ {
my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1"); my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
$cmd->stdout_like(qr{\[\d+\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) $cmd->stdout_like(qr{\[\d{10}\.\d+\] 127\.0\.0\.1 : \[0\], 84 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\) \[\d{10}\.\d+\] 127\.0\.0\.1 : \[1\], 84 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+ $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 # fping -e
{ {
my $cmd = Test::Command->new(cmd => "fping -e 127.0.0.1"); my $cmd = Test::Command->new(cmd => "fping -e 127.0.0.1");

@ -1,7 +1,6 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use Test::Command tests => 75; use Test::Command tests => 24;
use Test::More;
use File::Temp; use File::Temp;
# -f file read list of targets from a file ( - means stdin) (only if no -g specified) # -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"; print $tmpfile "127.0.0.1\n127.0.0.2\n";
close($tmpfile); 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 -') # fping without option (-> equivalent to 'fping -f -')
{ {
my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping"); 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(""); $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) # fping -g (range)
{ {
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.5"); 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(""); $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) # fping -g (cidr)
{ {
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1/30"); 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(""); $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"); my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/31");
$cmd->exit_is_num(0); $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(""); $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) # fping -g (cidr - too long prefixes)
{ {
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/33"); 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"); $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 # fping -H
{ {
my $cmd = Test::Command->new(cmd => "fping -H 1 127.0.0.1"); my $cmd = Test::Command->new(cmd => "fping -H 1 127.0.0.1");

@ -1,11 +1,10 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use Test::Command tests => 15; use Test::Command tests => 7;
use Test::More; use Test::More;
# -i n interval between sending ping packets (in millisec) (default 25) # -i n interval between sending ping packets (in millisec) (default 25)
# -l loop sending pings forever # -l loop sending pings forever
# -k set fwmark on ping packets
# -m ping multiple interfaces on target host # -m ping multiple interfaces on target host
# -M don't fragment # -M don't fragment
@ -20,55 +19,8 @@ $cmd->stderr_is_eq("");
# fping -l # fping -l
{ {
my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1'); my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1');
$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 84 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 : \[1\], 84 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\], 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\)
}); });
} }

@ -1,6 +1,6 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use Test::Command tests => 36; use Test::Command tests => 18;
# -n show targets by name (-d is equivalent) # -n show targets by name (-d is equivalent)
# -O n set the type of service (tos) flag on the ICMP packets # -O n set the type of service (tos) flag on the ICMP packets
@ -31,12 +31,7 @@ $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"); my $cmd = Test::Command->new(cmd => "fping -t100 -p 100 -o -c 5 8.8.8.7");
$cmd->exit_is_num(1); $cmd->exit_is_num(1);
$cmd->stdout_is_eq("8.8.8.7 : [0], timed out (NaN avg, 100% loss) $cmd->stdout_is_eq("");
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*$}); $cmd->stderr_like(qr{^\s*8\.8\.8\.7 : xmt/rcv/%loss = 5/0/100%, outage\(ms\) = 50\d\s*$});
} }
@ -68,81 +63,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 #!/usr/bin/perl -w
use Test::Command tests => 27; use Test::Command tests => 21;
use Test::More; use Test::More;
# -R random bytes # -R random bytes
@ -19,8 +19,8 @@ $cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%.*});
} }
SKIP: { SKIP: {
if($ENV{SKIP_IPV6}) { if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'Skip IPv6 tests', 3; skip 'No IPv6 on this host', 3;
} }
my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 ::1"); my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 ::1");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
@ -84,18 +84,10 @@ $cmd->stdout_is_eq("127.0.0.1 is alive\n");
$cmd->stderr_is_eq(""); $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 # fping -S
SKIP: { SKIP: {
if($ENV{SKIP_IPV6}) { if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'Skip IPv6 tests', 3; skip 'No IPv6 on this host', 3;
} }
my $cmd = Test::Command->new(cmd => "fping -S ::1 ::1"); my $cmd = Test::Command->new(cmd => "fping -S ::1 ::1");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
@ -103,17 +95,6 @@ SKIP: {
$cmd->stderr_is_eq(""); $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 # fping -S
{ {
my $cmd = Test::Command->new(cmd => "fping -S bla"); my $cmd = Test::Command->new(cmd => "fping -S bla");

@ -1,11 +1,9 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use Test::Command tests => 15; use Test::Command tests => 12;
# -u show targets that are unreachable # -u show targets that are unreachable
# -v show version # -v show version
# -x shows if >=N hosts are reachable or not
# -X exits true immediately when N hosts are found
# fping -u # fping -u
{ {
@ -19,7 +17,9 @@ $cmd->stderr_is_eq("");
{ {
my $cmd = Test::Command->new(cmd => "fping -v"); my $cmd = Test::Command->new(cmd => "fping -v");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
$cmd->stdout_like(qr{ping: Version [45]\.\d+(-rc\d+)?}); $cmd->stdout_like(qr{ping: Version 4\.\d+(-rc\d+)?
fping: comments to david\@schweikert\.ch
});
$cmd->stderr_is_eq(""); $cmd->stderr_is_eq("");
} }
@ -38,11 +38,3 @@ $cmd->exit_is_num(1);
$cmd->stdout_is_eq("Not enough hosts reachable (required: 2, reachable: 1)\n"); $cmd->stdout_is_eq("Not enough hosts reachable (required: 2, reachable: 1)\n");
$cmd->stderr_is_eq(""); $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,22 @@
#!/usr/bin/perl -w
use Test::Command;
use Test::More;
if( $^O eq 'darwin' ) {
plan skip_all => 'Test irrelevant on MacOS';
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 #!/usr/bin/perl -w
use Test::Command tests => 84; use Test::Command tests => 33;
use Test::More;
# some options require a numeric argument for my $arg (qw(b B c C H i O p Q r t)) {
for my $arg (qw(b B c C H i O p Q r t x X)) { my $cmd = Test::Command->new(cmd => "fping -$arg xxx");
for my $test_input (qw(xxx '')) { $cmd->exit_is_num(1);
my $cmd = Test::Command->new(cmd => "fping -$arg $test_input"); $cmd->stdout_is_eq("");
$cmd->exit_is_num(1); $cmd->stderr_like(qr{Usage:});
$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,12 +15,13 @@ my $re_num = qr{\d+(?:\.\d+)?};
# fping # fping
{ {
my $cmd = Test::Command->new(cmd => "fping -q -i 10 -p 20 -c 3 -t200 8.8.8.8 www.france-telecom.fr www.google.com"); 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");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
$cmd->stdout_is_eq(""); $cmd->stdout_is_eq("");
$cmd->stderr_like(qr{8\.8\.8\.8\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num $cmd->stderr_like(qr{8\.8\.8\.8\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]/[123]/\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\.google\.com\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]/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
}); });
} }
@ -58,23 +59,23 @@ $cmd->stderr_is_eq("");
# fping -A -n (IPv6) # fping -A -n (IPv6)
SKIP: { SKIP: {
if($ENV{SKIP_IPV6}) { if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
skip 'Skip IPv6 tests', 3; skip 'No IPv6 on this host', 3;
} }
my $cmd = Test::Command->new(cmd => "fping -6 -n -A dns.google"); my $cmd = Test::Command->new(cmd => "fping -6 -n -A dns.google");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
$cmd->stdout_like(qr{^dns.google \(2001:4860:4860::88(44|88)\) is alive\n$}); $cmd->stdout_is_eq("dns.google (2001:4860:4860::8888) is alive\n");
$cmd->stderr_is_eq(""); $cmd->stderr_is_eq("");
} }
# fping -m # fping -m
SKIP: { SKIP: {
if($ENV{SKIP_IPV6}) { if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
skip 'Skip IPv6 tests', 3; skip 'No IPv6 on this host', 3;
} }
my $cmd = Test::Command->new(cmd => "fping -A -m dns.google"); my $cmd = Test::Command->new(cmd => "fping -A -m dns.google");
$cmd->exit_is_num(0); $cmd->exit_is_num(0);
$cmd->stdout_like(qr{^.* is alive\n.* is alive\n.* is alive\n.* is alive\n}); $cmd->stdout_is_eq("2001:4860:4860::8888 is alive\n8.8.8.8 is alive\n");
$cmd->stderr_is_eq(""); $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"); my $cmd = Test::Command->new(cmd => "fping -c 2 -Q 1 -N 127.0.0.1");
$cmd->exit_is_num(0); $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 xmt sent absolute 1 1
DIMENSION rcv received absolute 1 1 DIMENSION rcv received absolute 1 1
BEGIN fping\.127_0_0_1_packets BEGIN fping\.127_0_0_1_packets
SET xmt = 1 SET xmt = 1
SET rcv = 1 SET rcv = 1
END 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 DIMENSION returned '' absolute 1 1
BEGIN fping\.127_0_0_1_quality BEGIN fping\.127_0_0_1_quality
SET returned = 100 SET returned = 100
END 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 min minimum absolute 10 1000
DIMENSION max maximum absolute 1 1000000 DIMENSION max maximum absolute 10 1000
DIMENSION avg average absolute 1 1000000 DIMENSION avg average absolute 10 1000
BEGIN fping\.127_0_0_1_latency BEGIN fping\.127_0_0_1_latency
SET min = \d+ SET min = \d{1,2}
SET avg = \d+ SET avg = \d{1,2}
SET max = \d+ SET max = \d{1,2}
END} END}
); );
$cmd->stderr_like(qr{127.0.0.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+}); $cmd->stderr_like(qr{127.0.0.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+});

@ -0,0 +1,135 @@
#!/usr/bin/perl -w
use Test::Command;
use Test::More;
plan tests => 18;
# summary
{
my $cmd = Test::Command->new(cmd => "fping -c 2 -J 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\{
"hosts": \{
"127\.0\.0\.1": \{
"xmt": 2,
"rcv": 2,
"loss_percentage": 0,
"min": \d.\d+,
"avg": \d.\d+,
"max": \d.\d+
\}
\}
\}}
);
$cmd->stderr_is_eq("");
}
# all RTTs
{
my $cmd = Test::Command->new(cmd => "fping -C 2 -J 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\{
"hosts": \{
"127\.0\.0\.1": \[
\d.\d+,
\d.\d+
\]
\}
\}}
);
$cmd->stderr_is_eq("");
}
# summary with stats and outage
{
my $cmd = Test::Command->new(cmd => "fping -c 2 -s -o -J 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\{
"hosts": \{
"127\.0\.0\.1": \{
"xmt": 2,
"rcv": 2,
"loss_percentage": 0,
"outage": 0,
"min": \d.\d+,
"avg": \d.\d+,
"max": \d.\d+
\}
\},
"stats": \{
"targets": 1,
"alive": 1,
"unreachable": 0,
"unknown_addresses": 0,
"timeouts": 0,
"icmp_echos_sent": 2,
"icmp_echo_replies_received": 2,
"other_icmp_received": 0,
"min_rtt": \d.\d+,
"avg_rtt": \d.\d+,
"max_rtt": \d.\d+,
"elapsed_real_time": \d.\d+
\}
\}}
);
$cmd->stderr_is_eq("");
}
# all RTTs with stats
{
my $cmd = Test::Command->new(cmd => "fping -C 2 -s -J 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\{
"hosts": \{
"127\.0\.0\.1": \[
\d.\d+,
\d.\d+
\]
\},
"stats": \{
"targets": 1,
"alive": 1,
"unreachable": 0,
"unknown_addresses": 0,
"timeouts": 0,
"icmp_echos_sent": 2,
"icmp_echo_replies_received": 2,
"other_icmp_received": 0,
"min_rtt": \d.\d+,
"avg_rtt": \d.\d+,
"max_rtt": \d.\d+,
"elapsed_real_time": \d.\d+
\}
\}}
);
$cmd->stderr_is_eq("");
}
# more indentation
{
my $cmd = Test::Command->new(cmd => "fping -c 2 --json=4 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\{
"hosts": \{
"127\.0\.0\.1": \{
"xmt": 2,
"rcv": 2,
"loss_percentage": 0,
"min": \d.\d+,
"avg": \d.\d+,
"max": \d.\d+
\}
\}
\}}
);
$cmd->stderr_is_eq("");
}
# no pretty-print
{
my $cmd = Test::Command->new(cmd => "fping -c 2 --json=0 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\{"hosts":\{"127\.0\.0\.1":\{"xmt":2,"rcv":2,"loss_percentage":0,"min":\d.\d+,"avg":\d.\d+,"max":\d.\d+\}\}\}});
$cmd->stderr_is_eq("");
}

@ -6,11 +6,6 @@
set -e set -e
set -x set -x
# skip on macos
if [[ "$OSTYPE" == "darwin"* ]]; then
exit 0
fi
make dist make dist
VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//') VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//')
if [ -z "$VERSION" ]; then if [ -z "$VERSION" ]; then

@ -3,25 +3,7 @@ dnl Process this file with autoconf to produce a configure script.
dnl Minimum Autoconf version required. dnl Minimum Autoconf version required.
AC_PREREQ(2.59) AC_PREREQ(2.59)
AC_INIT([fping],[5.2]) AC_INIT([fping],[4.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 dnl --disable-ipv4
AC_ARG_ENABLE([ipv4], AC_ARG_ENABLE([ipv4],
@ -51,27 +33,22 @@ AM_CONDITIONAL([IPV6], [test "x$have_ipv6" = "xyes"])
AM_COND_IF([IPV6], [AC_DEFINE([IPV6], [1], [IPv6 enabled])]) AM_COND_IF([IPV6], [AC_DEFINE([IPV6], [1], [IPv6 enabled])])
AC_ARG_ENABLE([timestamp], AC_ARG_ENABLE([timestamp],
AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMPNS)])) AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMP)]))
AS_IF([test "x$enable_timestamp" != "xno"], [ AS_IF([test "x$enable_timestamp" != "xno"], [
AC_CHECK_DECL([SO_TIMESTAMPNS], [AC_DEFINE(HAVE_SO_TIMESTAMPNS, [1], [SO_TIMESTAMPNS is defined])], [have_so_timestamp="no"], [#include <sys/types.h> AC_CHECK_DECL([SO_TIMESTAMP], [AC_DEFINE(HAVE_SO_TIMESTAMP, [1], [SO_TIMESTAMP is defined])], [have_so_timestamp="no"], [#include <sys/types.h>
#include <sys/socket.h>]) #include <sys/socket.h>])
]) ])
dnl Test if --enable-timestamp is explicitely enabled and make an error if this platform doesn't support it 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"], [ AS_IF([test "x$enable_timestamp" = "xyes" -a "x$have_so_timestamp" = "xno"], [
AC_MSG_ERROR([--enable-timestamp not supported on this platform]) 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], AC_ARG_ENABLE([safe-limits],
AS_HELP_STRING([--enable-safe-limits], [Restrict timing parameters (-i, -p) within "safe" limits])) AS_HELP_STRING([--enable-safe-limits], [Restrict timing parameters (-i, -p) within "safe" limits]))
AS_IF([test "x$enable_safe_limits" = "xyes"], [ AS_IF([test "x$enable_safe_limits" = "xyes"], [
AC_DEFINE(FPING_SAFE_LIMITS, [1], [safe limits should be enforced])]) AC_DEFINE(FPING_SAFE_LIMITS, [1], [safe limits should be enforced])])
AC_ARG_ENABLE([debug], AC_CANONICAL_TARGET
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_INIT_AUTOMAKE([-Wall -Werror foreign])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
@ -81,7 +58,7 @@ dnl Checks for programs.
AC_PROG_CC AC_PROG_CC
AM_PROG_CC_C_O AM_PROG_CC_C_O
m4_version_prereq([2.70],,[AC_PROG_CC_STDC]) AC_PROG_CC_STDC
AC_PROG_CPP AC_PROG_CPP
AC_PROG_INSTALL AC_PROG_INSTALL
@ -95,13 +72,6 @@ AC_CHECK_FUNC(connect)
if test $ac_cv_func_connect = no; then if test $ac_cv_func_connect = no; then
AC_CHECK_LIB(socket, connect) AC_CHECK_LIB(socket, connect)
fi 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([ AH_TOP([
#ifndef CONFIG_H #ifndef 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"]

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

@ -19,8 +19,7 @@ of targets to check; if a target does not respond within a certain time limit
and/or retry limit it is designated as unreachable. B<fping> also supports and/or retry limit it is designated as unreachable. B<fping> also supports
sending a specified number of pings to a target, or looping indefinitely (as in sending a specified number of pings to a target, or looping indefinitely (as in
B<ping> ). Unlike B<ping>, B<fping> is meant to be used in scripts, so its B<ping> ). Unlike B<ping>, B<fping> is meant to be used in scripts, so its
output is designed to be easy to parse. Current statistics can be obtained without output is designed to be easy to parse.
termination of process with signal SIGQUIT (^\ from the keyboard on most systems).
=head1 OPTIONS =head1 OPTIONS
@ -66,8 +65,7 @@ default is 1.5.
Number of request packets to send to each target. In this mode, a line is 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>). 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 Also, statistics about responses for each target are displayed when all
requests have been sent (or when interrupted). This option overrides B<-a> requests have been sent (or when interrupted).
or B<-u>.
=item B<-C>, B<--vcount>=I<N> =item B<-C>, B<--vcount>=I<N>
@ -78,12 +76,11 @@ designed for automated response-time statistics gathering. For example:
somehost : 91.7 37.0 29.2 - 36.8 somehost : 91.7 37.0 29.2 - 36.8
shows the response time in milliseconds for each of the five requests, with the 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 C<-> indicating that no response was received to the fourth request.
option overrides B<-a> or B<-u>.
=item B<-d>, B<--rdns> =item B<-d>, B<--rdns>
Use DNS to lookup address of ping target. This allows you to give fping Use DNS to lookup address of return ping packet. This allows you to give fping
a list of IP addresses as input and print hostnames in the output. This is similar 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 to option B<-n>/B<--name>, but will force a reverse-DNS lookup even if you give
hostnames as target (NAME->IP->NAME). hostnames as target (NAME->IP->NAME).
@ -93,23 +90,16 @@ hostnames as target (NAME->IP->NAME).
Add Unix timestamps in front of output lines generated with in looping or counting Add Unix timestamps in front of output lines generated with in looping or counting
modes (B<-l>, B<-c>, or B<-C>). 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> =item B<-e>, B<--elapsed>
Show elapsed (round-trip) time of packets. Show elapsed (round-trip) time of packets.
=item B<-f>, B<--file> =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> =item B<-g>, B<--generate> I<addr/mask>
@ -142,10 +132,11 @@ to any target (default is 10, minimum is 1).
Set the interface (requires SO_BINDTODEVICE support). Set the interface (requires SO_BINDTODEVICE support).
=item B<-k>, B<--fwmark>=I<FWMARK> =item B<-J>, B<--json>[=I<N>]
Set FWMARK on ping packets for policy-based routing. Requires Linux kernel Output in JSON format to stdout (implies -q).
2.6.25<=, and root privileges or cap_net_admin. Optionally specify JSON indentation (default: 2, max: 16).
Indentation == 0 will disable pretty-printing.
=item B<-l>, B<--loop> =item B<-l>, B<--loop>
@ -164,11 +155,11 @@ Set the "Don't Fragment" bit in the IP header (used to determine/test the MTU).
=item B<-n>, B<--name> =item B<-n>, B<--name>
If targets are specified as IP addresses, do a reverse-DNS lookup on them If targets are specified as IP addresses, do a reverse-DNS lookup on them
to print hostnames in the output. to
=item B<-N>, B<--netdata> =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> =item B<-o>, B<--outage>
@ -190,11 +181,9 @@ 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 Quiet. Don't show per-probe results, but only the final summary. Also don't
show ICMP error messages. 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> Like B<-q>, but show summary results every n seconds.
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> =item B<-r>, B<--retry>=I<N>
@ -247,11 +236,6 @@ Print B<fping> version information.
Given a list of hosts, this mode checks if number of reachable hosts is >= N Given a list of hosts, this mode checks if number of reachable hosts is >= N
and exits true in that case. 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 =back
=head1 EXAMPLES =head1 EXAMPLES
@ -287,17 +271,12 @@ B<fping website: L<http://www.fping.org>>
=head1 DIAGNOSTICS =head1 DIAGNOSTICS
Exit status is 0 if all the hosts (or the number of hosts specified with B<-x> Exit status is 0 if all the hosts are reachable, 1 if some hosts
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 were unreachable, 2 if any IP addresses were not found, 3 for invalid command
line arguments, and 4 for a system call failure. line arguments, and 4 for a system call failure.
=head1 RESTRICTIONS =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 If fping was configured with C<--enable-safe-limits>, the following values are
not allowed for non-root users: not allowed for non-root users:

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

File diff suppressed because it is too large Load Diff

@ -7,32 +7,21 @@
#include <sys/types.h> #include <sys/types.h>
#include <netinet/in.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 */ /* fping.c */
void crash_and_burn( char *message ); void crash_and_burn( char *message );
void errno_crash_and_burn( char *message ); void errno_crash_and_burn( char *message );
int in_cksum( unsigned short *p, int n ); int in_cksum( unsigned short *p, int n );
extern int nonzero_payload_flag; int random_data_flag;
/* socket.c */ /* socket.c */
int open_ping_socket_ipv4(int *socktype); int open_ping_socket_ipv4();
void init_ping_buffer_ipv4(size_t ping_data_size); 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); void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr);
int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id); int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
#ifdef IPV6 #ifdef IPV6
int open_ping_socket_ipv6(int *socktype); int open_ping_socket_ipv6();
void init_ping_buffer_ipv6(size_t ping_data_size); 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); void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr);
int socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id); int socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
#endif #endif

@ -238,14 +238,12 @@ optparse_long(struct optparse *options,
/* Parse as long option. */ /* Parse as long option. */
options->errmsg[0] = '\0'; options->errmsg[0] = '\0';
options->optopt = 0; options->optopt = 0;
options->optlongname = 0;
options->optarg = 0; options->optarg = 0;
option += 2; /* skip "--" */ option += 2; /* skip "--" */
options->optind++; options->optind++;
for (int i = 0; !longopts_end(longopts, i); i++) { for (int i = 0; !longopts_end(longopts, i); i++) {
const char *name = longopts[i].longname; const char *name = longopts[i].longname;
if (longopts_match(name, option)) { if (longopts_match(name, option)) {
options->optlongname = option;
if (longindex) if (longindex)
*longindex = i; *longindex = i;
options->optopt = longopts[i].shortname; options->optopt = longopts[i].shortname;

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

@ -35,20 +35,17 @@
* https://github.com/schweikert/fping/issues/48 * https://github.com/schweikert/fping/issues/48
*/ */
#include "config.h"
#include "seqmap.h" #include "seqmap.h"
#include "limits.h" #include "limits.h"
#include "options.h" #include "options.h"
#include "fping.h"
#include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/* description of the data structure used: /* description of the data structure used:
* *
* - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in * - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in
* the timeout interval (SEQMAP_TIMEOUT_IN_NS) * the timeout interval (SEQMAP_TIMEOUT_IN_S)
* - we store the values in an array with SEQMAP_MAXSEQ elements * - we store the values in an array with SEQMAP_MAXSEQ elements
* - current sequence number % SEQMAP_MAXSEQ gives the current index * - current sequence number % SEQMAP_MAXSEQ gives the current index
* - when entering a value, we check that the current entry is expired * - when entering a value, we check that the current entry is expired
@ -57,7 +54,7 @@
static SEQMAP_VALUE* seqmap_map = NULL; static SEQMAP_VALUE* seqmap_map = NULL;
static unsigned int seqmap_next_id = 0; static unsigned int seqmap_next_id = 0;
#define SEQMAP_TIMEOUT_IN_NS 10000000000 #define SEQMAP_TIMEOUT_IN_S 10
#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX #define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
void seqmap_init() void seqmap_init()
@ -68,7 +65,7 @@ void seqmap_init()
} }
} }
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t timestamp) unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval* now)
{ {
unsigned int current_id; unsigned int current_id;
SEQMAP_VALUE* next_value; SEQMAP_VALUE* next_value;
@ -81,27 +78,26 @@ 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 /* check if expired (note that unused seqmap values will have fields set to
* 0, so will be seen as expired */ * 0, so will be seen as expired */
next_value = &seqmap_map[seqmap_next_id]; next_value = &seqmap_map[seqmap_next_id];
if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) { 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=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n", 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_NS, host_nr, ping_count, seqmap_next_id); SEQMAP_TIMEOUT_IN_S, host_nr, ping_count, seqmap_next_id);
exit(4); exit(4);
} }
/* store the value */ /* store the value */
next_value->host_nr = host_nr; next_value->host_nr = host_nr;
next_value->ping_count = ping_count; next_value->ping_count = ping_count;
next_value->ping_ts = timestamp; next_value->ping_ts.tv_sec = now->tv_sec;
next_value->ping_ts.tv_usec = now->tv_usec;
/* increase next id */ /* increase next id */
current_id = seqmap_next_id; current_id = seqmap_next_id;
seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ; 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; return current_id;
} }
SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now) SEQMAP_VALUE* seqmap_fetch(unsigned int id, struct timeval* now)
{ {
SEQMAP_VALUE* value; SEQMAP_VALUE* value;
@ -112,13 +108,9 @@ SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now)
value = &seqmap_map[id]; value = &seqmap_map[id];
/* verify that value is not expired */ /* verify that value is not expired */
if (now - value->ping_ts >= SEQMAP_TIMEOUT_IN_NS) { if (now->tv_sec - value->ping_ts.tv_sec >= SEQMAP_TIMEOUT_IN_S) {
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; return NULL;
} }
dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d\n", id, value->host_nr, value->ping_count);
return value; return value;
} }

@ -2,20 +2,19 @@
#define SEQMAP_H #define SEQMAP_H
#include <sys/time.h> #include <sys/time.h>
#include <stdint.h>
typedef struct seqmap_value typedef struct seqmap_value
{ {
unsigned int host_nr; unsigned int host_nr;
unsigned int ping_count; unsigned int ping_count;
int64_t ping_ts; struct timeval ping_ts;
} SEQMAP_VALUE; } SEQMAP_VALUE;
#define SEQMAP_MAXSEQ 65535 #define SEQMAP_MAXSEQ 65535
void seqmap_init(); void seqmap_init();
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t now); unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval *now);
SEQMAP_VALUE *seqmap_fetch(unsigned int id, int64_t now); SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now);
#endif #endif

@ -47,7 +47,7 @@
char* ping_buffer_ipv4 = 0; char* ping_buffer_ipv4 = 0;
size_t ping_pkt_size_ipv4; size_t ping_pkt_size_ipv4;
int open_ping_socket_ipv4(int *socktype) int open_ping_socket_ipv4()
{ {
struct protoent* proto; struct protoent* proto;
int s; int s;
@ -57,12 +57,10 @@ int open_ping_socket_ipv4(int *socktype)
crash_and_burn("icmp: unknown protocol"); crash_and_burn("icmp: unknown protocol");
/* create raw socket for ICMP calls (ping) */ /* create raw socket for ICMP calls (ping) */
*socktype = SOCK_RAW; s = socket(AF_INET, SOCK_RAW, proto->p_proto);
s = socket(AF_INET, *socktype, proto->p_proto);
if (s < 0) { if (s < 0) {
/* try non-privileged icmp (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_INET, SOCK_DGRAM, proto->p_proto);
s = socket(AF_INET, *socktype, proto->p_proto);
if (s < 0) { if (s < 0) {
return -1; return -1;
} }
@ -91,25 +89,15 @@ void init_ping_buffer_ipv4(size_t ping_data_size)
crash_and_burn("can't malloc ping packet"); crash_and_burn("can't malloc ping packet");
} }
void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr, int *ident) void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr)
{ {
struct sockaddr_in sa; struct sockaddr_in sa;
socklen_t len = sizeof(sa); memset(&sa, 0, sizeof(sa));
memset(&sa, 0, len);
sa.sin_family = AF_INET; sa.sin_family = AF_INET;
sa.sin_addr = *src_addr; sa.sin_addr = *src_addr;
if (bind(s, (struct sockaddr*)&sa, len) < 0)
errno_crash_and_burn("cannot bind source address");
if (ident) {
memset(&sa, 0, len);
if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
errno_crash_and_burn("can't get ICMP socket identity");
if (sa.sin_port) if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
*ident = sa.sin_port; errno_crash_and_burn("cannot bind source address");
}
} }
unsigned short calcsum(unsigned short* buffer, int length) unsigned short calcsum(unsigned short* buffer, int length)
@ -133,7 +121,6 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len,
{ {
struct icmp* icp; struct icmp* icp;
int n; int n;
size_t i;
icp = (struct icmp*)ping_buffer_ipv4; icp = (struct icmp*)ping_buffer_ipv4;
@ -141,14 +128,11 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len,
icp->icmp_code = 0; icp->icmp_code = 0;
icp->icmp_cksum = 0; icp->icmp_cksum = 0;
icp->icmp_seq = htons(icmp_seq_nr); icp->icmp_seq = htons(icmp_seq_nr);
icp->icmp_id = icmp_id_nr; icp->icmp_id = htons(icmp_id_nr);
if (nonzero_payload_flag) { if (random_data_flag) {
// for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) { for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) {
// ping_buffer_ipv4[n] = random() & 0xFF; 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,22 +46,20 @@
char* ping_buffer_ipv6 = 0; char* ping_buffer_ipv6 = 0;
size_t ping_pkt_size_ipv6; size_t ping_pkt_size_ipv6;
int open_ping_socket_ipv6(int *socktype) int open_ping_socket_ipv6()
{ {
struct protoent* proto; struct protoent* proto;
int s; int s;
/* confirm that ICMP6 is available on this machine */ /* confirm that ICMP is available on this machine */
if ((proto = getprotobyname("ipv6-icmp")) == NULL) 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, SOCK_RAW, proto->p_proto);
s = socket(AF_INET6, *socktype, proto->p_proto);
if (s < 0) { 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, SOCK_DGRAM, proto->p_proto);
s = socket(AF_INET6, *socktype, proto->p_proto);
if (s < 0) { if (s < 0) {
return -1; return -1;
} }
@ -90,42 +88,31 @@ void init_ping_buffer_ipv6(size_t ping_data_size)
crash_and_burn("can't malloc ping packet"); crash_and_burn("can't malloc ping packet");
} }
void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident) void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr)
{ {
struct sockaddr_in6 sa; struct sockaddr_in6 sa;
socklen_t len = sizeof(sa);
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6; sa.sin6_family = AF_INET6;
sa.sin6_addr = *src_addr; sa.sin6_addr = *src_addr;
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0) if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
errno_crash_and_burn("cannot bind source address"); errno_crash_and_burn("cannot bind source address");
if (ident) {
memset(&sa, 0, len);
if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
errno_crash_and_burn("can't get ICMP6 socket identity");
if (sa.sin6_port)
*ident = sa.sin6_port;
}
} }
int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr) 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; struct icmp6_hdr* icp;
int n; int n;
size_t i;
icp = (struct icmp6_hdr*)ping_buffer_ipv6; icp = (struct icmp6_hdr*)ping_buffer_ipv6;
icp->icmp6_type = ICMP6_ECHO_REQUEST; icp->icmp6_type = ICMP6_ECHO_REQUEST;
icp->icmp6_code = 0; icp->icmp6_code = 0;
icp->icmp6_seq = htons(icmp_seq_nr); icp->icmp6_seq = htons(icmp_seq_nr);
icp->icmp6_id = icmp_id_nr; icp->icmp6_id = htons(icmp_id_nr);
if (nonzero_payload_flag) { if (random_data_flag) {
for (n = sizeof(struct icmp6_hdr), i = 0xA; n < ping_pkt_size_ipv6; ++n, i+=1) { for (n = sizeof(struct icmp6_hdr); n < ping_pkt_size_ipv6; ++n) {
ping_buffer_ipv6[n] = i & 0xFF; ping_buffer_ipv6[n] = random() & 0xFF;
} }
} }

Loading…
Cancel
Save