Compare commits

..

5 Commits

Author SHA1 Message Date
David Schweikert a993bf5043 reformat 8 years ago
David Schweikert 7a5f9b29d2 portability fix 8 years ago
David Schweikert 36030dce3b Merge branch 'version3' of github.com:schweikert/fping into version3 8 years ago
David Schweikert 08e5cabe45 portability fixes 8 years ago
David Schweikert b079eaf8d4 fix compatibility issue with GNU Hurd 8 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

@ -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
.gitignore vendored

@ -4,7 +4,6 @@
src/*.gcno
src/*.gcda
src/*.gcov
src/tags
.deps
Makefile
Makefile.in

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

@ -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,246 +0,0 @@
fping 5.2 (2024-04-21)
======================
## New features
- New option -X / --fast-reachable to exit immediately once N hosts have been
found (#260, thanks @chriscray and @gsnw)
- New option -k / -fwmark to set Linux fwmark mask (#289, thanks @tomangert and
@deepkv)
## Bugfixes and other changes
- Always output fatal error messages (#303, thanks @auerswal)
- Fallback to SO\_TIMESTAMP if SO\_TIMESTAMPNS is not available (#279, thanks
@gsnw)
- Fix "not enough sequence numbers available" error on BSD-like systems (#307,
thanks @cagney, @gsnw)
- Fix running in unprivileged mode (#248, thanks @sfan5)
- Fix build issue for NetBSD/alpha (#255, thanks @0-wiz-0)
- Fix build issue for OpenBSD/alpha (#275, thanks @gsnw)
- Fix build warning for long int usage (#258, thanks @gsnw)
- Fix build error with musl libc (#263, thanks @kraj)
- Fix to guard against division by zero (#293, thanks @auerswal)
- Decouple -a/-u effects from -c (#298, thanks @auerswal)
- Added contrib/Dockerfile (#224, thanks @darless)
- Remove host from Netdata chart titles (#253, thanks @ilyam8)
- Add additional tests (#292, #297, thanks @auerswal)
- Update github action os images (#282, thanks @gsnw)
- Fix Azure pipeline tests (#308, thanks @gsnw)
- Various autoconf fixes (#286, #283, thanks @gsnw)
- Extended configure script with --enable-debug and output cpu usage (#311,
thanks @gsnw)
- Documentation: Update Netdata website link (#257, thanks @ilyam8)
- Documentation: fix description of --file option (#268, thanks @MohGeek)
- Documentation: improve exit status description (#294, thanks @auerswal)
- Documentation: move description of -i MSEC (#298, thanks @auerswal)
- Documentation: improve help output for options -c and -C (#302, #auerswal)
fping 5.1 (2022-02-06)
======================
## Bugfixes and other changes
- Use setcap to specify specific files in fping.spec (#232, thanks @zdyxry)
- Netdata: use host instead name as family label (#226, thanks @k0ste)
- Netdata: use formatstring macro PRId64 (#229, thanks @gsnw)
- Allow -4 option to be given multiple times (#215, thanks @normanr)
- Documentation fix (#208, thanks @timgates42)
- Retain privileges until after privileged setsockopt (#200, thanks @simetnicbr)
- Set bind to source only when option is set (#198, thanks @dinoex)
- Update Azure test pipeline (#197, thanks @gsnw)
- Fix getnameinfo not called properly for IPv4 (#227, thanks @aafbsd)
- Fixed wrong timestamp under Free- and OpenBSD and macOS (#217, thanks @gsnw)
- Documentation updates (#240, thanks @auerswal)
- Updated autotools (autoconf 2.71, automake 1.16.5, libtool 2.4.6)
fping 5.0 (2020-08-05)
======================
## Incompatible Changes
- In non-quiet loop and count mode, a line is printed for every lost packet
(#175, thanks @kbucheli):
```
$ fping -D -c2 8.8.8.8 8.8.8.7
[1596092373.18423] 8.8.8.8 : [0], 64 bytes, 12.8 ms (12.8 avg, 0% loss)
[1596092374.18223] 8.8.8.7 : [0], timed out (NaN avg, 100% loss)
[1596092374.18424] 8.8.8.8 : [1], 64 bytes, 12.3 ms (12.5 avg, 0% loss)
[1596092375.18344] 8.8.8.7 : [1], timed out (NaN avg, 100% loss)
8.8.8.8 : xmt/rcv/%loss = 2/2/0%, min/avg/max = 12.3/12.5/12.8
8.8.8.7 : xmt/rcv/%loss = 2/0/100%
```
- The returned size in bytes now always excludes the IP header, so if before it
reported '84 bytes' e.g. when using 'fping -l', now it reports '64 bytes'.
This is to make the reported size consistent with ping(8) from iputils and
also with fping when pinging a IPv6 host (which never included the IPv6
header size).
## New features
- The number of sent pings is only counted when the pings are received or have
timed out, ensuring that the loss ratio will be always correct. This makes it
possible, for example, to use loop mode (-l) with interval statistics (-Q)
and a timeout larger than period, without having the issue that initially
some pings would be reported as missing (#193)
- Improved precision of measurements from 10us to 1us (#136, thanks @tycho)
## Bugfixes and other changes
- The reported size of received packets is now always correct on Linux even for
packets > 4096 bytes (#180)
- Travis CI automated testing now also macos testing and additional ubuntu
distributions (#196)
fping 4.4 (2020-07-24)
======================
## Bugfixes and other changes
- Fix wrong ident used for normal (non-unprivileged) pings (#191, thanks @tycho)
- Fix build with --disable-ipv6 (#187, thanks Polynomial-C)
fping 4.3 (2020-07-11)
======================
## New features
- Linux unprivileged ping support (#173, thanks @tycho)
- Add SIGQUIT summary support similar to ping (#185, thanks @laddp)
## Bugfixes and other changes
- Corrected long option name of -s to --stats (#148, thanks @wopfel)
- Do not fail if using fping6 with -6 flag (#149, thanks @stromnet)
- Fail if interface binding (-I) does not work (#162, thanks @kbucheli)
- Fix using option -4 when fping is compiled IPv4-only (#154, thanks @pbhenson)
- Add Azure pipeline test build (#153 and #170, thanks @gsnw)
- GCC 10 compatibility fixes (#167 and #168, thanks @cranderson)
- Macos build fix (#174, thanks @tycho)
- Fix xmt stats in Netdata output (#172, thanks @vlvkobal)
- Only increase num_alive if response is not a duplicate (#151, thanks @brownowski)
- Use line buffering for stdout (#179, thanks @bg6cq)
fping 4.2 (2019-02-19)
======================
## New features
- New option -x / --reachable to check if the number of reachable hosts is >= a certain
number. Useful for example to implement connectivity-checks (#138, thanks @deepak0004)
## Bugfixes and other changes
- Allow decimal numbers for '-t', '-i', '-p', and '-Q'
- Fix build with --disable-ipv6 (#134, thanks @Polynomial-C)
- Fix hang with '-6', with ipv6 kernel module, but not loaded (#140, thanks @abelbeck)
- Assume '-6' if the binary is named 'fping6' (this is mostly for special
embedded-distro use cases, and not meant to be used generally in place of
compiling IPv6-only binary or using '-6', see also the notes in #139, thanks
abelbeck)
- Get rid of warning "timeout (-t) value larger than period (-p) produces unexpected results"
(#142, thanks @MrDragon1122)
fping 4.1 (2018-09-17)
======================
## Bugfixes and other changes
- Fix problem when socket fd is 0 (#125, thanks Ramón Novoa!)
- Fix running on servers with disabled IPv6 (#118, thanks Simon Matter)
- Allow running "fping -h" or "--help" even when raw socket can't be opened (#131, thanks @teto)
- Fix build issue with FreeBSD and IPv6 (#132, thanks @gsnw)
fping 4.0 (2017-04-23)
======================
## Incompatible Changes
##### fping and fping6 unification
fping and fping6 are now unified into one binary. It means that, for example,
doing 'fping google.com' is going to ping the IPv6 IP of google.com on
IPv6-enabled hosts.
If you need exact compatibility with old versions, you can configure and
install fping twice: once for ipv4, and once for ipv6:
./configure --disable-ipv6; make clean install
./configure --disable-ipv4 --program-suffix=6; make clean install
##### Option -n, not the same as -d anymore
Option -n / --name is now doing a reverse-DNS lookups on host addresses,
only if they are given as IP address, but not for hostnames. For example,
if you write 'fping -n google.com', fping would previously do a
forward-DNS lookup on google.com, and then a reverse-DNS lookup on the
resolved IP address. Now, it is just going to keep the name 'google.com'.
That same behavior can be achieved with the option -d / --rdns (which was
previously an alias for -n).
fping<4.0 fping>=4.0
fping -n NAME NAME->IP->IPNAME NAME
fping -d NAME NAME->IP->IPNAME NAME->IP->IPNAME
##### Discarding of late packets
fping will now discard replies, if they arrive after the defined timeout
for reply packets, specified with -t. This change is relevant only for the
count and loop modes, where the measured times should be now more
consistent (see github issue [#32][i32] for details).
To prevent loosing reply packets because of this change, the default
timeout in count and loop modes is now automatically adjusted to the
period interval (up to 2000 ms), but it can be overriden with the -t
option. The default timeout for non-loop/count modes remains 500 ms.
##### No restrictions by default
fping will not enforce -i >= 1 and -p >= 10 anymore, except if you
'./configure --enable-safe-limits'.
The reasoning to removing the restrictions by default, is that users can
clog the network with other tools anyway, and these restrictions are
sometimes getting in the way (for example if you try to ping a lot of
hosts).
##### Default interval (-i) changed from 25ms to 10ms
The default minimum interval between ping probes has been changed from
25ms to 10ms. The reason is that 25ms is very high, considering today's
fast networks: it generates at most 31 kbps of traffic (for IPv4 and
default payload size).
## New features
- Unified 'fping' and 'fping6' into one binary ([#80][i80])
- Long option names for all options
- IPv6 enabled by default
- New option -4 to force IPv4
- New option -6 to force IPv6
- Keep original name if a hostname is given with -n/--name
- Option -d/--rdns now always does a rdns-lookup, even for names, as '-n' was doing until now
- Enforce -t timeout on reply packets, by discarding late packets ([#32][i32])
- Auto-adjust timeout for -c/-C/-l mode to value of -p
## Bugfixes and other changes
- -i/-p restrictions disabled by default (enable with --enable-safe-limits)
- Default interval -i changed from 25ms to 10ms
- Fix compatibility issue with GNU Hurd
- A C99 compiler is now required
- Option parsing with optparse (https://github.com/skeeto/optparse). Thanks Christopher Wellons!
- New changelog file format
[i32]: https://github.com/schweikert/fping/issues/32
[i80]: https://github.com/schweikert/fping/issues/80
(see doc/CHANGELOG.pre-v4 for older changes)

@ -1,3 +1,7 @@
Unreleased (version 3 branch)
* Fix portability issue with GNU Hurd
* Fix C89 portability issue
2017-02-09 David Schweikert <david@schweikert.ch>
* Version 3.16
* (feature) Support kernel-timestamping of received packets (#46)
@ -20,7 +24,7 @@
2017-01-10 David Schweikert <david@schweikert.ch>
* Version 3.14
* (feature) Ignore network and broadcast for cidrs /31 and /32 (#102, Martin Topholm)
* (feature) New option '-M' to set the "Don't Fragment" flag (#91, Don Bowman)
* (feature) New option '-M' to set the "Don't Fragment" flag (#91, Don Bowman)
* (feature) New option '-N' to output statistics for netdata (see: http://my-netdata.io/, #105, Costa Tsaousis)
* (feature) New option '-o' to calculate total outage time (#90, @jgerbeck)
* (bugfix) Exit code should be 2 when the hostname can't be resolved
@ -154,7 +158,7 @@
* Removed unused variables from code
* updated to current autoconf standards
* Merged Debian changes (see below)
----------------------------------------------------------------------
fping (2.4b2-to-ipv6-16.1) unstable; urgency=low
@ -163,7 +167,7 @@ fping (2.4b2-to-ipv6-16.1) unstable; urgency=low
* Fixes FTBFS on kfreebsd (Closes: #555398)
* Fixes typo "Paramter" in binary
-- Axel Beckert <abe@deuxchevaux.org> Sat, 23 Jan 2010 16:22:02 +0100
-- Axel Beckert <abe@deuxchevaux.org> Sat, 23 Jan 2010 16:22:02 +0100
fping (2.4b2-to-ipv6-16) unstable; urgency=low
@ -318,45 +322,45 @@ Jeroen Massar
- Revision v2.4b2-to-IPv6
- Added IPv6 support.
- Added -I option for selecting source IPv4/IPv6 address.
- Makefile.in now generates a Makefile which will build both
- Makefile.in now generates a Makefile which will build both
fping (IPv4) and fping6 (IPv6). Thus it makes an fping (IPv4 only)
and an fping6 (IPv6 only).
- num_unreachable was counted twice when a sendto() generated errors.
- See http://unfix.org/projects/ipv6/
- See http://unfix.org/projects/ipv6/
Tue Mar 14 2001
Jason Ewasiuk <jasone@remote.net>
- Revision v2.4b1
- added -g option for generating IPs from a start to an end value
- two available options, generate IPs from start IP to end IP
or from a passed netmask, such as 192.168.1.0/24
- added -g option for generating IPs from a start to an end value
- two available options, generate IPs from start IP to end IP
or from a passed netmask, such as 192.168.1.0/24
Thu Feb 15 2001
Jason Ewasiuk <jasone@remote.net>
- Revision v2.3b1
- formatting changes to code layout (fping.c)
NOTE: Best viewed with a tab stop of 4
- merged in changes from Debian c/o Herbert Xu
<herbert@gondor.apana.org.au>
- Compilation fix on alphas with glibc
- Alignment issues (note from JE: in wait_for_reply())
- A typo with the time specified on the command line
(note from JE: bug was using 10 instead of 100)
- Drop privileges after obtaining socket
(note from JE: might be moot, since prog exits if
user is not root)
- touched all files in package to this date
- couple new #ifdefs added for future WIN32 support
(Haven't got to adding this yet, will take a lot of rewriting.)
- formatting changes to code layout (fping.c)
NOTE: Best viewed with a tab stop of 4
- merged in changes from Debian c/o Herbert Xu
<herbert@gondor.apana.org.au>
- Compilation fix on alphas with glibc
- Alignment issues (note from JE: in wait_for_reply())
- A typo with the time specified on the command line
(note from JE: bug was using 10 instead of 100)
- Drop privileges after obtaining socket
(note from JE: might be moot, since prog exits if
user is not root)
- touched all files in package to this date
- couple new #ifdefs added for future WIN32 support
(Haven't got to adding this yet, will take a lot of rewriting.)
Fri Dec 8 10:33:13 2000 Roland Schemers <schemers@stanford.edu>
* stop using sys_errlist and start using strerror
fixed bug in output of -C
* stop using sys_errlist and start using strerror
fixed bug in output of -C
Wed Jan 8 11:18:37 1997 Roland Schemers <schemers@stanford.edu>
* Created ChangeLog file. What follows was from the CHANGES file.
* Created ChangeLog file. What follows was from the CHANGES file.
* Revision 2.0 1994/10/31 21:26:23 morgan
@ -394,7 +398,7 @@ Wed Jan 8 11:18:37 1997 Roland Schemers <schemers@stanford.edu>
Took out setuid(getuid()) and used access() system call to
check for access to the file specified with "-f".
* Revision 1.21 1993/07/20 18:08:19 schemers
commented out the test to make sure the ping packet came from the
@ -442,7 +446,7 @@ modified the -s option to include min, max, and average round-trip times,
and over all elapsed time.
Modified action taken when a error is returned from sendto. The action
taken now considers the host unreachable and prints the hostname
taken now considers the host unreachable and prints the hostname
followed by the errno message. The program will not exit and will continue
to try other hosts.
@ -486,7 +490,7 @@ Changed usage to and stats to print to stderr instead of stdout.
RCS header info from original fping.c package (no longer required)
/*
/*
***************************************************
*
* Standard RCS Header information (see co(1))

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

@ -0,0 +1,55 @@
fping 3 README
--------------
fping is a program to send ICMP echo probes to network hosts, similar to ping,
but much better performing when pinging multiple hosts. fping has a long long
story: Roland Schemers did publish a first version of it in 1992 and it has
established itself since then as a standard tool.
Current maintainer:
David Schweikert <david@schweikert.ch>
Website:
http://fping.org/
Mailing-list:
https://groups.google.com/group/fping-users
Installation
------------
If you want to install fping from source, proceed as follows:
0. Run ./autogen.sh
(only if you got the source from github)
1. Run ./configure with the correct arguments
(see: ./configure --help)
2. Run make; make install
3. Make fping either setuid, or, if under Linux:
sudo setcap cap_net_raw+ep fping
4. Have a look at the fping(8) manual for usage help
(fping -h will also give a minimal help output)
IPv6 support
------------
You can can compile fping with support for IPv6 addresses. A separate binary
is used for that, called fping6. To build it, use ./configure --enable-ipv6
(possibly combined with --enable-ipv4 to also build fping for IPv4). E.g.:
# ./configure --prefix=/usr/local --enable-ipv4 --enable-ipv6
# make
# make install
# sudo setcap cap_net_raw+ep /usr/local/bin/fping*
Credits
-------
Original author: Roland Schemers (schemers@stanford.edu)
Previous maintainer: RL "Bob" Morgan (morgan@stanford.edu)
Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl)
Other contributors: see ChangeLog

@ -1,8 +1,8 @@
[![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)
# fping
# fping 3
fping is a program to send ICMP echo probes to network hosts, similar to ping,
but much better performing when pinging multiple hosts. fping has a long long
@ -13,7 +13,7 @@ _Current maintainer_:
David Schweikert \<david@schweikert.ch\>
_Website_:
https://fping.org/
http://fping.org/
_Mailing-list_:
https://groups.google.com/group/fping-users
@ -22,29 +22,32 @@ _Mailing-list_:
If you want to install fping from source, proceed as follows:
0. Run `./autogen.sh`
(only if you got the source from Github).
1. Run `./configure` with the correct arguments.
(see: `./configure --help`)
2. Run `make; make install`.
0. Run ./autogen.sh
(only if you got the source from github)
1. Run ./configure with the correct arguments
(see: ./configure --help)
2. Run make; make install
3. Make fping either setuid, or, if under Linux:
`sudo setcap cap_net_raw,cap_net_admin+ep fping`
If you can't run fping as root or can't use the cap_net_raw capability, you can
also run fping in unprivileged mode. This works on MacOS and also on Linux,
provided that your GID is included in the range defined in
`/proc/sys/net/ipv4/ping_group_range`. This is particularly useful for running
fping in rootless / unprivileged containers. The --fwmark option needs root or
cap_net_admin. setuid will not work for --fwmark.
sudo setcap cap_net_raw+ep fping
4. Have a look at the fping(8) manual for usage help
(fping -h will also give a minimal help output)
## Usage
Have a look at the [fping(8)](doc/fping.pod) manual page for usage help.
(`fping -h` will also give a minimal help output.)
See: [fping man-page](doc/fping.pod)
## Credits
## IPv6 support
You can can compile fping with support for IPv6 addresses. A separate binary
is used for that, called fping6. To build it, use ./configure --enable-ipv6
(possibly combined with --enable-ipv4 to also build fping for IPv4). E.g.:
* Original author: Roland Schemers (schemers@stanford.edu)
* Previous maintainer: RL "Bob" Morgan (morgan@stanford.edu)
* Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl)
* Other contributors: see [CHANGELOG.md](CHANGELOG.md)
# ./configure --prefix=/usr/local --enable-ipv4 --enable-ipv6
# make
# make install
# sudo setcap cap_net_raw+ep /usr/local/bin/fping*
## Credits
Original author: Roland Schemers (schemers@stanford.edu)
Previous maintainer: RL "Bob" Morgan (morgan@stanford.edu)
Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl)
Other contributors: see ChangeLog

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

@ -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
set -x
if [[ "$OSTYPE" == "darwin"* ]]; then
exit 0
fi
AUTOCONF=http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz
AUTOMAKE=http://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.gz
LIBTOOL=http://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz
AUTOCONF=http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
AUTOMAKE=http://ftp.gnu.org/gnu/automake/automake-1.14.1.tar.gz
LIBTOOL=http://alpha.gnu.org/gnu/libtool/libtool-2.4.2.418.tar.gz
PREFIX=$(pwd)/ci/build
PATH=$(pwd)/ci/build/bin:$PATH

@ -9,10 +9,11 @@ if [ ! -d ci ]; then
fi
autoreconf -i
./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping
make CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage"
./configure --enable-ipv4 --enable-ipv6 --prefix=/opt/fping
make CFLAGS="-g -fprofile-arcs -ftest-coverage"
## setcap currently doesn't work anymore on travis-ci
#sudo setcap cap_net_raw+ep src/fping
#sudo setcap cap_net_raw+ep src/fping6
## setcap debugging:
#pwd
#df -k .
@ -25,4 +26,6 @@ make CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage"
# use setuid, since setcap is not available
sudo chown root src/fping
sudo chown root src/fping6
sudo chmod u+s src/fping
sudo chmod u+s src/fping6

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

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

@ -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,7 +1,9 @@
#!/bin/bash
sudo setcap cap_net_raw,cap_net_admin+ep src/fping
sudo setcap cap_net_raw+ep src/fping
sudo setcap cap_net_raw+ep src/fping6
if [[ ! $PATH =~ fping/src ]]; then
PATH=/home/dws/checkouts/fping/src:$PATH
echo "# WARNING: must set PATH:"
echo PATH=/home/dws/checkouts/fping/src:\$PATH
fi

@ -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.5/8 alias
fi
if [[ ! $PATH =~ /Users/dws/checkouts/fping/src ]]; then
echo "# WARNING: must set PATH:"
echo PATH=/Users/dws/checkouts/fping/src:\$PATH
fi

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

@ -1,40 +1,68 @@
#!/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 if 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\.\.\.\]
$cmd1->stdout_is_eq(<<END);
Probing options:
.*
-v, --version show version
}s);
$cmd1->stderr_is_eq("");
# fping -4 -h (normal option parsing code path)
my $cmd4 = Test::Command->new(cmd => "fping -4 -h");
$cmd4->exit_is_num(0);
$cmd4->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\]
Usage: fping [options] [targets...]
-a show targets that are alive
-A show targets by address
-b n amount of ping data to send, in bytes (default 56)
-B f set exponential backoff factor to f
-c n count of pings to send to each target (default 1)
-C n same as -c, report results in verbose format
-D print timestamp before each output line
-e show elapsed time on return packets
-f file read list of targets from a file ( - means stdin) (only if no -g specified)
-g generate target list (only if no -f specified)
(specify the start and end IP in the target list, or supply a IP netmask)
(ex. fping -g 192.168.1.0 192.168.1.255 or fping -g 192.168.1.0/24)
-H n Set the IP TTL value (Time To Live hops)
-i n interval between sending ping packets (in millisec) (default 25)
${I_HELP} -l loop sending pings forever
-m use all IPs of provided hostnames (e.g. IPv4 and IPv6), use with -A
-M set the Don't Fragment flag
-n show targets by name (-d is equivalent)
-N output compatible for netdata (-l -Q are required)
-o show the accumulated outage time (lost packets * packet interval)
-O n set the type of service (tos) flag on the ICMP packets
-p n interval between ping packets to one target (in millisec)
(in looping and counting modes, default 1000)
-q quiet (don't show per-target/per-ping results)
-Q n same as -q, but show summary every n seconds
-r n number of retries (default 3)
-R random packet data (to foil link data compression)
-s print final stats
-S addr set source address
-t n individual target initial timeout (in millisec) (default 500)
-T n ignored (for compatibility with fping 2.4)
-u show targets that are unreachable
-v show version
targets list of targets to check (if no -f specified)
Probing options:
.*
-v, --version show version
}s);
$cmd4->stderr_is_eq("");
END
$cmd1->stderr_is_eq("");
# fping -v
my $cmd2 = Test::Command->new(cmd => "fping -v");
$cmd2->exit_is_num(0);
$cmd2->stdout_like(qr{fping: Version \S+});
$cmd2->stdout_like(qr{fping: Version \S+
fping: comments to david\@schweikert\.ch\n});
$cmd2->stderr_is_eq("");
# fping with unknown option
my $cmd3 = Test::Command->new(cmd => "fping -Z");
$cmd3->exit_is_num(1);
$cmd3->stdout_is_eq("");
$cmd3->stderr_like(qr{^fping: (illegal|invalid) option -- '?Z'?\nsee 'fping -h' for usage information\n$});
if($^O eq 'darwin') {
$cmd3->stderr_is_eq("fping: illegal option -- Z\nsee 'fping -h' for usage information\n");
}
else {
$cmd3->stderr_is_eq("fping: invalid option -- 'Z'\nsee 'fping -h' for usage information\n");
}

@ -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");
@ -24,7 +24,7 @@ END
my $cmd5 = Test::Command->new(cmd => "fping -H 300 127.0.0.1");
$cmd5->exit_is_num(1);
$cmd5->stdout_is_eq("");
$cmd5->stderr_is_eq("fping: ttl 300 out of range\n");
$cmd5->stderr_is_eq("ttl 300 out of range\n");
# fping -a -u
my $cmd6 = Test::Command->new(cmd => "fping -a -u 127.0.0.1");
@ -38,11 +38,11 @@ $cmd7->exit_is_num(1);
$cmd7->stdout_is_eq("");
$cmd7->stderr_is_eq("fping: specify only one of c, l\n");
# fping -b 65509
my $cmd8 = Test::Command->new(cmd => "fping -b 65509 127.0.0.1");
# fping -b 65489
my $cmd8 = Test::Command->new(cmd => "fping -b 65489 127.0.0.1");
$cmd8->exit_is_num(1);
$cmd8->stdout_is_eq("");
$cmd8->stderr_is_eq("fping: data size 65509 not valid, must be lower than 65488\n");
$cmd8->stderr_is_eq("fping: data size 65489 not valid, must be lower than 65488\n");
# fping -B 0.9
my $cmd9 = Test::Command->new(cmd => "fping -B 0.9 127.0.0.1");
@ -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,65 +1,14 @@
#!/usr/bin/perl -w
use Test::Command tests => 32;
use Test::Command tests => 14;
use Test::More;
use Time::HiRes qw(gettimeofday tv_interval);
# -4 only use IPv4 addresses
# -6 only use IPv6 addresses
# -a show targets that are alive
# -A show targets by address
# -b n amount of ping data to send, in bytes (default 56)
# -B f set exponential backoff factor to f
# fping -4 -6
{
my $cmd = Test::Command->new(cmd => "fping -4 -6 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: can't specify both -4 and -6\n");
}
# fping -6 -4
{
my $cmd = Test::Command->new(cmd => "fping -6 -4 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: can't specify both -4 and -6\n");
}
# fping -4
{
my $cmd = Test::Command->new(cmd => "fping -4 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("127.0.0.1 is alive\n");
$cmd->stderr_is_eq("");
}
{
my $cmd = Test::Command->new(cmd => "fping -4 ::1");
$cmd->exit_is_num(2);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{^::1:.*(not supported|not known)});
}
# fping -6
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -6 ::1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("::1 is alive\n");
$cmd->stderr_is_eq("");
}
{
my $cmd = Test::Command->new(cmd => "fping -6 127.0.0.1");
$cmd->exit_is_num(2);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{127\.0\.0\.1:.*(not supported|not known)});
}
# fping -a
{
my $cmd = Test::Command->new(cmd => "fping -a 127.0.0.1 127.0.0.2");
@ -70,7 +19,7 @@ $cmd->stderr_is_eq("");
# fping -A
{
my $cmd = Test::Command->new(cmd => "fping -4 -A localhost");
my $cmd = Test::Command->new(cmd => "fping -A localhost");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("127.0.0.1 is alive\n");
$cmd->stderr_is_eq("");
@ -85,17 +34,14 @@ $cmd->stderr_is_eq("");
}
# fping -B
SKIP: {
if($^O eq 'darwin') {
skip 'timing test not reliable on macOS', 5;
}
my $t0 = [gettimeofday];
my $cmd = Test::Command->new(cmd => "fping -t 100 -r 3 -B 2 8.8.8.7");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("8.8.8.7 is unreachable\n");
$cmd->stderr_like(qr{^(|(8.8.8.7: error while sending ping: No route to host\n)+)$});
my $elapsed = tv_interval($t0);
# 0.1 + 0.2 + 0.4 + 0.8 = 1.5
cmp_ok($elapsed, '>=', 1.5);
cmp_ok($elapsed, '<', 1.9);
{
my $t0 = [gettimeofday];
my $cmd = Test::Command->new(cmd => "fping -t 100 -r 3 -B 2 8.8.8.7");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("8.8.8.7 is unreachable\n");
$cmd->stderr_like(qr{^(|(8.8.8.7: error while sending ping: No route to host\n)+)$});
my $elapsed = tv_interval($t0);
# 0.1 + 0.2 + 0.4 + 0.8 = 1.5
cmp_ok($elapsed, '>=', 1.5);
cmp_ok($elapsed, '<', 1.8);
}

@ -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
@ -9,120 +9,31 @@ use Test::Command tests => 51;
# fping -c n
{
my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 localhost 127.0.0.1");
my $cmd = Test::Command->new(cmd => "fping -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->stdout_like(qr{localhost : \[0\], 84 bytes, 0\.\d+ ms \(0\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 84 bytes, 0\.\d+ ms \(0.\d+ avg, 0% loss\)
localhost : \[1\], 84 bytes, 0\.\d+ ms \(0\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 84 bytes, 0\.\d+ ms \(0\.\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+
127\.0\.0\.1 : 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 = 0\.\d+/0\.\d+/0\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = 0\.\d+/0\.\d+/0\.\d+
});
}
# fping -C n
{
my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1");
my $cmd = Test::Command->new(cmd => "fping -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->stdout_like(qr{localhost : \[0\], 84 bytes, 0\.\d+ ms \(0\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 84 bytes, 0\.\d+ ms \(0.\d+ avg, 0% loss\)
localhost : \[1\], 84 bytes, 0\.\d+ ms \(0\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 84 bytes, 0\.\d+ ms \(0\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
127\.0\.0\.1 : \d\.\d+ \d\.\d+
});
}
# fping -C n -q
{
my $cmd = Test::Command->new(cmd => "fping -C 5 -q -p 100 localhost");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{localhost :( \d\.\d+){5}
});
}
# fping -C n -a (-a is ignored)
{
my $cmd = Test::Command->new(cmd => "fping -a -C 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
127\.0\.0\.1 : \d\.\d+ \d\.\d+
});
}
# fping -C n -u (-u is ignored)
{
my $cmd = Test::Command->new(cmd => "fping -u -C 2 -p 100 localhost 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
127\.0\.0\.1 : \d\.\d+ \d\.\d+
});
}
# fping -C n -i -q
{
my $cmd = Test::Command->new(cmd => "fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{127\.0\.0\.1 :( \d\.\d+){20}
127\.0\.0\.2 :( \d\.\d+){20}
$cmd->stderr_like(qr{localhost : 0\.\d+ 0\.\d+
127\.0\.0\.1 : 0\.\d+ 0\.\d+
});
}
@ -130,82 +41,19 @@ $cmd->stderr_like(qr{127\.0\.0\.1 :( \d\.\d+){20}
{
my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\[\d+\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
\[\d+\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -D (timestamp not before 2001-09-09)
{
my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -D --timestamp-format=ctime
{
my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=ctime -c 2 -p 100 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -D --timestamp-format=iso
{
my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=iso -c 2 -p 100 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
$cmd->stdout_like(qr{\[\d{10}\.\d+\] 127\.0\.0\.1 : \[0\], 84 bytes, 0\.\d+ ms \(0.\d+ avg, 0% loss\)
\[\d{10}\.\d+\] 127\.0\.0\.1 : \[1\], 84 bytes, 0\.\d+ ms \(0\.\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 = 0\.\d+/0\.\d+/0\.\d+
});
}
# fping -D --timestamp-format=rfc3339
{
my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=rfc3339 -c 2 -p 100 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -D --timestamp-format
{
my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format -c 2 -p 100 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{Usage:});
}
# fping -D --timestamp-format="%Y-%m-%d %H:%M:%S"
{
my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=\"%Y-%m-%d %H:%M:%S\" -c 2 -p 100 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{Usage:});
}
# fping -e
{
my $cmd = Test::Command->new(cmd => "fping -e 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(\d\.\d+ ms\)
$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(0\.\d+ ms\)
});
$cmd->stderr_is_eq("");

@ -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,80 +61,12 @@ $cmd->stdout_is_eq("127.0.0.2 is alive\n127.0.0.3 is alive\n");
$cmd->stderr_is_eq("");
}
# fping -g (cidr - long prefixes: host)
{
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/32");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("127.0.0.2 is alive\n");
$cmd->stderr_is_eq("");
}
# fping -g (cidr - too long prefixes)
{
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/33");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 33)\n");
}
# fping -g (cidr - too short prefixes)
{
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/0");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 0)\n");
}
# fping -g (cidr - too many addresses)
{
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.0/8");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
}
# fping -g (range - no IPv6 generator)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 ::1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
}
# fping -g (range - no IPv6 generator - start address IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
}
# fping -g (range - no IPv6 generator - end address IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -6 -g 127.0.0.1 ::1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
}
# fping -g (CIDR - no IPv6 generator)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -6 -g ::1/128");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
$cmd->stderr_is_eq("Error: netmask must be between 1 and 32 (is: 33)\n");
}
# fping -H

@ -1,11 +1,10 @@
#!/usr/bin/perl -w
use Test::Command tests => 15;
use Test::Command tests => 7;
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
@ -20,55 +19,8 @@ $cmd->stderr_is_eq("");
# fping -l
{
my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1');
$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
});
}
# fping -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\)
$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 84 bytes, 0\.\d+ ms \(0.\d+ avg, 0% loss\)
127\.0\.0\.1 : \[1\], 84 bytes, 0\.\d+ ms \(0\.\d+ avg, 0% loss\)
});
}

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 36;
use Test::Command tests => 12;
# -n show targets by name (-d is equivalent)
# -O n set the type of service (tos) flag on the ICMP packets
@ -11,32 +11,11 @@ use Test::Command tests => 36;
# fping -n -> test-14-internet-hosts
# fping -d -n
{
my $cmd = Test::Command->new(cmd => "fping -d -n 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: use either one of -d or -n\n");
}
# fping -n -d
{
my $cmd = Test::Command->new(cmd => "fping -n -d 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: use either one of -d or -n\n");
}
# fping -o
{
my $cmd = Test::Command->new(cmd => "fping -t100 -p 100 -o -c 5 8.8.8.7");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("8.8.8.7 : [0], timed out (NaN avg, 100% loss)
8.8.8.7 : [1], timed out (NaN avg, 100% loss)
8.8.8.7 : [2], timed out (NaN avg, 100% loss)
8.8.8.7 : [3], timed out (NaN avg, 100% loss)
8.8.8.7 : [4], timed out (NaN avg, 100% loss)
");
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{^\s*8\.8\.8\.7 : xmt/rcv/%loss = 5/0/100%, outage\(ms\) = 50\d\s*$});
}
@ -53,7 +32,7 @@ $cmd->stderr_is_eq("");
my $cmd = Test::Command->new(cmd => "fping -q -p 100 -c 3 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = 0\.\d+/0\.\d+/0\.\d+
});
}
@ -63,86 +42,9 @@ my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 400 -c 4 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -Q (longer test to show two time stamps and reset statistics)
{
my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 550 -c 5 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -Q n ignores non-number characters after the number, except for keywords
{
my $cmd = Test::Command->new(cmd => "fping -Q 1whatever -p 550 -c 5 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -Q n ignores unknown keywords
{
my $cmd = Test::Command->new(cmd => "fping -Q 1,not_a_keyword -p 550 -c 5 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
});
}
# fping -Q n,cumulative
{
my $cmd = Test::Command->new(cmd => "fping -Q 1,cumulative -p 550 -c 5 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
\[\d+:\d+:\d+\]
127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = 0\.\d+/0\.\d+/0\.\d+
127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = 0\.\d+/0\.\d+/0\.\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 => 18;
use Test::More;
# -R random bytes
@ -19,10 +19,10 @@ $cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%.*});
}
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
if(system("/sbin/ifconfig | grep inet6") != 0) {
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 => "fping6 -q -R -c3 -p100 ::1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{::1 : xmt/rcv/%loss = 3/3/0%.*});
@ -46,10 +46,10 @@ $cmd->stderr_like(qr{\s*
\s*1 ICMP Echo Replies received
\s*0 other ICMP received
\s*\d\.\d+ ms \(min round trip time\)
\s*\d\.\d+ ms \(avg round trip time\)
\s*\d\.\d+ ms \(max round trip time\)
\s*\d\.\d+ sec \(elapsed real time\)
\s*0.\d+ ms \(min round trip time\)
\s*0.\d+ ms \(avg round trip time\)
\s*0.\d+ ms \(max round trip time\)
\s*0.\d+ sec \(elapsed real time\)
});
}
@ -69,10 +69,10 @@ $cmd->stderr_like(qr{\s*
\s*0 ICMP Echo Replies received
\s*0 other ICMP received
\s*\d\.\d+ ms \(min round trip time\)
\s*\d\.\d+ ms \(avg round trip time\)
\s*\d\.\d+ ms \(max round trip time\)
\s*\d\.\d+ sec \(elapsed real time\)
\s*0.\d+ ms \(min round trip time\)
\s*0.\d+ ms \(avg round trip time\)
\s*0.\d+ ms \(max round trip time\)
\s*0.\d+ sec \(elapsed real time\)
});
}
@ -84,42 +84,15 @@ $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
# fping6 -S
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'No IPv6 on this host', 3;
}
my $cmd = Test::Command->new(cmd => "fping -S ::1 ::1");
my $cmd = Test::Command->new(cmd => "fping6 -S ::1 ::1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("::1 is alive\n");
$cmd->stderr_is_eq("");
}
# fping -S (wrong IPv6 source address)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -S 2001:db8::1 ::1");
$cmd->exit_is_num(4);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{fping: cannot bind source address : .+\n});
}
# fping -S
{
my $cmd = Test::Command->new(cmd => "fping -S bla");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: can't parse source address: bla\n");
}
# (note: fping -t also tested in test-4-options-a-b.pl)
# fping -t tested in test-4-options-a-b.pl

@ -0,0 +1,24 @@
#!/usr/bin/perl -w
use Test::Command tests => 6;
# -u show targets that are unreachable
# -v show version
# fping -u
{
my $cmd = Test::Command->new(cmd => "fping -r0 -u 8.8.0.0 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("8.8.0.0\n");
$cmd->stderr_is_eq("");
}
# fping -v
{
my $cmd = Test::Command->new(cmd => "fping -v");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{ping: Version 3\.\d+(-rc\d+)?
fping: comments to david\@schweikert\.ch
});
$cmd->stderr_is_eq("");
}

@ -1,48 +0,0 @@
#!/usr/bin/perl -w
use Test::Command tests => 15;
# -u show targets that are unreachable
# -v show version
# -x shows if >=N hosts are reachable or not
# -X exits true immediately when N hosts are found
# fping -u
{
my $cmd = Test::Command->new(cmd => "fping -r0 -u 8.8.0.0 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("8.8.0.0\n");
$cmd->stderr_is_eq("");
}
# fping -v
{
my $cmd = Test::Command->new(cmd => "fping -v");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{ping: Version [45]\.\d+(-rc\d+)?});
$cmd->stderr_is_eq("");
}
# fping -x
{
my $cmd = Test::Command->new(cmd => "fping -x 1 8.8.0.0 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n");
$cmd->stderr_is_eq("");
}
# fping -x
{
my $cmd = Test::Command->new(cmd => "fping -x 2 8.8.0.0 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("Not enough hosts reachable (required: 2, reachable: 1)\n");
$cmd->stderr_is_eq("");
}
# fping -X
{
my $cmd = Test::Command->new(cmd => "fping -X 1 --generate 127.0.0.0/29");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n");
$cmd->stderr_is_eq("");
}

@ -0,0 +1,32 @@
#!/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 => 6;
# run without privileges
my $fping_bin = `which fping`; chomp $fping_bin;
my $fping6_bin = `which fping6`; chomp $fping6_bin;
system("cp $fping_bin /tmp/fping.copy; chmod +x /tmp/fping.copy");
system("cp $fping6_bin /tmp/fping6.copy; chmod +x /tmp/fping6.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\?\) : .*\n});
}
# fping6
{
my $cmd = Test::Command->new(cmd => "/tmp/fping6.copy ::1");
$cmd->exit_is_num(4);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{: can't create raw socket \(must run as root\?\) : .*\n});
}

@ -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");
$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:});
}
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:});
}

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
use Test::Command tests => 3;
use Test::Command tests => 6;
# fping
{
@ -9,3 +9,11 @@ $cmd->exit_is_num(2);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{^nosuchname\.example\.com: .*not (known|found)});
}
# fping6
{
my $cmd = Test::Command->new(cmd => "fping6 nosuchname.example.com");
$cmd->exit_is_num(2);
$cmd->stdout_is_eq("");
$cmd->stderr_like(qr{^nosuchname\.example\.com: .*not (known|found)});
}

@ -9,18 +9,19 @@ if(!gethostbyname("www.google.com")) {
exit 0;
}
plan tests => 30;
plan tests => 18;
my $re_num = qr{\d+(?:\.\d+)?};
# fping
{
my $cmd = Test::Command->new(cmd => "fping -q -i 10 -p 20 -c 3 -t200 8.8.8.8 www.france-telecom.fr www.google.com");
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->stdout_is_eq("");
$cmd->stderr_like(qr{8\.8\.8\.8\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
www\.france-telecom\.fr\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
www\.google\.com\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
$cmd->stderr_like(qr{8\.8\.8\.8\s*: xmt/rcv/%loss = [123]/3/\d+%, min/avg/max = $re_num/$re_num/$re_num
4\.2\.2\.5\s*: xmt/rcv/%loss = [123]/3/\d+%, min/avg/max = $re_num/$re_num/$re_num
www\.france-telecom\.fr\s*: xmt/rcv/%loss = [123]/3/\d+%, min/avg/max = $re_num/$re_num/$re_num
www\.google\.com\s*: xmt/rcv/%loss = [123]/3/\d+%, min/avg/max = $re_num/$re_num/$re_num
});
}
@ -28,69 +29,45 @@ www\.google\.com\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re
{
my $cmd = Test::Command->new(cmd => "fping -A -n 8.8.8.8");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("dns.google (8.8.8.8) is alive\n");
$cmd->stdout_is_eq("google-public-dns-a.google.com (8.8.8.8) is alive\n");
$cmd->stderr_is_eq("");
}
# fping -4 -A -n
{
my $cmd = Test::Command->new(cmd => "fping -4 -A -n dns.google");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{^dns.google \(8\.8\.(4\.4|8\.8)\) is alive\n$});
$cmd->stderr_is_eq("");
}
# fping -4 --addr --rdns
{
my $cmd = Test::Command->new(cmd => "fping -4 --addr --rdns www.apple.com");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{^\S+\.akamaitechnologies\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$});
$cmd->stderr_is_eq("");
}
# fping -4 --addr --name
# fping -A -n
{
my $cmd = Test::Command->new(cmd => "fping -4 --addr --name www.google.com");
my $cmd = Test::Command->new(cmd => "fping -A -n google-public-dns-a.google.com");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{^www\.google\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$});
$cmd->stdout_is_eq("google-public-dns-a.google.com (8.8.8.8) is alive\n");
$cmd->stderr_is_eq("");
}
# fping -A -n (IPv6)
# fping6 -A -n
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
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 => "fping6 -n -A 2001:4860:4860::8888");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{^dns.google \(2001:4860:4860::88(44|88)\) is alive\n$});
$cmd->stdout_is_eq("google-public-dns-a.google.com (2001:4860:4860::8888) is alive\n");
$cmd->stderr_is_eq("");
}
# fping -m
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -A -m dns.google");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{^.* is alive\n.* is alive\n.* is alive\n.* is alive\n});
$cmd->stderr_is_eq("");
}
# fping -m -A
{
my $cmd = Test::Command->new(cmd => "fping -4 -A -m www.cloudflare.com");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{\d+\.\d+\.\d+\.\d+ is alive\n\d+\.\d+\.\d+\.\d+ is alive\n});
$cmd->stderr_is_eq("");
}
#SKIP: {
# if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
# skip 'No IPv6 on this host', 3;
# }
# my $cmd = Test::Command->new(cmd => "fping -A -m google-public-dns-a.google.com");
# $cmd->exit_is_num(0);
# $cmd->stdout_is_eq("2001:4860:4860::8888 is alive\n8.8.8.8 is alive\n");
# $cmd->stderr_is_eq("");
#}
# fping -n
{
my $cmd = Test::Command->new(cmd => "fping -n 8.8.8.8");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("dns.google is alive\n");
$cmd->stdout_is_eq("google-public-dns-a.google.com is alive\n");
$cmd->stderr_is_eq("");
}

@ -9,27 +9,27 @@ 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
DIMENSION min minimum absolute 1 1000000
DIMENSION max maximum absolute 1 1000000
DIMENSION avg average absolute 1 1000000
CHART fping\.127_0_0_1_latency '' 'FPing Latency for host 127\.0\.0\.1' ms '127_0_0_1' fping\.latency area 110000 1
DIMENSION min minimum absolute 10 1000
DIMENSION max maximum absolute 10 1000
DIMENSION avg average absolute 10 1000
BEGIN fping\.127_0_0_1_latency
SET min = \d+
SET avg = \d+
SET max = \d+
SET min = \d{1,2}
SET avg = \d{1,2}
SET max = \d{1,2}
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 = 0.\d+/0.\d+/0.\d+});
}

@ -7,4 +7,4 @@ use Test::Command tests => 3;
my $cmd1 = Test::Command->new(cmd => "fping -a -g 2001:db8:120:4161::4/64");
$cmd1->exit_is_num(1);
$cmd1->stdout_is_eq("");
$cmd1->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
$cmd1->stderr_is_eq("Error: -g works only with IPv4 addresses\n");

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

@ -3,75 +3,43 @@ 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])
AC_INIT([fping],[3.16])
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 make ipv4 and ipv6 options
AC_ARG_ENABLE([ipv4],
AS_HELP_STRING([--disable-ipv4], [Disable support for pinging IPv4 hosts]))
AM_CONDITIONAL([IPV4], [test "x$enable_ipv4" != "xno"])
AM_COND_IF([IPV4], [AC_DEFINE([IPV4], [1], [IPv4 enabled])])
[ --enable-ipv4 Build IPv4 capable fping],
[case "${enableval}" in
yes) ipv4=true ;;
no) ipv4=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ipv4]) ;;
esac],[ipv4=true])
AM_CONDITIONAL([IPV4], [test x$ipv4 = xtrue])
dnl --disable-ipv6
AC_ARG_ENABLE([ipv6],
AS_HELP_STRING([--disable-ipv6], [Disable support for pinging IPv6 hosts]))
AS_IF([test "x$enable_ipv6" != "xno"], [
dnl Test if IPv6 is supported
AC_CHECK_HEADERS([netinet/icmp6.h], [have_ipv6="yes"], [], [[
#include <netinet/in.h>
#include <sys/types.h>
]])
])
dnl Can't disable both IPv4 and IPv6
AS_IF([test "x$enable_ipv4" = "xno" -a "x$enable_ipv6" = "xno"], [
AC_MSG_ERROR([Need to enable IPv4 or IPv6. Can't disable both!)])
])
dnl IPv6 required, but not supported?
AS_IF([test \( "x$enable_ipv6" = "xyes" -o "x$enable_ipv4" = "xno" \) -a "x$have_ipv6" != "xyes" ], [
AC_MSG_ERROR([IPv6 not supported on this platform (netinet/icmp6.h header not found)])
])
AM_CONDITIONAL([IPV6], [test "x$have_ipv6" = "xyes"])
AM_COND_IF([IPV6], [AC_DEFINE([IPV6], [1], [IPv6 enabled])])
[ --enable-ipv6 Build IPv6 capable fping6],
[case "${enableval}" in
yes) ipv6=true ;;
no) ipv6=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ipv6]) ;;
esac],[ipv6=false])
AM_CONDITIONAL([IPV6], [test x$ipv6 = xtrue])
if test x$ipv4 = xfalse && test x$ipv6 = xfalse; then
AC_MSG_ERROR([You must enable at least one of IPv4 and IPv6.])
fi
AC_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"], [
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], [set define])], [have_so_timestamp="no"], [#include <sys/types.h>
#include <sys/socket.h>])
])
dnl Test if --enable-timestamp is explicitely enabled and make an error if this platform doesn't support it
AS_IF([test "x$enable_timestamp" = "xyes" -a "x$have_so_timestamp" = "xno"], [
AC_MSG_ERROR([--enable-timestamp not supported on this platform])
])
AS_IF([test "x$only_clock_realtime" = "xyes"], [AC_DEFINE(ONLY_CLOCK_REALTIME, [1], [ONLY_CLOCK_REALTIME is defined])])
AC_ARG_ENABLE([safe-limits],
AS_HELP_STRING([--enable-safe-limits], [Restrict timing parameters (-i, -p) within "safe" limits]))
AS_IF([test "x$enable_safe_limits" = "xyes"], [
AC_DEFINE(FPING_SAFE_LIMITS, [1], [safe limits should be enforced])])
AC_ARG_ENABLE([debug],
AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@]), [enable_debug=$enableval], [enable_debug=no])
AS_IF([test "x$enable_debug" = "xyes"], [
AC_DEFINE([DEBUG], [1], [Define if debugging is enabled])])
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AM_MAINTAINER_MODE
@ -81,7 +49,6 @@ dnl Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O
m4_version_prereq([2.70],,[AC_PROG_CC_STDC])
AC_PROG_CPP
AC_PROG_INSTALL
@ -95,13 +62,6 @@ AC_CHECK_FUNC(connect)
if test $ac_cv_func_connect = no; then
AC_CHECK_LIB(socket, connect)
fi
AC_CHECK_FUNC(sigaction)
if test $ac_cv_func_sigaction = yes; then
AC_DEFINE([USE_SIGACTION],[1],[Define if sigaction is available.])
fi
AC_CHECK_FUNCS([strftime], [],
[AC_MSG_ERROR([strftime function is required but not found])])
AH_TOP([
#ifndef CONFIG_H
@ -120,7 +80,7 @@ AH_BOTTOM([
])
dnl Checks for header files.
AC_CHECK_HEADERS([unistd.h sys/file.h stdlib.h sys/select.h])
AC_CHECK_HEADERS(unistd.h sys/file.h stdlib.h sys/select.h getopt.h)
AC_CONFIG_FILES([Makefile
doc/Makefile

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

@ -1,8 +1,8 @@
Summary: send ICMP echo probes to multiple hosts
Name: fping
Version: 4.2
Version: 3.4
Release: 1
License: Freely redistributable without restriction
License: BSD with advertising
Group: Applications/System
Source0: http://fping.org/dist/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
@ -47,15 +47,14 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root,-)
%attr(4755, root, root) /usr/sbin/fping
%attr(4755, root, root) /usr/sbin/fping6
%doc README.md COPYING CHANGELOG.md
%doc README COPYING ChangeLog
/usr/share/man/man8/fping.8.gz
/usr/share/man/man8/fping6.8.gz
%post
if [ -x /usr/sbin/setcap ]; then
/bin/chmod 0755 /usr/sbin/fping*
/usr/sbin/setcap cap_net_raw,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*
fi
%changelog

@ -1,6 +1,17 @@
man_MANS = fping.8
man_MANS =
EXTRA_DIST = fping.8 fping.pod README.1992 CHANGELOG.pre-v4
if IPV4
man_MANS += fping.8
endif
if IPV6
man_MANS += fping6.8
endif
EXTRA_DIST = fping.8 fping6.8 fping.pod README.1992
fping.8: fping.pod
pod2man -c "" -s 8 -r "fping" $< >$@
fping6.8: fping.pod
pod2man -c "" -s 8 -r "fping" -n fping6 $< >$@

@ -4,7 +4,8 @@ fping - send ICMP ECHO_REQUEST packets to network hosts
=head1 SYNOPSIS
B<fping> [ I<options> ] [ I<systems...> ]
B<fping> [ I<options> ] [ I<systems...> ]
B<fping6> [ I<options> ] [ I<systems...> ]
=head1 DESCRIPTION
@ -19,31 +20,25 @@ of targets to check; if a target does not respond within a certain time limit
and/or retry limit it is designated as unreachable. B<fping> also supports
sending a specified number of pings to a target, or looping indefinitely (as in
B<ping> ). Unlike B<ping>, B<fping> is meant to be used in scripts, so its
output is designed to be easy to parse. Current statistics can be obtained without
termination of process with signal SIGQUIT (^\ from the keyboard on most systems).
output is designed to be easy to parse.
The binary named B<fping6> is the same as B<fping>, except that it uses IPv6
addresses instead of IPv4.
=head1 OPTIONS
=over 5
=item B<-4>, B<--ipv4>
Restrict name resolution and IPs to IPv4 addresses.
=item B<-6>, B<--ipv6>
Restrict name resolution and IPs to IPv6 addresses.
=item B<-a>, B<--alive>
=item B<-a>
Show systems that are alive.
Show systems that are alive.
=item B<-A>, B<--addr>
=item B<-A>
Display targets by address rather than DNS name. Combined with -d, the output
will be both the ip and (if available) the hostname.
=item B<-b>, B<--size>=I<BYTES>
=item B<-b> I<n>
Number of bytes of ping data to send. The minimum size (normally 12) allows
room for the data that B<fping> needs to do its work (sequence number,
@ -51,67 +46,56 @@ timestamp). The reported received data size includes the IP header (normally
20 bytes) and ICMP header (8 bytes), so the minimum total size is 40 bytes.
Default is 56, as in B<ping>. Maximum is the theoretical maximum IP datagram
size (64K), though most systems limit this to a smaller, system-dependent
number.
number.
=item B<-B>, B<--backoff>=I<N>
=item B<-B> I<n>
Backoff factor. In the default mode, B<fping> sends several requests to a
target before giving up, waiting longer for a reply on each successive request.
This parameter is the value by which the wait time (B<-t>) is multiplied on each
successive request; it must be entered as a floating-point number (x.y). The
default is 1.5.
default is 1.5.
=item B<-c>, B<--count>=I<N>
=item B<-c> I<n>
Number of request packets to send to each target. In this mode, a line is
displayed for each received response (this can suppressed with B<-q> or B<-Q>).
Also, statistics about responses for each target are displayed when all
requests have been sent (or when interrupted). This option overrides B<-a>
or B<-u>.
requests have been sent (or when interrupted).
=item B<-C>, B<--vcount>=I<N>
=item B<-C> I<n>
Similar to B<-c>, but the per-target statistics are displayed in a format
designed for automated response-time statistics gathering. For example:
designed for automated response-time statistics gathering. For example:
$ fping -C 5 -q somehost
somehost : 91.7 37.0 29.2 - 36.8
% fping -C 5 -q somehost
somehost : 91.7 37.0 29.2 - 36.8
shows the response time in milliseconds for each of the five requests, with the
C<-> indicating that no response was received to the fourth request. This
option overrides B<-a> or B<-u>.
C<-> indicating that no response was received to the fourth request.
=item B<-d>, B<--rdns>
=item B<-d>
Use DNS to lookup address of ping target. This allows you to give fping
a list of IP addresses as input and print hostnames in the output. This is similar
to option B<-n>/B<--name>, but will force a reverse-DNS lookup even if you give
hostnames as target (NAME->IP->NAME).
Use DNS to lookup address of return ping packet. This allows you to give fping
a list of IP addresses as input and print hostnames in the output.
=item B<-D>, B<--timestamp>
=item B<-D>
Add Unix timestamps in front of output lines generated with in looping or counting
modes (B<-l>, B<-c>, or B<-C>).
Subcommand: B<--timestamp-format>=I<ctime|iso|rfc3339>
=item B<-e>
Allow to change the timestamp format of the B<-D> option to the following format types.
Show elapsed (round-trip) time of packets.
I<ctime> = "%c" (Example: Mon Jun 10 07:50:00 2024)
=item B<-f>
I<iso> = "%Y-%m-%dT%T%z" (Example: 2024-06-10T07:50:00+0200)
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:
I<rfc3339> = "%Y-%m-%d %H:%M:%S" (Example: 2024-06-10 07:50:00)
% fping < targets_file
=item B<-e>, B<--elapsed>
Show elapsed (round-trip) time of packets.
=item B<-f>, B<--file>
Read list of targets from a file.
=item B<-g>, B<--generate> I<addr/mask>
=item B<-g> I<addr/mask>
Generate a target list from a supplied IP netmask, or a starting and ending IP.
Specify the netmask or start/end in the targets portion of the command line. If
@ -119,147 +103,123 @@ a network with netmask is given, the network and broadcast addresses will be
excluded. ex. To ping the network 192.168.1.0/24, the specified command line
could look like either:
$ fping -g 192.168.1.0/24
fping -g 192.168.1.0/24
or
or
$ fping -g 192.168.1.1 192.168.1.254
fping -g 192.168.1.1 192.168.1.254
=item B<-h>, B<--help>
=item B<-h>
Print usage message.
=item B<-H>, B<--ttl>=I<N>
Set the IP TTL field (time to live hops).
=item B<-i>, B<--interval>=I<MSEC>
=item B<-i> I<n>
The minimum amount of time (in milliseconds) between sending a ping packet
to any target (default is 10, minimum is 1).
=item B<-I>, B<--iface>=I<IFACE>
Set the interface (requires SO_BINDTODEVICE support).
=item B<-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.
to any target (default is 25, minimum is 1).
=item B<-l>, B<--loop>
=item B<-l>
Loop sending packets to each target indefinitely. Can be interrupted with
Ctrl-C; statistics about responses for each target are then displayed.
Ctrl-C; statistics about responses for each target are then displayed.
=item B<-m>, B<--all>
=item B<-m>
Send pings to each of a target host's multiple IP addresses (use of option '-A'
is recommended).
=item B<-M>, B<--dontfrag>
=item B<-M>
Set the "Don't Fragment" bit in the IP header (used to determine/test the MTU).
=item B<-n>, B<--name>
=item B<-n>
If targets are specified as IP addresses, do a reverse-DNS lookup on them
to print hostnames in the output.
Same as -d.
=item B<-N>, B<--netdata>
=item B<-N>
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>
Calculate "outage time" based on the number of lost pings and the interval used (useful for network convergence tests).
=item B<-O>, B<--tos>=I<N>
=item B<-O> I<n>
Set the typ of service flag (TOS). I<N> can be either decimal or hexadecimal
(0xh) format.
Set the typ of service flag (TOS). I<n> can be either decimal or hexadecimal
(0xh) format.
=item B<-p>, B<--period>=I<MSEC>
=item B<-p> <n>
In looping or counting modes (B<-l>, B<-c>, or B<-C>), this parameter sets
the time in milliseconds that B<fping> waits between successive packets to
an individual target. Default is 1000 and minimum is 10.
=item B<-q>, B<--quiet>
=item B<-q>
Quiet. Don't show per-probe results, but only the final summary. Also don't
show ICMP error messages.
=item B<-Q>, B<--squiet>=I<SECS[,cumulative]>
=item B<-Q> I<n>
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.
Like B<-q>, but show summary results every n seconds.
=item B<-r>, B<--retry>=I<N>
=item B<-r> I<n>
Retry limit (default 3). This is the number of times an attempt at pinging
a target will be made, not including the first try.
a target will be made, not including the first try.
=item B<-R>, B<--random>
=item B<-R>
Instead of using all-zeros as the packet data, generate random bytes.
Use to defeat, e.g., link data compression.
=item B<-s>, B<--stats>
=item B<-s>
Print cumulative statistics upon exit.
Print cumulative statistics upon exit.
=item B<-S>, B<--src>=I<addr>
=item B<-S> I<addr>
Set source address.
Set source address.
=item B<-t>, B<--timeout>=I<MSEC>
=item B<-I> I<if>
Initial target timeout in milliseconds. In the default, non-loop mode, the
default timeout is 500ms, and it represents the amount of time that B<fping>
waits for a response to its first request. Successive timeouts are multiplied
by the backoff factor specified with B<-B>.
Set the interface (requires SO_BINDTODEVICE support)
In loop/count mode, the default timeout is automatically adjusted to match
the "period" value (but not more than 2000ms). You can still adjust the timeout
value with this option, if you wish to, but note that setting a value larger
than "period" produces inconsistent results, because the timeout value can
be respected only for the last ping.
=item B<-t> I<n>
Also note that any received replies that are larger than the timeout value, will
be discarded.
Initial target timeout in milliseconds (default 500). In the default mode, this
is the amount of time that B<fping> waits for a response to its first request.
Successive timeouts are multiplied by the backoff factor specified with B<-B>.
Note that this option has no effect looping or counting modes (B<-l>, B<-c>, or
B<-C>).
=item B<-T> I<n>
Ignored (for compatibility with fping 2.4).
Ignored (for compatibility with fping 2.4).
=item B<-u>, B<--unreach>
=item B<-u>
Show targets that are unreachable.
Show targets that are unreachable.
=item B<-v>, B<--version>
=item B<-v>
Print B<fping> version information.
Print B<fping> version information.
=item B<-x>, B<--reachable>=I<N>
=item B<-H> I<n>
Given a list of hosts, this mode checks if number of reachable hosts is >= N
and exits true in that case.
=item B<-X>, B<--fast-reachable>=I<N>
Given a list of hosts, this mode immediately exits true once N alive hosts
have been found.
Set the IP TTL field (time to live hops).
=back
=head1 EXAMPLES
Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to
each host), and report every ping RTT at the end:
Generate ~1000 pings per second to a host until canceled, printing statistics
on the fly at one second intervals, and printing statistics at the end:
$ fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2
# fping -s -l -i 1 -p 1 -T 1 -Q 1 127.0.0.1
Note that ping intervals less than 1ms can only be used as root.
=head1 AUTHORS
@ -287,19 +247,14 @@ 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:
In order to avoid users mistakingly flooding the network, the following values
are not allowed for non-root users:
=over 4

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

@ -1,11 +1,18 @@
AM_CFLAGS = -Wall -Wextra -Wno-sign-compare
sbin_PROGRAMS = fping
fping_SOURCES = fping.c seqmap.c socket4.c fping.h options.h seqmap.h optparse.c optparse.h
fping_DEPENDENCIES = ../config.h
prog =
if IPV4
prog += fping
endif
if IPV6
fping_SOURCES += socket6.c
fping_CFLAGS = $(AM_CFLAGS) -DIPV6
prog += fping6
endif
sbin_PROGRAMS = ${prog}
fping_SOURCES = fping.c seqmap.c socket.c socket4.c fping.h options.h seqmap.h
fping_DEPENDENCIES = ../config.h
fping6_SOURCES = fping.c seqmap.c socket.c socket6.c fping.h options.h seqmap.h
fping6_DEPENDENCIES = ../config.h
fping6_CFLAGS = $(AM_CFLAGS) -DIPV6

File diff suppressed because it is too large Load Diff

@ -7,33 +7,24 @@
#include <sys/types.h>
#include <netinet/in.h>
/* this requires variadic macros, part of C99 */
#if (defined(DEBUG) || defined(_DEBUG))
extern int64_t current_time_ns;
extern int trace_flag;
#define dbg_printf(fmt, ...) do { if (trace_flag) { fprintf(stderr, "[%10.5f] ", (double)(current_time_ns / 1000)/1000000); fprintf(stderr, fmt, __VA_ARGS__); } } while (0)
#ifndef IPV6
#define FPING_INADDR struct in_addr
#define FPING_ICMPHDR struct icmp
#else
#define dbg_printf(fmt, ...)
#define FPING_INADDR struct in6_addr
#define FPING_ICMPHDR struct icmp6_hdr
#endif
/* fping.c */
void crash_and_burn( char *message );
void errno_crash_and_burn( char *message );
int in_cksum( unsigned short *p, int n );
extern int nonzero_payload_flag;
int random_data_flag;
/* socket.c */
int open_ping_socket_ipv4(int *socktype);
void init_ping_buffer_ipv4(size_t ping_data_size);
void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr, int *ident);
int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
#ifdef IPV6
int open_ping_socket_ipv6(int *socktype);
void init_ping_buffer_ipv6(size_t ping_data_size);
void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr, int *ident);
int socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
#endif
int open_ping_socket();
void init_ping_buffer(size_t ping_data_size);
void socket_set_src_addr(int s, FPING_INADDR src_addr);
int socket_sendto_ping(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
#endif

@ -1 +0,0 @@
ctags -R --fields=+S /usr/include ..

@ -20,7 +20,7 @@
/* constants */
#ifndef DEFAULT_INTERVAL
#define DEFAULT_INTERVAL 10 /* default time between packets (msec) */
#define DEFAULT_INTERVAL 25 /* default time between packets (msec) */
#endif
#ifndef DEFAULT_PERHOST_INTERVAL /* default time between packets */
@ -29,7 +29,6 @@
#ifndef DEFAULT_TIMEOUT
#define DEFAULT_TIMEOUT 500 /* individual host timeouts */
#define AUTOTUNE_TIMEOUT_MAX 2000
#endif

@ -1,266 +0,0 @@
#include "optparse.h"
#define MSG_INVALID "invalid option"
#define MSG_MISSING "option requires an argument"
#define MSG_TOOMANY "option takes no arguments"
static int
opterror(struct optparse *options, const char *message, const char *data)
{
unsigned p = 0;
while (*message)
options->errmsg[p++] = *message++;
const char *sep = " -- '";
while (*sep)
options->errmsg[p++] = *sep++;
while (p < sizeof(options->errmsg) - 2 && *data)
options->errmsg[p++] = *data++;
options->errmsg[p++] = '\'';
options->errmsg[p++] = '\0';
return '?';
}
void optparse_init(struct optparse *options, char **argv)
{
options->argv = argv;
options->permute = 1;
options->optind = 1;
options->subopt = 0;
options->optarg = 0;
options->errmsg[0] = '\0';
}
static inline int
is_dashdash(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
}
static inline int
is_shortopt(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
}
static inline int
is_longopt(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
}
static void
permute(struct optparse *options, int index)
{
char *nonoption = options->argv[index];
for (int i = index; i < options->optind - 1; i++)
options->argv[i] = options->argv[i + 1];
options->argv[options->optind - 1] = nonoption;
}
static int
argtype(const char *optstring, char c)
{
if (c == ':')
return -1;
for (; *optstring && c != *optstring; optstring++);
if (!*optstring)
return -1;
int count = OPTPARSE_NONE;
if (optstring[1] == ':')
count += optstring[2] == ':' ? 2 : 1;
return count;
}
int optparse(struct optparse *options, const char *optstring)
{
options->errmsg[0] = '\0';
options->optopt = 0;
options->optarg = 0;
char *option = options->argv[options->optind];
if (option == 0) {
return -1;
} else if (is_dashdash(option)) {
options->optind++; /* consume "--" */
return -1;
} else if (!is_shortopt(option)) {
if (options->permute) {
int index = options->optind;
options->optind++;
int r = optparse(options, optstring);
permute(options, index);
options->optind--;
return r;
} else {
return -1;
}
}
option += options->subopt + 1;
options->optopt = option[0];
int type = argtype(optstring, option[0]);
char *next = options->argv[options->optind + 1];
switch (type) {
case -1: {
options->optind++;
char str[2] = {option[0]};
return opterror(options, MSG_INVALID, str);
}
case OPTPARSE_NONE:
if (option[1]) {
options->subopt++;
} else {
options->subopt = 0;
options->optind++;
}
return option[0];
case OPTPARSE_REQUIRED:
options->subopt = 0;
options->optind++;
if (option[1]) {
options->optarg = option + 1;
} else if (next != 0) {
options->optarg = next;
options->optind++;
} else {
options->optarg = 0;
char str[2] = {option[0]};
return opterror(options, MSG_MISSING, str);
}
return option[0];
case OPTPARSE_OPTIONAL:
options->subopt = 0;
options->optind++;
if (option[1])
options->optarg = option + 1;
else
options->optarg = 0;
return option[0];
}
return 0;
}
char *optparse_arg(struct optparse *options)
{
options->subopt = 0;
char *option = options->argv[options->optind];
if (option != 0)
options->optind++;
return option;
}
static inline int
longopts_end(const struct optparse_long *longopts, int i)
{
return !longopts[i].longname && !longopts[i].shortname;
}
static void
optstring_from_long(const struct optparse_long *longopts, char *optstring)
{
char *p = optstring;
for (int i = 0; !longopts_end(longopts, i); i++) {
if (longopts[i].shortname) {
*p++ = longopts[i].shortname;
for (int a = 0; a < (int)longopts[i].argtype; a++)
*p++ = ':';
}
}
*p = '\0';
}
/* Unlike strcmp(), handles options containing "=". */
static int
longopts_match(const char *longname, const char *option)
{
if (longname == 0)
return 0;
const char *a = option, *n = longname;
for (; *a && *n && *a != '='; a++, n++)
if (*a != *n)
return 0;
return *n == '\0' && (*a == '\0' || *a == '=');
}
/* Return the part after "=", or NULL. */
static char *
longopts_arg(char *option)
{
for (; *option && *option != '='; option++);
if (*option == '=')
return option + 1;
else
return 0;
}
static int
long_fallback(struct optparse *options,
const struct optparse_long *longopts,
int *longindex)
{
char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
optstring_from_long(longopts, optstring);
int result = optparse(options, optstring);
if (longindex != 0) {
*longindex = -1;
if (result != -1)
for (int i = 0; !longopts_end(longopts, i); i++)
if (longopts[i].shortname == options->optopt)
*longindex = i;
}
return result;
}
int
optparse_long(struct optparse *options,
const struct optparse_long *longopts,
int *longindex)
{
char *option = options->argv[options->optind];
if (option == 0) {
return -1;
} else if (is_dashdash(option)) {
options->optind++; /* consume "--" */
return -1;
} else if (is_shortopt(option)) {
return long_fallback(options, longopts, longindex);
} else if (!is_longopt(option)) {
if (options->permute) {
int index = options->optind;
options->optind++;
int r = optparse_long(options, longopts, longindex);
permute(options, index);
options->optind--;
return r;
} else {
return -1;
}
}
/* Parse as long option. */
options->errmsg[0] = '\0';
options->optopt = 0;
options->optlongname = 0;
options->optarg = 0;
option += 2; /* skip "--" */
options->optind++;
for (int i = 0; !longopts_end(longopts, i); i++) {
const char *name = longopts[i].longname;
if (longopts_match(name, option)) {
options->optlongname = option;
if (longindex)
*longindex = i;
options->optopt = longopts[i].shortname;
char *arg = longopts_arg(option);
if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
return opterror(options, MSG_TOOMANY, name);
} if (arg != 0) {
options->optarg = arg;
} else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
options->optarg = options->argv[options->optind++];
if (options->optarg == 0)
return opterror(options, MSG_MISSING, name);
}
return options->optopt;
}
}
return opterror(options, MSG_INVALID, option);
}

@ -1,103 +0,0 @@
#ifndef OPTPARSE_H
#define OPTPARSE_H
/**
* Optparse -- portable, reentrant, embeddable, getopt-like option parser
*
* The POSIX getopt() option parser has three fatal flaws. These flaws
* are solved by Optparse.
*
* 1) Parser state is stored entirely in global variables, some of
* which are static and inaccessible. This means only one thread can
* use getopt(). It also means it's not possible to recursively parse
* nested sub-arguments while in the middle of argument parsing.
* Optparse fixes this by storing all state on a local struct.
*
* 2) The POSIX standard provides no way to properly reset the parser.
* This means for portable code that getopt() is only good for one
* run, over one argv with one optstring. It also means subcommand
* options cannot be processed with getopt(). Most implementations
* provide a method to reset the parser, but it's not portable.
* Optparse provides an optparse_arg() function for stepping over
* subcommands and continuing parsing of options with another
* optstring. The Optparse struct itself can be passed around to
* subcommand handlers for additional subcommand option parsing. A
* full reset can be achieved by with an additional optparse_init().
*
* 3) Error messages are printed to stderr. This can be disabled with
* opterr, but the messages themselves are still inaccessible.
* Optparse solves this by writing an error message in its errmsg
* field. The downside to Optparse is that this error message will
* always be in English rather than the current locale.
*
* Optparse should be familiar with anyone accustomed to getopt(), and
* it could be a nearly drop-in replacement. The optstring is the same
* and the fields have the same names as the getopt() global variables
* (optarg, optind, optopt).
*
* Optparse also supports GNU-style long options with optparse_long().
* The interface is slightly different and simpler than getopt_long().
*
* By default, argv is permuted as it is parsed, moving non-option
* arguments to the end. This can be disabled by setting the `permute`
* field to 0 after initialization.
*/
struct optparse {
char **argv;
int permute;
int optind;
int optopt;
char *optlongname;
char *optarg;
char errmsg[64];
int subopt;
};
enum optparse_argtype { OPTPARSE_NONE, OPTPARSE_REQUIRED, OPTPARSE_OPTIONAL };
struct optparse_long {
const char *longname;
int shortname;
enum optparse_argtype argtype;
};
/**
* Initializes the parser state.
*/
void optparse_init(struct optparse *options, char **argv);
/**
* Read the next option in the argv array.
* @param optstring a getopt()-formatted option string.
* @return the next option character, -1 for done, or '?' for error
*
* Just like getopt(), a character followed by no colons means no
* argument. One colon means the option has a required argument. Two
* colons means the option takes an optional argument.
*/
int optparse(struct optparse *options, const char *optstring);
/**
* Handles GNU-style long options in addition to getopt() options.
* This works a lot like GNU's getopt_long(). The last option in
* longopts must be all zeros, marking the end of the array. The
* longindex argument may be NULL.
*/
int
optparse_long(struct optparse *options,
const struct optparse_long *longopts,
int *longindex);
/**
* Used for stepping over non-option arguments.
* @return the next non-option argument, or NULL for no more arguments
*
* Argument parsing can continue with optparse() after using this
* function. That would be used to parse the options for the
* subcommand returned by optparse_arg(). This function allows you to
* ignore the value of optind.
*/
char *optparse_arg(struct optparse *options);
#endif

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

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

@ -0,0 +1,79 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "config.h"
#include "fping.h"
int open_ping_socket_ipv4();
int open_ping_socket_ipv6();
void init_ping_buffer_ipv4(size_t ping_data_size);
void init_ping_buffer_ipv6(size_t ping_data_size);
void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr);
void socket_set_src_addr_ipv6(int s, FPING_INADDR src_addr);
int socket_sendto_ping_ipv4(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);
int open_ping_socket()
{
#ifndef IPV6
return open_ping_socket_ipv4();
#else
return open_ping_socket_ipv6();
#endif
}
void init_ping_buffer(size_t ping_data_size)
{
#ifndef IPV6
return init_ping_buffer_ipv4(ping_data_size);
#else
return init_ping_buffer_ipv6(ping_data_size);
#endif
}
void socket_set_src_addr(int s, FPING_INADDR src_addr)
{
#ifndef IPV6
socket_set_src_addr_ipv4(s, src_addr);
#else
socket_set_src_addr_ipv6(s, src_addr);
#endif
}
int socket_sendto_ping(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
{
#ifndef IPV6
return socket_sendto_ping_ipv4(s, saddr, saddr_len, icmp_seq_nr, icmp_id_nr);
#else
return socket_sendto_ping_ipv6(s, saddr, saddr_len, icmp_seq_nr, icmp_id_nr);
#endif
}

@ -44,10 +44,10 @@
#include <string.h>
#include <sys/socket.h>
char* ping_buffer_ipv4 = 0;
size_t ping_pkt_size_ipv4;
char* ping_buffer = 0;
size_t ping_pkt_size;
int open_ping_socket_ipv4(int *socktype)
int open_ping_socket_ipv4()
{
struct protoent* proto;
int s;
@ -57,14 +57,12 @@ int open_ping_socket_ipv4(int *socktype)
crash_and_burn("icmp: unknown protocol");
/* create raw socket for ICMP calls (ping) */
*socktype = SOCK_RAW;
s = socket(AF_INET, *socktype, proto->p_proto);
s = socket(AF_INET, SOCK_RAW, proto->p_proto);
if (s < 0) {
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
*socktype = SOCK_DGRAM;
s = socket(AF_INET, *socktype, proto->p_proto);
s = socket(AF_INET, SOCK_DGRAM, proto->p_proto);
if (s < 0) {
return -1;
errno_crash_and_burn("can't create socket (must run as root?)");
}
}
@ -85,31 +83,21 @@ int open_ping_socket_ipv4(int *socktype)
void init_ping_buffer_ipv4(size_t ping_data_size)
{
/* allocate ping buffer */
ping_pkt_size_ipv4 = ping_data_size + ICMP_MINLEN;
ping_buffer_ipv4 = (char*)calloc(1, ping_pkt_size_ipv4);
if (!ping_buffer_ipv4)
ping_pkt_size = ping_data_size + ICMP_MINLEN;
ping_buffer = (char*)calloc(1, ping_pkt_size);
if (!ping_buffer)
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, FPING_INADDR src_addr)
{
struct sockaddr_in sa;
socklen_t len = sizeof(sa);
memset(&sa, 0, len);
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr = *src_addr;
if (bind(s, (struct sockaddr*)&sa, len) < 0)
errno_crash_and_burn("cannot bind source address");
if (ident) {
memset(&sa, 0, len);
if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
errno_crash_and_burn("can't get ICMP socket identity");
sa.sin_addr = src_addr;
if (sa.sin_port)
*ident = sa.sin_port;
}
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
errno_crash_and_burn("cannot bind source address");
}
unsigned short calcsum(unsigned short* buffer, int length)
@ -133,28 +121,24 @@ 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;
icp = (struct icmp*)ping_buffer;
icp->icmp_type = ICMP_ECHO;
icp->icmp_code = 0;
icp->icmp_cksum = 0;
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;
icp->icmp_id = htons(icmp_id_nr);
if (random_data_flag) {
for (n = ((void*)&icp->icmp_data - (void*)icp); n < ping_pkt_size; ++n) {
ping_buffer[n] = random() & 0xFF;
}
}
icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size_ipv4);
icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size);
n = sendto(s, icp, ping_pkt_size_ipv4, 0, saddr, saddr_len);
n = sendto(s, icp, ping_pkt_size, 0, saddr, saddr_len);
return n;
}

@ -43,27 +43,25 @@
#include <netinet/icmp6.h>
char* ping_buffer_ipv6 = 0;
size_t ping_pkt_size_ipv6;
char* ping_buffer = 0;
size_t ping_pkt_size;
int open_ping_socket_ipv6(int *socktype)
int open_ping_socket_ipv6()
{
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) */
*socktype = SOCK_RAW;
s = socket(AF_INET6, *socktype, proto->p_proto);
/* create raw socket for ICMP calls (ping) */
s = socket(AF_INET6, SOCK_RAW, proto->p_proto);
if (s < 0) {
/* try non-privileged icmp6 (works on Mac OSX without privileges, for example) */
*socktype = SOCK_DGRAM;
s = socket(AF_INET6, *socktype, proto->p_proto);
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
s = socket(AF_INET6, SOCK_DGRAM, proto->p_proto);
if (s < 0) {
return -1;
errno_crash_and_burn("can't create raw socket (must run as root?)");
}
}
@ -84,54 +82,43 @@ int open_ping_socket_ipv6(int *socktype)
void init_ping_buffer_ipv6(size_t ping_data_size)
{
/* allocate ping buffer */
ping_pkt_size_ipv6 = ping_data_size + sizeof(struct icmp6_hdr);
ping_buffer_ipv6 = (char*)calloc(1, ping_pkt_size_ipv6);
if (!ping_buffer_ipv6)
ping_pkt_size = ping_data_size + sizeof(struct icmp6_hdr);
ping_buffer = (char*)calloc(1, ping_pkt_size);
if (!ping_buffer)
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, FPING_INADDR src_addr)
{
struct sockaddr_in6 sa;
socklen_t len = sizeof(sa);
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6;
sa.sin6_addr = *src_addr;
sa.sin6_addr = src_addr;
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
errno_crash_and_burn("cannot bind source address");
if (ident) {
memset(&sa, 0, len);
if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
errno_crash_and_burn("can't get ICMP6 socket identity");
if (sa.sin6_port)
*ident = sa.sin6_port;
}
}
int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
{
struct icmp6_hdr* icp;
int n;
size_t i;
icp = (struct icmp6_hdr*)ping_buffer_ipv6;
icp = (struct icmp6_hdr*)ping_buffer;
icp->icmp6_type = ICMP6_ECHO_REQUEST;
icp->icmp6_code = 0;
icp->icmp6_seq = htons(icmp_seq_nr);
icp->icmp6_id = icmp_id_nr;
icp->icmp6_id = htons(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; ++n) {
ping_buffer[n] = random() & 0xFF;
}
}
icp->icmp6_cksum = 0; /* The IPv6 stack calculates the checksum for us... */
n = sendto(s, icp, ping_pkt_size_ipv6, 0, saddr, saddr_len);
n = sendto(s, icp, ping_pkt_size, 0, saddr, saddr_len);
return n;
}

@ -0,0 +1 @@
gcc -DHAVE_CONFIG_H -D_BSD_SOURCE -D_POSIX_SOURCE -I.. -Wall -std=c89 -pedantic -c -o fping.o fping.c
Loading…
Cancel
Save