From: David Schweikert Date: Tue, 19 Aug 2025 08:05:27 +0000 (+0200) Subject: Fix changelog entry for the new -p lower limit X-Git-Tag: v5.4 X-Git-Url: https://git.gsnw.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b6f26e25a9ce501555ba3f1ad6541774c65dec0;p=fping.git Fix changelog entry for the new -p lower limit --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cd88bc..07434d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,9 @@ fping 5.4 (2025-08-19) - Memory allocation safety checks for event storage (thanks David.A for bug report) - Fix off-by-one boundary check in seqmap code (thanks David.A for bug report) -- The minimum value for the per-host interval (-i flag) is now 0.001 (milliseconds), - since it probably never makes sense to use a smaller value, and to avoid trying - to do a too large memory allocation. +- The minimum value for the period (-p flag) is now 0.001 milliseconds, + since it probably never makes sense to use a smaller value, and to avoid doing + a very large memory allocation for event storage. fping 5.3 (2025-01-02) ====================== diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/CHANGELOG.md b/ci/tmp.4rIIEYCP9c/fping-5.3/CHANGELOG.md new file mode 100644 index 0000000..7cd88bc --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/CHANGELOG.md @@ -0,0 +1,299 @@ +fping 5.4 (2025-08-19) +====================== + +## Bugfixes + +- Memory allocation safety checks for event storage (thanks David.A for bug report) +- Fix off-by-one boundary check in seqmap code (thanks David.A for bug report) +- The minimum value for the per-host interval (-i flag) is now 0.001 (milliseconds), + since it probably never makes sense to use a smaller value, and to avoid trying + to do a too large memory allocation. + +fping 5.3 (2025-01-02) +====================== + +## New features + +- New option --icmp-timestamp to send ICMP timestamp requests (ICMP type 13) + instead of ICMP Echo requests (#353 #363, thanks @auerswal and @gsnw-sebast) +- New option --print-ttl to print returned TTL value (#354, thanks @nalves599) +- New option --print-tos to print returned TOS value (#335 #346 #347, thanks + @auerswal and @gsnw-sebast) +- New option --check-source (#334, thanks @auerswal) +- Predefined various timestamp formats (#321, thanks @auerswal and @gsnw-sebast) +- Print cumulative stats with -Q SECS,cumulative (#315, thanks @auerswal) + +## Bugfixes and other changes + +- ci: Upgrade actions/upload-artifact to v4 (#360, thanks @gsnw-sebast) +- ci: Azure Pipeline only trigger when changes are made in the development branch + (#359, thanks @gsnw-sebast) +- ci: Upgrade actions/upload-artifact to v3 (#355, thanks @pevik) +- ci: Azure Pipeline YAML add docker build (#354, thanks @gsnw-sebast) +- Dockerfile: change distribution from ubuntu to debian (#350, thanks + @gsnw-sebast) +- Fix warning unused parameter 'reply_timestamp' under macOS (#348, thanks + @gsnw-sebast) +- Fix increase maximum -s value to 65507 (#344, thanks @pevik) +- ci: use File::Temp to create temporary directory (#343, thanks @auerswal) +- Fix -k, --fwmark with setuid fping executable (#342, thanks @auerswal) +- Another batch of additional tests (take 2) (#341, thanks @auerswal) +- Document that -a and -u are overridden by -c and -C (#338, thanks @auerswal) +- Fix macOS build warning sets SEQMAP_TIMEOUT_IN_NSSEQMAP_TIMEOUT_IN_NS as INT64_C + (#336, thanks @gsnw-sebast) +- Fix inconsistent limits for address generation via -g, --generator using either + range or CIDR (#331, thanks @auerswal) +- Some additional tests (#329, thanks @auerswal) +- ci: skip an unreliable test on macOS (#328, thanks @auerswal) +- Fix incorrect return-value check for a scanf like function (CWE-253) (#323, + thanks @gsnw-sebast) +- A few more tests to increase code coverage a little bit (#320, thanks @auerswal) +- Github fix: Change to codeql-action-v2 (#319, thanks @gsnw-sebast) +- Developer function: Debug with Visual Studio Code (#318, thanks @gsnw-sebast) + +fping 5.2 (2024-04-21) +====================== + +## New features + +- New option -X / --fast-reachable to exit immediately once N hosts have been + found (#260, thanks @chriscray and @gsnw) + +- New option -k / -fwmark to set Linux fwmark mask (#289, thanks @tomangert and + @deepkv) + +## Bugfixes and other changes + +- Always output fatal error messages (#303, thanks @auerswal) +- Fallback to SO\_TIMESTAMP if SO\_TIMESTAMPNS is not available (#279, thanks + @gsnw) +- Fix "not enough sequence numbers available" error on BSD-like systems (#307, + thanks @cagney, @gsnw) +- Fix running in unprivileged mode (#248, thanks @sfan5) +- Fix build issue for NetBSD/alpha (#255, thanks @0-wiz-0) +- Fix build issue for OpenBSD/alpha (#275, thanks @gsnw) +- Fix build warning for long int usage (#258, thanks @gsnw) +- Fix build error with musl libc (#263, thanks @kraj) +- Fix to guard against division by zero (#293, thanks @auerswal) +- Decouple -a/-u effects from -c (#298, thanks @auerswal) +- Added contrib/Dockerfile (#224, thanks @darless) +- Remove host from Netdata chart titles (#253, thanks @ilyam8) +- Add additional tests (#292, #297, thanks @auerswal) +- Update github action os images (#282, thanks @gsnw) +- Fix Azure pipeline tests (#308, thanks @gsnw) +- Various autoconf fixes (#286, #283, thanks @gsnw) +- Extended configure script with --enable-debug and output cpu usage (#311, + thanks @gsnw) +- Documentation: Update Netdata website link (#257, thanks @ilyam8) +- Documentation: fix description of --file option (#268, thanks @MohGeek) +- Documentation: improve exit status description (#294, thanks @auerswal) +- Documentation: move description of -i MSEC (#298, thanks @auerswal) +- Documentation: improve help output for options -c and -C (#302, #auerswal) + + +fping 5.1 (2022-02-06) +====================== + +## Bugfixes and other changes + +- Use setcap to specify specific files in fping.spec (#232, thanks @zdyxry) +- Netdata: use host instead name as family label (#226, thanks @k0ste) +- Netdata: use formatstring macro PRId64 (#229, thanks @gsnw) +- Allow -4 option to be given multiple times (#215, thanks @normanr) +- Documentation fix (#208, thanks @timgates42) +- Retain privileges until after privileged setsockopt (#200, thanks @simetnicbr) +- Set bind to source only when option is set (#198, thanks @dinoex) +- Update Azure test pipeline (#197, thanks @gsnw) +- Fix getnameinfo not called properly for IPv4 (#227, thanks @aafbsd) +- Fixed wrong timestamp under Free- and OpenBSD and macOS (#217, thanks @gsnw) +- Documentation updates (#240, thanks @auerswal) +- Updated autotools (autoconf 2.71, automake 1.16.5, libtool 2.4.6) + + +fping 5.0 (2020-08-05) +====================== + +## Incompatible Changes + +- In non-quiet loop and count mode, a line is printed for every lost packet + (#175, thanks @kbucheli): + + ``` + $ fping -D -c2 8.8.8.8 8.8.8.7 + [1596092373.18423] 8.8.8.8 : [0], 64 bytes, 12.8 ms (12.8 avg, 0% loss) + [1596092374.18223] 8.8.8.7 : [0], timed out (NaN avg, 100% loss) + [1596092374.18424] 8.8.8.8 : [1], 64 bytes, 12.3 ms (12.5 avg, 0% loss) + [1596092375.18344] 8.8.8.7 : [1], timed out (NaN avg, 100% loss) + + 8.8.8.8 : xmt/rcv/%loss = 2/2/0%, min/avg/max = 12.3/12.5/12.8 + 8.8.8.7 : xmt/rcv/%loss = 2/0/100% + ``` + +- The returned size in bytes now always excludes the IP header, so if before it + reported '84 bytes' e.g. when using 'fping -l', now it reports '64 bytes'. + This is to make the reported size consistent with ping(8) from iputils and + also with fping when pinging a IPv6 host (which never included the IPv6 + header size). + +## New features + +- The number of sent pings is only counted when the pings are received or have + timed out, ensuring that the loss ratio will be always correct. This makes it + possible, for example, to use loop mode (-l) with interval statistics (-Q) + and a timeout larger than period, without having the issue that initially + some pings would be reported as missing (#193) + +- Improved precision of measurements from 10us to 1us (#136, thanks @tycho) + +## Bugfixes and other changes + +- The reported size of received packets is now always correct on Linux even for + packets > 4096 bytes (#180) + +- Travis CI automated testing now also macos testing and additional ubuntu + distributions (#196) + +fping 4.4 (2020-07-24) +====================== +## Bugfixes and other changes + +- Fix wrong ident used for normal (non-unprivileged) pings (#191, thanks @tycho) +- Fix build with --disable-ipv6 (#187, thanks Polynomial-C) + +fping 4.3 (2020-07-11) +====================== + +## New features + +- Linux unprivileged ping support (#173, thanks @tycho) +- Add SIGQUIT summary support similar to ping (#185, thanks @laddp) + +## Bugfixes and other changes + +- Corrected long option name of -s to --stats (#148, thanks @wopfel) +- Do not fail if using fping6 with -6 flag (#149, thanks @stromnet) +- Fail if interface binding (-I) does not work (#162, thanks @kbucheli) +- Fix using option -4 when fping is compiled IPv4-only (#154, thanks @pbhenson) +- Add Azure pipeline test build (#153 and #170, thanks @gsnw) +- GCC 10 compatibility fixes (#167 and #168, thanks @cranderson) +- Macos build fix (#174, thanks @tycho) +- Fix xmt stats in Netdata output (#172, thanks @vlvkobal) +- Only increase num_alive if response is not a duplicate (#151, thanks @brownowski) +- Use line buffering for stdout (#179, thanks @bg6cq) + +fping 4.2 (2019-02-19) +====================== + +## New features + +- New option -x / --reachable to check if the number of reachable hosts is >= a certain + number. Useful for example to implement connectivity-checks (#138, thanks @deepak0004) + +## Bugfixes and other changes + +- Allow decimal numbers for '-t', '-i', '-p', and '-Q' +- Fix build with --disable-ipv6 (#134, thanks @Polynomial-C) +- Fix hang with '-6', with ipv6 kernel module, but not loaded (#140, thanks @abelbeck) +- Assume '-6' if the binary is named 'fping6' (this is mostly for special + embedded-distro use cases, and not meant to be used generally in place of + compiling IPv6-only binary or using '-6', see also the notes in #139, thanks + abelbeck) +- Get rid of warning "timeout (-t) value larger than period (-p) produces unexpected results" + (#142, thanks @MrDragon1122) + + +fping 4.1 (2018-09-17) +====================== + +## Bugfixes and other changes + +- Fix problem when socket fd is 0 (#125, thanks Ramón Novoa!) +- Fix running on servers with disabled IPv6 (#118, thanks Simon Matter) +- Allow running "fping -h" or "--help" even when raw socket can't be opened (#131, thanks @teto) +- Fix build issue with FreeBSD and IPv6 (#132, thanks @gsnw) + +fping 4.0 (2017-04-23) +====================== + +## Incompatible Changes + +##### fping and fping6 unification + +fping and fping6 are now unified into one binary. It means that, for example, +doing 'fping google.com' is going to ping the IPv6 IP of google.com on +IPv6-enabled hosts. + +If you need exact compatibility with old versions, you can configure and +install fping twice: once for ipv4, and once for ipv6: + + ./configure --disable-ipv6; make clean install + ./configure --disable-ipv4 --program-suffix=6; make clean install + +##### Option -n, not the same as -d anymore + +Option -n / --name is now doing a reverse-DNS lookups on host addresses, +only if they are given as IP address, but not for hostnames. For example, +if you write 'fping -n google.com', fping would previously do a +forward-DNS lookup on google.com, and then a reverse-DNS lookup on the +resolved IP address. Now, it is just going to keep the name 'google.com'. +That same behavior can be achieved with the option -d / --rdns (which was +previously an alias for -n). + + fping<4.0 fping>=4.0 + fping -n NAME NAME->IP->IPNAME NAME + fping -d NAME NAME->IP->IPNAME NAME->IP->IPNAME + +##### Discarding of late packets + +fping will now discard replies, if they arrive after the defined timeout +for reply packets, specified with -t. This change is relevant only for the +count and loop modes, where the measured times should be now more +consistent (see github issue [#32][i32] for details). + +To prevent loosing reply packets because of this change, the default +timeout in count and loop modes is now automatically adjusted to the +period interval (up to 2000 ms), but it can be overriden with the -t +option. The default timeout for non-loop/count modes remains 500 ms. + +##### No restrictions by default + +fping will not enforce -i >= 1 and -p >= 10 anymore, except if you +'./configure --enable-safe-limits'. + +The reasoning to removing the restrictions by default, is that users can +clog the network with other tools anyway, and these restrictions are +sometimes getting in the way (for example if you try to ping a lot of +hosts). + +##### Default interval (-i) changed from 25ms to 10ms + +The default minimum interval between ping probes has been changed from +25ms to 10ms. The reason is that 25ms is very high, considering today's +fast networks: it generates at most 31 kbps of traffic (for IPv4 and +default payload size). + +## New features + +- Unified 'fping' and 'fping6' into one binary ([#80][i80]) +- Long option names for all options +- IPv6 enabled by default +- New option -4 to force IPv4 +- New option -6 to force IPv6 +- Keep original name if a hostname is given with -n/--name +- Option -d/--rdns now always does a rdns-lookup, even for names, as '-n' was doing until now +- Enforce -t timeout on reply packets, by discarding late packets ([#32][i32]) +- Auto-adjust timeout for -c/-C/-l mode to value of -p + +## Bugfixes and other changes + +- -i/-p restrictions disabled by default (enable with --enable-safe-limits) +- Default interval -i changed from 25ms to 10ms +- Fix compatibility issue with GNU Hurd +- A C99 compiler is now required +- Option parsing with optparse (https://github.com/skeeto/optparse). Thanks Christopher Wellons! +- New changelog file format + +[i32]: https://github.com/schweikert/fping/issues/32 +[i80]: https://github.com/schweikert/fping/issues/80 + +(see doc/CHANGELOG.pre-v4 for older changes) diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/COPYING b/ci/tmp.4rIIEYCP9c/fping-5.3/COPYING new file mode 100644 index 0000000..cceb651 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/COPYING @@ -0,0 +1,17 @@ + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/INSTALL b/ci/tmp.4rIIEYCP9c/fping-5.3/INSTALL new file mode 100644 index 0000000..e23597f --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/INSTALL @@ -0,0 +1,177 @@ +Basic Installation +================== + + These are generic installation instructions. + + --> See the README file for fping-specific instructions. <-- + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/Makefile.am b/ci/tmp.4rIIEYCP9c/fping-5.3/Makefile.am new file mode 100644 index 0000000..2ea59b9 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = doc src + +EXTRA_DIST = CHANGELOG.md contrib README.md ci/*.sh ci/*.pl diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/README.md b/ci/tmp.4rIIEYCP9c/fping-5.3/README.md new file mode 100644 index 0000000..8cf4f88 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/README.md @@ -0,0 +1,50 @@ +[![Build Status](https://travis-ci.org/schweikert/fping.svg?branch=develop)](https://travis-ci.org/schweikert/fping) +[![Coverage Status](https://coveralls.io/repos/github/schweikert/fping/badge.svg?branch=develop)](https://coveralls.io/github/schweikert/fping?branch=develop) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/11559/badge.svg?flat=1")](https://scan.coverity.com/projects/schweikert-fping) + +# fping + +fping is a program to send ICMP echo probes to network hosts, similar to ping, +but much better performing when pinging multiple hosts. fping has a long long +story: Roland Schemers did publish a first version of it in 1992 and it has +established itself since then as a standard tool. + +_Current maintainer_: + David Schweikert \ + +_Website_: + https://fping.org/ + +_Mailing-list_: + https://groups.google.com/group/fping-users + +## Installation + +If you want to install fping from source, proceed as follows: + +0. Run `./autogen.sh` + (only if you got the source from Github). +1. Run `./configure` with the correct arguments. + (see: `./configure --help`) +2. Run `make; make install`. +3. Make fping either setuid, or, if under Linux: + `sudo setcap cap_net_raw,cap_net_admin+ep fping` + +If you can't run fping as root or can't use the cap_net_raw capability, you can +also run fping in unprivileged mode. This works on MacOS and also on Linux, +provided that your GID is included in the range defined in +`/proc/sys/net/ipv4/ping_group_range`. This is particularly useful for running +fping in rootless / unprivileged containers. The --fwmark option needs root or +cap_net_admin. + +## Usage + +Have a look at the [fping(8)](doc/fping.pod) manual page for usage help. +(`fping -h` will also give a minimal help output.) + +## Credits + +* Original author: Roland Schemers (schemers@stanford.edu) +* Previous maintainer: RL "Bob" Morgan (morgan@stanford.edu) +* Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl) +* Other contributors: see [CHANGELOG.md](CHANGELOG.md) diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-1-autotools.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-1-autotools.sh new file mode 100755 index 0000000..f0ea2e0 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-1-autotools.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +set -e +set -x + +if [[ "$OSTYPE" == "darwin"* ]]; then + exit 0 +fi + +AUTOCONF=http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz +AUTOMAKE=http://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.gz +LIBTOOL=http://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz +PREFIX=$(pwd)/ci/build +PATH=$(pwd)/ci/build/bin:$PATH + +if [ ! -d ci ]; then + echo "you must run this in the root fping directory" >&2 + exit 1 +fi + +# remove standard versions +sudo apt-get remove -qq autoconf automake autotools-dev libtool + +# prepare build environment +cd ci +rm -rf build +mkdir -p build/src +cd build/src + +# autoconf +( +AUTOCONF_FILE=$(basename $AUTOCONF) +AUTOCONF_DIR=$(echo $AUTOCONF_FILE | sed -e 's/\.tar.*//') +wget $AUTOCONF +tar xf $AUTOCONF_FILE +cd $AUTOCONF_DIR +./configure --prefix=$PREFIX +make install +) + +# automake +( +AUTOMAKE_FILE=$(basename $AUTOMAKE) +AUTOMAKE_DIR=$(echo $AUTOMAKE_FILE | sed -e 's/\.tar.*//') +wget $AUTOMAKE +tar xf $AUTOMAKE_FILE +cd $AUTOMAKE_DIR +./configure --prefix=$PREFIX +make install +) + +# libtool +( +LIBTOOL_FILE=$(basename $LIBTOOL) +LIBTOOL_DIR=$(echo $LIBTOOL_FILE | sed -e 's/\.tar.*//') +wget $LIBTOOL +tar xf $LIBTOOL_FILE +cd $LIBTOOL_DIR +./configure --prefix=$PREFIX +make install +) diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-2-test-command.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-2-test-command.sh new file mode 100755 index 0000000..77f3905 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-2-test-command.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -ex + +curl -L http://cpanmin.us | perl - -L $HOME/perl5 App::cpanminus +$HOME/perl5/bin/cpanm --sudo Test::Command diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-3-prepare-macos.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-3-prepare-macos.sh new file mode 100755 index 0000000..09125eb --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-3-prepare-macos.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# only do this on Mac OS X +if [ `uname -s` != "Darwin" ]; then + exit 0; +fi + +if [[ ! `ifconfig lo0` =~ 127\.0\.0\.2 ]]; then + sudo ifconfig lo0 127.0.0.2/8 alias + sudo ifconfig lo0 127.0.0.3/8 alias + sudo ifconfig lo0 127.0.0.4/8 alias + sudo ifconfig lo0 127.0.0.5/8 alias +fi diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-4-compile.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-4-compile.sh new file mode 100755 index 0000000..e2a660c --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-4-compile.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -x + +PATH=$(pwd)/ci/build/bin:$PATH + +if [ ! -d ci ]; then + echo "you must run this in the root fping directory" >&2 + exit 1 +fi + +autoreconf -i +./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping +make CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage" +## setcap currently doesn't work anymore on travis-ci +#sudo setcap cap_net_raw+ep src/fping +## setcap debugging: +#pwd +#df -k . +#which setcap +#uname -a +#mount +# +#sudo apt-get install strace +#sudo strace setcap cap_net_raw+ep src/fping + +# use setuid, since setcap is not available +sudo chown root src/fping +sudo chmod u+s src/fping diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-bintray.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-bintray.sh new file mode 100755 index 0000000..0dc8800 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-bintray.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# upload to bintray.com/schweikert + +set -e + +VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//') +if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then + REPO=release +else + REPO=beta +fi +curl -T fping-$VERSION.tar.gz -uschweikert:$BINTRAY_API_KEY https://api.bintray.com/content/schweikert/$REPO/fping/$VERSION/fping-$VERSION.tar.gz +echo diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coveralls.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coveralls.sh new file mode 100755 index 0000000..9080f0b --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coveralls.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -xe + +if [ "$TRAVIS_DIST" = "trusty" ]; then + echo "skip coveralls on trusty because coveralls errors out due to python issues" + exit 0 +elif [ "$TRAVIS_OS_NAME" = "osx" ]; then + pip3 install --user cpp-coveralls + PATH="${PATH}:$(python3 -c 'import site; print(site.USER_BASE)')/bin" +else + pip install --user cpp-coveralls +fi + +export COVERALLS_PARALLEL=true +coveralls --build-root src --exclude src/optparse.c --exclude ci --exclude config.h --gcov-options '\-lp' diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coverity.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coverity.sh new file mode 100755 index 0000000..b009d2f --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coverity.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +COVERITY_SCAN_PROJECT_NAME=schweikert/fping +COVERITY_SCAN_EMAIL=david@schweikert.ch + +if [ -z "$COVERITY_SCAN_TOKEN" ]; then + echo "ERROR: COVERITY_SCAN_TOKEN not defined." >&2 + exit 1 +fi + +curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 \ + --form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN +tar xfz /tmp/cov-analysis-linux64.tgz +./autogen.sh +./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping +cov-analysis-linux64-*/bin/cov-build --dir cov-int make -j4 +tar cfz cov-int.tar.gz cov-int +curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME \ + --form token=$COVERITY_SCAN_TOKEN \ + --form email=$COVERITY_SCAN_EMAIL \ + --form file=@cov-int.tar.gz \ + --form version="`git rev-parse --short HEAD`" \ + --form description="`git rev-parse --short HEAD` / $TRAVIS_BUILD_ID " diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/prepare-linux.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/prepare-linux.sh new file mode 100755 index 0000000..efe8b3b --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/prepare-linux.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +sudo setcap cap_net_raw,cap_net_admin+ep src/fping + +if [[ ! $PATH =~ fping/src ]]; then + PATH=/home/dws/checkouts/fping/src:$PATH +fi diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-lcov.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-lcov.sh new file mode 100755 index 0000000..c7470b6 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-lcov.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +lcov -c -no-external \ + -d . \ + -b src \ + -o lcov-all.info + +lcov --remove lcov-all.info -o lcov.info \ + '*/optparse.c' diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-tests.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-tests.sh new file mode 100755 index 0000000..9d5a308 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-tests.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -ex + +PATH=`pwd`/src:$PATH + +prove ci/test-*.pl +ci/test-tarball.sh diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-01-basics.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-01-basics.pl new file mode 100755 index 0000000..e54bc22 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-01-basics.pl @@ -0,0 +1,55 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 15; +use Test::More; + +# ping 127.0.0.1 +{ + my $cmd = Test::Command->new(cmd => "fping 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +# ping ::1 +SKIP: { + #system("/sbin/ifconfig >&2"); + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("::1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +# ping ff02::1 +SKIP: { + #system("/sbin/ifconfig >&2"); + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping ff02::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("ff02::1 is alive\n"); + $cmd->stderr_like(qr{ \[<- .*\]}); +} + +# ping 3 times 127.0.0.1 +{ + my $cmd = Test::Command->new(cmd => "fping -p 100 -C3 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + $cmd->stderr_like(qr{127\.0\.0\.1 : \d\.\d+ \d\.\d+ \d\.\d+\n}); +} + +# invalid target name +{ + my $cmd = Test::Command->new(cmd => "fping host.name.invalid"); + $cmd->exit_is_num(2); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{host\.name\.invalid: .+\n}); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-02-help.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-02-help.pl new file mode 100755 index 0000000..0f66d13 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-02-help.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 15; + +my $I_HELP = " -I, --iface=IFACE bind to a particular interface\n"; +$I_HELP = '' if $^O eq 'darwin'; + +# fping -h (special pre-parse code path) +my $cmd1 = Test::Command->new(cmd => "fping -h"); +$cmd1->exit_is_num(0); +$cmd1->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\] + +Probing options: +.* + -v, --version show version +}s); +$cmd1->stderr_is_eq(""); + +# fping -4 -h (normal option parsing code path) +my $cmd4 = Test::Command->new(cmd => "fping -4 -h"); +$cmd4->exit_is_num(0); +$cmd4->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\] + +Probing options: +.* + -v, --version show version +}s); +$cmd4->stderr_is_eq(""); + +# fping -v +my $cmd2 = Test::Command->new(cmd => "fping -v"); +$cmd2->exit_is_num(0); +$cmd2->stdout_like(qr{fping: Version \S+}); +$cmd2->stderr_is_eq(""); + +# fping with unknown option +my $cmd3 = Test::Command->new(cmd => "fping -Z"); +$cmd3->exit_is_num(1); +$cmd3->stdout_is_eq(""); +$cmd3->stderr_like(qr{^fping: (illegal|invalid) option -- '?Z'?\nsee 'fping -h' for usage information\n$}); + +# fping with unknown long option +my $cmd5 = Test::Command->new(cmd => "fping --unknown-long-option"); +$cmd5->exit_is_num(1); +$cmd5->stdout_is_eq(""); +$cmd5->stderr_like(qr{^fping: (illegal|invalid) option -- '?unknown-long-option'?\nsee 'fping -h' for usage information\n$}); diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-03-forbidden.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-03-forbidden.pl new file mode 100755 index 0000000..97962c1 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-03-forbidden.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 36; + +# fping -i 0 +my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29"); +$cmd1->exit_is_num(1); +$cmd1->stdout_is_eq(""); +$cmd1->stderr_is_eq(<= 1 +END + +# fping -p 9 +my $cmd2 = Test::Command->new(cmd => "fping -c3 -p 9 127.0.0.1"); +$cmd2->exit_is_num(1); +$cmd2->stdout_is_eq(""); +$cmd2->stderr_is_eq(<= 10 +END + +# fping -H 300 +my $cmd5 = Test::Command->new(cmd => "fping -H 300 127.0.0.1"); +$cmd5->exit_is_num(1); +$cmd5->stdout_is_eq(""); +$cmd5->stderr_is_eq("fping: ttl 300 out of range\n"); + +# fping -a -u +my $cmd6 = Test::Command->new(cmd => "fping -a -u 127.0.0.1"); +$cmd6->exit_is_num(1); +$cmd6->stdout_is_eq(""); +$cmd6->stderr_is_eq("fping: specify only one of a, u\n"); + +# fping -c -l +my $cmd7 = Test::Command->new(cmd => "fping -c3 -l 127.0.0.1"); +$cmd7->exit_is_num(1); +$cmd7->stdout_is_eq(""); +$cmd7->stderr_is_eq("fping: specify only one of c, l\n"); + +# fping -b 65508 +my $cmd8 = Test::Command->new(cmd => "fping -b 65508 127.0.0.1"); +$cmd8->exit_is_num(1); +$cmd8->stdout_is_eq(""); +$cmd8->stderr_is_eq("fping: data size 65508 not valid, must not be larger than 65507\n"); + +# fping -B 0.9 +my $cmd9 = Test::Command->new(cmd => "fping -B 0.9 127.0.0.1"); +$cmd9->exit_is_num(1); +$cmd9->stdout_is_eq(""); +$cmd9->stderr_is_eq("fping: backoff factor 0.9 not valid, must be between 1.0 and 5.0\n"); + +# fping -B 5.1 +my $cmd10 = Test::Command->new(cmd => "fping -B 5.1 127.0.0.1"); +$cmd10->exit_is_num(1); +$cmd10->stdout_is_eq(""); +$cmd10->stderr_is_eq("fping: backoff factor 5.1 not valid, must be between 1.0 and 5.0\n"); + +# non-negative only +for my $arg (qw(i p Q t)) { + my $cmd = Test::Command->new(cmd => "fping -$arg -1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{Usage:}); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-04-options-a-b.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-04-options-a-b.pl new file mode 100755 index 0000000..ea7eb89 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-04-options-a-b.pl @@ -0,0 +1,218 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 68; +use Test::More; +use Time::HiRes qw(gettimeofday tv_interval); + +# -4 only use IPv4 addresses +# -6 only use IPv6 addresses +# -a show targets that are alive +# -A show targets by address +# -b n amount of ping data to send, in bytes (default 56) +# -B f set exponential backoff factor to f + +# fping -4 -6 +{ +my $cmd = Test::Command->new(cmd => "fping -4 -6 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: can't specify both -4 and -6\n"); +} + +# fping -6 -4 +{ +my $cmd = Test::Command->new(cmd => "fping -6 -4 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: can't specify both -4 and -6\n"); +} + +# fping -4 +{ +my $cmd = Test::Command->new(cmd => "fping -4 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +{ +my $cmd = Test::Command->new(cmd => "fping -4 ::1"); +$cmd->exit_is_num(2); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^::1:.*(not supported|not known)}); +} + +# fping -6 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("::1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +{ +my $cmd = Test::Command->new(cmd => "fping -6 127.0.0.1"); +$cmd->exit_is_num(2); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{127\.0\.0\.1:.*(not supported|not known)}); +} + +# fping -a +{ +my $cmd = Test::Command->new(cmd => "fping -a 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1\n127.0.0.2\n"); +$cmd->stderr_is_eq(""); +} + +# fping -a --print-ttl +{ +my $cmd = Test::Command->new(cmd => "fping -a --print-ttl 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 \(TTL \d+\)\n127\.0\.0\.2 \(TTL \d+\)\n}); +$cmd->stderr_is_eq(""); +} + +# fping -a --icmp-timestamp +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping -a --icmp-timestamp 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+}); +$cmd->stderr_is_eq(""); +} + +# fping --print-ttl +{ +my $cmd = Test::Command->new(cmd => "fping --print-ttl 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TTL \d+\)}); +$cmd->stderr_is_eq(""); +} + +# fping --icmp-timestamp +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive, timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+}); +$cmd->stderr_is_eq(""); +} + +# fping --icmp-timestamp --print-tos --print-ttl -e +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp --print-tos --print-ttl -e 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive, timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\) \(\d+(\.\d*)? ms\)}); +$cmd->stderr_is_eq(""); +} + +# fping --icmp-timestamp ::1 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp ::1"); + $cmd->exit_is_num(2); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{^::1:.*(not supported|not known)}); +} + +# fping --print-ttl with IPv6 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --print-ttl ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{::1 is alive \(TTL unknown\)\n}); + $cmd->stderr_is_eq(""); +} + +# fping -A +{ +my $cmd = Test::Command->new(cmd => "fping -4 -A localhost"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -b +{ +my $cmd = Test::Command->new(cmd => "fping -b 1000 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping --icmp-timestamp -b +{ +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 1000 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); +} + +# fping -b --icmp-timestamp +{ +my $cmd = Test::Command->new(cmd => "fping -b 1000 --icmp-timestamp 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); +} + +# fping --icmp-timestamp -b 12 (ICMP Timestamp data size) +{ +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 12 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); +} + +# fping -6 --icmp-timestamp +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 --icmp-timestamp ::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{ICMP Timestamp is IPv4 only}); +} + +# fping --icmp-timestamp -6 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -6 ::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: can't specify both -4 and -6\n"); +} + +# fping -B +SKIP: { + if($^O eq 'darwin') { + skip 'timing test not reliable on macOS', 5; + } + my $t0 = [gettimeofday]; + my $cmd = Test::Command->new(cmd => "fping -t 100 -r 3 -B 2 8.8.8.7"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq("8.8.8.7 is unreachable\n"); + $cmd->stderr_like(qr{^(|(8.8.8.7: error while sending ping: No route to host\n)+)$}); + my $elapsed = tv_interval($t0); + # 0.1 + 0.2 + 0.4 + 0.8 = 1.5 + cmp_ok($elapsed, '>=', 1.5); + cmp_ok($elapsed, '<', 1.9); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-05-options-c-e.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-05-options-c-e.pl new file mode 100755 index 0000000..d1cc767 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-05-options-c-e.pl @@ -0,0 +1,365 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 87; +use Test::More; + +# -c n count of pings to send to each target (default 1) +# -C n same as -c, report results in verbose format +# --check-source discard replies not from target address +# -d reverse name lookup +# -D print timestamp before each output line +# -e show elapsed time on return packets + +# fping -c n +{ +my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n --print-tos --print-ttl +{ +my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 --print-tos --print-ttl localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +}); + +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n -q +{ +my $cmd = Test::Command->new(cmd => "fping -q -c 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n -a (-a is ignored) +{ +my $cmd = Test::Command->new(cmd => "fping -a -c 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n -u (-u is ignored) +{ +my $cmd = Test::Command->new(cmd => "fping -u -c 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n ff02::1 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -c 1 ff02::1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{ff02::1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)\n}); + $cmd->stderr_like(qr{ \[<- .*\] +ff02::1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+\n}); +} + +# fping --icmp-timestamp -c n 127.0.0.1 +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp -c 2 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ +127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping --icmp-timestamp --print-tos --print-ttl -c n 127.0.0.1 +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp --print-tos --print-ttl -p 100 -c 2 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -C n +{ +my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ +127\.0\.0\.1 : \d\.\d+ \d\.\d+ +}); +} + +# fping -C n --print-tos --print-ttl +{ +my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 --print-tos --print-ttl localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +}); + +$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ +127\.0\.0\.1 : \d\.\d+ \d\.\d+ +}); +} + +# fping -C n -q +{ +my $cmd = Test::Command->new(cmd => "fping -C 5 -q -p 100 localhost"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{localhost :( \d\.\d+){5} +}); +} + +# fping -C n -a (-a is ignored) +{ +my $cmd = Test::Command->new(cmd => "fping -a -C 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ +127\.0\.0\.1 : \d\.\d+ \d\.\d+ +}); +} + +# fping -C n -u (-u is ignored) +{ +my $cmd = Test::Command->new(cmd => "fping -u -C 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ +127\.0\.0\.1 : \d\.\d+ \d\.\d+ +}); +} + +# fping -C n -i -q +{ +my $cmd = Test::Command->new(cmd => "fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{127\.0\.0\.1 :( \d\.\d+){20} +127\.0\.0\.2 :( \d\.\d+){20} +}); +} + +# fping -C n ff02::1 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -C 1 ff02::1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{ff02::1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)\n}); + $cmd->stderr_like(qr{ \[<- .*\]\nff02::1 : \d\.\d+\n}); +} + +# fping --check-source +{ +my $cmd = Test::Command->new(cmd => "fping --check-source 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping --check-source (to IPv6 multicast address -> accept no reply) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --check-source ff02::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq("ff02::1 is unreachable\n"); + $cmd->stderr_is_eq(""); +} + +# fping -c N --check-source +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -c1 --check-source 127.0.0.1 ff02::1"); + $cmd->exit_is_num(1); + $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +ff02::1 : \[0\], timed out \(NaN avg, 100% loss\) +}); + $cmd->stderr_like(qr{ +127\.0\.0\.1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +ff02::1 : xmt/rcv/%loss = 1/0/100% +}); +} + +# fping -C N --check-source +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -C1 --check-source 127.0.0.1 ff02::1"); + $cmd->exit_is_num(1); + $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +ff02::1 : \[0\], timed out \(NaN avg, 100% loss\) +}); + $cmd->stderr_like(qr{ +127\.0\.0\.1 : \d\.\d+ +ff02::1 : - +}); +} + +# fping -d +{ +my $cmd = Test::Command->new(cmd => "fping -d 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("localhost is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -D +{ +my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[\d+\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[\d+\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D (timestamp not before 2001-09-09) +{ +my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D --timestamp-format=ctime +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=ctime -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D --timestamp-format=iso +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=iso -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D --timestamp-format=rfc3339 +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=rfc3339 -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D --timestamp-format +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{Usage:}); +} + +# fping -D --timestamp-format="%Y-%m-%d %H:%M:%S" +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=\"%Y-%m-%d %H:%M:%S\" -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{Usage:}); +} + +# fping -e +{ +my $cmd = Test::Command->new(cmd => "fping -e 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(\d\.\d+ ms\) +}); +$cmd->stderr_is_eq(""); +} + +# fping -e -a +{ +my $cmd = Test::Command->new(cmd => "fping -e -a 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 \(\d\.\d+ ms\) +}); +$cmd->stderr_is_eq(""); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-06-options-f-h.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-06-options-f-h.pl new file mode 100755 index 0000000..c9b520a --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-06-options-f-h.pl @@ -0,0 +1,231 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 75; +use Test::More; +use File::Temp; + +# -f file read list of targets from a file ( - means stdin) (only if no -g specified) +# -g generate target list (only if no -f specified) +# (specify the start and end IP in the target list, or supply a IP netmask) +# (ex. ../src/fping -g 192.168.1.0 192.168.1.255 or ../src/fping -g 192.168.1.0/24) +# -H n Set the IP TTL value (Time To Live hops) + +my $tmpfile = File::Temp->new(); +print $tmpfile "127.0.0.1\n127.0.0.2\n"; +close($tmpfile); + +my $tmpfile2 = File::Temp->new(); +print $tmpfile2 "# comment\n127.0.0.1\n\n127.0.0.2\n"; +close($tmpfile2); + +# fping without option (-> equivalent to 'fping -f -') +{ +my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -f - +{ +my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping -f -"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -f file +{ +my $cmd = Test::Command->new(cmd => "fping -f ".$tmpfile->filename); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -f file (with comment and empty line) +{ +my $cmd = Test::Command->new(cmd => "fping -f ".$tmpfile2->filename); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -f non-existing-file (error) +{ +my $cmd = Test::Command->new(cmd => "fping -f file-does-not-exist"); +$cmd->exit_is_num(4); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{: fopen :}); +} + +# fping -g (error: no argument) +{ +my $cmd = Test::Command->new(cmd => "fping -g"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]}); +} + +# fping -g (error: single argument, but not in cidr format) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]}); +} + +# fping -g (error: CIDR network is not an IP address) +{ +my $cmd = Test::Command->new(cmd => "fping -g xxx/32"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{can't parse address xxx}); +} + +# fping -g (error: start of range is not an IP address) +{ +my $cmd = Test::Command->new(cmd => "fping -g xxx 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{can't parse address xxx}); +} + +# fping -g (error: end of range is not an IP address) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 yyy"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{can't parse address yyy}); +} + +# fping -g (error: too many arguments) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.2 127.0.0.3"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]}); +} + +# fping -g (range) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.5"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n127.0.0.3 is alive\n127.0.0.4 is alive\n127.0.0.5 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -g (empty range) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq(""); +} + +# fping -g (too large range) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.255.255.254"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n"); +} + +# fping -g (cidr) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1/30"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -g (cidr - long prefixes: point-to-point) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/31"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.2 is alive\n127.0.0.3 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -g (cidr - long prefixes: host) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/32"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -g (cidr - too long prefixes) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/33"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 33)\n"); +} + +# fping -g (cidr - too short prefixes) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/0"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 0)\n"); +} + +# fping -g (cidr - too many addresses) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.0/8"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n"); +} + +# fping -g (range - no IPv6 generator) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 ::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); +} + +# fping -g (range - no IPv6 generator - start address IPv6) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 127.0.0.1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); +} + +# fping -g (range - no IPv6 generator - end address IPv6) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -g 127.0.0.1 ::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); +} + +# fping -g (CIDR - no IPv6 generator) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -g ::1/128"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); +} + +# fping -H +{ +my $cmd = Test::Command->new(cmd => "fping -H 1 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-07-options-i-m.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-07-options-i-m.pl new file mode 100755 index 0000000..426286a --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-07-options-i-m.pl @@ -0,0 +1,94 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 16; +use Test::More; + +# -i n interval between sending ping packets (in millisec) (default 25) +# -l loop sending pings forever +# -k set fwmark on ping packets +# -m ping multiple interfaces on target host +# -M don't fragment + +# fping -i n +{ +my $cmd = Test::Command->new(cmd => "fping -i 100 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -l +{ +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1'); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); +} + +# fping -l --print-tos --print-ttl +{ +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 --print-ttl --print-tos -l 127.0.0.1'); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +}); +} + +# fping -k +SKIP: { +if($^O ne 'linux') { + skip '-k option is only supported on Linux', 3; +} +my $cmd = Test::Command->new(cmd => 'fping -k 256 127.0.0.1'); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -l with SIGQUIT +{ +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill -QUIT fping; sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1'); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[3\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[4\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = \d+/\d+/\d+%, min/avg/max = \d+\.\d+/\d+\.\d+/\d+\.\d+ +}); +} + +# fping -l -Q +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 2; +} +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 850 -l -Q 1 127.0.0.1'); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d\d:\d\d:\d\d\] +127\.0\.0\.1 : xmt/rcv/%loss = \d/\d/\d%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d\d:\d\d:\d\d\] +127\.0\.0\.1 : xmt/rcv/%loss = \d/\d/\d%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -l -t +{ +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -t 1500 -l 127.0.0.1'); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); +} + +# fping -M +SKIP: { + if($^O eq 'darwin') { + skip '-M option not supported on macOS', 3; + } + my $cmd = Test::Command->new(cmd => "fping -M 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +# fping -m -> test-14-internet-hosts diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-08-options-n-q.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-08-options-n-q.pl new file mode 100755 index 0000000..d614db1 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-08-options-n-q.pl @@ -0,0 +1,187 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 48; +use Test::More; + +# -n show targets by name (-d is equivalent) +# -O n set the type of service (tos) flag on the ICMP packets +# -p n interval between ping packets to one target (in millisec) +# (in looping and counting modes, default 1000) +# -q quiet (don't show per-target/per-ping results) +# -Q n same as -q, but show summary every n seconds + +# fping -n -> test-14-internet-hosts + +# fping -d -n +{ +my $cmd = Test::Command->new(cmd => "fping -d -n 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: use either one of -d or -n\n"); +} + +# fping -n -d +{ +my $cmd = Test::Command->new(cmd => "fping -n -d 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: use either one of -d or -n\n"); +} + +# fping -o +{ +my $cmd = Test::Command->new(cmd => "fping -t100 -p 100 -o -c 5 8.8.8.7"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq("8.8.8.7 : [0], timed out (NaN avg, 100% loss) +8.8.8.7 : [1], timed out (NaN avg, 100% loss) +8.8.8.7 : [2], timed out (NaN avg, 100% loss) +8.8.8.7 : [3], timed out (NaN avg, 100% loss) +8.8.8.7 : [4], timed out (NaN avg, 100% loss) +"); +$cmd->stderr_like(qr{^\s*8\.8\.8\.7 : xmt/rcv/%loss = 5/0/100%, outage\(ms\) = 50\d\s*$}); +} + +# fping -O +{ +my $cmd = Test::Command->new(cmd => "fping -O 2 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -O --print-tos +{ +my $cmd = Test::Command->new(cmd => "fping -O 2 --print-tos 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TOS \d+\) +}); +$cmd->stderr_is_eq(""); +} + +# fping -a -O --print-tos +{ +my $cmd = Test::Command->new(cmd => "fping -a -O 32 --print-tos 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 \(TOS \d+\) +}); +$cmd->stderr_is_eq(""); +} + +# fping --print-tos +{ +my $cmd = Test::Command->new(cmd => "fping --print-tos 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TOS 0\) +}); +$cmd->stderr_is_eq(""); +} + +# fping --print-tos with IPv6 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --print-tos ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{::1 is alive \(TOS unknown\)\n}); + $cmd->stderr_is_eq(""); +} + +# fping -q +{ +my $cmd = Test::Command->new(cmd => "fping -q -p 100 -c 3 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 400 -c 4 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q (longer test to show two time stamps and reset statistics) +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 550 -c 5 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q n ignores non-number characters after the number, except for keywords +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1whatever -p 550 -c 5 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q n ignores unknown keywords +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1,not_a_keyword -p 550 -c 5 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q n,cumulative +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1,cumulative -p 550 -c 5 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q -o +{ +my $cmd = Test::Command->new(cmd => "fping -c4 -Q1 -p550 -o 8.8.8.7"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +8\.8\.8\.7 : xmt/rcv/%loss = 1/0/100%, outage\(ms\) = 55\d +\[\d+:\d+:\d+\] +8\.8\.8\.7 : xmt/rcv/%loss = 2/0/100%, outage\(ms\) = 110\d +8\.8\.8\.7 : xmt/rcv/%loss = 4/0/100%, outage\(ms\) = 220\d +}); +} + +# fping -Q n,cumulative -o +{ +my $cmd = Test::Command->new(cmd => "fping -c4 -Q1,cumulative -p550 -o 8.8.8.7"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +8\.8\.8\.7 : xmt/rcv/%loss = 1/0/100%, outage\(ms\) = 55\d +\[\d+:\d+:\d+\] +8\.8\.8\.7 : xmt/rcv/%loss = 3/0/100%, outage\(ms\) = 165\d +8\.8\.8\.7 : xmt/rcv/%loss = 4/0/100%, outage\(ms\) = 220\d +}); +} + diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-09-option-r-t.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-09-option-r-t.pl new file mode 100755 index 0000000..2c26d24 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-09-option-r-t.pl @@ -0,0 +1,149 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 30; +use Test::More; + +# -R random bytes +# -r n number of retries (default 3) +# -s print final stats +# -S addr set source address +# -t n individual target initial timeout (in millisec) (default 500) +# -T n ignored (for compatibility with fping 2.4) + +# fping -R +{ +my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%.*}); +} + +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{::1 : xmt/rcv/%loss = 3/3/0%.*}); +} + +# fping -r tested in test-4-options-a-b.pl + +# fping -s +{ +my $cmd = Test::Command->new(cmd => "fping -s 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_like(qr{\s* +\s*1 targets +\s*1 alive +\s*0 unreachable +\s*0 unknown addresses +\s* +\s*0 timeouts \(waiting for response\) +\s*1 ICMP Echos sent +\s*1 ICMP Echo Replies received +\s*0 other ICMP received + +\s*\d\.\d+ ms \(min round trip time\) +\s*\d\.\d+ ms \(avg round trip time\) +\s*\d\.\d+ ms \(max round trip time\) +\s*\d\.\d+ sec \(elapsed real time\) +}); +} + +# fping -s (no host reachable) +{ +my $cmd = Test::Command->new(cmd => "fping -r0 -t100 -s 8.8.0.0"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq("8.8.0.0 is unreachable\n"); +$cmd->stderr_like(qr{\s* +\s*1 targets +\s*0 alive +\s*1 unreachable +\s*0 unknown addresses +\s* +\s*1 timeouts \(waiting for response\) +\s*1 ICMP Echos sent +\s*0 ICMP Echo Replies received +\s*0 other ICMP received + +\s*\d\.\d+ ms \(min round trip time\) +\s*\d\.\d+ ms \(avg round trip time\) +\s*\d\.\d+ ms \(max round trip time\) +\s*\d\.\d+ sec \(elapsed real time\) +}); +} + +# fping -s (both valid and invalid host name) +{ +my $cmd = Test::Command->new(cmd => "fping -s 127.0.0.1 host.name.invalid"); +$cmd->exit_is_num(2); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_like(qr{host\.name\.invalid: .+ +\s* +\s*1 targets +\s*1 alive +\s*0 unreachable +\s*1 unknown addresses +\s* +\s*0 timeouts \(waiting for response\) +\s*1 ICMP Echos sent +\s*1 ICMP Echo Replies received +\s*0 other ICMP received + +\s*\d\.\d+ ms \(min round trip time\) +\s*\d\.\d+ ms \(avg round trip time\) +\s*\d\.\d+ ms \(max round trip time\) +\s*\d\.\d+ sec \(elapsed real time\) +}); +} + +# fping -S +{ +my $cmd = Test::Command->new(cmd => "fping -S 127.0.0.1 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -S (wrong source address) +{ +my $cmd = Test::Command->new(cmd => "fping -S 192.0.2.47 127.0.0.1"); +$cmd->exit_is_num(4); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{fping: cannot bind source address : .+\n}); +} + +# fping -S +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -S ::1 ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("::1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +# fping -S (wrong IPv6 source address) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -S 2001:db8::1 ::1"); + $cmd->exit_is_num(4); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{fping: cannot bind source address : .+\n}); +} + +# fping -S +{ +my $cmd = Test::Command->new(cmd => "fping -S bla"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: can't parse source address: bla\n"); +} + +# (note: fping -t also tested in test-4-options-a-b.pl) diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-10-option-u-x.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-10-option-u-x.pl new file mode 100755 index 0000000..db45737 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-10-option-u-x.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 15; + +# -u show targets that are unreachable +# -v show version +# -x shows if >=N hosts are reachable or not +# -X exits true immediately when N hosts are found + +# fping -u +{ +my $cmd = Test::Command->new(cmd => "fping -r0 -u 8.8.0.0 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq("8.8.0.0\n"); +$cmd->stderr_is_eq(""); +} + +# fping -v +{ +my $cmd = Test::Command->new(cmd => "fping -v"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{ping: Version [45]\.\d+(-rc\d+)?}); +$cmd->stderr_is_eq(""); +} + +# fping -x +{ +my $cmd = Test::Command->new(cmd => "fping -x 1 8.8.0.0 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n"); +$cmd->stderr_is_eq(""); +} + +# fping -x +{ +my $cmd = Test::Command->new(cmd => "fping -x 2 8.8.0.0 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq("Not enough hosts reachable (required: 2, reachable: 1)\n"); +$cmd->stderr_is_eq(""); +} + +# fping -X +{ +my $cmd = Test::Command->new(cmd => "fping -X 1 --generate 127.0.0.0/29"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n"); +$cmd->stderr_is_eq(""); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-11-unpriv.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-11-unpriv.pl new file mode 100755 index 0000000..debf2af --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-11-unpriv.pl @@ -0,0 +1,95 @@ +#!/usr/bin/perl -w + +use English; +use File::Copy; +use File::Temp qw/ tempdir /; +use Test::Command; +use Test::More; + +if( $^O eq 'darwin' ) { + plan skip_all => 'Test irrelevant on MacOS'; + exit 0; +} + +sub get_ping_gid_range { + open FD, "/proc/sys/net/ipv4/ping_group_range" or return undef; + chomp(my $line = ); + my @range = split(/\s+/, $line); + close FD; + return @range; +} + +my @gids = split(' ', $EGID); +my @allowed = get_ping_gid_range(); + +# Make a copy of the binary so that we get rid of setuid bit +my $tmpdir = tempdir(CLEANUP => 1); +my $fping_bin = `which fping`; chomp $fping_bin; +my $fping_copy = "$tmpdir/fping.copy"; +copy($fping_bin, $fping_copy); +chmod 0755, $fping_copy; + +# Determine what test to run, based on whether unprivileged +# pings are allowed. +if(scalar grep { $_ >= $allowed[0] && $_ <= $allowed[1] } @gids) { + diag('test unprivileged mode'); + test_unprivileged_works(); +} +else { + test_privileged_fails(); +} + +sub test_unprivileged_works { + plan tests => 15; + + { + my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive\n"); + $cmd->stderr_is_eq(""); + } + { + my $cmd = Test::Command->new(cmd => "$fping_copy --print-tos 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive (TOS unknown)\n"); + $cmd->stderr_is_eq(""); + } + { + my $cmd = Test::Command->new(cmd => "$fping_copy --print-ttl 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive (TTL unknown)\n"); + $cmd->stderr_is_eq(""); + } + SKIP: { + if($^O ne 'linux') { + skip '-k option is only supported on Linux', 3; + } + my $cmd = Test::Command->new(cmd => "$fping_copy -4 -k 256 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive\n"); + $cmd->stderr_like(qr{fwmark ipv4: .+\n}); + } + SKIP: { + if($^O ne 'linux') { + skip '-k option is only supported on Linux', 3; + } + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "$fping_copy -6 -k 256 ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("::1 is alive\n"); + $cmd->stderr_like(qr{fwmark ipv6: .+\n}); + } +} + +sub test_privileged_fails { + plan tests => 3; + + { + my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1"); + $cmd->exit_is_num(4); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{: can't create socket \(must run as root\?\)}); + } +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-12-option-type.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-12-option-type.pl new file mode 100755 index 0000000..6514425 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-12-option-type.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 84; +use Test::More; + +# some options require a numeric argument +for my $arg (qw(b B c C H i O p Q r t x X)) { + for my $test_input (qw(xxx '')) { + my $cmd = Test::Command->new(cmd => "fping -$arg $test_input"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{Usage:}); + } +} + +# fping -k, only supported on Linux, requires a number +SKIP: { + if($^O ne 'linux') { + skip '-k option is only supported on Linux', 6; + } + for my $test_input (qw(xxx '')) { + my $cmd = Test::Command->new(cmd => "fping -k $test_input 127.0.0.1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{Usage:}); + } +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-13-unknown-host.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-13-unknown-host.pl new file mode 100755 index 0000000..65c8312 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-13-unknown-host.pl @@ -0,0 +1,11 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 3; + +# fping +{ +my $cmd = Test::Command->new(cmd => "fping nosuchname.example.com"); +$cmd->exit_is_num(2); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^nosuchname\.example\.com: .*not (known|found)}); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-14-ping-internet-hosts.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-14-ping-internet-hosts.pl new file mode 100755 index 0000000..3c18cc4 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-14-ping-internet-hosts.pl @@ -0,0 +1,106 @@ +#!/usr/bin/perl -w + +use Test::Command; +use Test::More; + +# evaluate if we have internet +if(!gethostbyname("www.google.com")) { + plan skip_all => 'Can\'t resolve www.google.com -> no internet?'; + exit 0; +} + +plan tests => 30; + +my $re_num = qr{\d+(?:\.\d+)?}; + +# fping +{ +my $cmd = Test::Command->new(cmd => "fping -q -i 10 -p 20 -c 3 -t200 8.8.8.8 www.france-telecom.fr www.google.com"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{8\.8\.8\.8\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num +www\.france-telecom\.fr\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num +www\.google\.com\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num +}); +} + +# fping -A -n +{ +my $cmd = Test::Command->new(cmd => "fping -A -n 8.8.8.8"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("dns.google (8.8.8.8) is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -4 -A -n +{ +my $cmd = Test::Command->new(cmd => "fping -4 -A -n dns.google"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{^dns.google \(8\.8\.(4\.4|8\.8)\) is alive\n$}); +$cmd->stderr_is_eq(""); +} + +# fping -4 --addr --rdns +{ +my $cmd = Test::Command->new(cmd => "fping -4 --addr --rdns www.apple.com"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{^\S+\.akamaitechnologies\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$}); +$cmd->stderr_is_eq(""); +} + +# fping -4 --addr --name +{ +my $cmd = Test::Command->new(cmd => "fping -4 --addr --name www.google.com"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{^www\.google\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$}); +$cmd->stderr_is_eq(""); +} + +# fping -A -n (IPv6) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -n -A dns.google"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{^dns.google \(2001:4860:4860::88(44|88)\) is alive\n$}); + $cmd->stderr_is_eq(""); +} + +# fping -m +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -A -m dns.google"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{^.* is alive\n.* is alive\n.* is alive\n.* is alive\n}); + $cmd->stderr_is_eq(""); +} + +# fping -m -A +{ +my $cmd = Test::Command->new(cmd => "fping -4 -A -m www.cloudflare.com"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\d+\.\d+\.\d+\.\d+ is alive\n\d+\.\d+\.\d+\.\d+ is alive\n}); +$cmd->stderr_is_eq(""); +} + +# fping -n +{ +my $cmd = Test::Command->new(cmd => "fping -n 8.8.8.8"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("dns.google is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -M +SKIP: { + if($^O eq 'darwin') { + skip '-M option not supported on macOS', 3; + } + my $cmd = Test::Command->new(cmd => "fping -r 0 -b 10000 -M 8.8.8.8"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq("8.8.8.8 is unreachable\n"); + $cmd->stderr_is_eq("8.8.8.8: error while sending ping: Message too long\n"); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-15-netdata.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-15-netdata.pl new file mode 100755 index 0000000..83dc439 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-15-netdata.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl -w + +use Test::Command; +use Test::More; + +plan tests => 3; + +# fping +{ +my $cmd = Test::Command->new(cmd => "fping -c 2 -Q 1 -N 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{CHART fping\.127_0_0_1_packets '' 'FPing Packets' packets '127.0.0.1' fping\.packets line 110020 1 +DIMENSION xmt sent absolute 1 1 +DIMENSION rcv received absolute 1 1 +BEGIN fping\.127_0_0_1_packets +SET xmt = 1 +SET rcv = 1 +END +CHART fping\.127_0_0_1_quality '' 'FPing Quality' percentage '127.0.0.1' fping\.quality area 110010 1 +DIMENSION returned '' absolute 1 1 +BEGIN fping\.127_0_0_1_quality +SET returned = 100 +END +CHART fping\.127_0_0_1_latency '' 'FPing Latency' ms '127.0.0.1' fping\.latency area 110000 1 +DIMENSION min minimum absolute 1 1000000 +DIMENSION max maximum absolute 1 1000000 +DIMENSION avg average absolute 1 1000000 +BEGIN fping\.127_0_0_1_latency +SET min = \d+ +SET avg = \d+ +SET max = \d+ +END} +); +$cmd->stderr_like(qr{127.0.0.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+}); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-56.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-56.pl new file mode 100755 index 0000000..e36cc14 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-56.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl -w + +# regression testing for github issue #56 +# +use Test::Command; +use Test::More; + +if( $^O eq 'darwin' ) { + plan skip_all => 'Test disabled on MacOS'; + exit 0; +} + +plan tests => 3; + +my $cmd1 = Test::Command->new(cmd => "fping -t100 -p100 -C3 255.255.255.255"); +$cmd1->exit_is_num(1); +$cmd1->stdout_is_eq(""); +$cmd1->stderr_is_eq("\n255.255.255.255 : - - -\n"); diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-58.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-58.pl new file mode 100755 index 0000000..db5161a --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-58.pl @@ -0,0 +1,10 @@ +#!/usr/bin/perl -w + +# regression testing for github issue #58 + +use Test::Command tests => 3; + +my $cmd1 = Test::Command->new(cmd => "fping -a -g 2001:db8:120:4161::4/64"); +$cmd1->exit_is_num(1); +$cmd1->stdout_is_eq(""); +$cmd1->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-tarball.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-tarball.sh new file mode 100755 index 0000000..da43a25 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-tarball.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# make sure that the .tar.gz file contains everything necessary +# to build fping + +set -e +set -x + +# skip on macos +if [[ "$OSTYPE" == "darwin"* ]]; then + exit 0 +fi + +make dist +VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//') +if [ -z "$VERSION" ]; then + echo "tar.gz file not found." >&2 + exit 1 +fi + +# unarchive +TMPDIR=$(mktemp -d --tmpdir=ci) +cd $TMPDIR +tar xf ../../fping-$VERSION.tar.gz +DIRNAME=$(ls) + +# build +cd $DIRNAME +./configure --enable-ipv4 --enable-ipv6 --prefix=/opt/fping +make +sudo make install diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/configure.ac b/ci/tmp.4rIIEYCP9c/fping-5.3/configure.ac new file mode 100644 index 0000000..d573075 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/configure.ac @@ -0,0 +1,129 @@ +dnl Process this file with autoconf to produce a configure script. + +dnl Minimum Autoconf version required. +AC_PREREQ(2.59) + +AC_INIT([fping],[5.4]) + +m4_ifdef([AC_AUTOCONF_VERSION],[AC_USE_SYSTEM_EXTENSIONS], [AC_GNU_SOURCE]) + +# Detect Operatingsystem +AC_CANONICAL_TARGET +only_clock_realtime=no + +case "${target}" in + *darwin*) + only_clock_realtime=yes + ;; + *freebsd*) + only_clock_realtime=yes + ;; + *openbsd*) + only_clock_realtime=yes + ;; +esac + +dnl --disable-ipv4 +AC_ARG_ENABLE([ipv4], + AS_HELP_STRING([--disable-ipv4], [Disable support for pinging IPv4 hosts])) +AM_CONDITIONAL([IPV4], [test "x$enable_ipv4" != "xno"]) +AM_COND_IF([IPV4], [AC_DEFINE([IPV4], [1], [IPv4 enabled])]) + +dnl --disable-ipv6 +AC_ARG_ENABLE([ipv6], + AS_HELP_STRING([--disable-ipv6], [Disable support for pinging IPv6 hosts])) +AS_IF([test "x$enable_ipv6" != "xno"], [ + dnl Test if IPv6 is supported + AC_CHECK_HEADERS([netinet/icmp6.h], [have_ipv6="yes"], [], [[ + #include + #include + ]]) +]) +dnl Can't disable both IPv4 and IPv6 +AS_IF([test "x$enable_ipv4" = "xno" -a "x$enable_ipv6" = "xno"], [ + AC_MSG_ERROR([Need to enable IPv4 or IPv6. Can't disable both!)]) +]) +dnl IPv6 required, but not supported? +AS_IF([test \( "x$enable_ipv6" = "xyes" -o "x$enable_ipv4" = "xno" \) -a "x$have_ipv6" != "xyes" ], [ + AC_MSG_ERROR([IPv6 not supported on this platform (netinet/icmp6.h header not found)]) +]) +AM_CONDITIONAL([IPV6], [test "x$have_ipv6" = "xyes"]) +AM_COND_IF([IPV6], [AC_DEFINE([IPV6], [1], [IPv6 enabled])]) + +AC_ARG_ENABLE([timestamp], + AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMPNS)])) +AS_IF([test "x$enable_timestamp" != "xno"], [ + AC_CHECK_DECL([SO_TIMESTAMPNS], [AC_DEFINE(HAVE_SO_TIMESTAMPNS, [1], [SO_TIMESTAMPNS is defined])], [have_so_timestamp="no"], [#include +#include ]) +]) +dnl Test if --enable-timestamp is explicitely enabled and make an error if this platform doesn't support it +AS_IF([test "x$enable_timestamp" = "xyes" -a "x$have_so_timestamp" = "xno"], [ + AC_MSG_ERROR([--enable-timestamp not supported on this platform]) +]) +AS_IF([test "x$only_clock_realtime" = "xyes"], [AC_DEFINE(ONLY_CLOCK_REALTIME, [1], [ONLY_CLOCK_REALTIME is defined])]) + +AC_ARG_ENABLE([safe-limits], + AS_HELP_STRING([--enable-safe-limits], [Restrict timing parameters (-i, -p) within "safe" limits])) +AS_IF([test "x$enable_safe_limits" = "xyes"], [ + AC_DEFINE(FPING_SAFE_LIMITS, [1], [safe limits should be enforced])]) + +AC_ARG_ENABLE([debug], + AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@]), [enable_debug=$enableval], [enable_debug=no]) +AS_IF([test "x$enable_debug" = "xyes"], [ + AC_DEFINE([DEBUG], [1], [Define if debugging is enabled])]) + +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AM_MAINTAINER_MODE + +AC_CONFIG_HEADERS([config.h]) + +dnl Checks for programs. + +AC_PROG_CC +AM_PROG_CC_C_O +m4_version_prereq([2.70],,[AC_PROG_CC_STDC]) +AC_PROG_CPP +AC_PROG_INSTALL + +dnl Checks for libraries. + +AC_CHECK_FUNC(gethostbyname) +if test $ac_cv_func_gethostbyname = no; then + AC_CHECK_LIB(nsl, gethostbyname) +fi +AC_CHECK_FUNC(connect) +if test $ac_cv_func_connect = no; then + AC_CHECK_LIB(socket, connect) +fi +AC_CHECK_FUNC(sigaction) +if test $ac_cv_func_sigaction = yes; then + AC_DEFINE([USE_SIGACTION],[1],[Define if sigaction is available.]) +fi + +AC_CHECK_FUNCS([strftime], [], + [AC_MSG_ERROR([strftime function is required but not found])]) + +AH_TOP([ +#ifndef CONFIG_H +#define CONFIG_H +]) + +AH_BOTTOM([ +/* some OSes do not define this ... lets take a wild guess */ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffffU +#endif + +#endif /* CONFIG_H */ + +]) + +dnl Checks for header files. +AC_CHECK_HEADERS([unistd.h sys/file.h stdlib.h sys/select.h]) + +AC_CONFIG_FILES([Makefile + doc/Makefile + src/Makefile]) + +AC_OUTPUT diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/Dockerfile b/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/Dockerfile new file mode 100644 index 0000000..c20a1d6 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/Dockerfile @@ -0,0 +1,17 @@ +FROM debian:stable + +# Base +RUN apt-get update && apt-get install -y \ + build-essential \ + automake \ + autoconf \ + m4 + +# Add source code +COPY ./ /app + +# Compile +WORKDIR /app +RUN autoreconf --install +RUN ./configure && make && make install +ENTRYPOINT ["fping"] \ No newline at end of file diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/fping.spec b/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/fping.spec new file mode 100644 index 0000000..71d1ea0 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/fping.spec @@ -0,0 +1,74 @@ +Summary: send ICMP echo probes to multiple hosts +Name: fping +Version: 4.2 +Release: 1 +License: Freely redistributable without restriction +Group: Applications/System +Source0: http://fping.org/dist/%{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot + +%description +fping is a program to send ICMP echo probes to network hosts, similar to ping, +but much better performing when pinging multiple hosts. fping has a very long +history: Roland Schemers did publish a first version of it in 1992 and it has +established itself since then as a standard tool for network diagnostics and +statistics. + +%prep +%setup -q + +%build + +if [ ! -f ./configure ] ; then + ./autogen.sh +fi + +# fping +%configure --enable-ipv4 +make + +# fping6 +%configure --enable-ipv6 +make +%{__mv} -f src/fping src/fping6 + +%install +rm -rf $RPM_BUILD_ROOT +make DESTDIR=$RPM_BUILD_ROOT install + +# fping6 +%{__install} -Dp -m4755 src/fping6 %{buildroot}%{_sbindir}/fping6 +%{__ln_s} -f fping.8 %{buildroot}%{_mandir}/man8/fping6.8 + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%attr(4755, root, root) /usr/sbin/fping +%attr(4755, root, root) /usr/sbin/fping6 +%doc README.md COPYING CHANGELOG.md +/usr/share/man/man8/fping.8.gz +/usr/share/man/man8/fping6.8.gz + +%post +if [ -x /usr/sbin/setcap ]; then + /bin/chmod 0755 /usr/sbin/fping* + /usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping + /usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping6 +fi + +%changelog +* Mon Dec 24 2012 Marcus Vinicius Ferreira +- Missing './configure' script when cloning from master. +- Making 'fping6'. +- Fix setuid permission to 'rwsr-xr-x'. +- doc files. +- Replacing setuid permission if 'setcap' is present on post-install. +- Using 'http://fping.org/dist/' for release source distributions. + +* Mon Jul 16 2012 Stephen Schaefer +- Initial build + +# vim:ft=spec: + diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/CHANGELOG.pre-v4 b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/CHANGELOG.pre-v4 new file mode 100644 index 0000000..fc9a0aa --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/CHANGELOG.pre-v4 @@ -0,0 +1,627 @@ +2017-02-09 David Schweikert + * Version 3.16 + * (feature) Support kernel-timestamping of received packets (#46) + * (feature) Simplify restrictions: only -i >= 1 and -p >= 10 are enforced now + * (bugfix) Fix option -m to return all IPs of a hostname + * (bugfix) Fix option -H (ttl) for IPv6 + * (bugfix) Fix option -M (don't fragment) for IPv6 + * (bugfix) Fix option -O (ToS) for IPv6 + * (bugfix) Fix compatibility issue with AIX (#69, @blentzgh) + * (bugfix) Fix option -q not suppressing some ICMP error messages (#83) + * (bugfix) Fix option -M expecting an argument, when it shouldn't + * (bugfix) Fix minor issues found by Coverity Scan + +2017-01-11 David Schweikert + * Version 3.15 + * (bugfix) Fix compiler errors on platforms other than Linux (related + to the new -M option, #109) + * Test suite fixes for macOS + +2017-01-10 David Schweikert + * Version 3.14 + * (feature) Ignore network and broadcast for cidrs /31 and /32 (#102, Martin Topholm) + * (feature) New option '-M' to set the "Don't Fragment" flag (#91, Don Bowman) + * (feature) New option '-N' to output statistics for netdata (see: http://my-netdata.io/, #105, Costa Tsaousis) + * (feature) New option '-o' to calculate total outage time (#90, @jgerbeck) + * (bugfix) Exit code should be 2 when the hostname can't be resolved + (fixes #98, reported by @green-fox) + * (bugfix) Fix issue compliling on RHEL/Centos 7 (#95, @jbackman) + * (bugfix) Lower -i limit to 1 instead of 10 + * (bugfix) Improve interval preciseness of -Q reporting + * (bugfix) Fix occasional false positive in -Q reporting (#97) + * (bugfix) Solaris 10 portability fix (#107, Peter Bray) + +2015-10-21 David Schweikert + * Version 3.13 + * (bugfix) Fix ICMP errors sometimes causing crashes with fping >= 3.11 + (fixes #85, reported by Jamie Heilman and Bill Blough) + +2015-10-14 David Schweikert + * Version 3.12 + * (bugfix) Fix fping6 -R (fixes #84, reported by Stuart Henderson) + +2015-10-12 David Schweikert + * Version 3.11 + * (feature) New option -R to use random bytes instead of NULLs (#72, Anthony DeRobertis) + * (feature) Small documentation and performance improvements (Ryan Underwood) + * (bugfix) Fix double entries with fping -u and unreachable hosts + * (internal) Use sockaddr_storage and simplify code, so that we can one day support both IPv4 and IPv6 with the same binary + +2014-05-03 David Schweikert + * Version 3.10 + * Fix confusing error message with -g and IPv6 addresses (#58, reported by Axel Beckert) + * Allow option '-f' also for non-root (since setuid privileges are dropped) + * Do not retry twice DNS lookup on DNS lookup problem + * Remove support for NIS groups + * Better document -B backoff-factor and when it can be used (#33, Oleksiy Zagorskyi) + * More tests added + +2014-03-08 David Schweikert + * Version 3.9 + * Fix random output on socket error (reported by Aleksandrs Saveljevs, #56) + * Support ppc64le architecture by including alpha libtool version + (reported by Amit Kumar Gupta and Aravinda B Thunug) + * Fix compilation problem on FreeBSD (#57) + * Initial test suite and continous intergration (with travis-ci.org / coveralls.io) + * Don't output usage information on error + +2013-11-08 David Schweikert + * Version 3.8 + * Fix segmentation fault introduced in version 3.7 with loop mode (reported + by Vlad Glagolev, #55) + +2013-11-04 David Schweikert + * Version 3.7 + * Allow running as non-root on Mac OS X by using non-privileged ICMP (#7) + * Remove unnecessary IPv6 socket options + * Fix again compatibility issue with FreeBSD (Shawn Chu) + * Fix fping hanging forever on permanent sendto failure (Shawn Chu) + * Fix duplicate echo reply packets causing early stop in count mode + (reported by Ramon Schwammberger, #53) + +2013-10-10 David Schweikert + * Version 3.6 + * Fix loop issue after 65536 pings (reported by Peter Folk and GBert, #12) + * Minimum ping data size is now 0 + * Removed setsockopt IPV6_CHECKSUM, which shouldn't be set and breaks + compiling on Solaris (reported by Juergen Arndt) + * Fix wrong min RTT value with -Q option (reported by Alexander Ivanov, #51) + +2013-05-22 David Schweikert + * Version 3.5 + * Fix sprint_tm buffer size crash (reported by Japheth Cleaver) + * Addded -D flag to print timestamps (Toke Høiland-Jørgensen) + * Fix fping6 build on OS X 10.8 (unknown contributor) + * Fix compatibility issue with FreeBSD (Alexandre Raynaud, Jason Harris, #39) + * Fping.spec: fix setuid permissions and provides fping6 (Marcus Vinicius Ferreira) + * Re-create configure script with autoconf 2.69 for aarch64 support (Chuck Anderson, #45) + +2012-09-04 David Schweikert + * Version 3.4 + * Revert "Output statistics to stdout instead of stderr", because it breaks + tools assuming the output goes to stderr + +2012-08-19 David Schweikert + * Version 3.3 + * Do not output icmp errors with -q (#1) + * Add --enable-ipv4 and --enable-ipv6 options to configure (Niclas Zeising) + * Fix removing of unreachable hosts when doing loop (Thomas Liske, #13 #23) + * Fix -A for fping6 (reported by Matt LaPlante, #14) + * Fix "options inet6" breaking IPv4 name resolution (reported by Matt LaPlante, #17) + * Output statistics to stdout instead of stderr (suggested by Simon Leinen, #9) + * Set default data size to 56 bytes on all architectures (#18) + * Added contrib/fping.spec (Stephen Schaefer, #24) + * Convert man-page source to POD for easier maintenance + * Fix error message on DNS error for IPv6 hosts (#27) + * Fix -n flag in fping6 (#28) + * Man-page fix: TOS option typo (Thomas Liske, #23) + * Man-page fix: inconsistency in regards to numeric arguments (Robert Henney) + * Man-page fix: better description of option -q (#15) + +2012-05-29 David Schweikert + * Version 3.2 + * Improve documentation for -g option (G.W. Haywood) + * Performance optimization for big select timeouts (#10, Andrey Bondarenko) + * Fix restart of select call after interrupt signal (#8, Boian Bonev) + * Fix infinite loop caused by linked list corruption (#11, Boian Bonev) + +2012-04-26 David Schweikert + * Version 3.1 + * -g option (generate): exclude network and broadcast address for cidr + ranges (idea by Eric Brander) + * do not explicitely check if running as root, to make it possible to + install fping with linux capabilities instead of making it setuid + (setcap cap_net_raw+ep fping) + * ANSI C (C89) compiler now a requirement + * Portability fixes + * Reorganized source directory + * Bugfix: fix timeout issue on Solaris (Sandor Geller) + * Man-page fixes (Axel Beckert) + * Added -H option to specify number of hops (Paul Duda) + * Output usage information to stdout when called with -h (Paul Duda) + +2011-12-28 David Schweikert + * Version 3.0 + * rewritten main loop for improved performance + * -T parameter (select timeout) now obsolete + * Maintenance taken over from unresponsive previous maintainer + (anybody please step up, if you disagree) + * New homepage: www.fping.org + +2009-12-21 Tobi Oetiker + * Version v2.4b2-to3-ipv6 + * added -On option to set the TOS octet + * Removed unused variables from code + * updated to current autoconf standards + * Merged Debian changes (see below) + +---------------------------------------------------------------------- + +fping (2.4b2-to-ipv6-16.1) unstable; urgency=low + + * NMU during Moenchengladbach BSP + * Fixes FTBFS on kfreebsd (Closes: #555398) + * Fixes typo "Paramter" in binary + + -- Axel Beckert Sat, 23 Jan 2010 16:22:02 +0100 + +fping (2.4b2-to-ipv6-16) unstable; urgency=low + + * Fix the following bugs + - Network byte order sensitivity was missing completely. + Added hopefully all missing calls. + - The sequence numbering scheme used led to packet drops. + Changed it to a more senseful numbering scheme. + - Some minor C programming mistakes ('=' instead of '=='). + Patch by Stephan Fuhrmann; closes: #502569 + * Add support for command line select timeout setting + Patch by Marton Balint; closes: #502575 + * Remove symlinks in /usr/sbin; closes: #377732 + * Standards-Version is 3.8.0 + + -- Anibal Monsalve Salazar Sat, 18 Oct 2008 12:04:52 +1100 + +fping (2.4b2-to-ipv6-15) unstable; urgency=low + + * Added interface binding (-I) for fping + Patch by Peter Naulls + Closes: #439014 + * Fixed a couple of typos in fping.8. Closes: #423180 + * Added homepage control header + * Bumped Standards-Version to 3.7.3 + * Fixed the following lintian issue: + - debian-rules-sets-DH_COMPAT + + -- Anibal Monsalve Salazar Mon, 03 Mar 2008 17:46:17 +1100 + +fping (2.4b2-to-ipv6-13) unstable; urgency=low + + * Fixed stdout flush problem, closes: #340146. + Patch by Bart Martens . + + -- Anibal Monsalve Salazar Fri, 30 Dec 2005 08:30:09 +1100 + +fping (2.4b2-to-ipv6-12) unstable; urgency=low + + * Fixed "problem with option -r (retry limit)", closes: #318402. + Patch by Qingning Huo . + + -- Anibal Monsalve Salazar Sat, 08 Oct 2005 21:26:35 +1000 + +fping (2.4b2-to-ipv6-11) unstable; urgency=low + + * Fixed "would be useful to specify 'source address' like ping for multi + homed machines", closes: #198486. + Patch by Marc Haber . + + -- Anibal Monsalve Salazar Thu, 02 Jun 2005 08:14:54 +1000 + +fping (2.4b2-to-ipv6-10) unstable; urgency=low + + * Fixed "unnecessary delay with the -c option after the last packet" + (Closes: #293856). Patch by Niko Tyni + + -- Anibal Monsalve Salazar Sun, 06 Feb 2005 23:25:57 +1100 + +fping (2.4b2-to-ipv6-9) unstable; urgency=low + + * Fixed "fping6 always does reverse lookup" (Closes: #273647). + Patch by Jeroen Massar and forwarded by Bernhard Schmidt + + -- Anibal Monsalve Salazar Mon, 10 Jan 2005 00:01:32 +1100 + +fping (2.4b2-to-ipv6-7) unstable; urgency=low + + * Build fping in build/ipv[46] instead of build and build-ipv6. + * Made DNS errors non-fatal for IPv6 (closes: #198056). + + -- Herbert Xu Fri, 20 Jun 2003 21:36:30 +1000 + +fping (2.4b2-to-ipv6-6) unstable; urgency=low + + * Do not use incorrect linux.h file (closes: #85468). + + -- Herbert Xu Sat, 17 May 2003 14:13:11 +1000 + +fping (2.4b2-to-ipv6-5) unstable; urgency=low + + * Fixed yet another divide by zero bug (closes: #148445). + + -- Herbert Xu Tue, 4 Jun 2002 12:18:03 +1000 + +fping (2.4b2-to-ipv6-4) unstable; urgency=low + + * Made fping6 setuid (closes: #136386). + * Moved fping back into bin. + * Partially applied IPv6 patch to fix IPv6 checksums (closes: #136479). + + -- Herbert Xu Sun, 7 Apr 2002 20:36:56 +1000 + +fping (2.4b2-to-ipv6-3) unstable; urgency=low + + * Added compatibility symlink for fping (closes: #135203). + + -- Herbert Xu Sat, 23 Feb 2002 08:34:11 +1100 + +fping (2.4b2-to-ipv6-2) unstable; urgency=low + + * Fixed another divide by zero error (closes: #132370). + + -- Herbert Xu Thu, 7 Feb 2002 20:10:48 +1100 + +fping (2.4b2-to-ipv6-1) unstable; urgency=low + + * New upstream release. + * Install fping into sbin as done by upstream. + + -- Herbert Xu Fri, 1 Feb 2002 22:11:59 +1100 + +fping (2.2b2-3) unstable; urgency=low + + * Removed INSTALL file from package (closes: #84050). + * Fixed alignment bug. + + -- Herbert Xu Sat, 10 Feb 2001 19:25:18 +1100 + +fping (2.2b2-2) unstable; urgency=low + + * Made changes for dpkg-statoverride (closes: #83838). + + -- Herbert Xu Sun, 28 Jan 2001 21:53:05 +1100 + +fping (2.2b2-1) unstable; urgency=low + + * New upstream release. + * Fixed typo that prevented -d from working (closes: #83255). + * Drop root privileges after opening the socket (closes: #81589). + * Fixed the options [tip], they were out by a factor of 10 + (Richard Kettlewell, closes: #83742). + + -- Herbert Xu Sun, 28 Jan 2001 00:09:41 +1100 + +fping (2.2b1-2) unstable; urgency=low + + * Fixed typo in control file, spotted by William Ono (closes: #49909). + + -- Herbert Xu Mon, 15 May 2000 12:27:03 +1000 + +fping (2.2b1-1) unstable; urgency=low + + * Initial release. + * Fixed divide by zero error (closes: #29902). + + -- Herbert Xu Sat, 30 Oct 1999 16:36:19 +1000 +--------------------------------------------------------------------------------- + +Wed Jan 16 2002 +Jeroen Massar +- Revision v2.4b2-to-IPv6 + - Added IPv6 support. + - Added -I option for selecting source IPv4/IPv6 address. + - Makefile.in now generates a Makefile which will build both + fping (IPv4) and fping6 (IPv6). Thus it makes an fping (IPv4 only) + and an fping6 (IPv6 only). + - num_unreachable was counted twice when a sendto() generated errors. + - See http://unfix.org/projects/ipv6/ + +Tue Mar 14 2001 +Jason Ewasiuk +- Revision v2.4b1 + - added -g option for generating IPs from a start to an end value + - two available options, generate IPs from start IP to end IP + or from a passed netmask, such as 192.168.1.0/24 + +Thu Feb 15 2001 +Jason Ewasiuk +- 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 + + - 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 + + * stop using sys_errlist and start using strerror + fixed bug in output of -C + +Wed Jan 8 11:18:37 1997 Roland Schemers + + * Created ChangeLog file. What follows was from the CHANGES file. + +* Revision 2.0 1994/10/31 21:26:23 morgan + + Substantial rewrite, including new features: + + support some traditional ping features: + loop mode + specify size of data packets + specify how many pings to send + show per-response data + interpret ICMPs other than ICMP Echo response + + also + + rewrote main loop completely + make timings in tenths of milliseconds + do exponential backoff on retries + port to more systems + add some debugging stuff + do better checking on whether received ICMP is for us + +* Revision 1.24 1993/12/10 23:11:39 schemers + + commented out seteuid(getuid()) since it isn't needed + +* Revision 1.23 1993/12/10 18:33:41 schemers + + Took out the -f option for non-root users. This can be enabled by + defining ENABLE_F_OPTION before compiling. There is a call to + access before opening the file, but there is a race condition. + Reading from stdin is much safer. + + +* Revision 1.22 1993/11/16 19:49:24 schemers + + Took out setuid(getuid()) and used access() system call to + check for access to the file specified with "-f". + +* Revision 1.21 1993/07/20 18:08:19 schemers + + commented out the test to make sure the ping packet came from the + same IP address as the one we sent to. This could cause problems on + multi-homed hosts. + +* Revision 1.20 1993/02/23 00:16:38 schemers + +fixed syntax error (should have compiled before checking in...) + +* Revision 1.19 1993/02/23 00:15:15 schemers + +turned off printing of "is alive" when -a is specified. + +* Revision 1.18 1992/07/28 15:16:44 schemers + +added a fflush(stdout) call before the summary is sent to stderr, so +everything shows up in the right order. + +* Revision 1.17 1992/07/23 03:29:42 schemers +* Revision 1.16 1992/07/22 19:24:37 schemers + +Fixed declaration of timeval_diff. Didn't notice the problem because +I use 'cc' in stead of gcc under Ultrix. Time to switch? :-) + +Modified file reaing so it would skip blank lines or lines starting +with a '#'. Now you can do something like: + +fping -ad < /etc/hosts + +* Revision 1.15 1992/07/21 17:07:18 schemers + +Put in sanity checks so only root can specify "dangerous" options. +Changed usage to show switchs in alphabetical order. +* Revision 1.14 1992/07/21 16:40:52 schemers +* Revision 1.13 1992/07/17 21:02:17 schemers + +Changed the default timeout to 2500 msec, and retry to 3. This was +due to suggestions from people with slow (WAN) networks. The default +1 sec timeout was too fast. + + +Added '-e' option for showing elapsed (round-trip) times on pakets, and +modified the -s option to include min, max, and average round-trip times, +and over all elapsed time. + +Modified action taken when a error is returned from sendto. The action +taken now considers the host unreachable and prints the hostname +followed by the errno message. The program will not exit and will continue +to try other hosts. + +* Revision 1.12 1992/07/17 16:38:54 schemers +* Revision 1.11 1992/07/17 16:28:38 schemers + + move socket create call so I could do a setuid(getuid()) before the + fopen call is made. Once the socket is created root privs aren't needed + to send stuff out on it. + + moved num_timeout counter. It really was for debug purposes and didn't + make sense to the general public :-) Now it is the number of timeouts + (pings that didn't get received with the time limit). + + +* Revision 1.10 1992/07/16 16:24:38 schemers +* Revision 1.9 1992/07/16 16:00:04 schemers +* Revision 1.8 1992/07/16 05:44:41 schemers + +Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE +for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added +check for __cplusplus. + +Now compiles ok under Ultrix 3.1, and Sun4 using cc. Also compiled +ok using g++ 2.2.2. + +Changed '-a' and '-u' flags to be mutually exclusive (makes sense, since +specifiying both '-a' and '-u' is the same as not specifiying anything. +Since '-a' and '-u' are mutually exclusive, these options now only print +the hostname, and not the 'is alive' or 'is unreachable' messages. +This makes it much easier to do stuff like: + +#!/usr/local/bin/perl +$hosts_to_backup=`cat /etc/hosts.backup|fping -a`; + +Since you don't have to strip off the 'is alive' messages. + +Changed usage to and stats to print to stderr instead of stdout. + +----------------------------------------------------------------------------- + +RCS header info from original fping.c package (no longer required) + +/* + *************************************************** + * + * Standard RCS Header information (see co(1)) + * + * $Author: schemers $ + * + * $Date: 1997/01/08 20:29:33 $ + * + * $Revision: 2.2 $ + * + * $Locker: $ + * + * $Source: /afs/ir/group/networking/src/fping/fping-2.2/src/RCS/fping.c,v $ + * + * $State: Exp $ + * + * $Log: fping.c,v $ + * + * Revision 2.2 1997/01/08 20:29:33 schemers + * changes for autoconf/automake + * + * Revision 2.1 1997/01/08 19:07:18 schemers + * checked in RL "Bob"'s changes before configure'ing + * + * Revision 2.0 1994/10/31 21:26:23 schemers + * many changes by RL "Bob" Morgan + * add timing data collection, loop mode, per-packet output, etc + * + * Revision 1.24 1993/12/10 23:11:39 schemers + * commented out seteuid(getuid()) since it isn't needed + * + * Revision 1.23 1993/12/10 18:33:41 schemers + * Took out the -f option for non-root users. This can be enabled by + * defining ENABLE_F_OPTION before compiling. There is a call to + * access before opening the file, but there is a race condition. + * Reading from stdin is much safer. + * + * Revision 1.22 1993/11/16 19:49:24 schemers + * Took out setuid(getuid()) and used access() system call to + * check for access to the file specified with "-f". + * + * Revision 1.21 1993/07/20 18:08:19 schemers + * commented out the test to make sure the ping packet came from the + * same IP address as the one we sent to. This could cause problems on + * multi-homed hosts. + * + * Revision 1.20 1993/02/23 00:16:38 schemers + * fixed syntax error (should have compiled before checking in...) + * + * Revision 1.19 1993/02/23 00:15:15 schemers + * turned off printing of "is alive" when -a is specified. + * + * Revision 1.18 1992/07/28 15:16:44 schemers + * added a fflush(stdout) call before the summary is sent to stderr, so + * everything shows up in the right order. + * + * Revision 1.17 1992/07/23 03:29:42 schemers + * fixed declaration of timeval_diff. + * + * Revision 1.16 1992/07/22 19:24:37 schemers + * Modified file reading so it would skip blanks lines or lines starting + * with a '#'. Now you can do something like: + * + * fping -ad < /etc/hosts + * + * Revision 1.15 1992/07/21 17:07:18 schemers + * Put in sanity checks so only root can specify "dangerous" options. + * Changed usage to show switchs in alphabetical order. + * + * Revision 1.14 1992/07/21 16:40:52 schemers + * Now when sendto returns an error, the host is considered unreachable and + * and the error message (from errno) is displayed. + * + * Revision 1.13 1992/07/17 21:02:17 schemers + * changed default timeout to 2500 msec (for WANs), and default try + * to 3. This gives 10 second overall timeout. + * + * Added -e option for showing elapsed (round-trip) time on packets + * + * Modified -s option to inlude to round-trip stats + * + * Added #ifndef DEFAULT_* stuff its easier to change the defaults + * + * Reorganized main loop. + * + * cleaned up timeval stuff. removed set_timeval and timeval_expired + * since they aren't needed anymore. Just use timeval_diff. + * + * Revision 1.12 1992/07/17 16:38:54 schemers + * move socket create call so I could do a setuid(getuid()) before the + * fopen call is made. Once the socket is created root privs aren't needed + * to send stuff out on it. + * + * Revision 1.11 1992/07/17 16:28:38 schemers + * moved num_timeout counter. It really was for debug purposes and didn't + * make sense to the general public :-) Now it is the number of timeouts + * (pings that didn't get received with the time limit). + * + * Revision 1.10 1992/07/16 16:24:38 schemers + * changed usage() to use fprintf(stderr,"..."); + * + * Revision 1.9 1992/07/16 16:00:04 schemers + * Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE + * for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added + * check for __cplusplus. + * + * Revision 1.8 1992/07/16 05:44:41 schemers + * changed -a and -u to only show hostname in results. This is + * for easier parsing. Also added -v flag + * + * Revision 1.7 1992/07/14 18:45:23 schemers + * initialized last_time in add_host function + * + * Revision 1.6 1992/07/14 18:32:40 schemers + * changed select to use FD_ macros + * + * Revision 1.5 1992/07/14 17:21:22 schemers + * standardized exit status codes + * + * Revision 1.4 1992/06/26 15:25:35 schemers + * changed name from rrping to fping + * + * Revision 1.3 1992/06/24 15:39:32 schemers + * added -d option for unreachable systems + * + * Revision 1.2 1992/06/23 03:01:23 schemers + * misc fixes from R.L. "Bob" Morgan + * + * Revision 1.1 1992/06/19 18:23:52 schemers + * Initial revision + * + *-------------------------------------------------- + * Copyright (c) 1992, 1994, 1997 Board of Trustees + * Leland Stanford Jr. University + *************************************************** + */ + + diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/Makefile.am b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/Makefile.am new file mode 100644 index 0000000..20adc28 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/Makefile.am @@ -0,0 +1,6 @@ +man_MANS = fping.8 + +EXTRA_DIST = fping.8 fping.pod README.1992 CHANGELOG.pre-v4 + +fping.8: fping.pod + pod2man -c "" -s 8 -r "fping" $< >$@ diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/README.1992 b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/README.1992 new file mode 100644 index 0000000..a1020cd --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/README.1992 @@ -0,0 +1,43 @@ +Original README (from 1992) + + fping - A tool to quickly ping N number of hosts to determine + their reachability. + + Roland J. Schemers III - Stanford University + schemers@Stanford.EDU + + fping is a ping(1) like program which uses the Internet Control + Message Protocol (ICMP) echo request to determine if a host is + up. fping is different from ping in that you can specify any + number of hosts on the command line, or specify a file containing + the lists of hosts to ping. Instead of trying one host until it + timeouts or replies, fping will send out a ping packet and move + on to the next host in a round-robin fashion. If a host replies, + it is noted and removed from the list of hosts to check. If a host + does not respond within a certain time limit and/or retry limit it + will be considered unreachable. + +Site + Stanford University has a large TCP/IP network with over 16,000 + assigned IP addresses and over 100 IP subnets. + +Problem and Issues + + With a large a number of IP addresses in use, its becomes more and + more time consuming to check on which IP addresses are actively + in use, and which critical machines (routers, bridges, servers, etc) + are reachable. One example is we have a program which goes through + all of our routers arp caches looking for IP addresses that are in + use. After finding a list of IP addresses that aren't in any arp + caches fping can then be used to see if these IP addresses really + aren't being used, or are just behind the routers. Checking 2500 + hosts (99% of which are unreachable) via ping can take hours. + + fping was written to solve the problem of pinging N number of hosts + in an efficient manner. By sending out pings in a round-robin fashion + and checking on responses as they come in at random, a large number of + hosts can be checked at once. + + Unlike ping, fping is meant to be used in scripts and its + output is easy to parse. + diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.8 b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.8 new file mode 100644 index 0000000..bc4abeb --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.8 @@ -0,0 +1,420 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "FPING 8" +.TH FPING 8 "2025-08-19" "fping" "" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +fping \- send ICMP ECHO_REQUEST packets to network hosts +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBfping\fR [ \fIoptions\fR ] [ \fIsystems...\fR ] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBfping\fR is a program like \fBping\fR which uses the Internet Control Message +Protocol (\s-1ICMP\s0) echo request to determine if a target host is responding. +\&\fBfping\fR differs from \fBping\fR in that you can specify any number of targets on the +command line, or specify a file containing the lists of targets to ping. +Instead of sending to one target until it times out or replies, \fBfping\fR will +send out a ping packet and move on to the next target in a round-robin fashion. +In the default mode, if a target replies, it is noted and removed from the list +of targets to check; if a target does not respond within a certain time limit +and/or retry limit it is designated as unreachable. \fBfping\fR also supports +sending a specified number of pings to a target, or looping indefinitely (as in +\&\fBping\fR ). Unlike \fBping\fR, \fBfping\fR is meant to be used in scripts, so its +output is designed to be easy to parse. Current statistics can be obtained without +termination of process with signal \s-1SIGQUIT\s0 (^\e from the keyboard on most systems). +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-4\fR, \fB\-\-ipv4\fR" 5 +.IX Item "-4, --ipv4" +Restrict name resolution and IPs to IPv4 addresses. +.IP "\fB\-6\fR, \fB\-\-ipv6\fR" 5 +.IX Item "-6, --ipv6" +Restrict name resolution and IPs to IPv6 addresses. +.IP "\fB\-a\fR, \fB\-\-alive\fR" 5 +.IX Item "-a, --alive" +Show systems that are alive. (Options \fB\-c\fR and \fB\-C\fR override \fB\-a\fR.) +.IP "\fB\-A\fR, \fB\-\-addr\fR" 5 +.IX Item "-A, --addr" +Display targets by address rather than \s-1DNS\s0 name. Combined with \-d, the output +will be both the ip and (if available) the hostname. +.IP "\fB\-b\fR, \fB\-\-size\fR=\fI\s-1BYTES\s0\fR" 5 +.IX Item "-b, --size=BYTES" +Number of bytes of ping data to send. The minimum size (normally 12) allows +room for the data that \fBfping\fR needs to do its work (sequence number, +timestamp). The reported received data size includes the \s-1IP\s0 header (normally +20 bytes) and \s-1ICMP\s0 header (8 bytes), so the minimum total size is 40 bytes. +Default is 56, as in \fBping\fR. Maximum is the theoretical maximum \s-1IP\s0 datagram +size (64K), though most systems limit this to a smaller, system-dependent +number. Cannot be used together with \fB\-\-icmp\-timestamp\fR. +.IP "\fB\-B\fR, \fB\-\-backoff\fR=\fIN\fR" 5 +.IX Item "-B, --backoff=N" +Backoff factor. In the default mode, \fBfping\fR sends several requests to a +target before giving up, waiting longer for a reply on each successive request. +This parameter is the value by which the wait time (\fB\-t\fR) is multiplied on each +successive request; it must be entered as a floating-point number (x.y). The +default is 1.5. +.IP "\fB\-c\fR, \fB\-\-count\fR=\fIN\fR" 5 +.IX Item "-c, --count=N" +Number of request packets to send to each target. In this mode, a line is +displayed for each received response (this can suppressed with \fB\-q\fR or \fB\-Q\fR). +Also, statistics about responses for each target are displayed when all +requests have been sent (or when interrupted). This option overrides \fB\-a\fR +or \fB\-u\fR. +.IP "\fB\-C\fR, \fB\-\-vcount\fR=\fIN\fR" 5 +.IX Item "-C, --vcount=N" +Similar to \fB\-c\fR, but the per-target statistics are displayed in a format +designed for automated response-time statistics gathering. For example: +.Sp +.Vb 2 +\& $ fping \-C 5 \-q somehost +\& somehost : 91.7 37.0 29.2 \- 36.8 +.Ve +.Sp +shows the response time in milliseconds for each of the five requests, with the +\&\f(CW\*(C`\-\*(C'\fR indicating that no response was received to the fourth request. This +option overrides \fB\-a\fR or \fB\-u\fR. +.IP "\fB\-\-check\-source\fR" 5 +.IX Item "--check-source" +Discard Echo replies that are sourced from a different address than the target +address. This avoids spurious reachability results on busy monitoring systems +where two \fBfping\fR instances with the same lower 16 bits of the process \s-1ID\s0 may +be running at the same time. +.IP "\fB\-d\fR, \fB\-\-rdns\fR" 5 +.IX Item "-d, --rdns" +Use \s-1DNS\s0 to lookup address of ping target. This allows you to give fping +a list of \s-1IP\s0 addresses as input and print hostnames in the output. This is similar +to option \fB\-n\fR/\fB\-\-name\fR, but will force a reverse-DNS lookup even if you give +hostnames as target (\s-1NAME\-\s0>\s-1IP\-\s0>\s-1NAME\s0). +.IP "\fB\-D\fR, \fB\-\-timestamp\fR" 5 +.IX Item "-D, --timestamp" +Add Unix timestamps in front of output lines generated with in looping or counting +modes (\fB\-l\fR, \fB\-c\fR, or \fB\-C\fR). +.Sp +Subcommand: \fB\-\-timestamp\-format\fR=\fIctime|iso|rfc3339\fR +.Sp +Allow to change the timestamp format of the \fB\-D\fR option to the following format types. +.Sp +\&\fIctime\fR = \*(L"%c\*(R" (Example: Mon Jun 10 07:50:00 2024) +.Sp +\&\fIiso\fR = \*(L"%Y\-%m\-%dT%T%z\*(R" (Example: 2024\-06\-10T07:50:00+0200) +.Sp +\&\fIrfc3339\fR = \*(L"%Y\-%m\-%d \f(CW%H:\fR%M:%S\*(R" (Example: 2024\-06\-10 07:50:00) +.IP "\fB\-e\fR, \fB\-\-elapsed\fR" 5 +.IX Item "-e, --elapsed" +Show elapsed (round-trip) time of packets. +.IP "\fB\-f\fR, \fB\-\-file\fR" 5 +.IX Item "-f, --file" +Read list of targets from a file. +.IP "\fB\-g\fR, \fB\-\-generate\fR \fIaddr/mask\fR" 5 +.IX Item "-g, --generate addr/mask" +Generate a target list from a supplied \s-1IP\s0 netmask, or a starting and ending \s-1IP.\s0 +Specify the netmask or start/end in the targets portion of the command line. If +a network with netmask is given, the network and broadcast addresses will be +excluded. ex. To ping the network 192.168.1.0/24, the specified command line +could look like either: +.Sp +.Vb 1 +\& $ fping \-g 192.168.1.0/24 +.Ve +.Sp +or +.Sp +.Vb 1 +\& $ fping \-g 192.168.1.1 192.168.1.254 +.Ve +.IP "\fB\-h\fR, \fB\-\-help\fR" 5 +.IX Item "-h, --help" +Print usage message. +.IP "\fB\-H\fR, \fB\-\-ttl\fR=\fIN\fR" 5 +.IX Item "-H, --ttl=N" +Set the \s-1IP TTL\s0 field (time to live hops). +.IP "\fB\-\-print\-ttl\fR" 5 +.IX Item "--print-ttl" +Displays the IPv4 \s-1TTL\s0 value from the \s-1IP\s0 Header in the output. +If \fBfping\fR cannot read the \s-1TTL\s0 value, \*(L"(\s-1TTL\s0 unknown)\*(R" is returned. +IPv4 only, requires root privileges or cap_net_raw. +.IP "\fB\-i\fR, \fB\-\-interval\fR=\fI\s-1MSEC\s0\fR" 5 +.IX Item "-i, --interval=MSEC" +The minimum amount of time (in milliseconds) between sending a ping packet +to any target (default is 10, minimum is 1). +.IP "\fB\-I\fR, \fB\-\-iface\fR=\fI\s-1IFACE\s0\fR" 5 +.IX Item "-I, --iface=IFACE" +Set the interface (requires \s-1SO_BINDTODEVICE\s0 support). +.IP "\fB\-\-icmp\-timestamp\fR" 5 +.IX Item "--icmp-timestamp" +Send \s-1ICMP\s0 timestamp requests (\s-1ICMP\s0 type 13) instead of \s-1ICMP\s0 Echo requests. +Print \s-1ICMP\s0 timestamps for originate, receive, and transmit, together with +the local receive time in the same format, in addition to normal output. +Cannot be used together with \fB\-b\fR because \s-1ICMP\s0 timestamp messages have a fixed size. +IPv4 only, requires root privileges or cap_net_raw. +.IP "\fB\-k\fR, \fB\-\-fwmark\fR=\fI\s-1FWMARK\s0\fR" 5 +.IX Item "-k, --fwmark=FWMARK" +Set \s-1FWMARK\s0 on ping packets for policy-based routing. Requires Linux kernel +2.6.25<=, and root privileges or cap_net_admin. +.IP "\fB\-l\fR, \fB\-\-loop\fR" 5 +.IX Item "-l, --loop" +Loop sending packets to each target indefinitely. Can be interrupted with +Ctrl-C; statistics about responses for each target are then displayed. +.IP "\fB\-m\fR, \fB\-\-all\fR" 5 +.IX Item "-m, --all" +Send pings to each of a target host's multiple \s-1IP\s0 addresses (use of option '\-A' +is recommended). +.IP "\fB\-M\fR, \fB\-\-dontfrag\fR" 5 +.IX Item "-M, --dontfrag" +Set the \*(L"Don't Fragment\*(R" bit in the \s-1IP\s0 header (used to determine/test the \s-1MTU\s0). +.IP "\fB\-n\fR, \fB\-\-name\fR" 5 +.IX Item "-n, --name" +If targets are specified as \s-1IP\s0 addresses, do a reverse-DNS lookup on them +to print hostnames in the output. +.IP "\fB\-N\fR, \fB\-\-netdata\fR" 5 +.IX Item "-N, --netdata" +Format output for netdata (\-l \-Q are required). See: +.IP "\fB\-o\fR, \fB\-\-outage\fR" 5 +.IX Item "-o, --outage" +Calculate \*(L"outage time\*(R" based on the number of lost pings and the interval used (useful for network convergence tests). +.IP "\fB\-O\fR, \fB\-\-tos\fR=\fIN\fR" 5 +.IX Item "-O, --tos=N" +Set the typ of service flag (\s-1TOS\s0). \fIN\fR can be either decimal or hexadecimal +(0xh) format. +.IP "\fB\-\-print\-tos\fR" 5 +.IX Item "--print-tos" +Displays the \s-1TOS\s0 value in the output. If \fBfping\fR cannot read the \s-1TOS\s0 value, +\&\*(L"(\s-1TOS\s0 unknown)\*(R" is returned. +IPv4 only, requires root privileges or cap_net_raw. +.IP "\fB\-p\fR, \fB\-\-period\fR=\fI\s-1MSEC\s0\fR" 5 +.IX Item "-p, --period=MSEC" +In looping or counting modes (\fB\-l\fR, \fB\-c\fR, or \fB\-C\fR), this parameter sets +the time in milliseconds that \fBfping\fR waits between successive packets to +an individual target. Default is 1000 and minimum is 10. +.IP "\fB\-q\fR, \fB\-\-quiet\fR" 5 +.IX Item "-q, --quiet" +Quiet. Don't show per-probe results, but only the final summary. Also don't +show \s-1ICMP\s0 error messages. +.IP "\fB\-Q\fR, \fB\-\-squiet\fR=\fISECS[,cumulative]\fR" 5 +.IX Item "-Q, --squiet=SECS[,cumulative]" +Like \fB\-q\fR, but additionally show interval summary results every \fI\s-1SECS\s0\fR +seconds. With \fIcumulative\fR, show summary results since start instead of +for the last interval, unless option \fB\-N\fR is used, too. +.IP "\fB\-r\fR, \fB\-\-retry\fR=\fIN\fR" 5 +.IX Item "-r, --retry=N" +Retry limit (default 3). This is the number of times an attempt at pinging +a target will be made, not including the first try. +.IP "\fB\-R\fR, \fB\-\-random\fR" 5 +.IX Item "-R, --random" +Instead of using all-zeros as the packet data, generate random bytes. +Use to defeat, e.g., link data compression. +.IP "\fB\-s\fR, \fB\-\-stats\fR" 5 +.IX Item "-s, --stats" +Print cumulative statistics upon exit. +.IP "\fB\-S\fR, \fB\-\-src\fR=\fIaddr\fR" 5 +.IX Item "-S, --src=addr" +Set source address. +.IP "\fB\-t\fR, \fB\-\-timeout\fR=\fI\s-1MSEC\s0\fR" 5 +.IX Item "-t, --timeout=MSEC" +Initial target timeout in milliseconds. In the default, non-loop mode, the +default timeout is 500ms, and it represents the amount of time that \fBfping\fR +waits for a response to its first request. Successive timeouts are multiplied +by the backoff factor specified with \fB\-B\fR. +.Sp +In loop/count mode, the default timeout is automatically adjusted to match +the \*(L"period\*(R" value (but not more than 2000ms). You can still adjust the timeout +value with this option, if you wish to, but note that setting a value larger +than \*(L"period\*(R" produces inconsistent results, because the timeout value can +be respected only for the last ping. +.Sp +Also note that any received replies that are larger than the timeout value, will +be discarded. +.IP "\fB\-T\fR \fIn\fR" 5 +.IX Item "-T n" +Ignored (for compatibility with fping 2.4). +.IP "\fB\-u\fR, \fB\-\-unreach\fR" 5 +.IX Item "-u, --unreach" +Show targets that are unreachable. (Options \fB\-c\fR and \fB\-C\fR override \fB\-u\fR.) +.IP "\fB\-v\fR, \fB\-\-version\fR" 5 +.IX Item "-v, --version" +Print \fBfping\fR version information. +.IP "\fB\-x\fR, \fB\-\-reachable\fR=\fIN\fR" 5 +.IX Item "-x, --reachable=N" +Given a list of hosts, this mode checks if number of reachable hosts is >= N +and exits true in that case. +.IP "\fB\-X\fR, \fB\-\-fast\-reachable\fR=\fIN\fR" 5 +.IX Item "-X, --fast-reachable=N" +Given a list of hosts, this mode immediately exits true once N alive hosts +have been found. +.SH "EXAMPLES" +.IX Header "EXAMPLES" +Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to +each host), and report every ping \s-1RTT\s0 at the end: +.PP +.Vb 1 +\& $ fping \-\-quiet \-\-interval=1 \-\-vcount=20 \-\-period=50 127.0.0.1 127.0.0.2 +.Ve +.SH "AUTHORS" +.IX Header "AUTHORS" +.IP "\(bu" 4 +Roland J. Schemers \s-1III,\s0 Stanford University, concept and versions 1.x +.IP "\(bu" 4 +\&\s-1RL\s0 \*(L"Bob\*(R" Morgan, Stanford University, versions 2.x +.IP "\(bu" 4 +David Papp, versions 2.3x and up +.IP "\(bu" 4 +David Schweikert, versions 3.0 and up +.PP +\&\fBfping website: \fR +.SH "DIAGNOSTICS" +.IX Header "DIAGNOSTICS" +Exit status is 0 if all the hosts (or the number of hosts specified with \fB\-x\fR +or \fB\-X\fR) are reachable, 1 if some (or too many with \fB\-x\fR or \fB\-X\fR) hosts +were unreachable, 2 if any \s-1IP\s0 addresses were not found, 3 for invalid command +line arguments, and 4 for a system call failure. +.SH "RESTRICTIONS" +.IX Header "RESTRICTIONS" +The number of addresses that can be generated using the \f(CW\*(C`\-g\*(C'\fR, \f(CW\*(C`\-\-generate\*(C'\fR +option is limited to 131070 (the number of host addresses in one 15\-bit IPv4 +prefix). +.PP +If fping was configured with \f(CW\*(C`\-\-enable\-safe\-limits\*(C'\fR, the following values are +not allowed for non-root users: +.IP "\(bu" 4 +\&\fB\-i\fR \fIn\fR, where \fIn\fR < 1 msec +.IP "\(bu" 4 +\&\fB\-p\fR \fIn\fR, where \fIn\fR < 10 msec +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\f(CWping(8)\fR diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.pod b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.pod new file mode 100644 index 0000000..7709225 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.pod @@ -0,0 +1,345 @@ +=head1 NAME + +fping - send ICMP ECHO_REQUEST packets to network hosts + +=head1 SYNOPSIS + +B [ I ] [ I ] + +=head1 DESCRIPTION + +B is a program like B which uses the Internet Control Message +Protocol (ICMP) echo request to determine if a target host is responding. +B differs from B in that you can specify any number of targets on the +command line, or specify a file containing the lists of targets to ping. +Instead of sending to one target until it times out or replies, B will +send out a ping packet and move on to the next target in a round-robin fashion. +In the default mode, if a target replies, it is noted and removed from the list +of targets to check; if a target does not respond within a certain time limit +and/or retry limit it is designated as unreachable. B also supports +sending a specified number of pings to a target, or looping indefinitely (as in +B ). Unlike B, B is meant to be used in scripts, so its +output is designed to be easy to parse. Current statistics can be obtained without +termination of process with signal SIGQUIT (^\ from the keyboard on most systems). + +=head1 OPTIONS + +=over 5 + +=item B<-4>, B<--ipv4> + +Restrict name resolution and IPs to IPv4 addresses. + +=item B<-6>, B<--ipv6> + +Restrict name resolution and IPs to IPv6 addresses. + +=item B<-a>, B<--alive> + +Show systems that are alive. (Options B<-c> and B<-C> override B<-a>.) + +=item B<-A>, B<--addr> + +Display targets by address rather than DNS name. Combined with -d, the output +will be both the ip and (if available) the hostname. + +=item B<-b>, B<--size>=I + +Number of bytes of ping data to send. The minimum size (normally 12) allows +room for the data that B needs to do its work (sequence number, +timestamp). The reported received data size includes the IP header (normally +20 bytes) and ICMP header (8 bytes), so the minimum total size is 40 bytes. +Default is 56, as in B. Maximum is the theoretical maximum IP datagram +size (64K), though most systems limit this to a smaller, system-dependent +number. Cannot be used together with B<--icmp-timestamp>. + +=item B<-B>, B<--backoff>=I + +Backoff factor. In the default mode, B sends several requests to a +target before giving up, waiting longer for a reply on each successive request. +This parameter is the value by which the wait time (B<-t>) is multiplied on each +successive request; it must be entered as a floating-point number (x.y). The +default is 1.5. + +=item B<-c>, B<--count>=I + +Number of request packets to send to each target. In this mode, a line is +displayed for each received response (this can suppressed with B<-q> or B<-Q>). +Also, statistics about responses for each target are displayed when all +requests have been sent (or when interrupted). This option overrides B<-a> +or B<-u>. + +=item B<-C>, B<--vcount>=I + +Similar to B<-c>, but the per-target statistics are displayed in a format +designed for automated response-time statistics gathering. For example: + + $ fping -C 5 -q somehost + somehost : 91.7 37.0 29.2 - 36.8 + +shows the response time in milliseconds for each of the five requests, with the +C<-> indicating that no response was received to the fourth request. This +option overrides B<-a> or B<-u>. + +=item B<--check-source> + +Discard Echo replies that are sourced from a different address than the target +address. This avoids spurious reachability results on busy monitoring systems +where two B instances with the same lower 16 bits of the process ID may +be running at the same time. + +=item B<-d>, B<--rdns> + +Use DNS to lookup address of ping target. This allows you to give fping +a list of IP addresses as input and print hostnames in the output. This is similar +to option B<-n>/B<--name>, but will force a reverse-DNS lookup even if you give +hostnames as target (NAME->IP->NAME). + +=item B<-D>, B<--timestamp> + +Add Unix timestamps in front of output lines generated with in looping or counting +modes (B<-l>, B<-c>, or B<-C>). + +Subcommand: B<--timestamp-format>=I + +Allow to change the timestamp format of the B<-D> option to the following format types. + +I = "%c" (Example: Mon Jun 10 07:50:00 2024) + +I = "%Y-%m-%dT%T%z" (Example: 2024-06-10T07:50:00+0200) + +I = "%Y-%m-%d %H:%M:%S" (Example: 2024-06-10 07:50:00) + +=item B<-e>, B<--elapsed> + +Show elapsed (round-trip) time of packets. + +=item B<-f>, B<--file> + +Read list of targets from a file. + +=item B<-g>, B<--generate> I + +Generate a target list from a supplied IP netmask, or a starting and ending IP. +Specify the netmask or start/end in the targets portion of the command line. If +a network with netmask is given, the network and broadcast addresses will be +excluded. ex. To ping the network 192.168.1.0/24, the specified command line +could look like either: + + $ fping -g 192.168.1.0/24 + +or + + $ fping -g 192.168.1.1 192.168.1.254 + +=item B<-h>, B<--help> + +Print usage message. + +=item B<-H>, B<--ttl>=I + +Set the IP TTL field (time to live hops). + +=item B<--print-ttl> + +Displays the IPv4 TTL value from the IP Header in the output. +If B cannot read the TTL value, "(TTL unknown)" is returned. +IPv4 only, requires root privileges or cap_net_raw. + +=item B<-i>, B<--interval>=I + +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 + +Set the interface (requires SO_BINDTODEVICE support). + +=item B<--icmp-timestamp> + +Send ICMP timestamp requests (ICMP type 13) instead of ICMP Echo requests. +Print ICMP timestamps for originate, receive, and transmit, together with +the local receive time in the same format, in addition to normal output. +Cannot be used together with B<-b> because ICMP timestamp messages have a fixed size. +IPv4 only, requires root privileges or cap_net_raw. + +=item B<-k>, B<--fwmark>=I + +Set FWMARK on ping packets for policy-based routing. Requires Linux kernel +2.6.25<=, and root privileges or cap_net_admin. + +=item B<-l>, B<--loop> + +Loop sending packets to each target indefinitely. Can be interrupted with +Ctrl-C; statistics about responses for each target are then displayed. + +=item B<-m>, B<--all> + +Send pings to each of a target host's multiple IP addresses (use of option '-A' +is recommended). + +=item B<-M>, B<--dontfrag> + +Set the "Don't Fragment" bit in the IP header (used to determine/test the MTU). + +=item B<-n>, B<--name> + +If targets are specified as IP addresses, do a reverse-DNS lookup on them +to print hostnames in the output. + +=item B<-N>, B<--netdata> + +Format output for netdata (-l -Q are required). See: L + +=item B<-o>, B<--outage> + +Calculate "outage time" based on the number of lost pings and the interval used (useful for network convergence tests). + +=item B<-O>, B<--tos>=I + +Set the typ of service flag (TOS). I can be either decimal or hexadecimal +(0xh) format. + +=item B<--print-tos> + +Displays the TOS value in the output. If B cannot read the TOS value, +"(TOS unknown)" is returned. +IPv4 only, requires root privileges or cap_net_raw. + +=item B<-p>, B<--period>=I + +In looping or counting modes (B<-l>, B<-c>, or B<-C>), this parameter sets +the time in milliseconds that B waits between successive packets to +an individual target. Default is 1000 and minimum is 10. + +=item B<-q>, B<--quiet> + +Quiet. Don't show per-probe results, but only the final summary. Also don't +show ICMP error messages. + +=item B<-Q>, B<--squiet>=I + +Like B<-q>, but additionally show interval summary results every I +seconds. With I, show summary results since start instead of +for the last interval, unless option B<-N> is used, too. + +=item B<-r>, B<--retry>=I + +Retry limit (default 3). This is the number of times an attempt at pinging +a target will be made, not including the first try. + +=item B<-R>, B<--random> + +Instead of using all-zeros as the packet data, generate random bytes. +Use to defeat, e.g., link data compression. + +=item B<-s>, B<--stats> + +Print cumulative statistics upon exit. + +=item B<-S>, B<--src>=I + +Set source address. + +=item B<-t>, B<--timeout>=I + +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 +waits for a response to its first request. Successive timeouts are multiplied +by the backoff factor specified with B<-B>. + +In loop/count mode, the default timeout is automatically adjusted to match +the "period" value (but not more than 2000ms). You can still adjust the timeout +value with this option, if you wish to, but note that setting a value larger +than "period" produces inconsistent results, because the timeout value can +be respected only for the last ping. + +Also note that any received replies that are larger than the timeout value, will +be discarded. + +=item B<-T> I + +Ignored (for compatibility with fping 2.4). + +=item B<-u>, B<--unreach> + +Show targets that are unreachable. (Options B<-c> and B<-C> override B<-u>.) + +=item B<-v>, B<--version> + +Print B version information. + +=item B<-x>, B<--reachable>=I + +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 + +Given a list of hosts, this mode immediately exits true once N alive hosts +have been found. + +=back + +=head1 EXAMPLES + +Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to +each host), and report every ping RTT at the end: + + $ fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2 + +=head1 AUTHORS + +=over 4 + +=item * + +Roland J. Schemers III, Stanford University, concept and versions 1.x + +=item * + +RL "Bob" Morgan, Stanford University, versions 2.x + +=item * + +David Papp, versions 2.3x and up + +=item * + +David Schweikert, versions 3.0 and up + +=back + +B> + +=head1 DIAGNOSTICS + +Exit status is 0 if all the hosts (or the number of hosts specified with B<-x> +or B<-X>) are reachable, 1 if some (or too many with B<-x> or B<-X>) hosts +were unreachable, 2 if any IP addresses were not found, 3 for invalid command +line arguments, and 4 for a system call failure. + +=head1 RESTRICTIONS + +The number of addresses that can be generated using the C<-g>, C<--generate> +option is limited to 131070 (the number of host addresses in one 15-bit IPv4 +prefix). + +If fping was configured with C<--enable-safe-limits>, the following values are +not allowed for non-root users: + +=over 4 + +=item * + +B<-i> I, where I < 1 msec + +=item * + +B<-p> I, where I < 10 msec + +=back + +=head1 SEE ALSO + +C diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/Makefile.am b/ci/tmp.4rIIEYCP9c/fping-5.3/src/Makefile.am new file mode 100644 index 0000000..c58e474 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/Makefile.am @@ -0,0 +1,11 @@ +AM_CFLAGS = -Wall -Wextra -Wno-sign-compare + +sbin_PROGRAMS = fping + +fping_SOURCES = fping.c seqmap.c socket4.c fping.h options.h seqmap.h optparse.c optparse.h +fping_DEPENDENCIES = ../config.h + +if IPV6 +fping_SOURCES += socket6.c +fping_CFLAGS = $(AM_CFLAGS) -DIPV6 +endif diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping new file mode 100755 index 0000000..b2aeb58 Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping differ diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o new file mode 100644 index 0000000..682a6a5 Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o differ diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-optparse.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-optparse.o new file mode 100644 index 0000000..2d9e14a Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-optparse.o differ diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-seqmap.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-seqmap.o new file mode 100644 index 0000000..a586164 Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-seqmap.o differ diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket4.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket4.o new file mode 100644 index 0000000..57976aa Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket4.o differ diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket6.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket6.o new file mode 100644 index 0000000..52db65d Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket6.o differ diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.c new file mode 100644 index 0000000..6779175 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.c @@ -0,0 +1,3201 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "fping.h" +#include "config.h" +#include "options.h" +#include "optparse.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "seqmap.h" + +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ + +#ifdef HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ + +#include +#include + +#include +#include +#include + +#if HAVE_SYS_FILE_H +#include +#endif /* HAVE_SYS_FILE_H */ + +#ifdef IPV6 +#include +#endif +#include + +#include +#include + +#include +#include +#include + +#include + +/*** compatibility ***/ + +/* Mac OS X's getaddrinfo() does not fail if we use an invalid combination, + * e.g. AF_INET6 with "127.0.0.1". If we pass AI_UNUSABLE to flags, it behaves + * like other platforms. But AI_UNUSABLE isn't available on other platforms, + * and we can safely use 0 for flags instead. + */ +#ifndef AI_UNUSABLE +#define AI_UNUSABLE 0 +#endif + +/* MSG_TRUNC available on Linux kernel 2.2+, makes recvmsg return the full + * length of the raw packet received, even if the buffer is smaller */ +#ifndef MSG_TRUNC +#define MSG_TRUNC 0 +#define RECV_BUFSIZE 4096 +#else +#define RECV_BUFSIZE 128 +#endif + +/*** externals ***/ + +extern char *optarg; +extern int optind, opterr; +#ifndef h_errno +extern int h_errno; +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*** Constants ***/ + +/* CLOCK_MONTONIC starts under macOS, OpenBSD and FreeBSD with undefined positive point and can not be use + * see github PR #217 + * The configure script detect the predefined operating systems an set CLOCK_REALTIME using over ONLY_CLOCK_REALTIME variable + */ +#if HAVE_SO_TIMESTAMPNS || ONLY_CLOCK_REALTIME +#define CLOCKID CLOCK_REALTIME +#endif + +#if !defined(CLOCKID) +#if defined(CLOCK_MONOTONIC) +#define CLOCKID CLOCK_MONOTONIC +#else +#define CLOCKID CLOCK_REALTIME +#endif +#endif + +/*** Ping packet defines ***/ + +#define MAX_IP_PACKET 65535 /* (theoretical) max IPv4 packet size */ +#define SIZE_IP_HDR 20 /* min IPv4 header size */ +#define SIZE_ICMP_HDR 8 /* from ip_icmp.h */ +#define MAX_PING_DATA (MAX_IP_PACKET - SIZE_IP_HDR - SIZE_ICMP_HDR) + +#define MAX_GENERATE 131070 /* maximum number of hosts that -g can generate */ + +/* sized so as to be like traditional ping */ +#define DEFAULT_PING_DATA_SIZE 56 + +/* ICMP Timestamp has a fixed payload size of 12 bytes */ +#define ICMP_TIMESTAMP_DATA_SIZE 12 + +#ifdef FPING_SAFE_LIMITS +#define MIN_INTERVAL_MS 1 /* in millisec */ +#define MIN_PERHOST_INTERVAL_MS 10 /* in millisec */ +#else +#define MIN_INTERVAL_MS 0 +/* Set a very low limit for the per-host interval, even if safe limits are + * disabled, so that the memory allocation of the event storage is not + * unreasonably high. 0.001 ms would mean in theory at least 592 mbps of data + * sent to a single host, which probably doesn't make sense in any scenario. */ +#define MIN_PERHOST_INTERVAL_MS 0.001 +#endif + +/* response time array flags */ +#define RESP_WAITING -1 +#define RESP_UNUSED -2 +#define RESP_ERROR -3 +#define RESP_TIMEOUT -4 + +/* debugging flags */ +#if defined(DEBUG) || defined(_DEBUG) +#define DBG_TRACE 1 +#define DBG_SENT_TIMES 2 +#define DBG_RANDOM_LOSE_FEW 4 +#define DBG_RANDOM_LOSE_MANY 8 +#define DBG_PRINT_PER_SYSTEM 16 +#define DBG_REPORT_ALL_RTTS 32 +#endif /* DEBUG || _DEBUG */ + +/* Long names for ICMP packet types */ +#define ICMP_TYPE_STR_MAX 18 +char *icmp_type_str[19] = { + "ICMP Echo Reply", /* 0 */ + "", + "", + "ICMP Unreachable", /* 3 */ + "ICMP Source Quench", /* 4 */ + "ICMP Redirect", /* 5 */ + "", + "", + "ICMP Echo", /* 8 */ + "", + "", + "ICMP Time Exceeded", /* 11 */ + "ICMP Parameter Problem", /* 12 */ + "ICMP Timestamp Request", /* 13 */ + "ICMP Timestamp Reply", /* 14 */ + "ICMP Information Request", /* 15 */ + "ICMP Information Reply", /* 16 */ + "ICMP Mask Request", /* 17 */ + "ICMP Mask Reply" /* 18 */ +}; + +char *icmp_unreach_str[16] = { + "ICMP Network Unreachable", /* 0 */ + "ICMP Host Unreachable", /* 1 */ + "ICMP Protocol Unreachable", /* 2 */ + "ICMP Port Unreachable", /* 3 */ + "ICMP Unreachable (Fragmentation Needed)", /* 4 */ + "ICMP Unreachable (Source Route Failed)", /* 5 */ + "ICMP Unreachable (Destination Network Unknown)", /* 6 */ + "ICMP Unreachable (Destination Host Unknown)", /* 7 */ + "ICMP Unreachable (Source Host Isolated)", /* 8 */ + "ICMP Unreachable (Communication with Network Prohibited)", /* 9 */ + "ICMP Unreachable (Communication with Host Prohibited)", /* 10 */ + "ICMP Unreachable (Network Unreachable For Type Of Service)", /* 11 */ + "ICMP Unreachable (Host Unreachable For Type Of Service)", /* 12 */ + "ICMP Unreachable (Communication Administratively Prohibited)", /* 13 */ + "ICMP Unreachable (Host Precedence Violation)", /* 14 */ + "ICMP Unreachable (Precedence cutoff in effect)" /* 15 */ +}; + +#define ICMP_UNREACH_MAXTYPE 15 + +struct event; +typedef struct host_entry { + int i; /* index into array */ + char *name; /* name as given by user */ + char *host; /* text description of host */ + struct sockaddr_storage saddr; /* internet address */ + socklen_t saddr_len; + int64_t timeout; /* time to wait for response */ + int64_t last_send_time; /* time of last packet sent */ + int num_sent; /* number of ping packets sent (for statistics) */ + int num_recv; /* number of pings received (duplicates ignored) */ + int num_recv_total; /* number of pings received, including duplicates */ + int64_t max_reply; /* longest response time */ + int64_t min_reply; /* shortest response time */ + int64_t total_time; /* sum of response times */ + /* _i -> splits (reset on every report interval) */ + int num_sent_i; /* number of ping packets sent */ + int num_recv_i; /* number of pings received */ + int64_t max_reply_i; /* longest response time */ + int64_t min_reply_i; /* shortest response time */ + int64_t total_time_i; /* sum of response times */ + int64_t *resp_times; /* individual response times */ + + /* to avoid allocating two struct events each time that we send a ping, we + * preallocate here two struct events for each ping that we might send for + * this host. */ + struct event *event_storage_ping; + struct event *event_storage_timeout; +} HOST_ENTRY; + +int event_storage_count; /* how many events can be stored in host_entry->event_storage_xxx */ + +/* basic algorithm to ensure that we have correct data at all times: + * + * 1. when a ping is sent: + * - two events get added into event_queue: + * - t+PERIOD: ping event + * - t+TIMEOUT: timeout event + * + * 2. when a ping is received: + * - record statistics (increase num_sent and num_received) + * - remove timeout event (we store the event in seqmap, so that we can retrieve it when the response is received) + * + * 3. when a timeout happens: + * - record statistics (increase num_sent only) + */ + +#define EV_TYPE_PING 1 +#define EV_TYPE_TIMEOUT 2 + +struct event { + struct event *ev_prev; + struct event *ev_next; + int64_t ev_time; + struct host_entry *host; + int ping_index; +}; + +struct event_queue { + struct event *first; + struct event *last; +}; + +/*** globals ***/ + +HOST_ENTRY **table = NULL; /* array of pointers to items in the list */ + +/* we keep two separate queues: a ping queue, for when the next ping should be + * sent, and a timeout queue. the reason for having two separate queues is that + * the ping period and the timeout value are different, so if we put them in + * the same event queue, we would need to scan many more entries when inserting + * into the sorted list. + */ +struct event_queue event_queue_ping; +struct event_queue event_queue_timeout; + +char *prog; +int ident4 = 0; /* our icmp identity field */ +int ident6 = 0; +int socket4 = -1; +int socktype4 = -1; +int using_sock_dgram4 = 0; +#ifndef IPV6 +int hints_ai_family = AF_INET; +#else +int socket6 = -1; +int socktype6 = -1; +int hints_ai_family = AF_UNSPEC; +#endif + +volatile sig_atomic_t status_snapshot = 0; +volatile sig_atomic_t finish_requested = 0; + +unsigned int debugging = 0; + +/* all time-related values are int64_t nanoseconds */ +unsigned int retry = DEFAULT_RETRY; +int64_t timeout = (int64_t)DEFAULT_TIMEOUT * 1000000; +int64_t interval = (int64_t)DEFAULT_INTERVAL * 1000000; +int64_t perhost_interval = (int64_t)DEFAULT_PERHOST_INTERVAL * 1000000; +float backoff = DEFAULT_BACKOFF_FACTOR; +unsigned int ping_data_size = DEFAULT_PING_DATA_SIZE; +unsigned int count = 1, min_reachable = 0; +unsigned int trials; +int64_t report_interval = 0; +unsigned int ttl = 0; +int src_addr_set = 0; +struct in_addr src_addr; +#ifdef IPV6 +int src_addr6_set = 0; +struct in6_addr src_addr6; +#endif + +/* global stats */ +int64_t max_reply = 0; +int64_t min_reply = 0; +int64_t total_replies = 0; +int64_t sum_replies = 0; +int max_hostname_len = 0; +int num_hosts = 0; /* total number of hosts */ +int num_alive = 0, /* total number alive */ + num_unreachable = 0, /* total number unreachable */ + num_noaddress = 0; /* total number of addresses not found */ +int num_timeout = 0, /* number of times select timed out */ + num_pingsent = 0, /* total pings sent */ + num_pingreceived = 0, /* total pings received */ + num_othericmprcvd = 0; /* total non-echo-reply ICMP received */ + +struct timespec current_time; /* current time (pseudo) */ +int64_t current_time_ns; +int64_t start_time; +int64_t end_time; +int64_t last_send_time; /* time last ping was sent */ +int64_t next_report_time; /* time next -Q report is expected */ + +/* switches */ +int generate_flag = 0; /* flag for IP list generation */ +int verbose_flag, quiet_flag, stats_flag, unreachable_flag, alive_flag; +int elapsed_flag, version_flag, count_flag, loop_flag, netdata_flag; +int per_recv_flag, report_all_rtts_flag, name_flag, addr_flag, backoff_flag, rdns_flag; +int multif_flag, timeout_flag, fast_reachable; +int outage_flag = 0; +int timestamp_flag = 0; +int timestamp_format_flag = 0; +int random_data_flag = 0; +int cumulative_stats_flag = 0; +int check_source_flag = 0; +int icmp_request_typ = 0; +int print_tos_flag = 0; +int print_ttl_flag = 0; +int size_flag = 0; +#if defined(DEBUG) || defined(_DEBUG) +int randomly_lose_flag, trace_flag, print_per_system_flag; +int lose_factor; +#endif /* DEBUG || _DEBUG */ + +unsigned int fwmark = 0; + +char *filename = NULL; /* file containing hosts to ping */ + +/*** forward declarations ***/ + +void add_name(char *name); +void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_len); +char *na_cat(char *name, struct in_addr ipaddr); +void crash_and_burn(char *message); +void errno_crash_and_burn(char *message); +char *get_host_by_address(struct in_addr in); +int send_ping(HOST_ENTRY *h, int index); +void usage(int); +int wait_for_reply(int64_t); +void print_per_system_stats(void); +void print_per_system_splits(void); +void stats_reset_interval(HOST_ENTRY *h); +void print_netdata(void); +void print_global_stats(void); +void main_loop(); +void signal_handler(int); +void finish(); +const char *sprint_tm(int64_t t); +void ev_enqueue(struct event_queue *queue, struct event *event); +struct event *ev_dequeue(struct event_queue *queue); +void ev_remove(struct event_queue *queue, struct event *event); +void add_cidr(char *); +void add_range(char *, char *); +void add_addr_range_ipv4(unsigned long, unsigned long); +void print_warning(char *fmt, ...); +int addr_cmp(struct sockaddr *a, struct sockaddr *b); +void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time); +void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time); +struct event *host_get_timeout_event(HOST_ENTRY *h, int index); +void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency); +void update_current_time(); +void print_timestamp_format(int64_t current_time_ns, int timestamp_format); +static uint32_t ms_since_midnight_utc(int64_t time_val); + +/************************************************************ + + Function: p_setsockopt + +************************************************************* + + Inputs: p_uid: privileged uid. Others as per setsockopt(2) + + Description: + + Elevates privileges to p_uid when required, calls + setsockopt, and drops privileges back. + +************************************************************/ + +int p_setsockopt(uid_t p_uid, int sockfd, int level, int optname, + const void *optval, socklen_t optlen) +{ + const uid_t saved_uid = geteuid(); + int res; + + if (p_uid != saved_uid && seteuid(p_uid)) { + perror("cannot elevate privileges for setsockopt"); + } + + res = setsockopt(sockfd, level, optname, optval, optlen); + + if (p_uid != saved_uid && seteuid(saved_uid)) { + perror("fatal error: could not drop privileges after setsockopt"); + /* continuing would be a security hole */ + exit(4); + } + + return res; +} + +/************************************************************ + + Function: main + +************************************************************* + + Inputs: int argc, char** argv + + Description: + + Main program entry point + +************************************************************/ + +int main(int argc, char **argv) +{ +/* Debug: CPU Performance */ +#if defined(DEBUG) || defined(_DEBUG) + clock_t perf_cpu_start, perf_cpu_end; + double perf_cpu_time_used; + perf_cpu_start = clock(); +#endif /* DEBUG || _DEBUG */ + + int c; + const uid_t suid = geteuid(); + int tos = 0; + struct optparse optparse_state; +#ifdef USE_SIGACTION + struct sigaction act; +#endif + + /* pre-parse -h/--help, so that we also can output help information + * without trying to open the socket, which might fail */ + prog = argv[0]; + if (argc == 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) { + usage(0); + } + + socket4 = open_ping_socket_ipv4(&socktype4); +#ifdef __linux__ + /* We only treat SOCK_DGRAM differently on Linux, where the IPv4 header + * structure is missing in the message. + */ + using_sock_dgram4 = (socktype4 == SOCK_DGRAM); +#endif + +#ifdef IPV6 + socket6 = open_ping_socket_ipv6(&socktype6); + /* if called (sym-linked) via 'fping6', imply '-6' + * for backward compatibility */ + if (strstr(prog, "fping6")) { + hints_ai_family = AF_INET6; + } +#endif + + memset(&src_addr, 0, sizeof(src_addr)); +#ifdef IPV6 + memset(&src_addr6, 0, sizeof(src_addr6)); +#endif + + if (!suid && suid != getuid()) { + /* *temporarily* drop privileges */ + if (seteuid(getuid()) == -1) + perror("cannot setuid"); + } + + optparse_init(&optparse_state, argv); + ident4 = ident6 = htons(getpid() & 0xFFFF); + verbose_flag = 1; + backoff_flag = 1; + opterr = 1; + + /* get command line options */ + + struct optparse_long longopts[] = { + { "ipv4", '4', OPTPARSE_NONE }, + { "ipv6", '6', OPTPARSE_NONE }, + { "alive", 'a', OPTPARSE_NONE }, + { "addr", 'A', OPTPARSE_NONE }, + { "size", 'b', OPTPARSE_REQUIRED }, + { "backoff", 'B', OPTPARSE_REQUIRED }, + { "count", 'c', OPTPARSE_REQUIRED }, + { "vcount", 'C', OPTPARSE_REQUIRED }, + { "rdns", 'd', OPTPARSE_NONE }, + { "timestamp", 'D', OPTPARSE_NONE }, + { "timestamp-format", '0', OPTPARSE_REQUIRED }, + { "elapsed", 'e', OPTPARSE_NONE }, + { "file", 'f', OPTPARSE_REQUIRED }, + { "generate", 'g', OPTPARSE_NONE }, + { "help", 'h', OPTPARSE_NONE }, + { "ttl", 'H', OPTPARSE_REQUIRED }, + { "interval", 'i', OPTPARSE_REQUIRED }, + { "iface", 'I', OPTPARSE_REQUIRED }, + { "icmp-timestamp", '0', OPTPARSE_NONE }, +#ifdef SO_MARK + { "fwmark", 'k', OPTPARSE_REQUIRED }, +#endif + { "loop", 'l', OPTPARSE_NONE }, + { "all", 'm', OPTPARSE_NONE }, + { "dontfrag", 'M', OPTPARSE_NONE }, + { "name", 'n', OPTPARSE_NONE }, + { "netdata", 'N', OPTPARSE_NONE }, + { "outage", 'o', OPTPARSE_NONE }, + { "tos", 'O', OPTPARSE_REQUIRED }, + { "period", 'p', OPTPARSE_REQUIRED }, + { "quiet", 'q', OPTPARSE_NONE }, + { "squiet", 'Q', OPTPARSE_REQUIRED }, + { "retry", 'r', OPTPARSE_REQUIRED }, + { "random", 'R', OPTPARSE_NONE }, + { "stats", 's', OPTPARSE_NONE }, + { "src", 'S', OPTPARSE_REQUIRED }, + { "timeout", 't', OPTPARSE_REQUIRED }, + { NULL, 'T', OPTPARSE_REQUIRED }, + { "unreach", 'u', OPTPARSE_NONE }, + { "version", 'v', OPTPARSE_NONE }, + { "reachable", 'x', OPTPARSE_REQUIRED }, + { "fast-reachable", 'X', OPTPARSE_REQUIRED }, + { "check-source", '0', OPTPARSE_NONE }, + { "print-tos", '0', OPTPARSE_NONE }, + { "print-ttl", '0', OPTPARSE_NONE }, +#if defined(DEBUG) || defined(_DEBUG) + { NULL, 'z', OPTPARSE_REQUIRED }, +#endif + { 0, 0, 0 } + }; + + float opt_value_float; + while ((c = optparse_long(&optparse_state, longopts, NULL)) != EOF) { + switch (c) { + case '0': + if(strstr(optparse_state.optlongname, "timestamp-format") != NULL) { + if(strcmp(optparse_state.optarg, "ctime") == 0) { + timestamp_format_flag = 1; + }else if(strcmp(optparse_state.optarg, "iso") == 0) { + timestamp_format_flag = 2; + }else if(strcmp(optparse_state.optarg, "rfc3339") == 0) { + timestamp_format_flag = 3; + }else{ + usage(1); + } + } else if (strstr(optparse_state.optlongname, "check-source") != NULL) { + check_source_flag = 1; + } else if (strstr(optparse_state.optlongname, "icmp-timestamp") != NULL) { +#ifdef IPV6 + if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) { + fprintf(stderr, "%s: ICMP Timestamp is IPv4 only\n", prog); + exit(1); + } + hints_ai_family = AF_INET; +#endif + icmp_request_typ = 13; + ping_data_size = ICMP_TIMESTAMP_DATA_SIZE; + } else if (strstr(optparse_state.optlongname, "print-tos") != NULL) { + print_tos_flag = 1; + } else if (strstr(optparse_state.optlongname, "print-ttl") != NULL) { + print_ttl_flag = 1; + } else { + usage(1); + } + break; + case '4': +#ifdef IPV6 + if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) { + fprintf(stderr, "%s: can't specify both -4 and -6\n", prog); + exit(1); + } + hints_ai_family = AF_INET; +#endif + break; + case '6': +#ifdef IPV6 + if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET6) { + fprintf(stderr, "%s: can't specify both -4 and -6\n", prog); + exit(1); + } + hints_ai_family = AF_INET6; +#else + fprintf(stderr, "%s: IPv6 not supported by this binary\n", prog); + exit(1); +#endif + break; + case 'M': +#ifdef IP_MTU_DISCOVER + if (socket4 >= 0) { + int val = IP_PMTUDISC_DO; + if (setsockopt(socket4, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val))) { + perror("setsockopt IP_MTU_DISCOVER"); + } + } +#ifdef IPV6 + if (socket6 >= 0) { + int val = IPV6_PMTUDISC_DO; + if (setsockopt(socket6, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val, sizeof(val))) { + perror("setsockopt IPV6_MTU_DISCOVER"); + } + } +#endif +#else + fprintf(stderr, "%s, -M option not supported on this platform\n", prog); + exit(1); +#endif + break; + + case 't': + if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1) + usage(1); + if (opt_value_float < 0) { + usage(1); + } + timeout = opt_value_float * 1000000; + timeout_flag = 1; + break; + + case 'r': + if (sscanf(optparse_state.optarg, "%u", &retry) != 1) + usage(1); + break; + + case 'i': + if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1) + usage(1); + if (opt_value_float < 0) { + usage(1); + } + interval = opt_value_float * 1000000; + break; + + case 'p': + if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1) + usage(1); + if (opt_value_float < 0) { + usage(1); + } + perhost_interval = opt_value_float * 1000000; + + break; + + case 'c': + if (!(count = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + + count_flag = 1; + break; + + case 'C': + if (!(count = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + + count_flag = 1; + report_all_rtts_flag = 1; + break; + + case 'b': + if (sscanf(optparse_state.optarg, "%u", &ping_data_size) != 1) + usage(1); + size_flag = 1; + break; + + case 'h': + usage(0); + break; + + case 'q': + verbose_flag = 0; + quiet_flag = 1; + break; + + case 'Q': + verbose_flag = 0; + quiet_flag = 1; + if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1) + usage(1); + if (opt_value_float < 0) { + usage(1); + } + report_interval = opt_value_float * 1e9; + + /* recognize keyword(s) after number, ignore everything else */ + { + char *comma = strchr(optparse_state.optarg, ','); + if ((comma != NULL) && (strcmp(++comma, "cumulative") == 0)) { + cumulative_stats_flag = 1; + } + } + + break; + + case 'e': + elapsed_flag = 1; + break; + + case 'm': + multif_flag = 1; + break; + + case 'N': + netdata_flag = 1; + break; + + case 'n': + name_flag = 1; + if (rdns_flag) { + fprintf(stderr, "%s: use either one of -d or -n\n", prog); + exit(1); + } + break; + + case 'd': + rdns_flag = 1; + if (name_flag) { + fprintf(stderr, "%s: use either one of -d or -n\n", prog); + exit(1); + } + break; + + case 'A': + addr_flag = 1; + break; + + case 'B': + if (!(backoff = atof(optparse_state.optarg))) + usage(1); + + break; + + case 's': + stats_flag = 1; + break; + + case 'D': + timestamp_flag = 1; + break; + + case 'R': + random_data_flag = 1; + break; + + case 'l': + loop_flag = 1; + backoff_flag = 0; + break; + + case 'u': + unreachable_flag = 1; + break; + + case 'a': + alive_flag = 1; + break; + + case 'H': + if (!(ttl = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + break; + +#if defined(DEBUG) || defined(_DEBUG) + case 'z': + if (sscanf(optparse_state.optarg, "0x%x", &debugging) != 1) + if (sscanf(optparse_state.optarg, "%u", &debugging) != 1) + usage(1); + + break; +#endif /* DEBUG || _DEBUG */ + + case 'v': + printf("%s: Version %s\n", prog, VERSION); + exit(0); + + case 'x': + if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + break; + + case 'X': + if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + fast_reachable = 1; + break; + + case 'f': + filename = optparse_state.optarg; + break; +#ifdef SO_MARK + case 'k': + if (!(fwmark = (unsigned int)atol(optparse_state.optarg))) + usage(1); + + if (socket4 >= 0) + if(-1 == p_setsockopt(suid, socket4, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark)) + perror("fwmark ipv4"); + +#ifdef IPV6 + if (socket6 >= 0) + if(-1 == p_setsockopt(suid, socket6, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark)) + perror("fwmark ipv6"); +#endif + + break; +#endif + + case 'g': + /* use IP list generation */ + /* mutually exclusive with using file input or command line targets */ + generate_flag = 1; + break; + + case 'S': + if (inet_pton(AF_INET, optparse_state.optarg, &src_addr)) { + src_addr_set = 1; + break; + } +#ifdef IPV6 + if (inet_pton(AF_INET6, optparse_state.optarg, &src_addr6)) { + src_addr6_set = 1; + break; + } +#endif + fprintf(stderr, "%s: can't parse source address: %s\n", prog, optparse_state.optarg); + exit(1); + + case 'I': +#ifdef SO_BINDTODEVICE + if (socket4 >= 0) { + if (p_setsockopt(suid, socket4, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) { + perror("binding to specific interface (SO_BINTODEVICE)"); + exit(1); + } + } +#ifdef IPV6 + if (socket6 >= 0) { + if (p_setsockopt(suid, socket6, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) { + perror("binding to specific interface (SO_BINTODEVICE), IPV6"); + exit(1); + } + } +#endif +#else + printf("%s: cant bind to a particular net interface since SO_BINDTODEVICE is not supported on your os.\n", prog); + exit(3); + ; +#endif + break; + + case 'T': + /* This option is ignored for compatibility reasons ("select timeout" is not meaningful anymore) */ + break; + + case 'O': + if (sscanf(optparse_state.optarg, "%i", &tos) == 1) { + if (socket4 >= 0) { + if (setsockopt(socket4, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) { + perror("setting type of service octet IP_TOS"); + } + } +#if defined(IPV6) && defined(IPV6_TCLASS) + if (socket6 >= 0) { + if (setsockopt(socket6, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos))) { + perror("setting type of service octet IPV6_TCLASS"); + } + } +#endif + } + else { + usage(1); + } + break; + + case 'o': + outage_flag = 1; + break; + + case '?': + fprintf(stderr, "%s: %s\n", argv[0], optparse_state.errmsg); + fprintf(stderr, "see 'fping -h' for usage information\n"); + exit(1); + break; + } + } + + /* permanently drop privileges */ + if (suid != getuid() && setuid(getuid())) { + perror("fatal: failed to permanently drop privileges"); + /* continuing would be a security hole */ + exit(4); + } + + /* validate various option settings */ + +#ifndef IPV6 + if (socket4 < 0) { + crash_and_burn("can't create socket (must run as root?)"); + } +#else + if ((socket4 < 0 && socket6 < 0) || (hints_ai_family == AF_INET6 && socket6 < 0)) { + crash_and_burn("can't create socket (must run as root?)"); + } +#endif + + if (ttl > 255) { + fprintf(stderr, "%s: ttl %u out of range\n", prog, ttl); + exit(1); + } + + if (unreachable_flag && alive_flag) { + fprintf(stderr, "%s: specify only one of a, u\n", prog); + exit(1); + } + + if (count_flag && loop_flag) { + fprintf(stderr, "%s: specify only one of c, l\n", prog); + exit(1); + } + + if (interval < (float)MIN_INTERVAL_MS * 1000000 && getuid()) { + fprintf(stderr, "%s: -i must be >= %g\n", prog, (float)MIN_INTERVAL_MS); + exit(1); + } + + if (perhost_interval < (float)MIN_PERHOST_INTERVAL_MS * 1000000 && getuid()) { + fprintf(stderr, "%s: -p must be >= %g\n", prog, (float)MIN_PERHOST_INTERVAL_MS); + exit(1); + } + + if (ping_data_size > MAX_PING_DATA) { + fprintf(stderr, "%s: data size %u not valid, must not be larger than %u\n", + prog, ping_data_size, (unsigned int)MAX_PING_DATA); + exit(1); + } + + if ((backoff > MAX_BACKOFF_FACTOR) || (backoff < MIN_BACKOFF_FACTOR)) { + fprintf(stderr, "%s: backoff factor %.1f not valid, must be between %.1f and %.1f\n", + prog, backoff, MIN_BACKOFF_FACTOR, MAX_BACKOFF_FACTOR); + exit(1); + } + + if (icmp_request_typ == 13 && size_flag != 0) { + fprintf(stderr, "%s: cannot change ICMP Timestamp size\n", prog); + exit(1); + } + + if (count_flag) { + if (verbose_flag) + per_recv_flag = 1; + + alive_flag = unreachable_flag = verbose_flag = 0; + } + + if (loop_flag) { + if (!report_interval) + per_recv_flag = 1; + + alive_flag = unreachable_flag = verbose_flag = 0; + } + + if (alive_flag || unreachable_flag || min_reachable) + verbose_flag = 0; + + trials = (count > retry + 1) ? count : retry + 1; + + /* auto-tune default timeout for count/loop modes + * see also github #32 */ + if (loop_flag || count_flag) { + if (!timeout_flag) { + timeout = perhost_interval; + if (timeout > (int64_t)AUTOTUNE_TIMEOUT_MAX * 1000000) { + timeout = (int64_t)AUTOTUNE_TIMEOUT_MAX * 1000000; + } + } + } + +#if defined(DEBUG) || defined(_DEBUG) + if (debugging & DBG_TRACE) + trace_flag = 1; + + if (debugging & DBG_RANDOM_LOSE_FEW) { + randomly_lose_flag = 1; + lose_factor = 1; /* ie, 1/4 */ + } + + if (debugging & DBG_RANDOM_LOSE_MANY) { + randomly_lose_flag = 1; + lose_factor = 5; /* ie, 3/4 */ + } + + if (debugging & DBG_PRINT_PER_SYSTEM) + print_per_system_flag = 1; + + if ((debugging & DBG_REPORT_ALL_RTTS) && !loop_flag) + report_all_rtts_flag = 1; + + if (trace_flag) { + fprintf(stderr, "%s:\n count: %u, retry: %u, interval: %.0f ms\n", + prog, count, retry, interval / 1e6); + fprintf(stderr, " perhost_interval: %.0f ms, timeout: %.0f\n", + perhost_interval / 1e6, timeout / 1e6); + fprintf(stderr, " ping_data_size = %u, trials = %u\n", + ping_data_size, trials); + + if (verbose_flag) + fprintf(stderr, " verbose_flag set\n"); + if (multif_flag) + fprintf(stderr, " multif_flag set\n"); + if (name_flag) + fprintf(stderr, " name_flag set\n"); + if (addr_flag) + fprintf(stderr, " addr_flag set\n"); + if (stats_flag) + fprintf(stderr, " stats_flag set\n"); + if (unreachable_flag) + fprintf(stderr, " unreachable_flag set\n"); + if (alive_flag) + fprintf(stderr, " alive_flag set\n"); + if (elapsed_flag) + fprintf(stderr, " elapsed_flag set\n"); + if (version_flag) + fprintf(stderr, " version_flag set\n"); + if (count_flag) + fprintf(stderr, " count_flag set\n"); + if (loop_flag) + fprintf(stderr, " loop_flag set\n"); + if (backoff_flag) + fprintf(stderr, " backoff_flag set\n"); + if (per_recv_flag) + fprintf(stderr, " per_recv_flag set\n"); + if (report_all_rtts_flag) + fprintf(stderr, " report_all_rtts_flag set\n"); + if (randomly_lose_flag) + fprintf(stderr, " randomly_lose_flag set\n"); + if (print_per_system_flag) + fprintf(stderr, " print_per_system_flag set\n"); + if (outage_flag) + fprintf(stderr, " outage_flag set\n"); + if (netdata_flag) + fprintf(stderr, " netdata_flag set\n"); + } +#endif /* DEBUG || _DEBUG */ + + /* set the TTL, if the -H option was set (otherwise ttl will be = 0) */ + if (ttl > 0) { + if (socket4 >= 0) { + if (setsockopt(socket4, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) { + perror("setting time to live"); + } + } +#ifdef IPV6 + if (socket6 >= 0) { + if (setsockopt(socket6, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))) { + perror("setting time to live"); + } + } +#endif + } + +#if HAVE_SO_TIMESTAMPNS + { + int opt = 1; + if (socket4 >= 0) { + if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) { + if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) { + perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option"); + } + } + } +#ifdef IPV6 + if (socket6 >= 0) { + if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) { + if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) { + perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option (IPv6)"); + } + } + } +#endif + } +#endif + + update_current_time(); + start_time = current_time_ns; + + /* handle host names supplied on command line or in a file */ + /* if the generate_flag is on, then generate the IP list */ + + argv = &argv[optparse_state.optind]; + argc -= optparse_state.optind; + + /* calculate how many ping can be in-flight per host */ + if (count_flag) { + event_storage_count = count; + } + else if (loop_flag) { + if (perhost_interval > timeout) { + event_storage_count = 1; + } + else { + event_storage_count = 1 + timeout / perhost_interval; + } + } + else { + event_storage_count = 1; + } + + /* file and generate are mutually exclusive */ + /* file and command line are mutually exclusive */ + /* generate requires command line parameters beyond the switches */ + if ((*argv && filename) || (filename && generate_flag) || (generate_flag && !*argv)) + usage(1); + + /* if no conditions are specified, then assume input from stdin */ + if (!*argv && !filename && !generate_flag) + filename = "-"; + + if (*argv && !generate_flag) { + while (*argv) { + add_name(*argv); + ++argv; + } + } + else if (filename) { + FILE *ping_file; + char line[132]; + char host[132]; + + if (strcmp(filename, "-") == 0) + ping_file = fdopen(0, "r"); + else + ping_file = fopen(filename, "r"); + + if (!ping_file) + errno_crash_and_burn("fopen"); + + while (fgets(line, sizeof(line), ping_file)) { + if (sscanf(line, "%s", host) != 1) + continue; + + if ((!*host) || (host[0] == '#')) /* magic to avoid comments */ + continue; + + add_name(host); + } + + fclose(ping_file); + } + else if (*argv && generate_flag) { + if (argc == 1) { + /* one target: we expect a cidr range (n.n.n.n/m) */ + add_cidr(argv[0]); + } + else if (argc == 2) { + add_range(argv[0], argv[1]); + } + else { + usage(1); + } + } + else { + usage(1); + } + + if (!num_hosts) { + exit(num_noaddress ? 2 : 1); + } + + if (socket4 >= 0 && (src_addr_set || socktype4 == SOCK_DGRAM)) { + socket_set_src_addr_ipv4(socket4, &src_addr, (socktype4 == SOCK_DGRAM) ? &ident4 : NULL); + } +#ifdef IPV6 + if (socket6 >= 0 && (src_addr6_set || socktype6 == SOCK_DGRAM)) { + socket_set_src_addr_ipv6(socket6, &src_addr6, (socktype6 == SOCK_DGRAM) ? &ident6 : NULL); + } +#endif + + /* allocate and initialize array to map host nr to host_entry */ + { + struct event *cursor = event_queue_ping.first; + int i = 0; + table = (HOST_ENTRY **)calloc(num_hosts, sizeof(HOST_ENTRY *)); + if (!table) + crash_and_burn("Can't malloc array of hosts"); + /* initialize table of hosts. we know that we have ping events scheduled + * for each of them */ + for (cursor = event_queue_ping.first; cursor; cursor = cursor->ev_next) { + table[i] = cursor->host; + cursor->host->i = i; + i++; + } + } + + init_ping_buffer_ipv4(ping_data_size); +#ifdef IPV6 + init_ping_buffer_ipv6(ping_data_size); +#endif + +#ifdef USE_SIGACTION + memset(&act, 0, sizeof(act)); + act.sa_handler = signal_handler; + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask, SIGINT); + sigaddset(&act.sa_mask, SIGQUIT); + act.sa_flags = SA_RESTART; + if (sigaction(SIGQUIT, &act, NULL) || sigaction(SIGINT, &act, NULL)) { + crash_and_burn("failure to set signal handler"); + } +#else + signal(SIGINT, signal_handler); + signal(SIGQUIT, signal_handler); +#endif + setlinebuf(stdout); + + if (report_interval) { + next_report_time = current_time_ns + report_interval; + } + + last_send_time = 0; + + seqmap_init(); + + /* main loop */ + main_loop(); + +/* Debug: CPU Performance */ +#if defined(DEBUG) || defined(_DEBUG) + perf_cpu_end = clock(); + perf_cpu_time_used = ((double) (perf_cpu_end - perf_cpu_start)) / CLOCKS_PER_SEC; + printf("[DEBUG] CPU time used: %f sec", perf_cpu_time_used); +#endif /* DEBUG || _DEBUG */ + + finish(); + + return 0; +} + +static inline int64_t timespec_ns(struct timespec *a) +{ + return ((int64_t)a->tv_sec * 1000000000) + a->tv_nsec; +} + +void add_cidr(char *addr) +{ + char *addr_end; + char *mask_str; + unsigned long mask; + unsigned long bitmask; + int ret; + struct addrinfo addr_hints; + struct addrinfo *addr_res; + unsigned long net_addr; + unsigned long net_last; + + /* Split address from mask */ + addr_end = strchr(addr, '/'); + if (addr_end == NULL) { + usage(1); + } + *addr_end = '\0'; + mask_str = addr_end + 1; + mask = atoi(mask_str); + + /* parse address (IPv4 only) */ + memset(&addr_hints, 0, sizeof(struct addrinfo)); + addr_hints.ai_family = AF_UNSPEC; + addr_hints.ai_flags = AI_NUMERICHOST; + ret = getaddrinfo(addr, NULL, &addr_hints, &addr_res); + if (ret) { + fprintf(stderr, "%s, can't parse address %s: %s\n", prog, addr, gai_strerror(ret)); + exit(1); + } + if (addr_res->ai_family != AF_INET) { + fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog); + exit(1); + } + net_addr = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); + freeaddrinfo(addr_res); + + /* check mask */ + if (mask < 1 || mask > 32) { + fprintf(stderr, "%s: netmask must be between 1 and 32 (is: %s)\n", prog, mask_str); + exit(1); + } + + /* convert mask integer from 1 to 32 to a bitmask */ + bitmask = ((unsigned long)0xFFFFFFFF) << (32 - mask); + + /* calculate network range */ + net_addr &= bitmask; + net_last = net_addr + ((unsigned long)0x1 << (32 - mask)) - 1; + + /* exclude network and broadcast address for regular prefixes */ + if (mask < 31) { + net_last--; + net_addr++; + } + + /* add all hosts in that network (net_addr and net_last inclusive) */ + add_addr_range_ipv4(net_addr, net_last); +} + +void add_range(char *start, char *end) +{ + struct addrinfo addr_hints; + struct addrinfo *addr_res; + unsigned long start_long; + unsigned long end_long; + int ret; + + /* parse start address (IPv4 only) */ + memset(&addr_hints, 0, sizeof(struct addrinfo)); + addr_hints.ai_family = AF_UNSPEC; + addr_hints.ai_flags = AI_NUMERICHOST; + ret = getaddrinfo(start, NULL, &addr_hints, &addr_res); + if (ret) { + fprintf(stderr, "%s: can't parse address %s: %s\n", prog, start, gai_strerror(ret)); + exit(1); + } + if (addr_res->ai_family != AF_INET) { + freeaddrinfo(addr_res); + fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog); + exit(1); + } + start_long = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); + + /* parse end address (IPv4 only) */ + memset(&addr_hints, 0, sizeof(struct addrinfo)); + addr_hints.ai_family = AF_UNSPEC; + addr_hints.ai_flags = AI_NUMERICHOST; + ret = getaddrinfo(end, NULL, &addr_hints, &addr_res); + if (ret) { + fprintf(stderr, "%s: can't parse address %s: %s\n", prog, end, gai_strerror(ret)); + exit(1); + } + if (addr_res->ai_family != AF_INET) { + freeaddrinfo(addr_res); + fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog); + exit(1); + } + end_long = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); + freeaddrinfo(addr_res); + + /* add IPv4 addresses from closed interval [start_long,end_long] */ + add_addr_range_ipv4(start_long, end_long); +} + +void add_addr_range_ipv4(unsigned long start_long, unsigned long end_long) +{ + /* check if generator limit is exceeded */ + if (end_long >= start_long + MAX_GENERATE) { + fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog); + exit(1); + } + + /* generate */ + for (; start_long <= end_long; start_long++) { + struct in_addr in_addr_tmp; + char buffer[20]; + in_addr_tmp.s_addr = htonl(start_long); + inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer)); + add_name(buffer); + } +} + +void main_loop() +{ + int64_t lt; + int64_t wait_time_ns; + struct event *event; + struct host_entry *h; + + while (event_queue_ping.first || event_queue_timeout.first) { + dbg_printf("%s", "# main_loop\n"); + + /* timeout event ? */ + if (event_queue_timeout.first && event_queue_timeout.first->ev_time - current_time_ns <= 0) { + event = ev_dequeue(&event_queue_timeout); + h = event->host; + + dbg_printf("%s [%d]: timeout event\n", h->host, event->ping_index); + + stats_add(h, event->ping_index, 0, -1); + + if (per_recv_flag) { + if (timestamp_flag) { + print_timestamp_format(current_time_ns, timestamp_format_flag); + } + printf("%-*s : [%d], timed out", + max_hostname_len, h->host, event->ping_index); + if (h->num_recv > 0) { + printf(" (%s avg, ", sprint_tm(h->total_time / h->num_recv)); + } + else { + printf(" (NaN avg, "); + } + if (h->num_recv <= h->num_sent) { + printf("%d%% loss)", + ((h->num_sent - h->num_recv) * 100) / h->num_sent); + } + else { + printf("%d%% return)", + (h->num_recv_total * 100) / h->num_sent); + } + printf("\n"); + } + + /* do we need to send a retry? */ + if (!loop_flag && !count_flag) { + if (h->num_sent < retry + 1) { + if (backoff_flag) { + h->timeout *= backoff; + } + send_ping(h, event->ping_index); + } + } + + /* note: we process first timeout events, because we might need to + * wait to process ping events, while we for sure never need to + * wait for timeout events. + */ + continue; + } + + /* ping event ? */ + if (event_queue_ping.first && event_queue_ping.first->ev_time - current_time_ns <= 0) { + /* Make sure that we don't ping more than once every "interval" */ + lt = current_time_ns - last_send_time; + if (lt < interval) + goto wait_for_reply; + + /* Dequeue the event */ + event = ev_dequeue(&event_queue_ping); + h = event->host; + + dbg_printf("%s [%d]: ping event\n", h->host, event->ping_index); + + /* Send the ping */ + send_ping(h, event->ping_index); + + /* Loop and count mode: schedule next ping */ + if (loop_flag || (count_flag && event->ping_index + 1 < count)) { + host_add_ping_event(h, event->ping_index + 1, event->ev_time + perhost_interval); + } + } + + wait_for_reply: + + /* When is the next ping next event? */ + wait_time_ns = -1; + if (event_queue_ping.first) { + wait_time_ns = event_queue_ping.first->ev_time - current_time_ns; + if (wait_time_ns < 0) + wait_time_ns = 0; + /* make sure that we wait enough, so that the inter-ping delay is + * bigger than 'interval' */ + if (wait_time_ns < interval) { + lt = current_time_ns - last_send_time; + if (lt < interval) { + wait_time_ns = interval - lt; + } + } + + dbg_printf("next ping event in %.0f ms (%s)\n", wait_time_ns / 1e6, event_queue_ping.first->host->host); + } + + /* When is the next timeout event? */ + if (event_queue_timeout.first) { + int64_t wait_time_timeout = event_queue_timeout.first->ev_time - current_time_ns; + if (wait_time_ns < 0 || wait_time_timeout < wait_time_ns) { + wait_time_ns = wait_time_timeout; + if (wait_time_ns < 0) { + wait_time_ns = 0; + } + } + + dbg_printf("next timeout event in %.0f ms (%s)\n", wait_time_timeout / 1e6, event_queue_timeout.first->host->host); + } + + /* When is the next report due? */ + if (report_interval && (loop_flag || count_flag)) { + int64_t wait_time_next_report = next_report_time - current_time_ns; + if (wait_time_next_report < wait_time_ns) { + wait_time_ns = wait_time_next_report; + if (wait_time_ns < 0) { + wait_time_ns = 0; + } + } + + dbg_printf("next report event in %0.f ms\n", wait_time_next_report / 1e6); + } + + /* if wait_time is still -1, it means that we are waiting for nothing... */ + if (wait_time_ns == -1) { + break; + } + + /* end of loop was requested by interrupt signal handler */ + if (finish_requested) { + break; + } + + /* Receive replies */ + /* (this is what sleeps during each loop iteration) */ + dbg_printf("waiting up to %.0f ms\n", wait_time_ns / 1e6); + if (wait_for_reply(wait_time_ns)) { + while (wait_for_reply(0)) + ; /* process other replies in the queue */ + } + + update_current_time(); + + if (status_snapshot) { + status_snapshot = 0; + print_per_system_splits(); + } + + /* Print report */ + if (report_interval && (loop_flag || count_flag) && (current_time_ns >= next_report_time)) { + if (netdata_flag) + print_netdata(); + else + print_per_system_splits(); + + while (current_time_ns >= next_report_time) { + next_report_time += report_interval; + } + } + } +} + +/************************************************************ + + Function: signal_handler + +************************************************************* + + Inputs: int signum + + Description: + + SIGQUIT signal handler - set flag and return + SIGINT signal handler - set flag and return + +************************************************************/ + +void signal_handler(int signum) +{ + switch (signum) { + case SIGINT: + finish_requested = 1; + break; + + case SIGQUIT: + status_snapshot = 1; + break; + } +} + +/************************************************************ + + Function: update_current_time + +*************************************************************/ + +void update_current_time() +{ + clock_gettime(CLOCKID, ¤t_time); + current_time_ns = timespec_ns(¤t_time); +} + +/************************************************************ + + Function: finish + +************************************************************* + + Inputs: void (none) + + Description: + + Main program clean up and exit point + +************************************************************/ + +void finish() +{ + int i; + HOST_ENTRY *h; + + update_current_time(); + end_time = current_time_ns; + + /* tot up unreachables */ + for (i = 0; i < num_hosts; i++) { + h = table[i]; + + if (!h->num_recv) { + num_unreachable++; + + if (verbose_flag || unreachable_flag) { + printf("%s", h->host); + + if (verbose_flag) + printf(" is unreachable"); + + printf("\n"); + } + } + } + + if (count_flag || loop_flag) + print_per_system_stats(); +#if defined(DEBUG) || defined(_DEBUG) + else if (print_per_system_flag) + print_per_system_stats(); +#endif /* DEBUG || _DEBUG */ + + if (stats_flag) + print_global_stats(); + + if (min_reachable) { + if ((num_hosts - num_unreachable) >= min_reachable) { + printf("Enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts - num_unreachable); + exit(0); + } + else { + printf("Not enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts - num_unreachable); + exit(1); + } + } + + if (num_noaddress) + exit(2); + else if (num_alive != num_hosts) + exit(1); + + exit(0); +} + +/************************************************************ + + Function: print_per_system_stats + +************************************************************* + + Inputs: void (none) + + Description: + + +************************************************************/ + +void print_per_system_stats(void) +{ + int i, j, avg, outage_ms; + HOST_ENTRY *h; + int64_t resp; + + if (verbose_flag || per_recv_flag) + fprintf(stderr, "\n"); + + for (i = 0; i < num_hosts; i++) { + h = table[i]; + fprintf(stderr, "%-*s :", max_hostname_len, h->host); + + if (report_all_rtts_flag) { + for (j = 0; j < h->num_sent; j++) { + if ((resp = h->resp_times[j]) >= 0) + fprintf(stderr, " %s", sprint_tm(resp)); + else + fprintf(stderr, " -"); + } + + fprintf(stderr, "\n"); + } + else { + if (h->num_recv <= h->num_sent) { + fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%", + h->num_sent, h->num_recv, h->num_sent > 0 ? ((h->num_sent - h->num_recv) * 100) / h->num_sent : 0); + + if (outage_flag) { + /* Time outage total */ + outage_ms = (h->num_sent - h->num_recv) * perhost_interval / 1e6; + fprintf(stderr, ", outage(ms) = %d", outage_ms); + } + } + else { + fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%", + h->num_sent, h->num_recv, + h->num_sent > 0 ? ((h->num_recv * 100) / h->num_sent) : 0); + } + + if (h->num_recv) { + avg = h->total_time / h->num_recv; + fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply)); + fprintf(stderr, "/%s", sprint_tm(avg)); + fprintf(stderr, "/%s", sprint_tm(h->max_reply)); + } + + fprintf(stderr, "\n"); + } + } +} + +/************************************************************ + + Function: print_netdata + +************************************************************* + + Inputs: void (none) + + Description: + + +************************************************************/ + +void print_netdata(void) +{ + static int sent_charts = 0; + + int i; + int64_t avg; + HOST_ENTRY *h; + + for (i = 0; i < num_hosts; i++) { + h = table[i]; + + if (!sent_charts) { + printf("CHART fping.%s_packets '' 'FPing Packets' packets '%s' fping.packets line 110020 %.0f\n", h->name, h->host, report_interval / 1e9); + printf("DIMENSION xmt sent absolute 1 1\n"); + printf("DIMENSION rcv received absolute 1 1\n"); + } + + printf("BEGIN fping.%s_packets\n", h->name); + printf("SET xmt = %d\n", h->num_sent_i); + printf("SET rcv = %d\n", h->num_recv_i); + printf("END\n"); + + if (!sent_charts) { + printf("CHART fping.%s_quality '' 'FPing Quality' percentage '%s' fping.quality area 110010 %.0f\n", h->name, h->host, report_interval / 1e9); + printf("DIMENSION returned '' absolute 1 1\n"); + /* printf("DIMENSION lost '' absolute 1 1\n"); */ + } + + printf("BEGIN fping.%s_quality\n", h->name); + /* + if( h->num_recv_i <= h->num_sent_i ) + printf("SET lost = %d\n", h->num_sent_i > 0 ? ( ( h->num_sent_i - h->num_recv_i ) * 100 ) / h->num_sent_i : 0 ); + else + printf("SET lost = 0\n"); +*/ + + printf("SET returned = %d\n", h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0); + printf("END\n"); + + if (!sent_charts) { + printf("CHART fping.%s_latency '' 'FPing Latency' ms '%s' fping.latency area 110000 %.0f\n", h->name, h->host, report_interval / 1e9); + printf("DIMENSION min minimum absolute 1 1000000\n"); + printf("DIMENSION max maximum absolute 1 1000000\n"); + printf("DIMENSION avg average absolute 1 1000000\n"); + } + + printf("BEGIN fping.%s_latency\n", h->name); + if (h->num_recv_i) { + avg = h->total_time_i / h->num_recv_i; + printf("SET min = %" PRId64 "\n", h->min_reply_i); + printf("SET avg = %" PRId64 "\n", avg); + printf("SET max = %" PRId64 "\n", h->max_reply_i); + } + printf("END\n"); + + stats_reset_interval(h); + } + + sent_charts = 1; +} + +/************************************************************ + + Function: print_per_system_splits + +************************************************************* + + Inputs: void (none) + + Description: + + +************************************************************/ + +void print_per_system_splits(void) +{ + int i, avg, outage_ms_i; + HOST_ENTRY *h; + struct tm *curr_tm; + + if (verbose_flag || per_recv_flag) + fprintf(stderr, "\n"); + + update_current_time(); + curr_tm = localtime((time_t *)¤t_time.tv_sec); + fprintf(stderr, "[%2.2d:%2.2d:%2.2d]\n", curr_tm->tm_hour, + curr_tm->tm_min, curr_tm->tm_sec); + + for (i = 0; i < num_hosts; i++) { + h = table[i]; + fprintf(stderr, "%-*s :", max_hostname_len, h->host); + + if (h->num_recv_i <= h->num_sent_i) { + fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%", + h->num_sent_i, h->num_recv_i, h->num_sent_i > 0 ? ((h->num_sent_i - h->num_recv_i) * 100) / h->num_sent_i : 0); + + if (outage_flag) { + /* Time outage */ + outage_ms_i = (h->num_sent_i - h->num_recv_i) * perhost_interval / 1e6; + fprintf(stderr, ", outage(ms) = %d", outage_ms_i); + } + } + else { + fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%", + h->num_sent_i, h->num_recv_i, h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0); + } + + if (h->num_recv_i) { + avg = h->total_time_i / h->num_recv_i; + fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply_i)); + fprintf(stderr, "/%s", sprint_tm(avg)); + fprintf(stderr, "/%s", sprint_tm(h->max_reply_i)); + } + + fprintf(stderr, "\n"); + if (!cumulative_stats_flag) { + stats_reset_interval(h); + } + } +} + +/************************************************************ + + Function: print_global_stats + +************************************************************* + + Inputs: void (none) + + Description: + + +************************************************************/ + +void print_global_stats(void) +{ + fprintf(stderr, "\n"); + fprintf(stderr, " %7d targets\n", num_hosts); + fprintf(stderr, " %7d alive\n", num_alive); + fprintf(stderr, " %7d unreachable\n", num_unreachable); + fprintf(stderr, " %7d unknown addresses\n", num_noaddress); + fprintf(stderr, "\n"); + fprintf(stderr, " %7d timeouts (waiting for response)\n", num_timeout); + fprintf(stderr, " %7d ICMP Echos sent\n", num_pingsent); + fprintf(stderr, " %7d ICMP Echo Replies received\n", num_pingreceived); + fprintf(stderr, " %7d other ICMP received\n", num_othericmprcvd); + fprintf(stderr, "\n"); + + if (total_replies == 0) { + min_reply = 0; + max_reply = 0; + total_replies = 1; + sum_replies = 0; + } + + fprintf(stderr, " %s ms (min round trip time)\n", sprint_tm(min_reply)); + fprintf(stderr, " %s ms (avg round trip time)\n", + sprint_tm(sum_replies / total_replies)); + fprintf(stderr, " %s ms (max round trip time)\n", sprint_tm(max_reply)); + fprintf(stderr, " %12.3f sec (elapsed real time)\n", + (end_time - start_time) / 1e9); + fprintf(stderr, "\n"); +} + +/************************************************************ + + Function: send_ping + +************************************************************* + + Inputs: int s, HOST_ENTRY *h + + Description: + + Compose and transmit an ICMP_ECHO REQUEST packet. The IP packet + will be added on by the kernel. The ID field is our UNIX process ID, + and the sequence number is an index into an array of outstanding + ping requests. The sequence number will later be used to quickly + figure out who the ping reply came from. + +************************************************************/ + +int send_ping(HOST_ENTRY *h, int index) +{ + int n; + int myseq; + int ret = 1; + uint8_t proto = ICMP_ECHO; + + update_current_time(); + h->last_send_time = current_time_ns; + myseq = seqmap_add(h->i, index, current_time_ns); + + dbg_printf("%s [%d]: send ping\n", h->host, index); + + if (h->saddr.ss_family == AF_INET && socket4 >= 0) { + if(icmp_request_typ == 13) + proto = ICMP_TSTAMP; + n = socket_sendto_ping_ipv4(socket4, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident4, proto); + } +#ifdef IPV6 + else if (h->saddr.ss_family == AF_INET6 && socket6 >= 0) { + n = socket_sendto_ping_ipv6(socket6, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident6); + } +#endif + else { + return 0; + } + + /* error sending? */ + if ( + (n < 0) +#if defined(EHOSTDOWN) + && errno != EHOSTDOWN +#endif + ) { + if (verbose_flag) { + print_warning("%s: error while sending ping: %s\n", h->host, strerror(errno)); + } + else { + dbg_printf("%s: error while sending ping: %s\n", h->host, strerror(errno)); + } + + h->num_sent++; + h->num_sent_i++; + if (!loop_flag) + h->resp_times[index] = RESP_ERROR; + + ret = 0; + } + else { + /* schedule timeout */ + host_add_timeout_event(h, index, current_time_ns + h->timeout); + + /* mark this trial as outstanding */ + if (!loop_flag) { + h->resp_times[index] = RESP_WAITING; + } + } + + num_pingsent++; + last_send_time = h->last_send_time; + + return (ret); +} + +int socket_can_read(struct timeval *timeout) +{ + int nfound; + fd_set readset; + int socketmax; + +#ifndef IPV6 + socketmax = socket4; +#else + socketmax = socket4 > socket6 ? socket4 : socket6; +#endif + +select_again: + FD_ZERO(&readset); + if (socket4 >= 0) + FD_SET(socket4, &readset); +#ifdef IPV6 + if (socket6 >= 0) + FD_SET(socket6, &readset); +#endif + + nfound = select(socketmax + 1, &readset, NULL, NULL, timeout); + if (nfound < 0) { + if (errno == EINTR) { + /* interrupted system call: redo the select */ + goto select_again; + } + else { + perror("select"); + } + } + + if (nfound > 0) { + if (socket4 >= 0 && FD_ISSET(socket4, &readset)) { + return socket4; + } +#ifdef IPV6 + if (socket6 >= 0 && FD_ISSET(socket6, &readset)) { + return socket6; + } +#endif + } + + return -1; +} + +int receive_packet(int64_t wait_time, +#if HAVE_SO_TIMESTAMPNS + int64_t *reply_timestamp, +#else + int64_t *reply_timestamp __attribute__((unused)), +#endif + struct sockaddr *reply_src_addr, + size_t reply_src_addr_len, + char *reply_buf, + size_t reply_buf_len) +{ + struct timeval to; + int s = 0; + int recv_len; + static unsigned char msg_control[40]; + struct iovec msg_iov = { + reply_buf, + reply_buf_len + }; + struct msghdr recv_msghdr = {0}; + recv_msghdr.msg_name = reply_src_addr; + recv_msghdr.msg_namelen = reply_src_addr_len; + recv_msghdr.msg_iov = &msg_iov; + recv_msghdr.msg_iovlen = 1; + recv_msghdr.msg_control = &msg_control; + recv_msghdr.msg_controllen = sizeof(msg_control); +#if HAVE_SO_TIMESTAMPNS + struct cmsghdr *cmsg; +#endif + + /* Wait for a socket to become ready */ + if (wait_time) { + to.tv_sec = wait_time / UINT64_C(1000000000); + to.tv_usec = (wait_time % UINT64_C(1000000000)) / 1000 + 1; + } + else { + to.tv_sec = 0; + to.tv_usec = 0; + } + s = socket_can_read(&to); + if (s == -1) { + return 0; /* timeout */ + } + + recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC); + if (recv_len <= 0) { + return 0; + } + +#if HAVE_SO_TIMESTAMPNS + /* ancilliary data */ + { + struct timespec reply_timestamp_ts; + for (cmsg = CMSG_FIRSTHDR(&recv_msghdr); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPNS) { + memcpy(&reply_timestamp_ts, CMSG_DATA(cmsg), sizeof(reply_timestamp_ts)); + *reply_timestamp = timespec_ns(&reply_timestamp_ts); + } + } + } +#endif + +#if defined(DEBUG) || defined(_DEBUG) + if (randomly_lose_flag) { + if ((random() & 0x07) <= lose_factor) + return 0; + } +#endif + + return recv_len; +} + +/* stats_add: update host statistics for a single packet that was received (or timed out) + * h: host entry to update + * index: if in count mode: index number for this ping packet (-1 otherwise) + * success: 1 if response received, 0 otherwise + * latency: response time, in ns + */ +void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency) +{ + /* sent count - we update only on receive/timeout, so that we don't get + * weird loss percentage, just because a packet was note recived yet. + */ + h->num_sent++; + h->num_sent_i++; + + if (!success) { + if (!loop_flag && index >= 0) { + h->resp_times[index] = RESP_TIMEOUT; + } + num_timeout++; + return; + } + + /* received count */ + h->num_recv++; + h->num_recv_i++; + + /* maximum */ + if (!h->max_reply || latency > h->max_reply) { + h->max_reply = latency; + } + if (!h->max_reply_i || latency > h->max_reply_i) { + h->max_reply_i = latency; + } + + /* minimum */ + if (!h->min_reply || latency < h->min_reply) { + h->min_reply = latency; + } + if (!h->min_reply_i || latency < h->min_reply_i) { + h->min_reply_i = latency; + } + + /* total time (for average) */ + h->total_time += latency; + h->total_time_i += latency; + + /* response time per-packet (count mode) */ + if (!loop_flag && index >= 0) { + h->resp_times[index] = latency; + } +} + +/* stats_reset_interval: reset interval statistics + * h: host entry to update + */ +void stats_reset_interval(HOST_ENTRY *h) +{ + h->num_sent_i = 0; + h->num_recv_i = 0; + h->max_reply_i = 0; + h->min_reply_i = 0; + h->total_time_i = 0; +} + +int decode_icmp_ipv4( + struct sockaddr *response_addr, + size_t response_addr_len, + char *reply_buf, + size_t reply_buf_len, + unsigned short *id, + unsigned short *seq, + int *ip_header_tos, + int *ip_header_ttl, + uint32_t *ip_header_otime_ms, + uint32_t *ip_header_rtime_ms, + uint32_t *ip_header_ttime_ms) +{ + struct icmp *icp; + int hlen = 0; + + if (!using_sock_dgram4) { + struct ip *ip = (struct ip *)reply_buf; + *ip_header_tos = ip->ip_tos; + *ip_header_ttl = ip->ip_ttl; + +#if defined(__alpha__) && __STDC__ && !defined(__GLIBC__) && !defined(__NetBSD__) && !defined(__OpenBSD__) + /* The alpha headers are decidedly broken. + * Using an ANSI compiler, it provides ip_vhl instead of ip_hl and + * ip_v. So, to get ip_hl, we mask off the bottom four bits. + */ + hlen = (ip->ip_vhl & 0x0F) << 2; +#else + hlen = ip->ip_hl << 2; +#endif + } + + if (reply_buf_len < hlen + ICMP_MINLEN) { + /* too short */ + if (verbose_flag) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf); + } + return -1; + } + + icp = (struct icmp *)(reply_buf + hlen); + + if ((icmp_request_typ == 0 && icp->icmp_type != ICMP_ECHOREPLY) || + (icmp_request_typ == 13 && icp->icmp_type != ICMP_TSTAMPREPLY)) { + /* Handle other ICMP packets */ + struct icmp *sent_icmp; + SEQMAP_VALUE *seqmap_value; + char addr_ascii[INET6_ADDRSTRLEN]; + HOST_ENTRY *h; + + /* reply icmp packet (hlen + ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */ + if (reply_buf_len < hlen + ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) { + /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */ + return -1; + } + + sent_icmp = (struct icmp *)(reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip)); + + if ((icmp_request_typ == 0 && sent_icmp->icmp_type != ICMP_ECHO) || + (icmp_request_typ == 13 && sent_icmp->icmp_type != ICMP_TSTAMP) || + sent_icmp->icmp_id != ident4) { + /* not caused by us */ + return -1; + } + + seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), current_time_ns); + if (seqmap_value == NULL) { + return -1; + } + + getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + + switch (icp->icmp_type) { + case ICMP_UNREACH: + h = table[seqmap_value->host_nr]; + if (icp->icmp_code > ICMP_UNREACH_MAXTYPE) { + print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s", + addr_ascii, h->host); + } + else { + print_warning("%s from %s for ICMP Echo sent to %s", + icmp_unreach_str[icp->icmp_code], addr_ascii, h->host); + } + + print_warning("\n"); + num_othericmprcvd++; + break; + + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + h = table[seqmap_value->host_nr]; + if (icp->icmp_type <= ICMP_TYPE_STR_MAX) { + print_warning("%s from %s for ICMP Echo sent to %s", + icmp_type_str[icp->icmp_type], addr_ascii, h->host); + } + else { + print_warning("ICMP %d from %s for ICMP Echo sent to %s", + icp->icmp_type, addr_ascii, h->host); + } + print_warning("\n"); + num_othericmprcvd++; + break; + } + + return -1; + } + + *id = icp->icmp_id; + *seq = ntohs(icp->icmp_seq); + if(icp->icmp_type == ICMP_TSTAMPREPLY) { + + /* Check that reply_buf_len is sufficiently big to contain the timestamps */ + if (reply_buf_len < hlen + ICMP_MINLEN + ICMP_TIMESTAMP_DATA_SIZE) { + if (verbose_flag) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + printf("received packet too short for ICMP Timestamp Reply (%d bytes from %s)\n", (int)reply_buf_len, buf); + } + return -1; + } + + *ip_header_otime_ms = ntohl(icp->icmp_dun.id_ts.its_otime); + *ip_header_rtime_ms = ntohl(icp->icmp_dun.id_ts.its_rtime); + *ip_header_ttime_ms = ntohl(icp->icmp_dun.id_ts.its_ttime); + } + + return hlen; +} + +#ifdef IPV6 +int decode_icmp_ipv6( + struct sockaddr *response_addr, + size_t response_addr_len, + char *reply_buf, + size_t reply_buf_len, + unsigned short *id, + unsigned short *seq) +{ + struct icmp6_hdr *icp; + + if (reply_buf_len < sizeof(struct icmp6_hdr)) { + if (verbose_flag) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf); + } + return 0; /* too short */ + } + + icp = (struct icmp6_hdr *)reply_buf; + + if (icp->icmp6_type != ICMP6_ECHO_REPLY) { + /* Handle other ICMP packets */ + struct icmp6_hdr *sent_icmp; + SEQMAP_VALUE *seqmap_value; + char addr_ascii[INET6_ADDRSTRLEN]; + HOST_ENTRY *h; + + /* reply icmp packet (ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */ + if (reply_buf_len < ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) { + /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */ + return 0; + } + + sent_icmp = (struct icmp6_hdr *)(reply_buf + sizeof(struct icmp6_hdr) + sizeof(struct ip)); + + if (sent_icmp->icmp6_type != ICMP_ECHO || sent_icmp->icmp6_id != ident6) { + /* not caused by us */ + return 0; + } + + seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), current_time_ns); + if (seqmap_value == NULL) { + return 0; + } + + getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + + switch (icp->icmp6_type) { + case ICMP_UNREACH: + h = table[seqmap_value->host_nr]; + if (icp->icmp6_code > ICMP_UNREACH_MAXTYPE) { + print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s", + addr_ascii, h->host); + } + else { + print_warning("%s from %s for ICMP Echo sent to %s", + icmp_unreach_str[icp->icmp6_code], addr_ascii, h->host); + } + + print_warning("\n"); + num_othericmprcvd++; + break; + + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + h = table[seqmap_value->host_nr]; + if (icp->icmp6_type <= ICMP_TYPE_STR_MAX) { + print_warning("%s from %s for ICMP Echo sent to %s", + icmp_type_str[icp->icmp6_type], addr_ascii, h->host); + } + else { + print_warning("ICMP %d from %s for ICMP Echo sent to %s", + icp->icmp6_type, addr_ascii, h->host); + } + print_warning("\n"); + num_othericmprcvd++; + break; + } + + return 0; + } + + *id = icp->icmp6_id; + *seq = ntohs(icp->icmp6_seq); + + return 1; +} +#endif + +int wait_for_reply(int64_t wait_time) +{ + int result; + static char buffer[RECV_BUFSIZE]; + struct sockaddr_storage response_addr; + int n, avg; + HOST_ENTRY *h; + int64_t this_reply; + int this_count; + int64_t recv_time = 0; + SEQMAP_VALUE *seqmap_value; + unsigned short id; + unsigned short seq; + int ip_header_tos = -1; + int ip_header_ttl = -1; + // ICMP Timestamp + uint32_t ip_header_otime_ms = 0x80000000U; + uint32_t ip_header_rtime_ms = 0x80000000U; + uint32_t ip_header_ttime_ms = 0x80000000U; + + /* Receive packet */ + result = receive_packet(wait_time, /* max. wait time, in ns */ + &recv_time, /* reply_timestamp */ + (struct sockaddr *)&response_addr, /* reply_src_addr */ + sizeof(response_addr), /* reply_src_addr_len */ + buffer, /* reply_buf */ + sizeof(buffer) /* reply_buf_len */ + ); + + if (result <= 0) { + return 0; + } + + update_current_time(); + if (recv_time == 0) + recv_time = current_time_ns; + + /* Process ICMP packet and retrieve id/seq */ + if (response_addr.ss_family == AF_INET) { + int ip_hlen = decode_icmp_ipv4( + (struct sockaddr *)&response_addr, + sizeof(response_addr), + buffer, + sizeof(buffer), + &id, + &seq, + &ip_header_tos, + &ip_header_ttl, + &ip_header_otime_ms, + &ip_header_rtime_ms, + &ip_header_ttime_ms); + if (ip_hlen < 0) { + return 1; + } + if (id != ident4) { + return 1; /* packet received, but not the one we are looking for! */ + } + if (!using_sock_dgram4) { + /* do not include IP header in returned size, to be consistent with ping(8) and also + * with fping with IPv6 hosts */ + result -= ip_hlen; + } + } +#ifdef IPV6 + else if (response_addr.ss_family == AF_INET6) { + if (!decode_icmp_ipv6( + (struct sockaddr *)&response_addr, + sizeof(response_addr), + buffer, + sizeof(buffer), + &id, + &seq)) { + return 1; + } + if (id != ident6) { + return 1; /* packet received, but not the one we are looking for! */ + } + } +#endif + else { + return 1; + } + + seqmap_value = seqmap_fetch(seq, current_time_ns); + if (seqmap_value == NULL) { + return 1; + } + + /* find corresponding host_entry */ + n = seqmap_value->host_nr; + h = table[n]; + this_count = seqmap_value->ping_count; + this_reply = recv_time - seqmap_value->ping_ts; + + /* update stats that include invalid replies */ + h->num_recv_total++; + num_pingreceived++; + + dbg_printf("received [%d] from %s\n", this_count, h->host); + + /* optionally require reply source equal to target address */ + if (check_source_flag && addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) { + dbg_printf("discarding reply from wrong source address\n"); + return 1; + } + + /* discard duplicates */ + if (!loop_flag && h->resp_times[this_count] >= 0) { + if (!per_recv_flag) { + fprintf(stderr, "%s : duplicate for [%d], %d bytes, %s ms", + h->host, this_count, result, sprint_tm(this_reply)); + + if (addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + fprintf(stderr, " [<- %s]", buf); + } + fprintf(stderr, "\n"); + } + return 1; + } + + /* discard reply if delay is larger than timeout + * (see also: github #32) */ + if (this_reply > h->timeout) { + return 1; + } + + /* update stats */ + stats_add(h, this_count, 1, this_reply); + // TODO: move to stats_add? + if (!max_reply || this_reply > max_reply) + max_reply = this_reply; + if (!min_reply || this_reply < min_reply) + min_reply = this_reply; + sum_replies += this_reply; + total_replies++; + + /* initialize timeout to initial timeout (without backoff) */ + h->timeout = timeout; + + /* remove timeout event */ + struct event *timeout_event = host_get_timeout_event(h, this_count); + if (timeout_event) { + ev_remove(&event_queue_timeout, timeout_event); + } + + /* print "is alive" */ + if (h->num_recv == 1) { + num_alive++; + if (fast_reachable && num_alive >= min_reachable) + finish_requested = 1; + + if (verbose_flag || alive_flag) { + printf("%s", h->host); + + if (verbose_flag) + printf(" is alive"); + } + } + + /* print received ping (unless --quiet) */ + if (per_recv_flag) { + if (timestamp_flag) { + print_timestamp_format(recv_time, timestamp_format_flag); + } + avg = h->total_time / h->num_recv; + printf("%-*s : [%d], %d bytes, %s ms", + max_hostname_len, h->host, this_count, result, sprint_tm(this_reply)); + printf(" (%s avg, ", sprint_tm(avg)); + + if (h->num_recv <= h->num_sent) { + printf("%d%% loss)", + ((h->num_sent - h->num_recv) * 100) / h->num_sent); + } + else { + printf("%d%% return)", + (h->num_recv_total * 100) / h->num_sent); + } + } + + if (verbose_flag || alive_flag || per_recv_flag) { + + if (addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + fprintf(stderr, " [<- %s]", buf); + } + + if (icmp_request_typ == 13) { + printf("%s timestamps: Originate=%u Receive=%u Transmit=%u Localreceive=%u", + alive_flag ? "" : ",", + ip_header_otime_ms, ip_header_rtime_ms, ip_header_ttime_ms, + ms_since_midnight_utc(recv_time)); + } + + if(print_tos_flag) { + if(ip_header_tos != -1) { + printf(" (TOS %d)", ip_header_tos); + } + else { + printf(" (TOS unknown)"); + } + } + + if (print_ttl_flag) { + if(ip_header_ttl != -1) { + printf(" (TTL %d)", ip_header_ttl); + } + else { + printf(" (TTL unknown)"); + } + } + + if (elapsed_flag && !per_recv_flag) + printf(" (%s ms)", sprint_tm(this_reply)); + + printf("\n"); + } + + return 1; +} + +/************************************************************ + + Function: add_name + +************************************************************* + + Inputs: char* name + + Description: + + process input name for addition to target list + name can turn into multiple targets via multiple interfaces (-m) + or via NIS groups + +************************************************************/ + +void add_name(char *name) +{ + struct addrinfo *res0, *res, hints; + int ret_ga; + char *printname; + char namebuf[256]; + char addrbuf[256]; + + /* getaddrinfo */ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_UNUSABLE; + hints.ai_socktype = SOCK_RAW; + hints.ai_family = hints_ai_family; + if (hints_ai_family == AF_INET) { + hints.ai_protocol = IPPROTO_ICMP; + } +#ifdef IPV6 + else if (hints_ai_family == AF_INET6) { + hints.ai_protocol = IPPROTO_ICMPV6; + } +#endif + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + } + ret_ga = getaddrinfo(name, NULL, &hints, &res0); + if (ret_ga) { + if (!quiet_flag) + print_warning("%s: %s\n", name, gai_strerror(ret_ga)); + num_noaddress++; + return; + } + + /* NOTE: we could/should loop with res on all addresses like this: + * for (res = res0; res; res = res->ai_next) { + * We don't do it yet, however, because is is an incompatible change + * (need to implement a separate option for this) + */ + for (res = res0; res; res = res->ai_next) { + /* name_flag: addr -> name lookup requested) */ + if (name_flag || rdns_flag) { + int do_rdns = rdns_flag ? 1 : 0; + if (name_flag) { + /* Was it a numerical address? Only then do a rdns-query */ + struct addrinfo *nres; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(name, NULL, &hints, &nres) == 0) { + do_rdns = 1; + freeaddrinfo(nres); + } + } + + if (do_rdns && getnameinfo(res->ai_addr, res->ai_addrlen, namebuf, sizeof(namebuf) / sizeof(char), NULL, 0, 0) == 0) { + printname = namebuf; + } + else { + printname = name; + } + } + else { + printname = name; + } + + /* addr_flag: name -> addr lookup requested */ + if (addr_flag) { + int ret; + ret = getnameinfo(res->ai_addr, res->ai_addrlen, addrbuf, + sizeof(addrbuf) / sizeof(char), NULL, 0, NI_NUMERICHOST); + if (ret) { + if (!quiet_flag) { + print_warning("%s: can't forward-lookup address (%s)\n", name, gai_strerror(ret)); + } + continue; + } + + if (name_flag || rdns_flag) { + char nameaddrbuf[512 + 3]; + snprintf(nameaddrbuf, sizeof(nameaddrbuf) / sizeof(char), "%s (%s)", printname, addrbuf); + add_addr(name, nameaddrbuf, res->ai_addr, res->ai_addrlen); + } + else { + add_addr(name, addrbuf, res->ai_addr, res->ai_addrlen); + } + } + else { + add_addr(name, printname, res->ai_addr, res->ai_addrlen); + } + + if (!multif_flag) { + break; + } + } + + freeaddrinfo(res0); +} + +/************************************************************ + + Function: add_addr + +************************************************************* + + Description: + + add single address to list of hosts to be pinged + +************************************************************/ + +void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_len) +{ + HOST_ENTRY *p; + int n; + int64_t *i; + + p = (HOST_ENTRY *)calloc(1, sizeof(HOST_ENTRY)); + if (!p) + crash_and_burn("can't allocate HOST_ENTRY"); + + p->name = strdup(name); + p->host = strdup(host); + memcpy(&p->saddr, ipaddr, ipaddr_len); + p->saddr_len = ipaddr_len; + p->timeout = timeout; + p->min_reply = 0; + + if (netdata_flag) { + char *s = p->name; + while (*s) { + if (!isalnum(*s)) + *s = '_'; + s++; + } + } + + if (strlen(p->host) > max_hostname_len) + max_hostname_len = strlen(p->host); + + /* array for response time results */ + if (!loop_flag) { + i = (int64_t *)malloc(trials * sizeof(int64_t)); + if (!i) + crash_and_burn("can't allocate resp_times array"); + + for (n = 1; n < trials; n++) + i[n] = RESP_UNUSED; + + p->resp_times = i; + } + + /* allocate event storage */ + p->event_storage_ping = (struct event *)calloc(event_storage_count, sizeof(struct event)); + if (!p->event_storage_ping) { + errno_crash_and_burn("can't allocate event_storage_ping"); + } + p->event_storage_timeout = (struct event *)calloc(event_storage_count, sizeof(struct event)); + if (!p->event_storage_timeout) { + errno_crash_and_burn("can't allocate event_storage_timeout"); + } + + /* schedule first ping */ + host_add_ping_event(p, 0, current_time_ns); + + num_hosts++; +} + +/************************************************************ + + Function: crash_and_burn + +************************************************************* + + Inputs: char* message + + Description: + +************************************************************/ + +void crash_and_burn(char *message) +{ + fprintf(stderr, "%s: %s\n", prog, message); + exit(4); +} + +/************************************************************ + + Function: errno_crash_and_burn + +************************************************************* + + Inputs: char* message + + Description: + +************************************************************/ + +void errno_crash_and_burn(char *message) +{ + fprintf(stderr, "%s: %s : %s\n", prog, message, strerror(errno)); + exit(4); +} + +/************************************************************ + + Function: print_warning + + Description: fprintf(stderr, ...), unless running with -q + +*************************************************************/ + +void print_warning(char *format, ...) +{ + va_list args; + if (!quiet_flag) { + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + } +} + +/************************************************************ + + Function: sprint_tm + +************************************************************* + + render nanosecond int64_t value into milliseconds string with three digits of + precision. + +************************************************************/ + +const char *sprint_tm(int64_t ns) +{ + static char buf[10]; + double t = (double)ns / 1e6; + + if (t < 0.0) { + /* negative (unexpected) */ + sprintf(buf, "%.2g", t); + } + else if (t < 1.0) { + /* <= 0.99 ms */ + sprintf(buf, "%.3f", t); + } + else if (t < 10.0) { + /* 1.00 - 9.99 ms */ + sprintf(buf, "%.2f", t); + } + else if (t < 100.0) { + /* 10.0 - 99.9 ms */ + sprintf(buf, "%.1f", t); + } + else if (t < 1000000.0) { + /* 100 - 1'000'000 ms */ + sprintf(buf, "%.0f", t); + } + else { + sprintf(buf, "%.3e", t); + } + + return (buf); +} + +/************************************************************ + + Function: addr_cmp + +*************************************************************/ +int addr_cmp(struct sockaddr *a, struct sockaddr *b) +{ + if (a->sa_family != b->sa_family) { + return a->sa_family - b->sa_family; + } + else { + if (a->sa_family == AF_INET) { + return ((struct sockaddr_in *)a)->sin_addr.s_addr - ((struct sockaddr_in *)b)->sin_addr.s_addr; + } + else if (a->sa_family == AF_INET6) { + return memcmp(&((struct sockaddr_in6 *)a)->sin6_addr, + &((struct sockaddr_in6 *)b)->sin6_addr, + sizeof(((struct sockaddr_in6 *)a)->sin6_addr)); + } + } + + return 0; +} + +void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time) +{ + struct event *event = &h->event_storage_ping[index % event_storage_count]; + event->host = h; + event->ping_index = index; + event->ev_time = ev_time; + ev_enqueue(&event_queue_ping, event); + + dbg_printf("%s [%d]: add ping event in %.0f ms\n", + event->host->host, index, (ev_time - current_time_ns) / 1e6); +} + +void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time) +{ + struct event *event = &h->event_storage_timeout[index % event_storage_count]; + event->host = h; + event->ping_index = index; + event->ev_time = ev_time; + ev_enqueue(&event_queue_timeout, event); + + dbg_printf("%s [%d]: add timeout event in %.0f ms\n", + event->host->host, index, (ev_time - current_time_ns) / 1e6); +} + +struct event *host_get_timeout_event(HOST_ENTRY *h, int index) +{ + return &h->event_storage_timeout[index % event_storage_count]; +} + +/************************************************************ + + Function: ev_enqueue + + Enqueue an event + + The queue is sorted by event->ev_time, so that queue->first always points to + the earliest event. + + We start scanning the queue from the tail, because we assume + that new events mostly get inserted with a event time higher + than the others. + +*************************************************************/ +void ev_enqueue(struct event_queue *queue, struct event *event) +{ + struct event *i; + struct event *i_prev; + + /* Empty list */ + if (queue->last == NULL) { + event->ev_next = NULL; + event->ev_prev = NULL; + queue->first = event; + queue->last = event; + return; + } + + /* Insert on tail? */ + if (event->ev_time - queue->last->ev_time >= 0) { + event->ev_next = NULL; + event->ev_prev = queue->last; + queue->last->ev_next = event; + queue->last = event; + return; + } + + /* Find insertion point */ + i = queue->last; + while (1) { + i_prev = i->ev_prev; + if (i_prev == NULL || event->ev_time - i_prev->ev_time >= 0) { + event->ev_prev = i_prev; + event->ev_next = i; + i->ev_prev = event; + if (i_prev != NULL) { + i_prev->ev_next = event; + } + else { + queue->first = event; + } + return; + } + i = i_prev; + } +} + +/************************************************************ + + Function: ev_dequeue + +*************************************************************/ +struct event *ev_dequeue(struct event_queue *queue) +{ + struct event *dequeued; + + if (queue->first == NULL) { + return NULL; + } + dequeued = queue->first; + ev_remove(queue, dequeued); + + return dequeued; +} + +/************************************************************ + + Function: ev_remove + +*************************************************************/ +void ev_remove(struct event_queue *queue, struct event *event) +{ + if (queue->first == event) { + queue->first = event->ev_next; + } + if (queue->last == event) { + queue->last = event->ev_prev; + } + if (event->ev_prev) { + event->ev_prev->ev_next = event->ev_next; + } + if (event->ev_next) { + event->ev_next->ev_prev = event->ev_prev; + } + event->ev_prev = NULL; + event->ev_next = NULL; +} + +/************************************************************ + + Function: print_human_readable_time from current_time_ns + +*************************************************************/ +void print_timestamp_format(int64_t current_time_ns, int timestamp_format) +{ + char time_buffer[100]; + time_t current_time_s; + struct tm *local_time; + + current_time_s = current_time_ns / 1000000000; + local_time = localtime(¤t_time_s); + switch(timestamp_format) { + case 1: + // timestamp-format ctime + strftime(time_buffer, sizeof(time_buffer), "%c", local_time); + printf("[%s] ", time_buffer); + break; + case 2: + // timestamp-format iso + strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%T%z", local_time); + printf("[%s] ", time_buffer); + break; + case 3: + // timestamp-format rfc3339 + strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d %H:%M:%S", local_time); + printf("[%s] ", time_buffer); + break; + default: + printf("[%.5f] ", (double)current_time_ns / 1e9); + } +} + +/************************************************************ + + Function: ms_since_midnight_utc + +************************************************************* + + Input: int64_t: current UTC time in ns + + Output: uint32_t: current time in ms since midnight UTC + + Description: + + Return ICMP Timestamp value corresponding to the given time value. + The given time value must be in UTC. + +*************************************************************/ +static uint32_t ms_since_midnight_utc(int64_t time_val) +{ + return (uint32_t)((time_val / 1000000) % (24 * 60 * 60 * 1000)); +} + +/************************************************************ + + Function: usage + +************************************************************* + + Inputs: int: 0 if output on request, 1 if output because of wrong argument + + Description: + +************************************************************/ + +void usage(int is_error) +{ + FILE *out = is_error ? stderr : stdout; + fprintf(out, "Usage: %s [options] [targets...]\n", prog); + fprintf(out, "\n"); + fprintf(out, "Probing options:\n"); + fprintf(out, " -4, --ipv4 only ping IPv4 addresses\n"); + fprintf(out, " -6, --ipv6 only ping IPv6 addresses\n"); + fprintf(out, " -b, --size=BYTES amount of ping data to send, in bytes (default: %d)\n", DEFAULT_PING_DATA_SIZE); + fprintf(out, " -B, --backoff=N set exponential backoff factor to N (default: 1.5)\n"); + fprintf(out, " -c, --count=N count mode: send N pings to each target and report stats\n"); + fprintf(out, " -f, --file=FILE read list of targets from a file ( - means stdin)\n"); + fprintf(out, " -g, --generate generate target list (only if no -f specified),\n"); + fprintf(out, " limited to at most %d targets\n", MAX_GENERATE); + fprintf(out, " (give start and end IP in the target list, or a CIDR address)\n"); + fprintf(out, " (ex. %s -g 192.168.1.0 192.168.1.255 or %s -g 192.168.1.0/24)\n", prog, prog); + fprintf(out, " -H, --ttl=N set the IP TTL value (Time To Live hops)\n"); + fprintf(out, " -i, --interval=MSEC interval between sending ping packets (default: %.0f ms)\n", interval / 1e6); +#ifdef SO_BINDTODEVICE + fprintf(out, " -I, --iface=IFACE bind to a particular interface\n"); +#endif +#ifdef SO_MARK + fprintf(out, " -k, --fwmark=FWMARK set the routing mark\n"); +#endif + fprintf(out, " -l, --loop loop mode: send pings forever\n"); + fprintf(out, " -m, --all use all IPs of provided hostnames (e.g. IPv4 and IPv6), use with -A\n"); + fprintf(out, " -M, --dontfrag set the Don't Fragment flag\n"); + fprintf(out, " -O, --tos=N set the type of service (tos) flag on the ICMP packets\n"); + fprintf(out, " -p, --period=MSEC interval between ping packets to one target (in ms)\n"); + fprintf(out, " (in loop and count modes, default: %.0f ms)\n", perhost_interval / 1e6); + fprintf(out, " -r, --retry=N number of retries (default: %d)\n", DEFAULT_RETRY); + fprintf(out, " -R, --random random packet data (to foil link data compression)\n"); + fprintf(out, " -S, --src=IP set source address\n"); + fprintf(out, " -t, --timeout=MSEC individual target initial timeout (default: %.0f ms,\n", timeout / 1e6); + fprintf(out, " except with -l/-c/-C, where it's the -p period up to 2000 ms)\n"); + fprintf(out, " --check-source discard replies not from target address\n"); + fprintf(out, " --icmp-timestamp use ICMP Timestamp instead of ICMP Echo\n"); + fprintf(out, "\n"); + fprintf(out, "Output options:\n"); + fprintf(out, " -a, --alive show targets that are alive\n"); + fprintf(out, " -A, --addr show targets by address\n"); + fprintf(out, " -C, --vcount=N same as -c, report results (not stats) in verbose format\n"); + fprintf(out, " -d, --rdns show targets by name (force reverse-DNS lookup)\n"); + fprintf(out, " -D, --timestamp print timestamp before each output line\n"); + fprintf(out, " --timestamp-format=FORMAT show timestamp in the given format (-D required): ctime|iso|rfc3339\n"); + fprintf(out, " -e, --elapsed show elapsed time on return packets\n"); + fprintf(out, " -n, --name show targets by name (reverse-DNS lookup for target IPs)\n"); + fprintf(out, " -N, --netdata output compatible for netdata (-l -Q are required)\n"); + fprintf(out, " -o, --outage show the accumulated outage time (lost packets * packet interval)\n"); + fprintf(out, " -q, --quiet quiet (don't show per-target/per-ping results)\n"); + fprintf(out, " -Q, --squiet=SECS[,cumulative] same as -q, but add interval summary every SECS seconds,\n"); + fprintf(out, " with 'cumulative', print stats since beginning\n"); + fprintf(out, " -s, --stats print final stats\n"); + fprintf(out, " -u, --unreach show targets that are unreachable\n"); + fprintf(out, " -v, --version show version\n"); + fprintf(out, " -x, --reachable=N shows if >=N hosts are reachable or not\n"); + fprintf(out, " -X, --fast-reachable=N exits true immediately when N hosts are found\n"); + fprintf(out, " --print-tos show received TOS value\n"); + fprintf(out, " --print-ttl show IP TTL value\n"); + exit(is_error); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.h b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.h new file mode 100644 index 0000000..f50710b --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.h @@ -0,0 +1,39 @@ +#ifndef _FPING_H +#define _FPING_H + +#define __APPLE_USE_RFC_3542 1 + +#include +#include +#include + +/* this requires variadic macros, part of C99 */ +#if (defined(DEBUG) || defined(_DEBUG)) +extern int64_t current_time_ns; +extern int trace_flag; +#define dbg_printf(fmt, ...) do { if (trace_flag) { fprintf(stderr, "[%10.5f] ", (double)(current_time_ns / 1000)/1000000); fprintf(stderr, fmt, __VA_ARGS__); } } while (0) + +#else +#define dbg_printf(fmt, ...) +#endif + + +/* fping.c */ +void crash_and_burn( char *message ); +void errno_crash_and_burn( char *message ); +int in_cksum( unsigned short *p, int n ); +extern int random_data_flag; + +/* socket.c */ +int open_ping_socket_ipv4(int *socktype); +void init_ping_buffer_ipv4(size_t ping_data_size); +void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr, int *ident); +int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id, uint8_t icmp_proto); +#ifdef IPV6 +int open_ping_socket_ipv6(int *socktype); +void init_ping_buffer_ipv6(size_t ping_data_size); +void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr, int *ident); +int socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id); +#endif + +#endif diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/options.h b/ci/tmp.4rIIEYCP9c/fping-5.3/src/options.h new file mode 100644 index 0000000..229975c --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/options.h @@ -0,0 +1,52 @@ + +/* + * Interval is the minimum amount of time between sending a ping packet to + * any host. + * + * Perhost_interval is the minimum amount of time between sending a ping + * packet to a particular responding host (when count is > 1) + * + * Timeout is the initial amount of time between sending a ping packet to + * a particular non-responding host. + * + * Retry is the number of ping packets to send to a non-responding host + * before giving up (in is-it-alive mode). + * + * Backoff factor is how much longer to wait on successive retries. + * + * + */ + +/* constants */ + +#ifndef DEFAULT_INTERVAL +#define DEFAULT_INTERVAL 10 /* default time between packets (msec) */ +#endif + +#ifndef DEFAULT_PERHOST_INTERVAL /* default time between packets */ +#define DEFAULT_PERHOST_INTERVAL 1000 /* to a particular destination */ +#endif /* in counting/looping mode */ + +#ifndef DEFAULT_TIMEOUT +#define DEFAULT_TIMEOUT 500 /* individual host timeouts */ +#define AUTOTUNE_TIMEOUT_MAX 2000 +#endif + + +#ifndef DEFAULT_RETRY +#define DEFAULT_RETRY 3 /* number of times to retry a host */ +#endif + +#ifndef DEFAULT_SELECT_TIME +#define DEFAULT_SELECT_TIME 10 /* default time to wait during select() */ +#endif + +#ifndef DEFAULT_BACKOFF_FACTOR +#define DEFAULT_BACKOFF_FACTOR 1.5 /* exponential timeout factor */ +#endif +#define MIN_BACKOFF_FACTOR 1.0 /* exponential timeout factor */ +#define MAX_BACKOFF_FACTOR 5.0 /* exponential timeout factor */ + +#ifndef DNS_TIMEOUT +#define DNS_TIMEOUT 1000 /* time in micro_sec for dns retry */ +#endif diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.c new file mode 100644 index 0000000..63a9f40 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.c @@ -0,0 +1,266 @@ +#include "optparse.h" + +#define MSG_INVALID "invalid option" +#define MSG_MISSING "option requires an argument" +#define MSG_TOOMANY "option takes no arguments" + +static int +opterror(struct optparse *options, const char *message, const char *data) +{ + unsigned p = 0; + while (*message) + options->errmsg[p++] = *message++; + const char *sep = " -- '"; + while (*sep) + options->errmsg[p++] = *sep++; + while (p < sizeof(options->errmsg) - 2 && *data) + options->errmsg[p++] = *data++; + options->errmsg[p++] = '\''; + options->errmsg[p++] = '\0'; + return '?'; +} + +void optparse_init(struct optparse *options, char **argv) +{ + options->argv = argv; + options->permute = 1; + options->optind = 1; + options->subopt = 0; + options->optarg = 0; + options->errmsg[0] = '\0'; +} + +static inline int +is_dashdash(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0'; +} + +static inline int +is_shortopt(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0'; +} + +static inline int +is_longopt(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0'; +} + +static void +permute(struct optparse *options, int index) +{ + char *nonoption = options->argv[index]; + for (int i = index; i < options->optind - 1; i++) + options->argv[i] = options->argv[i + 1]; + options->argv[options->optind - 1] = nonoption; +} + +static int +argtype(const char *optstring, char c) +{ + if (c == ':') + return -1; + for (; *optstring && c != *optstring; optstring++); + if (!*optstring) + return -1; + int count = OPTPARSE_NONE; + if (optstring[1] == ':') + count += optstring[2] == ':' ? 2 : 1; + return count; +} + +int optparse(struct optparse *options, const char *optstring) +{ + options->errmsg[0] = '\0'; + options->optopt = 0; + options->optarg = 0; + char *option = options->argv[options->optind]; + if (option == 0) { + return -1; + } else if (is_dashdash(option)) { + options->optind++; /* consume "--" */ + return -1; + } else if (!is_shortopt(option)) { + if (options->permute) { + int index = options->optind; + options->optind++; + int r = optparse(options, optstring); + permute(options, index); + options->optind--; + return r; + } else { + return -1; + } + } + option += options->subopt + 1; + options->optopt = option[0]; + int type = argtype(optstring, option[0]); + char *next = options->argv[options->optind + 1]; + switch (type) { + case -1: { + options->optind++; + char str[2] = {option[0]}; + return opterror(options, MSG_INVALID, str); + } + case OPTPARSE_NONE: + if (option[1]) { + options->subopt++; + } else { + options->subopt = 0; + options->optind++; + } + return option[0]; + case OPTPARSE_REQUIRED: + options->subopt = 0; + options->optind++; + if (option[1]) { + options->optarg = option + 1; + } else if (next != 0) { + options->optarg = next; + options->optind++; + } else { + options->optarg = 0; + char str[2] = {option[0]}; + return opterror(options, MSG_MISSING, str); + } + return option[0]; + case OPTPARSE_OPTIONAL: + options->subopt = 0; + options->optind++; + if (option[1]) + options->optarg = option + 1; + else + options->optarg = 0; + return option[0]; + } + return 0; +} + +char *optparse_arg(struct optparse *options) +{ + options->subopt = 0; + char *option = options->argv[options->optind]; + if (option != 0) + options->optind++; + return option; +} + +static inline int +longopts_end(const struct optparse_long *longopts, int i) +{ + return !longopts[i].longname && !longopts[i].shortname; +} + +static void +optstring_from_long(const struct optparse_long *longopts, char *optstring) +{ + char *p = optstring; + for (int i = 0; !longopts_end(longopts, i); i++) { + if (longopts[i].shortname) { + *p++ = longopts[i].shortname; + for (int a = 0; a < (int)longopts[i].argtype; a++) + *p++ = ':'; + } + } + *p = '\0'; +} + +/* Unlike strcmp(), handles options containing "=". */ +static int +longopts_match(const char *longname, const char *option) +{ + if (longname == 0) + return 0; + const char *a = option, *n = longname; + for (; *a && *n && *a != '='; a++, n++) + if (*a != *n) + return 0; + return *n == '\0' && (*a == '\0' || *a == '='); +} + +/* Return the part after "=", or NULL. */ +static char * +longopts_arg(char *option) +{ + for (; *option && *option != '='; option++); + if (*option == '=') + return option + 1; + else + return 0; +} + +static int +long_fallback(struct optparse *options, + const struct optparse_long *longopts, + int *longindex) +{ + char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */ + optstring_from_long(longopts, optstring); + int result = optparse(options, optstring); + if (longindex != 0) { + *longindex = -1; + if (result != -1) + for (int i = 0; !longopts_end(longopts, i); i++) + if (longopts[i].shortname == options->optopt) + *longindex = i; + } + return result; +} + +int +optparse_long(struct optparse *options, + const struct optparse_long *longopts, + int *longindex) +{ + char *option = options->argv[options->optind]; + if (option == 0) { + return -1; + } else if (is_dashdash(option)) { + options->optind++; /* consume "--" */ + return -1; + } else if (is_shortopt(option)) { + return long_fallback(options, longopts, longindex); + } else if (!is_longopt(option)) { + if (options->permute) { + int index = options->optind; + options->optind++; + int r = optparse_long(options, longopts, longindex); + permute(options, index); + options->optind--; + return r; + } else { + return -1; + } + } + + /* Parse as long option. */ + options->errmsg[0] = '\0'; + options->optopt = 0; + options->optlongname = 0; + options->optarg = 0; + option += 2; /* skip "--" */ + options->optind++; + for (int i = 0; !longopts_end(longopts, i); i++) { + const char *name = longopts[i].longname; + if (longopts_match(name, option)) { + options->optlongname = option; + if (longindex) + *longindex = i; + options->optopt = longopts[i].shortname; + char *arg = longopts_arg(option); + if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) { + return opterror(options, MSG_TOOMANY, name); + } if (arg != 0) { + options->optarg = arg; + } else if (longopts[i].argtype == OPTPARSE_REQUIRED) { + options->optarg = options->argv[options->optind++]; + if (options->optarg == 0) + return opterror(options, MSG_MISSING, name); + } + return options->optopt; + } + } + return opterror(options, MSG_INVALID, option); +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.h b/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.h new file mode 100644 index 0000000..7a555ed --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.h @@ -0,0 +1,103 @@ +#ifndef OPTPARSE_H +#define OPTPARSE_H + +/** + * Optparse -- portable, reentrant, embeddable, getopt-like option parser + * + * The POSIX getopt() option parser has three fatal flaws. These flaws + * are solved by Optparse. + * + * 1) Parser state is stored entirely in global variables, some of + * which are static and inaccessible. This means only one thread can + * use getopt(). It also means it's not possible to recursively parse + * nested sub-arguments while in the middle of argument parsing. + * Optparse fixes this by storing all state on a local struct. + * + * 2) The POSIX standard provides no way to properly reset the parser. + * This means for portable code that getopt() is only good for one + * run, over one argv with one optstring. It also means subcommand + * options cannot be processed with getopt(). Most implementations + * provide a method to reset the parser, but it's not portable. + * Optparse provides an optparse_arg() function for stepping over + * subcommands and continuing parsing of options with another + * optstring. The Optparse struct itself can be passed around to + * subcommand handlers for additional subcommand option parsing. A + * full reset can be achieved by with an additional optparse_init(). + * + * 3) Error messages are printed to stderr. This can be disabled with + * opterr, but the messages themselves are still inaccessible. + * Optparse solves this by writing an error message in its errmsg + * field. The downside to Optparse is that this error message will + * always be in English rather than the current locale. + * + * Optparse should be familiar with anyone accustomed to getopt(), and + * it could be a nearly drop-in replacement. The optstring is the same + * and the fields have the same names as the getopt() global variables + * (optarg, optind, optopt). + * + * Optparse also supports GNU-style long options with optparse_long(). + * The interface is slightly different and simpler than getopt_long(). + * + * By default, argv is permuted as it is parsed, moving non-option + * arguments to the end. This can be disabled by setting the `permute` + * field to 0 after initialization. + */ + +struct optparse { + char **argv; + int permute; + int optind; + int optopt; + char *optlongname; + char *optarg; + char errmsg[64]; + int subopt; +}; + +enum optparse_argtype { OPTPARSE_NONE, OPTPARSE_REQUIRED, OPTPARSE_OPTIONAL }; + +struct optparse_long { + const char *longname; + int shortname; + enum optparse_argtype argtype; +}; + +/** + * Initializes the parser state. + */ +void optparse_init(struct optparse *options, char **argv); + +/** + * Read the next option in the argv array. + * @param optstring a getopt()-formatted option string. + * @return the next option character, -1 for done, or '?' for error + * + * Just like getopt(), a character followed by no colons means no + * argument. One colon means the option has a required argument. Two + * colons means the option takes an optional argument. + */ +int optparse(struct optparse *options, const char *optstring); + +/** + * Handles GNU-style long options in addition to getopt() options. + * This works a lot like GNU's getopt_long(). The last option in + * longopts must be all zeros, marking the end of the array. The + * longindex argument may be NULL. + */ +int +optparse_long(struct optparse *options, + const struct optparse_long *longopts, + int *longindex); + +/** + * Used for stepping over non-option arguments. + * @return the next non-option argument, or NULL for no more arguments + * + * Argument parsing can continue with optparse() after using this + * function. That would be used to parse the options for the + * subcommand returned by optparse_arg(). This function allows you to + * ignore the value of optind. + */ +char *optparse_arg(struct optparse *options); + +#endif diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.c new file mode 100644 index 0000000..31bf725 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.c @@ -0,0 +1,124 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * seqmap.c: implementation of a mapping between sequence number and (host, ping_nr) + * we can't just use ping_nr*host_count + host_nr, because it can + * overflow the 16 bit of the icmp header field. See also: + * https://github.com/schweikert/fping/issues/48 + */ + +#include "config.h" +#include "seqmap.h" +#include "limits.h" +#include "options.h" +#include "fping.h" + +#include +#include +#include + +/* description of the data structure used: + * + * - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in + * the timeout interval (SEQMAP_TIMEOUT_IN_NS) + * - we store the values in an array with SEQMAP_MAXSEQ elements + * - current sequence number % SEQMAP_MAXSEQ gives the current index + * - when entering a value, we check that the current entry is expired + */ + +static SEQMAP_VALUE* seqmap_map = NULL; +static unsigned int seqmap_next_id = 0; + +#define SEQMAP_TIMEOUT_IN_NS INT64_C(10000000000) +#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX + +void seqmap_init() +{ + seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE)); + if (seqmap_map == NULL) { + perror("malloc error (can't allocate seqmap_map)"); + } +} + +unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t timestamp) +{ + unsigned int current_id; + SEQMAP_VALUE* next_value; + + if (!seqmap_map) { + fprintf(stderr, "fping internal error: seqmap not initialized.\n"); + exit(4); + } + + /* check if expired (note that unused seqmap values will have fields set to + * 0, so will be seen as expired */ + next_value = &seqmap_map[seqmap_next_id]; + if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) { + fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n", + SEQMAP_TIMEOUT_IN_NS, host_nr, ping_count, seqmap_next_id); + exit(4); + } + + /* store the value */ + next_value->host_nr = host_nr; + next_value->ping_count = ping_count; + next_value->ping_ts = timestamp; + + /* increase next id */ + current_id = seqmap_next_id; + seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ; + + dbg_printf("seqmap_add(host: %d, index: %d) -> %d\n", host_nr, ping_count, current_id); + + return current_id; +} + +SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now) +{ + SEQMAP_VALUE* value; + + if (id >= SEQMAP_MAXSEQ) { + return NULL; + } + + value = &seqmap_map[id]; + + /* verify that value is not expired */ + if (now - value->ping_ts >= SEQMAP_TIMEOUT_IN_NS) { + dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d -> DISCARDED %ld\n", id, value->host_nr, value->ping_count, + now - value->ping_ts); + return NULL; + } + + dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d\n", id, value->host_nr, value->ping_count); + + return value; +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.h b/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.h new file mode 100644 index 0000000..a1780b0 --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.h @@ -0,0 +1,21 @@ +#ifndef SEQMAP_H +#define SEQMAP_H + +#include +#include + +typedef struct seqmap_value +{ + unsigned int host_nr; + unsigned int ping_count; + int64_t ping_ts; + +} SEQMAP_VALUE; + +#define SEQMAP_MAXSEQ 65535 + +void seqmap_init(); +unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t now); +SEQMAP_VALUE *seqmap_fetch(unsigned int id, int64_t now); + +#endif diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket4.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket4.c new file mode 100644 index 0000000..c408c6d --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket4.c @@ -0,0 +1,166 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "config.h" +#include "fping.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char* ping_buffer_ipv4 = 0; +size_t ping_pkt_size_ipv4; + +int open_ping_socket_ipv4(int *socktype) +{ + struct protoent* proto; + int s; + + /* confirm that ICMP is available on this machine */ + if ((proto = getprotobyname("icmp")) == NULL) + crash_and_burn("icmp: unknown protocol"); + + /* create raw socket for ICMP calls (ping) */ + *socktype = SOCK_RAW; + s = socket(AF_INET, *socktype, proto->p_proto); + if (s < 0) { + /* try non-privileged icmp (works on Mac OSX without privileges, for example) */ + *socktype = SOCK_DGRAM; + s = socket(AF_INET, *socktype, proto->p_proto); + if (s < 0) { + return -1; + } + } + + /* Make sure that we use non-blocking IO */ + { + int flags; + + if ((flags = fcntl(s, F_GETFL, 0)) < 0) + perror("fcntl"); + + if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) + perror("fcntl"); + } + + return s; +} + +void init_ping_buffer_ipv4(size_t ping_data_size) +{ + /* allocate ping buffer */ + ping_pkt_size_ipv4 = ping_data_size + ICMP_MINLEN; + ping_buffer_ipv4 = (char*)calloc(1, ping_pkt_size_ipv4); + if (!ping_buffer_ipv4) + crash_and_burn("can't malloc ping packet"); +} + +void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr, int *ident) +{ + struct sockaddr_in sa; + socklen_t len = sizeof(sa); + + memset(&sa, 0, len); + sa.sin_family = AF_INET; + sa.sin_addr = *src_addr; + if (bind(s, (struct sockaddr*)&sa, len) < 0) + errno_crash_and_burn("cannot bind source address"); + + if (ident) { + memset(&sa, 0, len); + if (getsockname(s, (struct sockaddr *)&sa, &len) < 0) + errno_crash_and_burn("can't get ICMP socket identity"); + + if (sa.sin_port) + *ident = sa.sin_port; + } +} + +unsigned short calcsum(unsigned short* buffer, int length) +{ + unsigned long sum; + + /* initialize sum to zero and loop until length (in words) is 0 */ + for (sum = 0; length > 1; length -= 2) /* sizeof() returns number of bytes, we're interested in number of words */ + sum += *buffer++; /* add 1 word of buffer to sum and proceed to the next */ + + /* we may have an extra byte */ + if (length == 1) + sum += (char)*buffer; + + sum = (sum >> 16) + (sum & 0xFFFF); /* add high 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + return ~sum; +} + +int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr, uint8_t icmp_proto) +{ + struct icmp* icp; + struct timespec tsorig; + long tsorig_ms; + int n; + + icp = (struct icmp*)ping_buffer_ipv4; + + icp->icmp_type = icmp_proto; + if(icmp_proto == ICMP_TSTAMP) { + clock_gettime(CLOCK_REALTIME, &tsorig); + tsorig_ms = (tsorig.tv_sec % (24*60*60)) * 1000 + tsorig.tv_nsec / 1000000; + icp->icmp_otime = htonl(tsorig_ms); + icp->icmp_rtime = 0; + icp->icmp_ttime = 0; + } + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_seq = htons(icmp_seq_nr); + icp->icmp_id = icmp_id_nr; + + if (random_data_flag) { + for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) { + ping_buffer_ipv4[n] = random() & 0xFF; + } + } + + icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size_ipv4); + + n = sendto(s, icp, ping_pkt_size_ipv4, 0, saddr, saddr_len); + + return n; +} diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket6.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket6.c new file mode 100644 index 0000000..84a84ea --- /dev/null +++ b/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket6.c @@ -0,0 +1,136 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "config.h" +#include "fping.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +char* ping_buffer_ipv6 = 0; +size_t ping_pkt_size_ipv6; + +int open_ping_socket_ipv6(int *socktype) +{ + struct protoent* proto; + int s; + + /* confirm that ICMP6 is available on this machine */ + if ((proto = getprotobyname("ipv6-icmp")) == NULL) + crash_and_burn("ipv6-icmp: unknown protocol"); + + /* create raw socket for ICMP6 calls (ping) */ + *socktype = SOCK_RAW; + s = socket(AF_INET6, *socktype, proto->p_proto); + if (s < 0) { + /* try non-privileged icmp6 (works on Mac OSX without privileges, for example) */ + *socktype = SOCK_DGRAM; + s = socket(AF_INET6, *socktype, proto->p_proto); + if (s < 0) { + return -1; + } + } + + /* Make sure that we use non-blocking IO */ + { + int flags; + + if ((flags = fcntl(s, F_GETFL, 0)) < 0) + perror("fcntl"); + + if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) + perror("fcntl"); + } + + return s; +} + +void init_ping_buffer_ipv6(size_t ping_data_size) +{ + /* allocate ping buffer */ + ping_pkt_size_ipv6 = ping_data_size + sizeof(struct icmp6_hdr); + ping_buffer_ipv6 = (char*)calloc(1, ping_pkt_size_ipv6); + if (!ping_buffer_ipv6) + crash_and_burn("can't malloc ping packet"); +} + +void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident) +{ + struct sockaddr_in6 sa; + socklen_t len = sizeof(sa); + + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; + sa.sin6_addr = *src_addr; + if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0) + errno_crash_and_burn("cannot bind source address"); + + if (ident) { + memset(&sa, 0, len); + if (getsockname(s, (struct sockaddr *)&sa, &len) < 0) + errno_crash_and_burn("can't get ICMP6 socket identity"); + + if (sa.sin6_port) + *ident = sa.sin6_port; + } +} + +int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr) +{ + struct icmp6_hdr* icp; + int n; + + icp = (struct icmp6_hdr*)ping_buffer_ipv6; + icp->icmp6_type = ICMP6_ECHO_REQUEST; + icp->icmp6_code = 0; + icp->icmp6_seq = htons(icmp_seq_nr); + icp->icmp6_id = icmp_id_nr; + + if (random_data_flag) { + for (n = sizeof(struct icmp6_hdr); n < ping_pkt_size_ipv6; ++n) { + ping_buffer_ipv6[n] = random() & 0xFF; + } + } + + icp->icmp6_cksum = 0; /* The IPv6 stack calculates the checksum for us... */ + + n = sendto(s, icp, ping_pkt_size_ipv6, 0, saddr, saddr_len); + + return n; +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/CHANGELOG.md b/ci/tmp.VwGIuQgZdr/fping-5.4/CHANGELOG.md new file mode 100644 index 0000000..7cd88bc --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/CHANGELOG.md @@ -0,0 +1,299 @@ +fping 5.4 (2025-08-19) +====================== + +## Bugfixes + +- Memory allocation safety checks for event storage (thanks David.A for bug report) +- Fix off-by-one boundary check in seqmap code (thanks David.A for bug report) +- The minimum value for the per-host interval (-i flag) is now 0.001 (milliseconds), + since it probably never makes sense to use a smaller value, and to avoid trying + to do a too large memory allocation. + +fping 5.3 (2025-01-02) +====================== + +## New features + +- New option --icmp-timestamp to send ICMP timestamp requests (ICMP type 13) + instead of ICMP Echo requests (#353 #363, thanks @auerswal and @gsnw-sebast) +- New option --print-ttl to print returned TTL value (#354, thanks @nalves599) +- New option --print-tos to print returned TOS value (#335 #346 #347, thanks + @auerswal and @gsnw-sebast) +- New option --check-source (#334, thanks @auerswal) +- Predefined various timestamp formats (#321, thanks @auerswal and @gsnw-sebast) +- Print cumulative stats with -Q SECS,cumulative (#315, thanks @auerswal) + +## Bugfixes and other changes + +- ci: Upgrade actions/upload-artifact to v4 (#360, thanks @gsnw-sebast) +- ci: Azure Pipeline only trigger when changes are made in the development branch + (#359, thanks @gsnw-sebast) +- ci: Upgrade actions/upload-artifact to v3 (#355, thanks @pevik) +- ci: Azure Pipeline YAML add docker build (#354, thanks @gsnw-sebast) +- Dockerfile: change distribution from ubuntu to debian (#350, thanks + @gsnw-sebast) +- Fix warning unused parameter 'reply_timestamp' under macOS (#348, thanks + @gsnw-sebast) +- Fix increase maximum -s value to 65507 (#344, thanks @pevik) +- ci: use File::Temp to create temporary directory (#343, thanks @auerswal) +- Fix -k, --fwmark with setuid fping executable (#342, thanks @auerswal) +- Another batch of additional tests (take 2) (#341, thanks @auerswal) +- Document that -a and -u are overridden by -c and -C (#338, thanks @auerswal) +- Fix macOS build warning sets SEQMAP_TIMEOUT_IN_NSSEQMAP_TIMEOUT_IN_NS as INT64_C + (#336, thanks @gsnw-sebast) +- Fix inconsistent limits for address generation via -g, --generator using either + range or CIDR (#331, thanks @auerswal) +- Some additional tests (#329, thanks @auerswal) +- ci: skip an unreliable test on macOS (#328, thanks @auerswal) +- Fix incorrect return-value check for a scanf like function (CWE-253) (#323, + thanks @gsnw-sebast) +- A few more tests to increase code coverage a little bit (#320, thanks @auerswal) +- Github fix: Change to codeql-action-v2 (#319, thanks @gsnw-sebast) +- Developer function: Debug with Visual Studio Code (#318, thanks @gsnw-sebast) + +fping 5.2 (2024-04-21) +====================== + +## New features + +- New option -X / --fast-reachable to exit immediately once N hosts have been + found (#260, thanks @chriscray and @gsnw) + +- New option -k / -fwmark to set Linux fwmark mask (#289, thanks @tomangert and + @deepkv) + +## Bugfixes and other changes + +- Always output fatal error messages (#303, thanks @auerswal) +- Fallback to SO\_TIMESTAMP if SO\_TIMESTAMPNS is not available (#279, thanks + @gsnw) +- Fix "not enough sequence numbers available" error on BSD-like systems (#307, + thanks @cagney, @gsnw) +- Fix running in unprivileged mode (#248, thanks @sfan5) +- Fix build issue for NetBSD/alpha (#255, thanks @0-wiz-0) +- Fix build issue for OpenBSD/alpha (#275, thanks @gsnw) +- Fix build warning for long int usage (#258, thanks @gsnw) +- Fix build error with musl libc (#263, thanks @kraj) +- Fix to guard against division by zero (#293, thanks @auerswal) +- Decouple -a/-u effects from -c (#298, thanks @auerswal) +- Added contrib/Dockerfile (#224, thanks @darless) +- Remove host from Netdata chart titles (#253, thanks @ilyam8) +- Add additional tests (#292, #297, thanks @auerswal) +- Update github action os images (#282, thanks @gsnw) +- Fix Azure pipeline tests (#308, thanks @gsnw) +- Various autoconf fixes (#286, #283, thanks @gsnw) +- Extended configure script with --enable-debug and output cpu usage (#311, + thanks @gsnw) +- Documentation: Update Netdata website link (#257, thanks @ilyam8) +- Documentation: fix description of --file option (#268, thanks @MohGeek) +- Documentation: improve exit status description (#294, thanks @auerswal) +- Documentation: move description of -i MSEC (#298, thanks @auerswal) +- Documentation: improve help output for options -c and -C (#302, #auerswal) + + +fping 5.1 (2022-02-06) +====================== + +## Bugfixes and other changes + +- Use setcap to specify specific files in fping.spec (#232, thanks @zdyxry) +- Netdata: use host instead name as family label (#226, thanks @k0ste) +- Netdata: use formatstring macro PRId64 (#229, thanks @gsnw) +- Allow -4 option to be given multiple times (#215, thanks @normanr) +- Documentation fix (#208, thanks @timgates42) +- Retain privileges until after privileged setsockopt (#200, thanks @simetnicbr) +- Set bind to source only when option is set (#198, thanks @dinoex) +- Update Azure test pipeline (#197, thanks @gsnw) +- Fix getnameinfo not called properly for IPv4 (#227, thanks @aafbsd) +- Fixed wrong timestamp under Free- and OpenBSD and macOS (#217, thanks @gsnw) +- Documentation updates (#240, thanks @auerswal) +- Updated autotools (autoconf 2.71, automake 1.16.5, libtool 2.4.6) + + +fping 5.0 (2020-08-05) +====================== + +## Incompatible Changes + +- In non-quiet loop and count mode, a line is printed for every lost packet + (#175, thanks @kbucheli): + + ``` + $ fping -D -c2 8.8.8.8 8.8.8.7 + [1596092373.18423] 8.8.8.8 : [0], 64 bytes, 12.8 ms (12.8 avg, 0% loss) + [1596092374.18223] 8.8.8.7 : [0], timed out (NaN avg, 100% loss) + [1596092374.18424] 8.8.8.8 : [1], 64 bytes, 12.3 ms (12.5 avg, 0% loss) + [1596092375.18344] 8.8.8.7 : [1], timed out (NaN avg, 100% loss) + + 8.8.8.8 : xmt/rcv/%loss = 2/2/0%, min/avg/max = 12.3/12.5/12.8 + 8.8.8.7 : xmt/rcv/%loss = 2/0/100% + ``` + +- The returned size in bytes now always excludes the IP header, so if before it + reported '84 bytes' e.g. when using 'fping -l', now it reports '64 bytes'. + This is to make the reported size consistent with ping(8) from iputils and + also with fping when pinging a IPv6 host (which never included the IPv6 + header size). + +## New features + +- The number of sent pings is only counted when the pings are received or have + timed out, ensuring that the loss ratio will be always correct. This makes it + possible, for example, to use loop mode (-l) with interval statistics (-Q) + and a timeout larger than period, without having the issue that initially + some pings would be reported as missing (#193) + +- Improved precision of measurements from 10us to 1us (#136, thanks @tycho) + +## Bugfixes and other changes + +- The reported size of received packets is now always correct on Linux even for + packets > 4096 bytes (#180) + +- Travis CI automated testing now also macos testing and additional ubuntu + distributions (#196) + +fping 4.4 (2020-07-24) +====================== +## Bugfixes and other changes + +- Fix wrong ident used for normal (non-unprivileged) pings (#191, thanks @tycho) +- Fix build with --disable-ipv6 (#187, thanks Polynomial-C) + +fping 4.3 (2020-07-11) +====================== + +## New features + +- Linux unprivileged ping support (#173, thanks @tycho) +- Add SIGQUIT summary support similar to ping (#185, thanks @laddp) + +## Bugfixes and other changes + +- Corrected long option name of -s to --stats (#148, thanks @wopfel) +- Do not fail if using fping6 with -6 flag (#149, thanks @stromnet) +- Fail if interface binding (-I) does not work (#162, thanks @kbucheli) +- Fix using option -4 when fping is compiled IPv4-only (#154, thanks @pbhenson) +- Add Azure pipeline test build (#153 and #170, thanks @gsnw) +- GCC 10 compatibility fixes (#167 and #168, thanks @cranderson) +- Macos build fix (#174, thanks @tycho) +- Fix xmt stats in Netdata output (#172, thanks @vlvkobal) +- Only increase num_alive if response is not a duplicate (#151, thanks @brownowski) +- Use line buffering for stdout (#179, thanks @bg6cq) + +fping 4.2 (2019-02-19) +====================== + +## New features + +- New option -x / --reachable to check if the number of reachable hosts is >= a certain + number. Useful for example to implement connectivity-checks (#138, thanks @deepak0004) + +## Bugfixes and other changes + +- Allow decimal numbers for '-t', '-i', '-p', and '-Q' +- Fix build with --disable-ipv6 (#134, thanks @Polynomial-C) +- Fix hang with '-6', with ipv6 kernel module, but not loaded (#140, thanks @abelbeck) +- Assume '-6' if the binary is named 'fping6' (this is mostly for special + embedded-distro use cases, and not meant to be used generally in place of + compiling IPv6-only binary or using '-6', see also the notes in #139, thanks + abelbeck) +- Get rid of warning "timeout (-t) value larger than period (-p) produces unexpected results" + (#142, thanks @MrDragon1122) + + +fping 4.1 (2018-09-17) +====================== + +## Bugfixes and other changes + +- Fix problem when socket fd is 0 (#125, thanks Ramón Novoa!) +- Fix running on servers with disabled IPv6 (#118, thanks Simon Matter) +- Allow running "fping -h" or "--help" even when raw socket can't be opened (#131, thanks @teto) +- Fix build issue with FreeBSD and IPv6 (#132, thanks @gsnw) + +fping 4.0 (2017-04-23) +====================== + +## Incompatible Changes + +##### fping and fping6 unification + +fping and fping6 are now unified into one binary. It means that, for example, +doing 'fping google.com' is going to ping the IPv6 IP of google.com on +IPv6-enabled hosts. + +If you need exact compatibility with old versions, you can configure and +install fping twice: once for ipv4, and once for ipv6: + + ./configure --disable-ipv6; make clean install + ./configure --disable-ipv4 --program-suffix=6; make clean install + +##### Option -n, not the same as -d anymore + +Option -n / --name is now doing a reverse-DNS lookups on host addresses, +only if they are given as IP address, but not for hostnames. For example, +if you write 'fping -n google.com', fping would previously do a +forward-DNS lookup on google.com, and then a reverse-DNS lookup on the +resolved IP address. Now, it is just going to keep the name 'google.com'. +That same behavior can be achieved with the option -d / --rdns (which was +previously an alias for -n). + + fping<4.0 fping>=4.0 + fping -n NAME NAME->IP->IPNAME NAME + fping -d NAME NAME->IP->IPNAME NAME->IP->IPNAME + +##### Discarding of late packets + +fping will now discard replies, if they arrive after the defined timeout +for reply packets, specified with -t. This change is relevant only for the +count and loop modes, where the measured times should be now more +consistent (see github issue [#32][i32] for details). + +To prevent loosing reply packets because of this change, the default +timeout in count and loop modes is now automatically adjusted to the +period interval (up to 2000 ms), but it can be overriden with the -t +option. The default timeout for non-loop/count modes remains 500 ms. + +##### No restrictions by default + +fping will not enforce -i >= 1 and -p >= 10 anymore, except if you +'./configure --enable-safe-limits'. + +The reasoning to removing the restrictions by default, is that users can +clog the network with other tools anyway, and these restrictions are +sometimes getting in the way (for example if you try to ping a lot of +hosts). + +##### Default interval (-i) changed from 25ms to 10ms + +The default minimum interval between ping probes has been changed from +25ms to 10ms. The reason is that 25ms is very high, considering today's +fast networks: it generates at most 31 kbps of traffic (for IPv4 and +default payload size). + +## New features + +- Unified 'fping' and 'fping6' into one binary ([#80][i80]) +- Long option names for all options +- IPv6 enabled by default +- New option -4 to force IPv4 +- New option -6 to force IPv6 +- Keep original name if a hostname is given with -n/--name +- Option -d/--rdns now always does a rdns-lookup, even for names, as '-n' was doing until now +- Enforce -t timeout on reply packets, by discarding late packets ([#32][i32]) +- Auto-adjust timeout for -c/-C/-l mode to value of -p + +## Bugfixes and other changes + +- -i/-p restrictions disabled by default (enable with --enable-safe-limits) +- Default interval -i changed from 25ms to 10ms +- Fix compatibility issue with GNU Hurd +- A C99 compiler is now required +- Option parsing with optparse (https://github.com/skeeto/optparse). Thanks Christopher Wellons! +- New changelog file format + +[i32]: https://github.com/schweikert/fping/issues/32 +[i80]: https://github.com/schweikert/fping/issues/80 + +(see doc/CHANGELOG.pre-v4 for older changes) diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/COPYING b/ci/tmp.VwGIuQgZdr/fping-5.4/COPYING new file mode 100644 index 0000000..cceb651 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/COPYING @@ -0,0 +1,17 @@ + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/INSTALL b/ci/tmp.VwGIuQgZdr/fping-5.4/INSTALL new file mode 100644 index 0000000..e23597f --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/INSTALL @@ -0,0 +1,177 @@ +Basic Installation +================== + + These are generic installation instructions. + + --> See the README file for fping-specific instructions. <-- + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/Makefile.am b/ci/tmp.VwGIuQgZdr/fping-5.4/Makefile.am new file mode 100644 index 0000000..2ea59b9 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = doc src + +EXTRA_DIST = CHANGELOG.md contrib README.md ci/*.sh ci/*.pl diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/README.md b/ci/tmp.VwGIuQgZdr/fping-5.4/README.md new file mode 100644 index 0000000..8cf4f88 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/README.md @@ -0,0 +1,50 @@ +[![Build Status](https://travis-ci.org/schweikert/fping.svg?branch=develop)](https://travis-ci.org/schweikert/fping) +[![Coverage Status](https://coveralls.io/repos/github/schweikert/fping/badge.svg?branch=develop)](https://coveralls.io/github/schweikert/fping?branch=develop) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/11559/badge.svg?flat=1")](https://scan.coverity.com/projects/schweikert-fping) + +# fping + +fping is a program to send ICMP echo probes to network hosts, similar to ping, +but much better performing when pinging multiple hosts. fping has a long long +story: Roland Schemers did publish a first version of it in 1992 and it has +established itself since then as a standard tool. + +_Current maintainer_: + David Schweikert \ + +_Website_: + https://fping.org/ + +_Mailing-list_: + https://groups.google.com/group/fping-users + +## Installation + +If you want to install fping from source, proceed as follows: + +0. Run `./autogen.sh` + (only if you got the source from Github). +1. Run `./configure` with the correct arguments. + (see: `./configure --help`) +2. Run `make; make install`. +3. Make fping either setuid, or, if under Linux: + `sudo setcap cap_net_raw,cap_net_admin+ep fping` + +If you can't run fping as root or can't use the cap_net_raw capability, you can +also run fping in unprivileged mode. This works on MacOS and also on Linux, +provided that your GID is included in the range defined in +`/proc/sys/net/ipv4/ping_group_range`. This is particularly useful for running +fping in rootless / unprivileged containers. The --fwmark option needs root or +cap_net_admin. + +## Usage + +Have a look at the [fping(8)](doc/fping.pod) manual page for usage help. +(`fping -h` will also give a minimal help output.) + +## Credits + +* Original author: Roland Schemers (schemers@stanford.edu) +* Previous maintainer: RL "Bob" Morgan (morgan@stanford.edu) +* Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl) +* Other contributors: see [CHANGELOG.md](CHANGELOG.md) diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-1-autotools.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-1-autotools.sh new file mode 100755 index 0000000..f0ea2e0 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-1-autotools.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +set -e +set -x + +if [[ "$OSTYPE" == "darwin"* ]]; then + exit 0 +fi + +AUTOCONF=http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz +AUTOMAKE=http://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.gz +LIBTOOL=http://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz +PREFIX=$(pwd)/ci/build +PATH=$(pwd)/ci/build/bin:$PATH + +if [ ! -d ci ]; then + echo "you must run this in the root fping directory" >&2 + exit 1 +fi + +# remove standard versions +sudo apt-get remove -qq autoconf automake autotools-dev libtool + +# prepare build environment +cd ci +rm -rf build +mkdir -p build/src +cd build/src + +# autoconf +( +AUTOCONF_FILE=$(basename $AUTOCONF) +AUTOCONF_DIR=$(echo $AUTOCONF_FILE | sed -e 's/\.tar.*//') +wget $AUTOCONF +tar xf $AUTOCONF_FILE +cd $AUTOCONF_DIR +./configure --prefix=$PREFIX +make install +) + +# automake +( +AUTOMAKE_FILE=$(basename $AUTOMAKE) +AUTOMAKE_DIR=$(echo $AUTOMAKE_FILE | sed -e 's/\.tar.*//') +wget $AUTOMAKE +tar xf $AUTOMAKE_FILE +cd $AUTOMAKE_DIR +./configure --prefix=$PREFIX +make install +) + +# libtool +( +LIBTOOL_FILE=$(basename $LIBTOOL) +LIBTOOL_DIR=$(echo $LIBTOOL_FILE | sed -e 's/\.tar.*//') +wget $LIBTOOL +tar xf $LIBTOOL_FILE +cd $LIBTOOL_DIR +./configure --prefix=$PREFIX +make install +) diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-2-test-command.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-2-test-command.sh new file mode 100755 index 0000000..77f3905 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-2-test-command.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -ex + +curl -L http://cpanmin.us | perl - -L $HOME/perl5 App::cpanminus +$HOME/perl5/bin/cpanm --sudo Test::Command diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-3-prepare-macos.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-3-prepare-macos.sh new file mode 100755 index 0000000..09125eb --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-3-prepare-macos.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# only do this on Mac OS X +if [ `uname -s` != "Darwin" ]; then + exit 0; +fi + +if [[ ! `ifconfig lo0` =~ 127\.0\.0\.2 ]]; then + sudo ifconfig lo0 127.0.0.2/8 alias + sudo ifconfig lo0 127.0.0.3/8 alias + sudo ifconfig lo0 127.0.0.4/8 alias + sudo ifconfig lo0 127.0.0.5/8 alias +fi diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-4-compile.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-4-compile.sh new file mode 100755 index 0000000..e2a660c --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-4-compile.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -x + +PATH=$(pwd)/ci/build/bin:$PATH + +if [ ! -d ci ]; then + echo "you must run this in the root fping directory" >&2 + exit 1 +fi + +autoreconf -i +./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping +make CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage" +## setcap currently doesn't work anymore on travis-ci +#sudo setcap cap_net_raw+ep src/fping +## setcap debugging: +#pwd +#df -k . +#which setcap +#uname -a +#mount +# +#sudo apt-get install strace +#sudo strace setcap cap_net_raw+ep src/fping + +# use setuid, since setcap is not available +sudo chown root src/fping +sudo chmod u+s src/fping diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-bintray.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-bintray.sh new file mode 100755 index 0000000..0dc8800 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-bintray.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# upload to bintray.com/schweikert + +set -e + +VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//') +if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then + REPO=release +else + REPO=beta +fi +curl -T fping-$VERSION.tar.gz -uschweikert:$BINTRAY_API_KEY https://api.bintray.com/content/schweikert/$REPO/fping/$VERSION/fping-$VERSION.tar.gz +echo diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coveralls.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coveralls.sh new file mode 100755 index 0000000..9080f0b --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coveralls.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -xe + +if [ "$TRAVIS_DIST" = "trusty" ]; then + echo "skip coveralls on trusty because coveralls errors out due to python issues" + exit 0 +elif [ "$TRAVIS_OS_NAME" = "osx" ]; then + pip3 install --user cpp-coveralls + PATH="${PATH}:$(python3 -c 'import site; print(site.USER_BASE)')/bin" +else + pip install --user cpp-coveralls +fi + +export COVERALLS_PARALLEL=true +coveralls --build-root src --exclude src/optparse.c --exclude ci --exclude config.h --gcov-options '\-lp' diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coverity.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coverity.sh new file mode 100755 index 0000000..b009d2f --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coverity.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +COVERITY_SCAN_PROJECT_NAME=schweikert/fping +COVERITY_SCAN_EMAIL=david@schweikert.ch + +if [ -z "$COVERITY_SCAN_TOKEN" ]; then + echo "ERROR: COVERITY_SCAN_TOKEN not defined." >&2 + exit 1 +fi + +curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 \ + --form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN +tar xfz /tmp/cov-analysis-linux64.tgz +./autogen.sh +./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping +cov-analysis-linux64-*/bin/cov-build --dir cov-int make -j4 +tar cfz cov-int.tar.gz cov-int +curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME \ + --form token=$COVERITY_SCAN_TOKEN \ + --form email=$COVERITY_SCAN_EMAIL \ + --form file=@cov-int.tar.gz \ + --form version="`git rev-parse --short HEAD`" \ + --form description="`git rev-parse --short HEAD` / $TRAVIS_BUILD_ID " diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/prepare-linux.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/prepare-linux.sh new file mode 100755 index 0000000..efe8b3b --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/prepare-linux.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +sudo setcap cap_net_raw,cap_net_admin+ep src/fping + +if [[ ! $PATH =~ fping/src ]]; then + PATH=/home/dws/checkouts/fping/src:$PATH +fi diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-lcov.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-lcov.sh new file mode 100755 index 0000000..c7470b6 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-lcov.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +lcov -c -no-external \ + -d . \ + -b src \ + -o lcov-all.info + +lcov --remove lcov-all.info -o lcov.info \ + '*/optparse.c' diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-tests.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-tests.sh new file mode 100755 index 0000000..9d5a308 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-tests.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -ex + +PATH=`pwd`/src:$PATH + +prove ci/test-*.pl +ci/test-tarball.sh diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-01-basics.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-01-basics.pl new file mode 100755 index 0000000..e54bc22 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-01-basics.pl @@ -0,0 +1,55 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 15; +use Test::More; + +# ping 127.0.0.1 +{ + my $cmd = Test::Command->new(cmd => "fping 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +# ping ::1 +SKIP: { + #system("/sbin/ifconfig >&2"); + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("::1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +# ping ff02::1 +SKIP: { + #system("/sbin/ifconfig >&2"); + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping ff02::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("ff02::1 is alive\n"); + $cmd->stderr_like(qr{ \[<- .*\]}); +} + +# ping 3 times 127.0.0.1 +{ + my $cmd = Test::Command->new(cmd => "fping -p 100 -C3 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + $cmd->stderr_like(qr{127\.0\.0\.1 : \d\.\d+ \d\.\d+ \d\.\d+\n}); +} + +# invalid target name +{ + my $cmd = Test::Command->new(cmd => "fping host.name.invalid"); + $cmd->exit_is_num(2); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{host\.name\.invalid: .+\n}); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-02-help.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-02-help.pl new file mode 100755 index 0000000..0f66d13 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-02-help.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 15; + +my $I_HELP = " -I, --iface=IFACE bind to a particular interface\n"; +$I_HELP = '' if $^O eq 'darwin'; + +# fping -h (special pre-parse code path) +my $cmd1 = Test::Command->new(cmd => "fping -h"); +$cmd1->exit_is_num(0); +$cmd1->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\] + +Probing options: +.* + -v, --version show version +}s); +$cmd1->stderr_is_eq(""); + +# fping -4 -h (normal option parsing code path) +my $cmd4 = Test::Command->new(cmd => "fping -4 -h"); +$cmd4->exit_is_num(0); +$cmd4->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\] + +Probing options: +.* + -v, --version show version +}s); +$cmd4->stderr_is_eq(""); + +# fping -v +my $cmd2 = Test::Command->new(cmd => "fping -v"); +$cmd2->exit_is_num(0); +$cmd2->stdout_like(qr{fping: Version \S+}); +$cmd2->stderr_is_eq(""); + +# fping with unknown option +my $cmd3 = Test::Command->new(cmd => "fping -Z"); +$cmd3->exit_is_num(1); +$cmd3->stdout_is_eq(""); +$cmd3->stderr_like(qr{^fping: (illegal|invalid) option -- '?Z'?\nsee 'fping -h' for usage information\n$}); + +# fping with unknown long option +my $cmd5 = Test::Command->new(cmd => "fping --unknown-long-option"); +$cmd5->exit_is_num(1); +$cmd5->stdout_is_eq(""); +$cmd5->stderr_like(qr{^fping: (illegal|invalid) option -- '?unknown-long-option'?\nsee 'fping -h' for usage information\n$}); diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-03-forbidden.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-03-forbidden.pl new file mode 100755 index 0000000..97962c1 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-03-forbidden.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 36; + +# fping -i 0 +my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29"); +$cmd1->exit_is_num(1); +$cmd1->stdout_is_eq(""); +$cmd1->stderr_is_eq(<= 1 +END + +# fping -p 9 +my $cmd2 = Test::Command->new(cmd => "fping -c3 -p 9 127.0.0.1"); +$cmd2->exit_is_num(1); +$cmd2->stdout_is_eq(""); +$cmd2->stderr_is_eq(<= 10 +END + +# fping -H 300 +my $cmd5 = Test::Command->new(cmd => "fping -H 300 127.0.0.1"); +$cmd5->exit_is_num(1); +$cmd5->stdout_is_eq(""); +$cmd5->stderr_is_eq("fping: ttl 300 out of range\n"); + +# fping -a -u +my $cmd6 = Test::Command->new(cmd => "fping -a -u 127.0.0.1"); +$cmd6->exit_is_num(1); +$cmd6->stdout_is_eq(""); +$cmd6->stderr_is_eq("fping: specify only one of a, u\n"); + +# fping -c -l +my $cmd7 = Test::Command->new(cmd => "fping -c3 -l 127.0.0.1"); +$cmd7->exit_is_num(1); +$cmd7->stdout_is_eq(""); +$cmd7->stderr_is_eq("fping: specify only one of c, l\n"); + +# fping -b 65508 +my $cmd8 = Test::Command->new(cmd => "fping -b 65508 127.0.0.1"); +$cmd8->exit_is_num(1); +$cmd8->stdout_is_eq(""); +$cmd8->stderr_is_eq("fping: data size 65508 not valid, must not be larger than 65507\n"); + +# fping -B 0.9 +my $cmd9 = Test::Command->new(cmd => "fping -B 0.9 127.0.0.1"); +$cmd9->exit_is_num(1); +$cmd9->stdout_is_eq(""); +$cmd9->stderr_is_eq("fping: backoff factor 0.9 not valid, must be between 1.0 and 5.0\n"); + +# fping -B 5.1 +my $cmd10 = Test::Command->new(cmd => "fping -B 5.1 127.0.0.1"); +$cmd10->exit_is_num(1); +$cmd10->stdout_is_eq(""); +$cmd10->stderr_is_eq("fping: backoff factor 5.1 not valid, must be between 1.0 and 5.0\n"); + +# non-negative only +for my $arg (qw(i p Q t)) { + my $cmd = Test::Command->new(cmd => "fping -$arg -1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{Usage:}); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-04-options-a-b.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-04-options-a-b.pl new file mode 100755 index 0000000..ea7eb89 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-04-options-a-b.pl @@ -0,0 +1,218 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 68; +use Test::More; +use Time::HiRes qw(gettimeofday tv_interval); + +# -4 only use IPv4 addresses +# -6 only use IPv6 addresses +# -a show targets that are alive +# -A show targets by address +# -b n amount of ping data to send, in bytes (default 56) +# -B f set exponential backoff factor to f + +# fping -4 -6 +{ +my $cmd = Test::Command->new(cmd => "fping -4 -6 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: can't specify both -4 and -6\n"); +} + +# fping -6 -4 +{ +my $cmd = Test::Command->new(cmd => "fping -6 -4 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: can't specify both -4 and -6\n"); +} + +# fping -4 +{ +my $cmd = Test::Command->new(cmd => "fping -4 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +{ +my $cmd = Test::Command->new(cmd => "fping -4 ::1"); +$cmd->exit_is_num(2); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^::1:.*(not supported|not known)}); +} + +# fping -6 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("::1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +{ +my $cmd = Test::Command->new(cmd => "fping -6 127.0.0.1"); +$cmd->exit_is_num(2); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{127\.0\.0\.1:.*(not supported|not known)}); +} + +# fping -a +{ +my $cmd = Test::Command->new(cmd => "fping -a 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1\n127.0.0.2\n"); +$cmd->stderr_is_eq(""); +} + +# fping -a --print-ttl +{ +my $cmd = Test::Command->new(cmd => "fping -a --print-ttl 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 \(TTL \d+\)\n127\.0\.0\.2 \(TTL \d+\)\n}); +$cmd->stderr_is_eq(""); +} + +# fping -a --icmp-timestamp +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping -a --icmp-timestamp 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+}); +$cmd->stderr_is_eq(""); +} + +# fping --print-ttl +{ +my $cmd = Test::Command->new(cmd => "fping --print-ttl 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TTL \d+\)}); +$cmd->stderr_is_eq(""); +} + +# fping --icmp-timestamp +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive, timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+}); +$cmd->stderr_is_eq(""); +} + +# fping --icmp-timestamp --print-tos --print-ttl -e +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp --print-tos --print-ttl -e 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive, timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\) \(\d+(\.\d*)? ms\)}); +$cmd->stderr_is_eq(""); +} + +# fping --icmp-timestamp ::1 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp ::1"); + $cmd->exit_is_num(2); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{^::1:.*(not supported|not known)}); +} + +# fping --print-ttl with IPv6 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --print-ttl ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{::1 is alive \(TTL unknown\)\n}); + $cmd->stderr_is_eq(""); +} + +# fping -A +{ +my $cmd = Test::Command->new(cmd => "fping -4 -A localhost"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -b +{ +my $cmd = Test::Command->new(cmd => "fping -b 1000 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping --icmp-timestamp -b +{ +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 1000 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); +} + +# fping -b --icmp-timestamp +{ +my $cmd = Test::Command->new(cmd => "fping -b 1000 --icmp-timestamp 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); +} + +# fping --icmp-timestamp -b 12 (ICMP Timestamp data size) +{ +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 12 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); +} + +# fping -6 --icmp-timestamp +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 --icmp-timestamp ::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{ICMP Timestamp is IPv4 only}); +} + +# fping --icmp-timestamp -6 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -6 ::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: can't specify both -4 and -6\n"); +} + +# fping -B +SKIP: { + if($^O eq 'darwin') { + skip 'timing test not reliable on macOS', 5; + } + my $t0 = [gettimeofday]; + my $cmd = Test::Command->new(cmd => "fping -t 100 -r 3 -B 2 8.8.8.7"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq("8.8.8.7 is unreachable\n"); + $cmd->stderr_like(qr{^(|(8.8.8.7: error while sending ping: No route to host\n)+)$}); + my $elapsed = tv_interval($t0); + # 0.1 + 0.2 + 0.4 + 0.8 = 1.5 + cmp_ok($elapsed, '>=', 1.5); + cmp_ok($elapsed, '<', 1.9); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-05-options-c-e.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-05-options-c-e.pl new file mode 100755 index 0000000..d1cc767 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-05-options-c-e.pl @@ -0,0 +1,365 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 87; +use Test::More; + +# -c n count of pings to send to each target (default 1) +# -C n same as -c, report results in verbose format +# --check-source discard replies not from target address +# -d reverse name lookup +# -D print timestamp before each output line +# -e show elapsed time on return packets + +# fping -c n +{ +my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n --print-tos --print-ttl +{ +my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 --print-tos --print-ttl localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +}); + +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n -q +{ +my $cmd = Test::Command->new(cmd => "fping -q -c 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n -a (-a is ignored) +{ +my $cmd = Test::Command->new(cmd => "fping -a -c 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n -u (-u is ignored) +{ +my $cmd = Test::Command->new(cmd => "fping -u -c 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -c n ff02::1 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -c 1 ff02::1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{ff02::1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)\n}); + $cmd->stderr_like(qr{ \[<- .*\] +ff02::1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+\n}); +} + +# fping --icmp-timestamp -c n 127.0.0.1 +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp -c 2 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ +127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping --icmp-timestamp --print-tos --print-ttl -c n 127.0.0.1 +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 3; +} +my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp --print-tos --print-ttl -p 100 -c 2 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -C n +{ +my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ +127\.0\.0\.1 : \d\.\d+ \d\.\d+ +}); +} + +# fping -C n --print-tos --print-ttl +{ +my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 --print-tos --print-ttl localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +}); + +$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ +127\.0\.0\.1 : \d\.\d+ \d\.\d+ +}); +} + +# fping -C n -q +{ +my $cmd = Test::Command->new(cmd => "fping -C 5 -q -p 100 localhost"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{localhost :( \d\.\d+){5} +}); +} + +# fping -C n -a (-a is ignored) +{ +my $cmd = Test::Command->new(cmd => "fping -a -C 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ +127\.0\.0\.1 : \d\.\d+ \d\.\d+ +}); +} + +# fping -C n -u (-u is ignored) +{ +my $cmd = Test::Command->new(cmd => "fping -u -C 2 -p 100 localhost 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+ +127\.0\.0\.1 : \d\.\d+ \d\.\d+ +}); +} + +# fping -C n -i -q +{ +my $cmd = Test::Command->new(cmd => "fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{127\.0\.0\.1 :( \d\.\d+){20} +127\.0\.0\.2 :( \d\.\d+){20} +}); +} + +# fping -C n ff02::1 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -C 1 ff02::1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{ff02::1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)\n}); + $cmd->stderr_like(qr{ \[<- .*\]\nff02::1 : \d\.\d+\n}); +} + +# fping --check-source +{ +my $cmd = Test::Command->new(cmd => "fping --check-source 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping --check-source (to IPv6 multicast address -> accept no reply) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --check-source ff02::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq("ff02::1 is unreachable\n"); + $cmd->stderr_is_eq(""); +} + +# fping -c N --check-source +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -c1 --check-source 127.0.0.1 ff02::1"); + $cmd->exit_is_num(1); + $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +ff02::1 : \[0\], timed out \(NaN avg, 100% loss\) +}); + $cmd->stderr_like(qr{ +127\.0\.0\.1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +ff02::1 : xmt/rcv/%loss = 1/0/100% +}); +} + +# fping -C N --check-source +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -C1 --check-source 127.0.0.1 ff02::1"); + $cmd->exit_is_num(1); + $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +ff02::1 : \[0\], timed out \(NaN avg, 100% loss\) +}); + $cmd->stderr_like(qr{ +127\.0\.0\.1 : \d\.\d+ +ff02::1 : - +}); +} + +# fping -d +{ +my $cmd = Test::Command->new(cmd => "fping -d 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("localhost is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -D +{ +my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[\d+\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[\d+\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D (timestamp not before 2001-09-09) +{ +my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D --timestamp-format=ctime +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=ctime -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D --timestamp-format=iso +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=iso -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D --timestamp-format=rfc3339 +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=rfc3339 -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); + +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -D --timestamp-format +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{Usage:}); +} + +# fping -D --timestamp-format="%Y-%m-%d %H:%M:%S" +{ +my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=\"%Y-%m-%d %H:%M:%S\" -c 2 -p 100 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{Usage:}); +} + +# fping -e +{ +my $cmd = Test::Command->new(cmd => "fping -e 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(\d\.\d+ ms\) +}); +$cmd->stderr_is_eq(""); +} + +# fping -e -a +{ +my $cmd = Test::Command->new(cmd => "fping -e -a 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 \(\d\.\d+ ms\) +}); +$cmd->stderr_is_eq(""); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-06-options-f-h.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-06-options-f-h.pl new file mode 100755 index 0000000..c9b520a --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-06-options-f-h.pl @@ -0,0 +1,231 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 75; +use Test::More; +use File::Temp; + +# -f file read list of targets from a file ( - means stdin) (only if no -g specified) +# -g generate target list (only if no -f specified) +# (specify the start and end IP in the target list, or supply a IP netmask) +# (ex. ../src/fping -g 192.168.1.0 192.168.1.255 or ../src/fping -g 192.168.1.0/24) +# -H n Set the IP TTL value (Time To Live hops) + +my $tmpfile = File::Temp->new(); +print $tmpfile "127.0.0.1\n127.0.0.2\n"; +close($tmpfile); + +my $tmpfile2 = File::Temp->new(); +print $tmpfile2 "# comment\n127.0.0.1\n\n127.0.0.2\n"; +close($tmpfile2); + +# fping without option (-> equivalent to 'fping -f -') +{ +my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -f - +{ +my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping -f -"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -f file +{ +my $cmd = Test::Command->new(cmd => "fping -f ".$tmpfile->filename); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -f file (with comment and empty line) +{ +my $cmd = Test::Command->new(cmd => "fping -f ".$tmpfile2->filename); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -f non-existing-file (error) +{ +my $cmd = Test::Command->new(cmd => "fping -f file-does-not-exist"); +$cmd->exit_is_num(4); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{: fopen :}); +} + +# fping -g (error: no argument) +{ +my $cmd = Test::Command->new(cmd => "fping -g"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]}); +} + +# fping -g (error: single argument, but not in cidr format) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]}); +} + +# fping -g (error: CIDR network is not an IP address) +{ +my $cmd = Test::Command->new(cmd => "fping -g xxx/32"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{can't parse address xxx}); +} + +# fping -g (error: start of range is not an IP address) +{ +my $cmd = Test::Command->new(cmd => "fping -g xxx 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{can't parse address xxx}); +} + +# fping -g (error: end of range is not an IP address) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 yyy"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{can't parse address yyy}); +} + +# fping -g (error: too many arguments) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.2 127.0.0.3"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]}); +} + +# fping -g (range) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.5"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n127.0.0.3 is alive\n127.0.0.4 is alive\n127.0.0.5 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -g (empty range) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq(""); +} + +# fping -g (too large range) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.255.255.254"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n"); +} + +# fping -g (cidr) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1/30"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -g (cidr - long prefixes: point-to-point) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/31"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.2 is alive\n127.0.0.3 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -g (cidr - long prefixes: host) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/32"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -g (cidr - too long prefixes) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/33"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 33)\n"); +} + +# fping -g (cidr - too short prefixes) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/0"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 0)\n"); +} + +# fping -g (cidr - too many addresses) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.0/8"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n"); +} + +# fping -g (range - no IPv6 generator) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 ::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); +} + +# fping -g (range - no IPv6 generator - start address IPv6) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 127.0.0.1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); +} + +# fping -g (range - no IPv6 generator - end address IPv6) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -g 127.0.0.1 ::1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); +} + +# fping -g (CIDR - no IPv6 generator) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -g ::1/128"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); +} + +# fping -H +{ +my $cmd = Test::Command->new(cmd => "fping -H 1 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-07-options-i-m.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-07-options-i-m.pl new file mode 100755 index 0000000..426286a --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-07-options-i-m.pl @@ -0,0 +1,94 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 16; +use Test::More; + +# -i n interval between sending ping packets (in millisec) (default 25) +# -l loop sending pings forever +# -k set fwmark on ping packets +# -m ping multiple interfaces on target host +# -M don't fragment + +# fping -i n +{ +my $cmd = Test::Command->new(cmd => "fping -i 100 127.0.0.1 127.0.0.2"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -l +{ +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1'); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); +} + +# fping -l --print-tos --print-ttl +{ +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 --print-ttl --print-tos -l 127.0.0.1'); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\) +}); +} + +# fping -k +SKIP: { +if($^O ne 'linux') { + skip '-k option is only supported on Linux', 3; +} +my $cmd = Test::Command->new(cmd => 'fping -k 256 127.0.0.1'); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -l with SIGQUIT +{ +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill -QUIT fping; sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1'); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[3\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[4\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = \d+/\d+/\d+%, min/avg/max = \d+\.\d+/\d+\.\d+/\d+\.\d+ +}); +} + +# fping -l -Q +SKIP: { +if($^O eq 'darwin') { + skip 'On macOS, this test is unreliable', 2; +} +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 850 -l -Q 1 127.0.0.1'); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d\d:\d\d:\d\d\] +127\.0\.0\.1 : xmt/rcv/%loss = \d/\d/\d%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d\d:\d\d:\d\d\] +127\.0\.0\.1 : xmt/rcv/%loss = \d/\d/\d%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -l -t +{ +my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -t 1500 -l 127.0.0.1'); +$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) +}); +} + +# fping -M +SKIP: { + if($^O eq 'darwin') { + skip '-M option not supported on macOS', 3; + } + my $cmd = Test::Command->new(cmd => "fping -M 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +# fping -m -> test-14-internet-hosts diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-08-options-n-q.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-08-options-n-q.pl new file mode 100755 index 0000000..d614db1 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-08-options-n-q.pl @@ -0,0 +1,187 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 48; +use Test::More; + +# -n show targets by name (-d is equivalent) +# -O n set the type of service (tos) flag on the ICMP packets +# -p n interval between ping packets to one target (in millisec) +# (in looping and counting modes, default 1000) +# -q quiet (don't show per-target/per-ping results) +# -Q n same as -q, but show summary every n seconds + +# fping -n -> test-14-internet-hosts + +# fping -d -n +{ +my $cmd = Test::Command->new(cmd => "fping -d -n 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: use either one of -d or -n\n"); +} + +# fping -n -d +{ +my $cmd = Test::Command->new(cmd => "fping -n -d 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: use either one of -d or -n\n"); +} + +# fping -o +{ +my $cmd = Test::Command->new(cmd => "fping -t100 -p 100 -o -c 5 8.8.8.7"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq("8.8.8.7 : [0], timed out (NaN avg, 100% loss) +8.8.8.7 : [1], timed out (NaN avg, 100% loss) +8.8.8.7 : [2], timed out (NaN avg, 100% loss) +8.8.8.7 : [3], timed out (NaN avg, 100% loss) +8.8.8.7 : [4], timed out (NaN avg, 100% loss) +"); +$cmd->stderr_like(qr{^\s*8\.8\.8\.7 : xmt/rcv/%loss = 5/0/100%, outage\(ms\) = 50\d\s*$}); +} + +# fping -O +{ +my $cmd = Test::Command->new(cmd => "fping -O 2 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -O --print-tos +{ +my $cmd = Test::Command->new(cmd => "fping -O 2 --print-tos 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TOS \d+\) +}); +$cmd->stderr_is_eq(""); +} + +# fping -a -O --print-tos +{ +my $cmd = Test::Command->new(cmd => "fping -a -O 32 --print-tos 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 \(TOS \d+\) +}); +$cmd->stderr_is_eq(""); +} + +# fping --print-tos +{ +my $cmd = Test::Command->new(cmd => "fping --print-tos 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TOS 0\) +}); +$cmd->stderr_is_eq(""); +} + +# fping --print-tos with IPv6 +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping --print-tos ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{::1 is alive \(TOS unknown\)\n}); + $cmd->stderr_is_eq(""); +} + +# fping -q +{ +my $cmd = Test::Command->new(cmd => "fping -q -p 100 -c 3 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 400 -c 4 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q (longer test to show two time stamps and reset statistics) +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 550 -c 5 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q n ignores non-number characters after the number, except for keywords +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1whatever -p 550 -c 5 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q n ignores unknown keywords +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1,not_a_keyword -p 550 -c 5 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q n,cumulative +{ +my $cmd = Test::Command->new(cmd => "fping -Q 1,cumulative -p 550 -c 5 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +\[\d+:\d+:\d+\] +127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+ +}); +} + +# fping -Q -o +{ +my $cmd = Test::Command->new(cmd => "fping -c4 -Q1 -p550 -o 8.8.8.7"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +8\.8\.8\.7 : xmt/rcv/%loss = 1/0/100%, outage\(ms\) = 55\d +\[\d+:\d+:\d+\] +8\.8\.8\.7 : xmt/rcv/%loss = 2/0/100%, outage\(ms\) = 110\d +8\.8\.8\.7 : xmt/rcv/%loss = 4/0/100%, outage\(ms\) = 220\d +}); +} + +# fping -Q n,cumulative -o +{ +my $cmd = Test::Command->new(cmd => "fping -c4 -Q1,cumulative -p550 -o 8.8.8.7"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{\[\d+:\d+:\d+\] +8\.8\.8\.7 : xmt/rcv/%loss = 1/0/100%, outage\(ms\) = 55\d +\[\d+:\d+:\d+\] +8\.8\.8\.7 : xmt/rcv/%loss = 3/0/100%, outage\(ms\) = 165\d +8\.8\.8\.7 : xmt/rcv/%loss = 4/0/100%, outage\(ms\) = 220\d +}); +} + diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-09-option-r-t.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-09-option-r-t.pl new file mode 100755 index 0000000..2c26d24 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-09-option-r-t.pl @@ -0,0 +1,149 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 30; +use Test::More; + +# -R random bytes +# -r n number of retries (default 3) +# -s print final stats +# -S addr set source address +# -t n individual target initial timeout (in millisec) (default 500) +# -T n ignored (for compatibility with fping 2.4) + +# fping -R +{ +my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%.*}); +} + +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{::1 : xmt/rcv/%loss = 3/3/0%.*}); +} + +# fping -r tested in test-4-options-a-b.pl + +# fping -s +{ +my $cmd = Test::Command->new(cmd => "fping -s 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_like(qr{\s* +\s*1 targets +\s*1 alive +\s*0 unreachable +\s*0 unknown addresses +\s* +\s*0 timeouts \(waiting for response\) +\s*1 ICMP Echos sent +\s*1 ICMP Echo Replies received +\s*0 other ICMP received + +\s*\d\.\d+ ms \(min round trip time\) +\s*\d\.\d+ ms \(avg round trip time\) +\s*\d\.\d+ ms \(max round trip time\) +\s*\d\.\d+ sec \(elapsed real time\) +}); +} + +# fping -s (no host reachable) +{ +my $cmd = Test::Command->new(cmd => "fping -r0 -t100 -s 8.8.0.0"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq("8.8.0.0 is unreachable\n"); +$cmd->stderr_like(qr{\s* +\s*1 targets +\s*0 alive +\s*1 unreachable +\s*0 unknown addresses +\s* +\s*1 timeouts \(waiting for response\) +\s*1 ICMP Echos sent +\s*0 ICMP Echo Replies received +\s*0 other ICMP received + +\s*\d\.\d+ ms \(min round trip time\) +\s*\d\.\d+ ms \(avg round trip time\) +\s*\d\.\d+ ms \(max round trip time\) +\s*\d\.\d+ sec \(elapsed real time\) +}); +} + +# fping -s (both valid and invalid host name) +{ +my $cmd = Test::Command->new(cmd => "fping -s 127.0.0.1 host.name.invalid"); +$cmd->exit_is_num(2); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_like(qr{host\.name\.invalid: .+ +\s* +\s*1 targets +\s*1 alive +\s*0 unreachable +\s*1 unknown addresses +\s* +\s*0 timeouts \(waiting for response\) +\s*1 ICMP Echos sent +\s*1 ICMP Echo Replies received +\s*0 other ICMP received + +\s*\d\.\d+ ms \(min round trip time\) +\s*\d\.\d+ ms \(avg round trip time\) +\s*\d\.\d+ ms \(max round trip time\) +\s*\d\.\d+ sec \(elapsed real time\) +}); +} + +# fping -S +{ +my $cmd = Test::Command->new(cmd => "fping -S 127.0.0.1 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("127.0.0.1 is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -S (wrong source address) +{ +my $cmd = Test::Command->new(cmd => "fping -S 192.0.2.47 127.0.0.1"); +$cmd->exit_is_num(4); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{fping: cannot bind source address : .+\n}); +} + +# fping -S +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -S ::1 ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("::1 is alive\n"); + $cmd->stderr_is_eq(""); +} + +# fping -S (wrong IPv6 source address) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -S 2001:db8::1 ::1"); + $cmd->exit_is_num(4); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{fping: cannot bind source address : .+\n}); +} + +# fping -S +{ +my $cmd = Test::Command->new(cmd => "fping -S bla"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: can't parse source address: bla\n"); +} + +# (note: fping -t also tested in test-4-options-a-b.pl) diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-10-option-u-x.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-10-option-u-x.pl new file mode 100755 index 0000000..db45737 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-10-option-u-x.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 15; + +# -u show targets that are unreachable +# -v show version +# -x shows if >=N hosts are reachable or not +# -X exits true immediately when N hosts are found + +# fping -u +{ +my $cmd = Test::Command->new(cmd => "fping -r0 -u 8.8.0.0 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq("8.8.0.0\n"); +$cmd->stderr_is_eq(""); +} + +# fping -v +{ +my $cmd = Test::Command->new(cmd => "fping -v"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{ping: Version [45]\.\d+(-rc\d+)?}); +$cmd->stderr_is_eq(""); +} + +# fping -x +{ +my $cmd = Test::Command->new(cmd => "fping -x 1 8.8.0.0 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n"); +$cmd->stderr_is_eq(""); +} + +# fping -x +{ +my $cmd = Test::Command->new(cmd => "fping -x 2 8.8.0.0 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq("Not enough hosts reachable (required: 2, reachable: 1)\n"); +$cmd->stderr_is_eq(""); +} + +# fping -X +{ +my $cmd = Test::Command->new(cmd => "fping -X 1 --generate 127.0.0.0/29"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n"); +$cmd->stderr_is_eq(""); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-11-unpriv.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-11-unpriv.pl new file mode 100755 index 0000000..debf2af --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-11-unpriv.pl @@ -0,0 +1,95 @@ +#!/usr/bin/perl -w + +use English; +use File::Copy; +use File::Temp qw/ tempdir /; +use Test::Command; +use Test::More; + +if( $^O eq 'darwin' ) { + plan skip_all => 'Test irrelevant on MacOS'; + exit 0; +} + +sub get_ping_gid_range { + open FD, "/proc/sys/net/ipv4/ping_group_range" or return undef; + chomp(my $line = ); + my @range = split(/\s+/, $line); + close FD; + return @range; +} + +my @gids = split(' ', $EGID); +my @allowed = get_ping_gid_range(); + +# Make a copy of the binary so that we get rid of setuid bit +my $tmpdir = tempdir(CLEANUP => 1); +my $fping_bin = `which fping`; chomp $fping_bin; +my $fping_copy = "$tmpdir/fping.copy"; +copy($fping_bin, $fping_copy); +chmod 0755, $fping_copy; + +# Determine what test to run, based on whether unprivileged +# pings are allowed. +if(scalar grep { $_ >= $allowed[0] && $_ <= $allowed[1] } @gids) { + diag('test unprivileged mode'); + test_unprivileged_works(); +} +else { + test_privileged_fails(); +} + +sub test_unprivileged_works { + plan tests => 15; + + { + my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive\n"); + $cmd->stderr_is_eq(""); + } + { + my $cmd = Test::Command->new(cmd => "$fping_copy --print-tos 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive (TOS unknown)\n"); + $cmd->stderr_is_eq(""); + } + { + my $cmd = Test::Command->new(cmd => "$fping_copy --print-ttl 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive (TTL unknown)\n"); + $cmd->stderr_is_eq(""); + } + SKIP: { + if($^O ne 'linux') { + skip '-k option is only supported on Linux', 3; + } + my $cmd = Test::Command->new(cmd => "$fping_copy -4 -k 256 127.0.0.1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("127.0.0.1 is alive\n"); + $cmd->stderr_like(qr{fwmark ipv4: .+\n}); + } + SKIP: { + if($^O ne 'linux') { + skip '-k option is only supported on Linux', 3; + } + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "$fping_copy -6 -k 256 ::1"); + $cmd->exit_is_num(0); + $cmd->stdout_is_eq("::1 is alive\n"); + $cmd->stderr_like(qr{fwmark ipv6: .+\n}); + } +} + +sub test_privileged_fails { + plan tests => 3; + + { + my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1"); + $cmd->exit_is_num(4); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{: can't create socket \(must run as root\?\)}); + } +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-12-option-type.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-12-option-type.pl new file mode 100755 index 0000000..6514425 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-12-option-type.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 84; +use Test::More; + +# some options require a numeric argument +for my $arg (qw(b B c C H i O p Q r t x X)) { + for my $test_input (qw(xxx '')) { + my $cmd = Test::Command->new(cmd => "fping -$arg $test_input"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{Usage:}); + } +} + +# fping -k, only supported on Linux, requires a number +SKIP: { + if($^O ne 'linux') { + skip '-k option is only supported on Linux', 6; + } + for my $test_input (qw(xxx '')) { + my $cmd = Test::Command->new(cmd => "fping -k $test_input 127.0.0.1"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq(""); + $cmd->stderr_like(qr{Usage:}); + } +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-13-unknown-host.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-13-unknown-host.pl new file mode 100755 index 0000000..65c8312 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-13-unknown-host.pl @@ -0,0 +1,11 @@ +#!/usr/bin/perl -w + +use Test::Command tests => 3; + +# fping +{ +my $cmd = Test::Command->new(cmd => "fping nosuchname.example.com"); +$cmd->exit_is_num(2); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{^nosuchname\.example\.com: .*not (known|found)}); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-14-ping-internet-hosts.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-14-ping-internet-hosts.pl new file mode 100755 index 0000000..3c18cc4 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-14-ping-internet-hosts.pl @@ -0,0 +1,106 @@ +#!/usr/bin/perl -w + +use Test::Command; +use Test::More; + +# evaluate if we have internet +if(!gethostbyname("www.google.com")) { + plan skip_all => 'Can\'t resolve www.google.com -> no internet?'; + exit 0; +} + +plan tests => 30; + +my $re_num = qr{\d+(?:\.\d+)?}; + +# fping +{ +my $cmd = Test::Command->new(cmd => "fping -q -i 10 -p 20 -c 3 -t200 8.8.8.8 www.france-telecom.fr www.google.com"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{8\.8\.8\.8\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num +www\.france-telecom\.fr\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num +www\.google\.com\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num +}); +} + +# fping -A -n +{ +my $cmd = Test::Command->new(cmd => "fping -A -n 8.8.8.8"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("dns.google (8.8.8.8) is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -4 -A -n +{ +my $cmd = Test::Command->new(cmd => "fping -4 -A -n dns.google"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{^dns.google \(8\.8\.(4\.4|8\.8)\) is alive\n$}); +$cmd->stderr_is_eq(""); +} + +# fping -4 --addr --rdns +{ +my $cmd = Test::Command->new(cmd => "fping -4 --addr --rdns www.apple.com"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{^\S+\.akamaitechnologies\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$}); +$cmd->stderr_is_eq(""); +} + +# fping -4 --addr --name +{ +my $cmd = Test::Command->new(cmd => "fping -4 --addr --name www.google.com"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{^www\.google\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$}); +$cmd->stderr_is_eq(""); +} + +# fping -A -n (IPv6) +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -6 -n -A dns.google"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{^dns.google \(2001:4860:4860::88(44|88)\) is alive\n$}); + $cmd->stderr_is_eq(""); +} + +# fping -m +SKIP: { + if($ENV{SKIP_IPV6}) { + skip 'Skip IPv6 tests', 3; + } + my $cmd = Test::Command->new(cmd => "fping -A -m dns.google"); + $cmd->exit_is_num(0); + $cmd->stdout_like(qr{^.* is alive\n.* is alive\n.* is alive\n.* is alive\n}); + $cmd->stderr_is_eq(""); +} + +# fping -m -A +{ +my $cmd = Test::Command->new(cmd => "fping -4 -A -m www.cloudflare.com"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{\d+\.\d+\.\d+\.\d+ is alive\n\d+\.\d+\.\d+\.\d+ is alive\n}); +$cmd->stderr_is_eq(""); +} + +# fping -n +{ +my $cmd = Test::Command->new(cmd => "fping -n 8.8.8.8"); +$cmd->exit_is_num(0); +$cmd->stdout_is_eq("dns.google is alive\n"); +$cmd->stderr_is_eq(""); +} + +# fping -M +SKIP: { + if($^O eq 'darwin') { + skip '-M option not supported on macOS', 3; + } + my $cmd = Test::Command->new(cmd => "fping -r 0 -b 10000 -M 8.8.8.8"); + $cmd->exit_is_num(1); + $cmd->stdout_is_eq("8.8.8.8 is unreachable\n"); + $cmd->stderr_is_eq("8.8.8.8: error while sending ping: Message too long\n"); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-15-netdata.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-15-netdata.pl new file mode 100755 index 0000000..83dc439 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-15-netdata.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl -w + +use Test::Command; +use Test::More; + +plan tests => 3; + +# fping +{ +my $cmd = Test::Command->new(cmd => "fping -c 2 -Q 1 -N 127.0.0.1"); +$cmd->exit_is_num(0); +$cmd->stdout_like(qr{CHART fping\.127_0_0_1_packets '' 'FPing Packets' packets '127.0.0.1' fping\.packets line 110020 1 +DIMENSION xmt sent absolute 1 1 +DIMENSION rcv received absolute 1 1 +BEGIN fping\.127_0_0_1_packets +SET xmt = 1 +SET rcv = 1 +END +CHART fping\.127_0_0_1_quality '' 'FPing Quality' percentage '127.0.0.1' fping\.quality area 110010 1 +DIMENSION returned '' absolute 1 1 +BEGIN fping\.127_0_0_1_quality +SET returned = 100 +END +CHART fping\.127_0_0_1_latency '' 'FPing Latency' ms '127.0.0.1' fping\.latency area 110000 1 +DIMENSION min minimum absolute 1 1000000 +DIMENSION max maximum absolute 1 1000000 +DIMENSION avg average absolute 1 1000000 +BEGIN fping\.127_0_0_1_latency +SET min = \d+ +SET avg = \d+ +SET max = \d+ +END} +); +$cmd->stderr_like(qr{127.0.0.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+}); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-56.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-56.pl new file mode 100755 index 0000000..e36cc14 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-56.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl -w + +# regression testing for github issue #56 +# +use Test::Command; +use Test::More; + +if( $^O eq 'darwin' ) { + plan skip_all => 'Test disabled on MacOS'; + exit 0; +} + +plan tests => 3; + +my $cmd1 = Test::Command->new(cmd => "fping -t100 -p100 -C3 255.255.255.255"); +$cmd1->exit_is_num(1); +$cmd1->stdout_is_eq(""); +$cmd1->stderr_is_eq("\n255.255.255.255 : - - -\n"); diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-58.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-58.pl new file mode 100755 index 0000000..db5161a --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-58.pl @@ -0,0 +1,10 @@ +#!/usr/bin/perl -w + +# regression testing for github issue #58 + +use Test::Command tests => 3; + +my $cmd1 = Test::Command->new(cmd => "fping -a -g 2001:db8:120:4161::4/64"); +$cmd1->exit_is_num(1); +$cmd1->stdout_is_eq(""); +$cmd1->stderr_is_eq("fping: -g works only with IPv4 addresses\n"); diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-tarball.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-tarball.sh new file mode 100755 index 0000000..da43a25 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-tarball.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# make sure that the .tar.gz file contains everything necessary +# to build fping + +set -e +set -x + +# skip on macos +if [[ "$OSTYPE" == "darwin"* ]]; then + exit 0 +fi + +make dist +VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//') +if [ -z "$VERSION" ]; then + echo "tar.gz file not found." >&2 + exit 1 +fi + +# unarchive +TMPDIR=$(mktemp -d --tmpdir=ci) +cd $TMPDIR +tar xf ../../fping-$VERSION.tar.gz +DIRNAME=$(ls) + +# build +cd $DIRNAME +./configure --enable-ipv4 --enable-ipv6 --prefix=/opt/fping +make +sudo make install diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/configure.ac b/ci/tmp.VwGIuQgZdr/fping-5.4/configure.ac new file mode 100644 index 0000000..d573075 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/configure.ac @@ -0,0 +1,129 @@ +dnl Process this file with autoconf to produce a configure script. + +dnl Minimum Autoconf version required. +AC_PREREQ(2.59) + +AC_INIT([fping],[5.4]) + +m4_ifdef([AC_AUTOCONF_VERSION],[AC_USE_SYSTEM_EXTENSIONS], [AC_GNU_SOURCE]) + +# Detect Operatingsystem +AC_CANONICAL_TARGET +only_clock_realtime=no + +case "${target}" in + *darwin*) + only_clock_realtime=yes + ;; + *freebsd*) + only_clock_realtime=yes + ;; + *openbsd*) + only_clock_realtime=yes + ;; +esac + +dnl --disable-ipv4 +AC_ARG_ENABLE([ipv4], + AS_HELP_STRING([--disable-ipv4], [Disable support for pinging IPv4 hosts])) +AM_CONDITIONAL([IPV4], [test "x$enable_ipv4" != "xno"]) +AM_COND_IF([IPV4], [AC_DEFINE([IPV4], [1], [IPv4 enabled])]) + +dnl --disable-ipv6 +AC_ARG_ENABLE([ipv6], + AS_HELP_STRING([--disable-ipv6], [Disable support for pinging IPv6 hosts])) +AS_IF([test "x$enable_ipv6" != "xno"], [ + dnl Test if IPv6 is supported + AC_CHECK_HEADERS([netinet/icmp6.h], [have_ipv6="yes"], [], [[ + #include + #include + ]]) +]) +dnl Can't disable both IPv4 and IPv6 +AS_IF([test "x$enable_ipv4" = "xno" -a "x$enable_ipv6" = "xno"], [ + AC_MSG_ERROR([Need to enable IPv4 or IPv6. Can't disable both!)]) +]) +dnl IPv6 required, but not supported? +AS_IF([test \( "x$enable_ipv6" = "xyes" -o "x$enable_ipv4" = "xno" \) -a "x$have_ipv6" != "xyes" ], [ + AC_MSG_ERROR([IPv6 not supported on this platform (netinet/icmp6.h header not found)]) +]) +AM_CONDITIONAL([IPV6], [test "x$have_ipv6" = "xyes"]) +AM_COND_IF([IPV6], [AC_DEFINE([IPV6], [1], [IPv6 enabled])]) + +AC_ARG_ENABLE([timestamp], + AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMPNS)])) +AS_IF([test "x$enable_timestamp" != "xno"], [ + AC_CHECK_DECL([SO_TIMESTAMPNS], [AC_DEFINE(HAVE_SO_TIMESTAMPNS, [1], [SO_TIMESTAMPNS is defined])], [have_so_timestamp="no"], [#include +#include ]) +]) +dnl Test if --enable-timestamp is explicitely enabled and make an error if this platform doesn't support it +AS_IF([test "x$enable_timestamp" = "xyes" -a "x$have_so_timestamp" = "xno"], [ + AC_MSG_ERROR([--enable-timestamp not supported on this platform]) +]) +AS_IF([test "x$only_clock_realtime" = "xyes"], [AC_DEFINE(ONLY_CLOCK_REALTIME, [1], [ONLY_CLOCK_REALTIME is defined])]) + +AC_ARG_ENABLE([safe-limits], + AS_HELP_STRING([--enable-safe-limits], [Restrict timing parameters (-i, -p) within "safe" limits])) +AS_IF([test "x$enable_safe_limits" = "xyes"], [ + AC_DEFINE(FPING_SAFE_LIMITS, [1], [safe limits should be enforced])]) + +AC_ARG_ENABLE([debug], + AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@]), [enable_debug=$enableval], [enable_debug=no]) +AS_IF([test "x$enable_debug" = "xyes"], [ + AC_DEFINE([DEBUG], [1], [Define if debugging is enabled])]) + +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AM_MAINTAINER_MODE + +AC_CONFIG_HEADERS([config.h]) + +dnl Checks for programs. + +AC_PROG_CC +AM_PROG_CC_C_O +m4_version_prereq([2.70],,[AC_PROG_CC_STDC]) +AC_PROG_CPP +AC_PROG_INSTALL + +dnl Checks for libraries. + +AC_CHECK_FUNC(gethostbyname) +if test $ac_cv_func_gethostbyname = no; then + AC_CHECK_LIB(nsl, gethostbyname) +fi +AC_CHECK_FUNC(connect) +if test $ac_cv_func_connect = no; then + AC_CHECK_LIB(socket, connect) +fi +AC_CHECK_FUNC(sigaction) +if test $ac_cv_func_sigaction = yes; then + AC_DEFINE([USE_SIGACTION],[1],[Define if sigaction is available.]) +fi + +AC_CHECK_FUNCS([strftime], [], + [AC_MSG_ERROR([strftime function is required but not found])]) + +AH_TOP([ +#ifndef CONFIG_H +#define CONFIG_H +]) + +AH_BOTTOM([ +/* some OSes do not define this ... lets take a wild guess */ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffffU +#endif + +#endif /* CONFIG_H */ + +]) + +dnl Checks for header files. +AC_CHECK_HEADERS([unistd.h sys/file.h stdlib.h sys/select.h]) + +AC_CONFIG_FILES([Makefile + doc/Makefile + src/Makefile]) + +AC_OUTPUT diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/Dockerfile b/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/Dockerfile new file mode 100644 index 0000000..c20a1d6 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/Dockerfile @@ -0,0 +1,17 @@ +FROM debian:stable + +# Base +RUN apt-get update && apt-get install -y \ + build-essential \ + automake \ + autoconf \ + m4 + +# Add source code +COPY ./ /app + +# Compile +WORKDIR /app +RUN autoreconf --install +RUN ./configure && make && make install +ENTRYPOINT ["fping"] \ No newline at end of file diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/fping.spec b/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/fping.spec new file mode 100644 index 0000000..71d1ea0 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/fping.spec @@ -0,0 +1,74 @@ +Summary: send ICMP echo probes to multiple hosts +Name: fping +Version: 4.2 +Release: 1 +License: Freely redistributable without restriction +Group: Applications/System +Source0: http://fping.org/dist/%{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot + +%description +fping is a program to send ICMP echo probes to network hosts, similar to ping, +but much better performing when pinging multiple hosts. fping has a very long +history: Roland Schemers did publish a first version of it in 1992 and it has +established itself since then as a standard tool for network diagnostics and +statistics. + +%prep +%setup -q + +%build + +if [ ! -f ./configure ] ; then + ./autogen.sh +fi + +# fping +%configure --enable-ipv4 +make + +# fping6 +%configure --enable-ipv6 +make +%{__mv} -f src/fping src/fping6 + +%install +rm -rf $RPM_BUILD_ROOT +make DESTDIR=$RPM_BUILD_ROOT install + +# fping6 +%{__install} -Dp -m4755 src/fping6 %{buildroot}%{_sbindir}/fping6 +%{__ln_s} -f fping.8 %{buildroot}%{_mandir}/man8/fping6.8 + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%attr(4755, root, root) /usr/sbin/fping +%attr(4755, root, root) /usr/sbin/fping6 +%doc README.md COPYING CHANGELOG.md +/usr/share/man/man8/fping.8.gz +/usr/share/man/man8/fping6.8.gz + +%post +if [ -x /usr/sbin/setcap ]; then + /bin/chmod 0755 /usr/sbin/fping* + /usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping + /usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping6 +fi + +%changelog +* Mon Dec 24 2012 Marcus Vinicius Ferreira +- Missing './configure' script when cloning from master. +- Making 'fping6'. +- Fix setuid permission to 'rwsr-xr-x'. +- doc files. +- Replacing setuid permission if 'setcap' is present on post-install. +- Using 'http://fping.org/dist/' for release source distributions. + +* Mon Jul 16 2012 Stephen Schaefer +- Initial build + +# vim:ft=spec: + diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/CHANGELOG.pre-v4 b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/CHANGELOG.pre-v4 new file mode 100644 index 0000000..fc9a0aa --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/CHANGELOG.pre-v4 @@ -0,0 +1,627 @@ +2017-02-09 David Schweikert + * Version 3.16 + * (feature) Support kernel-timestamping of received packets (#46) + * (feature) Simplify restrictions: only -i >= 1 and -p >= 10 are enforced now + * (bugfix) Fix option -m to return all IPs of a hostname + * (bugfix) Fix option -H (ttl) for IPv6 + * (bugfix) Fix option -M (don't fragment) for IPv6 + * (bugfix) Fix option -O (ToS) for IPv6 + * (bugfix) Fix compatibility issue with AIX (#69, @blentzgh) + * (bugfix) Fix option -q not suppressing some ICMP error messages (#83) + * (bugfix) Fix option -M expecting an argument, when it shouldn't + * (bugfix) Fix minor issues found by Coverity Scan + +2017-01-11 David Schweikert + * Version 3.15 + * (bugfix) Fix compiler errors on platforms other than Linux (related + to the new -M option, #109) + * Test suite fixes for macOS + +2017-01-10 David Schweikert + * Version 3.14 + * (feature) Ignore network and broadcast for cidrs /31 and /32 (#102, Martin Topholm) + * (feature) New option '-M' to set the "Don't Fragment" flag (#91, Don Bowman) + * (feature) New option '-N' to output statistics for netdata (see: http://my-netdata.io/, #105, Costa Tsaousis) + * (feature) New option '-o' to calculate total outage time (#90, @jgerbeck) + * (bugfix) Exit code should be 2 when the hostname can't be resolved + (fixes #98, reported by @green-fox) + * (bugfix) Fix issue compliling on RHEL/Centos 7 (#95, @jbackman) + * (bugfix) Lower -i limit to 1 instead of 10 + * (bugfix) Improve interval preciseness of -Q reporting + * (bugfix) Fix occasional false positive in -Q reporting (#97) + * (bugfix) Solaris 10 portability fix (#107, Peter Bray) + +2015-10-21 David Schweikert + * Version 3.13 + * (bugfix) Fix ICMP errors sometimes causing crashes with fping >= 3.11 + (fixes #85, reported by Jamie Heilman and Bill Blough) + +2015-10-14 David Schweikert + * Version 3.12 + * (bugfix) Fix fping6 -R (fixes #84, reported by Stuart Henderson) + +2015-10-12 David Schweikert + * Version 3.11 + * (feature) New option -R to use random bytes instead of NULLs (#72, Anthony DeRobertis) + * (feature) Small documentation and performance improvements (Ryan Underwood) + * (bugfix) Fix double entries with fping -u and unreachable hosts + * (internal) Use sockaddr_storage and simplify code, so that we can one day support both IPv4 and IPv6 with the same binary + +2014-05-03 David Schweikert + * Version 3.10 + * Fix confusing error message with -g and IPv6 addresses (#58, reported by Axel Beckert) + * Allow option '-f' also for non-root (since setuid privileges are dropped) + * Do not retry twice DNS lookup on DNS lookup problem + * Remove support for NIS groups + * Better document -B backoff-factor and when it can be used (#33, Oleksiy Zagorskyi) + * More tests added + +2014-03-08 David Schweikert + * Version 3.9 + * Fix random output on socket error (reported by Aleksandrs Saveljevs, #56) + * Support ppc64le architecture by including alpha libtool version + (reported by Amit Kumar Gupta and Aravinda B Thunug) + * Fix compilation problem on FreeBSD (#57) + * Initial test suite and continous intergration (with travis-ci.org / coveralls.io) + * Don't output usage information on error + +2013-11-08 David Schweikert + * Version 3.8 + * Fix segmentation fault introduced in version 3.7 with loop mode (reported + by Vlad Glagolev, #55) + +2013-11-04 David Schweikert + * Version 3.7 + * Allow running as non-root on Mac OS X by using non-privileged ICMP (#7) + * Remove unnecessary IPv6 socket options + * Fix again compatibility issue with FreeBSD (Shawn Chu) + * Fix fping hanging forever on permanent sendto failure (Shawn Chu) + * Fix duplicate echo reply packets causing early stop in count mode + (reported by Ramon Schwammberger, #53) + +2013-10-10 David Schweikert + * Version 3.6 + * Fix loop issue after 65536 pings (reported by Peter Folk and GBert, #12) + * Minimum ping data size is now 0 + * Removed setsockopt IPV6_CHECKSUM, which shouldn't be set and breaks + compiling on Solaris (reported by Juergen Arndt) + * Fix wrong min RTT value with -Q option (reported by Alexander Ivanov, #51) + +2013-05-22 David Schweikert + * Version 3.5 + * Fix sprint_tm buffer size crash (reported by Japheth Cleaver) + * Addded -D flag to print timestamps (Toke Høiland-Jørgensen) + * Fix fping6 build on OS X 10.8 (unknown contributor) + * Fix compatibility issue with FreeBSD (Alexandre Raynaud, Jason Harris, #39) + * Fping.spec: fix setuid permissions and provides fping6 (Marcus Vinicius Ferreira) + * Re-create configure script with autoconf 2.69 for aarch64 support (Chuck Anderson, #45) + +2012-09-04 David Schweikert + * Version 3.4 + * Revert "Output statistics to stdout instead of stderr", because it breaks + tools assuming the output goes to stderr + +2012-08-19 David Schweikert + * Version 3.3 + * Do not output icmp errors with -q (#1) + * Add --enable-ipv4 and --enable-ipv6 options to configure (Niclas Zeising) + * Fix removing of unreachable hosts when doing loop (Thomas Liske, #13 #23) + * Fix -A for fping6 (reported by Matt LaPlante, #14) + * Fix "options inet6" breaking IPv4 name resolution (reported by Matt LaPlante, #17) + * Output statistics to stdout instead of stderr (suggested by Simon Leinen, #9) + * Set default data size to 56 bytes on all architectures (#18) + * Added contrib/fping.spec (Stephen Schaefer, #24) + * Convert man-page source to POD for easier maintenance + * Fix error message on DNS error for IPv6 hosts (#27) + * Fix -n flag in fping6 (#28) + * Man-page fix: TOS option typo (Thomas Liske, #23) + * Man-page fix: inconsistency in regards to numeric arguments (Robert Henney) + * Man-page fix: better description of option -q (#15) + +2012-05-29 David Schweikert + * Version 3.2 + * Improve documentation for -g option (G.W. Haywood) + * Performance optimization for big select timeouts (#10, Andrey Bondarenko) + * Fix restart of select call after interrupt signal (#8, Boian Bonev) + * Fix infinite loop caused by linked list corruption (#11, Boian Bonev) + +2012-04-26 David Schweikert + * Version 3.1 + * -g option (generate): exclude network and broadcast address for cidr + ranges (idea by Eric Brander) + * do not explicitely check if running as root, to make it possible to + install fping with linux capabilities instead of making it setuid + (setcap cap_net_raw+ep fping) + * ANSI C (C89) compiler now a requirement + * Portability fixes + * Reorganized source directory + * Bugfix: fix timeout issue on Solaris (Sandor Geller) + * Man-page fixes (Axel Beckert) + * Added -H option to specify number of hops (Paul Duda) + * Output usage information to stdout when called with -h (Paul Duda) + +2011-12-28 David Schweikert + * Version 3.0 + * rewritten main loop for improved performance + * -T parameter (select timeout) now obsolete + * Maintenance taken over from unresponsive previous maintainer + (anybody please step up, if you disagree) + * New homepage: www.fping.org + +2009-12-21 Tobi Oetiker + * Version v2.4b2-to3-ipv6 + * added -On option to set the TOS octet + * Removed unused variables from code + * updated to current autoconf standards + * Merged Debian changes (see below) + +---------------------------------------------------------------------- + +fping (2.4b2-to-ipv6-16.1) unstable; urgency=low + + * NMU during Moenchengladbach BSP + * Fixes FTBFS on kfreebsd (Closes: #555398) + * Fixes typo "Paramter" in binary + + -- Axel Beckert Sat, 23 Jan 2010 16:22:02 +0100 + +fping (2.4b2-to-ipv6-16) unstable; urgency=low + + * Fix the following bugs + - Network byte order sensitivity was missing completely. + Added hopefully all missing calls. + - The sequence numbering scheme used led to packet drops. + Changed it to a more senseful numbering scheme. + - Some minor C programming mistakes ('=' instead of '=='). + Patch by Stephan Fuhrmann; closes: #502569 + * Add support for command line select timeout setting + Patch by Marton Balint; closes: #502575 + * Remove symlinks in /usr/sbin; closes: #377732 + * Standards-Version is 3.8.0 + + -- Anibal Monsalve Salazar Sat, 18 Oct 2008 12:04:52 +1100 + +fping (2.4b2-to-ipv6-15) unstable; urgency=low + + * Added interface binding (-I) for fping + Patch by Peter Naulls + Closes: #439014 + * Fixed a couple of typos in fping.8. Closes: #423180 + * Added homepage control header + * Bumped Standards-Version to 3.7.3 + * Fixed the following lintian issue: + - debian-rules-sets-DH_COMPAT + + -- Anibal Monsalve Salazar Mon, 03 Mar 2008 17:46:17 +1100 + +fping (2.4b2-to-ipv6-13) unstable; urgency=low + + * Fixed stdout flush problem, closes: #340146. + Patch by Bart Martens . + + -- Anibal Monsalve Salazar Fri, 30 Dec 2005 08:30:09 +1100 + +fping (2.4b2-to-ipv6-12) unstable; urgency=low + + * Fixed "problem with option -r (retry limit)", closes: #318402. + Patch by Qingning Huo . + + -- Anibal Monsalve Salazar Sat, 08 Oct 2005 21:26:35 +1000 + +fping (2.4b2-to-ipv6-11) unstable; urgency=low + + * Fixed "would be useful to specify 'source address' like ping for multi + homed machines", closes: #198486. + Patch by Marc Haber . + + -- Anibal Monsalve Salazar Thu, 02 Jun 2005 08:14:54 +1000 + +fping (2.4b2-to-ipv6-10) unstable; urgency=low + + * Fixed "unnecessary delay with the -c option after the last packet" + (Closes: #293856). Patch by Niko Tyni + + -- Anibal Monsalve Salazar Sun, 06 Feb 2005 23:25:57 +1100 + +fping (2.4b2-to-ipv6-9) unstable; urgency=low + + * Fixed "fping6 always does reverse lookup" (Closes: #273647). + Patch by Jeroen Massar and forwarded by Bernhard Schmidt + + -- Anibal Monsalve Salazar Mon, 10 Jan 2005 00:01:32 +1100 + +fping (2.4b2-to-ipv6-7) unstable; urgency=low + + * Build fping in build/ipv[46] instead of build and build-ipv6. + * Made DNS errors non-fatal for IPv6 (closes: #198056). + + -- Herbert Xu Fri, 20 Jun 2003 21:36:30 +1000 + +fping (2.4b2-to-ipv6-6) unstable; urgency=low + + * Do not use incorrect linux.h file (closes: #85468). + + -- Herbert Xu Sat, 17 May 2003 14:13:11 +1000 + +fping (2.4b2-to-ipv6-5) unstable; urgency=low + + * Fixed yet another divide by zero bug (closes: #148445). + + -- Herbert Xu Tue, 4 Jun 2002 12:18:03 +1000 + +fping (2.4b2-to-ipv6-4) unstable; urgency=low + + * Made fping6 setuid (closes: #136386). + * Moved fping back into bin. + * Partially applied IPv6 patch to fix IPv6 checksums (closes: #136479). + + -- Herbert Xu Sun, 7 Apr 2002 20:36:56 +1000 + +fping (2.4b2-to-ipv6-3) unstable; urgency=low + + * Added compatibility symlink for fping (closes: #135203). + + -- Herbert Xu Sat, 23 Feb 2002 08:34:11 +1100 + +fping (2.4b2-to-ipv6-2) unstable; urgency=low + + * Fixed another divide by zero error (closes: #132370). + + -- Herbert Xu Thu, 7 Feb 2002 20:10:48 +1100 + +fping (2.4b2-to-ipv6-1) unstable; urgency=low + + * New upstream release. + * Install fping into sbin as done by upstream. + + -- Herbert Xu Fri, 1 Feb 2002 22:11:59 +1100 + +fping (2.2b2-3) unstable; urgency=low + + * Removed INSTALL file from package (closes: #84050). + * Fixed alignment bug. + + -- Herbert Xu Sat, 10 Feb 2001 19:25:18 +1100 + +fping (2.2b2-2) unstable; urgency=low + + * Made changes for dpkg-statoverride (closes: #83838). + + -- Herbert Xu Sun, 28 Jan 2001 21:53:05 +1100 + +fping (2.2b2-1) unstable; urgency=low + + * New upstream release. + * Fixed typo that prevented -d from working (closes: #83255). + * Drop root privileges after opening the socket (closes: #81589). + * Fixed the options [tip], they were out by a factor of 10 + (Richard Kettlewell, closes: #83742). + + -- Herbert Xu Sun, 28 Jan 2001 00:09:41 +1100 + +fping (2.2b1-2) unstable; urgency=low + + * Fixed typo in control file, spotted by William Ono (closes: #49909). + + -- Herbert Xu Mon, 15 May 2000 12:27:03 +1000 + +fping (2.2b1-1) unstable; urgency=low + + * Initial release. + * Fixed divide by zero error (closes: #29902). + + -- Herbert Xu Sat, 30 Oct 1999 16:36:19 +1000 +--------------------------------------------------------------------------------- + +Wed Jan 16 2002 +Jeroen Massar +- Revision v2.4b2-to-IPv6 + - Added IPv6 support. + - Added -I option for selecting source IPv4/IPv6 address. + - Makefile.in now generates a Makefile which will build both + fping (IPv4) and fping6 (IPv6). Thus it makes an fping (IPv4 only) + and an fping6 (IPv6 only). + - num_unreachable was counted twice when a sendto() generated errors. + - See http://unfix.org/projects/ipv6/ + +Tue Mar 14 2001 +Jason Ewasiuk +- Revision v2.4b1 + - added -g option for generating IPs from a start to an end value + - two available options, generate IPs from start IP to end IP + or from a passed netmask, such as 192.168.1.0/24 + +Thu Feb 15 2001 +Jason Ewasiuk +- 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 + + - 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 + + * stop using sys_errlist and start using strerror + fixed bug in output of -C + +Wed Jan 8 11:18:37 1997 Roland Schemers + + * Created ChangeLog file. What follows was from the CHANGES file. + +* Revision 2.0 1994/10/31 21:26:23 morgan + + Substantial rewrite, including new features: + + support some traditional ping features: + loop mode + specify size of data packets + specify how many pings to send + show per-response data + interpret ICMPs other than ICMP Echo response + + also + + rewrote main loop completely + make timings in tenths of milliseconds + do exponential backoff on retries + port to more systems + add some debugging stuff + do better checking on whether received ICMP is for us + +* Revision 1.24 1993/12/10 23:11:39 schemers + + commented out seteuid(getuid()) since it isn't needed + +* Revision 1.23 1993/12/10 18:33:41 schemers + + Took out the -f option for non-root users. This can be enabled by + defining ENABLE_F_OPTION before compiling. There is a call to + access before opening the file, but there is a race condition. + Reading from stdin is much safer. + + +* Revision 1.22 1993/11/16 19:49:24 schemers + + Took out setuid(getuid()) and used access() system call to + check for access to the file specified with "-f". + +* Revision 1.21 1993/07/20 18:08:19 schemers + + commented out the test to make sure the ping packet came from the + same IP address as the one we sent to. This could cause problems on + multi-homed hosts. + +* Revision 1.20 1993/02/23 00:16:38 schemers + +fixed syntax error (should have compiled before checking in...) + +* Revision 1.19 1993/02/23 00:15:15 schemers + +turned off printing of "is alive" when -a is specified. + +* Revision 1.18 1992/07/28 15:16:44 schemers + +added a fflush(stdout) call before the summary is sent to stderr, so +everything shows up in the right order. + +* Revision 1.17 1992/07/23 03:29:42 schemers +* Revision 1.16 1992/07/22 19:24:37 schemers + +Fixed declaration of timeval_diff. Didn't notice the problem because +I use 'cc' in stead of gcc under Ultrix. Time to switch? :-) + +Modified file reaing so it would skip blank lines or lines starting +with a '#'. Now you can do something like: + +fping -ad < /etc/hosts + +* Revision 1.15 1992/07/21 17:07:18 schemers + +Put in sanity checks so only root can specify "dangerous" options. +Changed usage to show switchs in alphabetical order. +* Revision 1.14 1992/07/21 16:40:52 schemers +* Revision 1.13 1992/07/17 21:02:17 schemers + +Changed the default timeout to 2500 msec, and retry to 3. This was +due to suggestions from people with slow (WAN) networks. The default +1 sec timeout was too fast. + + +Added '-e' option for showing elapsed (round-trip) times on pakets, and +modified the -s option to include min, max, and average round-trip times, +and over all elapsed time. + +Modified action taken when a error is returned from sendto. The action +taken now considers the host unreachable and prints the hostname +followed by the errno message. The program will not exit and will continue +to try other hosts. + +* Revision 1.12 1992/07/17 16:38:54 schemers +* Revision 1.11 1992/07/17 16:28:38 schemers + + move socket create call so I could do a setuid(getuid()) before the + fopen call is made. Once the socket is created root privs aren't needed + to send stuff out on it. + + moved num_timeout counter. It really was for debug purposes and didn't + make sense to the general public :-) Now it is the number of timeouts + (pings that didn't get received with the time limit). + + +* Revision 1.10 1992/07/16 16:24:38 schemers +* Revision 1.9 1992/07/16 16:00:04 schemers +* Revision 1.8 1992/07/16 05:44:41 schemers + +Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE +for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added +check for __cplusplus. + +Now compiles ok under Ultrix 3.1, and Sun4 using cc. Also compiled +ok using g++ 2.2.2. + +Changed '-a' and '-u' flags to be mutually exclusive (makes sense, since +specifiying both '-a' and '-u' is the same as not specifiying anything. +Since '-a' and '-u' are mutually exclusive, these options now only print +the hostname, and not the 'is alive' or 'is unreachable' messages. +This makes it much easier to do stuff like: + +#!/usr/local/bin/perl +$hosts_to_backup=`cat /etc/hosts.backup|fping -a`; + +Since you don't have to strip off the 'is alive' messages. + +Changed usage to and stats to print to stderr instead of stdout. + +----------------------------------------------------------------------------- + +RCS header info from original fping.c package (no longer required) + +/* + *************************************************** + * + * Standard RCS Header information (see co(1)) + * + * $Author: schemers $ + * + * $Date: 1997/01/08 20:29:33 $ + * + * $Revision: 2.2 $ + * + * $Locker: $ + * + * $Source: /afs/ir/group/networking/src/fping/fping-2.2/src/RCS/fping.c,v $ + * + * $State: Exp $ + * + * $Log: fping.c,v $ + * + * Revision 2.2 1997/01/08 20:29:33 schemers + * changes for autoconf/automake + * + * Revision 2.1 1997/01/08 19:07:18 schemers + * checked in RL "Bob"'s changes before configure'ing + * + * Revision 2.0 1994/10/31 21:26:23 schemers + * many changes by RL "Bob" Morgan + * add timing data collection, loop mode, per-packet output, etc + * + * Revision 1.24 1993/12/10 23:11:39 schemers + * commented out seteuid(getuid()) since it isn't needed + * + * Revision 1.23 1993/12/10 18:33:41 schemers + * Took out the -f option for non-root users. This can be enabled by + * defining ENABLE_F_OPTION before compiling. There is a call to + * access before opening the file, but there is a race condition. + * Reading from stdin is much safer. + * + * Revision 1.22 1993/11/16 19:49:24 schemers + * Took out setuid(getuid()) and used access() system call to + * check for access to the file specified with "-f". + * + * Revision 1.21 1993/07/20 18:08:19 schemers + * commented out the test to make sure the ping packet came from the + * same IP address as the one we sent to. This could cause problems on + * multi-homed hosts. + * + * Revision 1.20 1993/02/23 00:16:38 schemers + * fixed syntax error (should have compiled before checking in...) + * + * Revision 1.19 1993/02/23 00:15:15 schemers + * turned off printing of "is alive" when -a is specified. + * + * Revision 1.18 1992/07/28 15:16:44 schemers + * added a fflush(stdout) call before the summary is sent to stderr, so + * everything shows up in the right order. + * + * Revision 1.17 1992/07/23 03:29:42 schemers + * fixed declaration of timeval_diff. + * + * Revision 1.16 1992/07/22 19:24:37 schemers + * Modified file reading so it would skip blanks lines or lines starting + * with a '#'. Now you can do something like: + * + * fping -ad < /etc/hosts + * + * Revision 1.15 1992/07/21 17:07:18 schemers + * Put in sanity checks so only root can specify "dangerous" options. + * Changed usage to show switchs in alphabetical order. + * + * Revision 1.14 1992/07/21 16:40:52 schemers + * Now when sendto returns an error, the host is considered unreachable and + * and the error message (from errno) is displayed. + * + * Revision 1.13 1992/07/17 21:02:17 schemers + * changed default timeout to 2500 msec (for WANs), and default try + * to 3. This gives 10 second overall timeout. + * + * Added -e option for showing elapsed (round-trip) time on packets + * + * Modified -s option to inlude to round-trip stats + * + * Added #ifndef DEFAULT_* stuff its easier to change the defaults + * + * Reorganized main loop. + * + * cleaned up timeval stuff. removed set_timeval and timeval_expired + * since they aren't needed anymore. Just use timeval_diff. + * + * Revision 1.12 1992/07/17 16:38:54 schemers + * move socket create call so I could do a setuid(getuid()) before the + * fopen call is made. Once the socket is created root privs aren't needed + * to send stuff out on it. + * + * Revision 1.11 1992/07/17 16:28:38 schemers + * moved num_timeout counter. It really was for debug purposes and didn't + * make sense to the general public :-) Now it is the number of timeouts + * (pings that didn't get received with the time limit). + * + * Revision 1.10 1992/07/16 16:24:38 schemers + * changed usage() to use fprintf(stderr,"..."); + * + * Revision 1.9 1992/07/16 16:00:04 schemers + * Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE + * for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added + * check for __cplusplus. + * + * Revision 1.8 1992/07/16 05:44:41 schemers + * changed -a and -u to only show hostname in results. This is + * for easier parsing. Also added -v flag + * + * Revision 1.7 1992/07/14 18:45:23 schemers + * initialized last_time in add_host function + * + * Revision 1.6 1992/07/14 18:32:40 schemers + * changed select to use FD_ macros + * + * Revision 1.5 1992/07/14 17:21:22 schemers + * standardized exit status codes + * + * Revision 1.4 1992/06/26 15:25:35 schemers + * changed name from rrping to fping + * + * Revision 1.3 1992/06/24 15:39:32 schemers + * added -d option for unreachable systems + * + * Revision 1.2 1992/06/23 03:01:23 schemers + * misc fixes from R.L. "Bob" Morgan + * + * Revision 1.1 1992/06/19 18:23:52 schemers + * Initial revision + * + *-------------------------------------------------- + * Copyright (c) 1992, 1994, 1997 Board of Trustees + * Leland Stanford Jr. University + *************************************************** + */ + + diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/Makefile.am b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/Makefile.am new file mode 100644 index 0000000..20adc28 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/Makefile.am @@ -0,0 +1,6 @@ +man_MANS = fping.8 + +EXTRA_DIST = fping.8 fping.pod README.1992 CHANGELOG.pre-v4 + +fping.8: fping.pod + pod2man -c "" -s 8 -r "fping" $< >$@ diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/README.1992 b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/README.1992 new file mode 100644 index 0000000..a1020cd --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/README.1992 @@ -0,0 +1,43 @@ +Original README (from 1992) + + fping - A tool to quickly ping N number of hosts to determine + their reachability. + + Roland J. Schemers III - Stanford University + schemers@Stanford.EDU + + fping is a ping(1) like program which uses the Internet Control + Message Protocol (ICMP) echo request to determine if a host is + up. fping is different from ping in that you can specify any + number of hosts on the command line, or specify a file containing + the lists of hosts to ping. Instead of trying one host until it + timeouts or replies, fping will send out a ping packet and move + on to the next host in a round-robin fashion. If a host replies, + it is noted and removed from the list of hosts to check. If a host + does not respond within a certain time limit and/or retry limit it + will be considered unreachable. + +Site + Stanford University has a large TCP/IP network with over 16,000 + assigned IP addresses and over 100 IP subnets. + +Problem and Issues + + With a large a number of IP addresses in use, its becomes more and + more time consuming to check on which IP addresses are actively + in use, and which critical machines (routers, bridges, servers, etc) + are reachable. One example is we have a program which goes through + all of our routers arp caches looking for IP addresses that are in + use. After finding a list of IP addresses that aren't in any arp + caches fping can then be used to see if these IP addresses really + aren't being used, or are just behind the routers. Checking 2500 + hosts (99% of which are unreachable) via ping can take hours. + + fping was written to solve the problem of pinging N number of hosts + in an efficient manner. By sending out pings in a round-robin fashion + and checking on responses as they come in at random, a large number of + hosts can be checked at once. + + Unlike ping, fping is meant to be used in scripts and its + output is easy to parse. + diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.8 b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.8 new file mode 100644 index 0000000..bc4abeb --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.8 @@ -0,0 +1,420 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "FPING 8" +.TH FPING 8 "2025-08-19" "fping" "" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +fping \- send ICMP ECHO_REQUEST packets to network hosts +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBfping\fR [ \fIoptions\fR ] [ \fIsystems...\fR ] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBfping\fR is a program like \fBping\fR which uses the Internet Control Message +Protocol (\s-1ICMP\s0) echo request to determine if a target host is responding. +\&\fBfping\fR differs from \fBping\fR in that you can specify any number of targets on the +command line, or specify a file containing the lists of targets to ping. +Instead of sending to one target until it times out or replies, \fBfping\fR will +send out a ping packet and move on to the next target in a round-robin fashion. +In the default mode, if a target replies, it is noted and removed from the list +of targets to check; if a target does not respond within a certain time limit +and/or retry limit it is designated as unreachable. \fBfping\fR also supports +sending a specified number of pings to a target, or looping indefinitely (as in +\&\fBping\fR ). Unlike \fBping\fR, \fBfping\fR is meant to be used in scripts, so its +output is designed to be easy to parse. Current statistics can be obtained without +termination of process with signal \s-1SIGQUIT\s0 (^\e from the keyboard on most systems). +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-4\fR, \fB\-\-ipv4\fR" 5 +.IX Item "-4, --ipv4" +Restrict name resolution and IPs to IPv4 addresses. +.IP "\fB\-6\fR, \fB\-\-ipv6\fR" 5 +.IX Item "-6, --ipv6" +Restrict name resolution and IPs to IPv6 addresses. +.IP "\fB\-a\fR, \fB\-\-alive\fR" 5 +.IX Item "-a, --alive" +Show systems that are alive. (Options \fB\-c\fR and \fB\-C\fR override \fB\-a\fR.) +.IP "\fB\-A\fR, \fB\-\-addr\fR" 5 +.IX Item "-A, --addr" +Display targets by address rather than \s-1DNS\s0 name. Combined with \-d, the output +will be both the ip and (if available) the hostname. +.IP "\fB\-b\fR, \fB\-\-size\fR=\fI\s-1BYTES\s0\fR" 5 +.IX Item "-b, --size=BYTES" +Number of bytes of ping data to send. The minimum size (normally 12) allows +room for the data that \fBfping\fR needs to do its work (sequence number, +timestamp). The reported received data size includes the \s-1IP\s0 header (normally +20 bytes) and \s-1ICMP\s0 header (8 bytes), so the minimum total size is 40 bytes. +Default is 56, as in \fBping\fR. Maximum is the theoretical maximum \s-1IP\s0 datagram +size (64K), though most systems limit this to a smaller, system-dependent +number. Cannot be used together with \fB\-\-icmp\-timestamp\fR. +.IP "\fB\-B\fR, \fB\-\-backoff\fR=\fIN\fR" 5 +.IX Item "-B, --backoff=N" +Backoff factor. In the default mode, \fBfping\fR sends several requests to a +target before giving up, waiting longer for a reply on each successive request. +This parameter is the value by which the wait time (\fB\-t\fR) is multiplied on each +successive request; it must be entered as a floating-point number (x.y). The +default is 1.5. +.IP "\fB\-c\fR, \fB\-\-count\fR=\fIN\fR" 5 +.IX Item "-c, --count=N" +Number of request packets to send to each target. In this mode, a line is +displayed for each received response (this can suppressed with \fB\-q\fR or \fB\-Q\fR). +Also, statistics about responses for each target are displayed when all +requests have been sent (or when interrupted). This option overrides \fB\-a\fR +or \fB\-u\fR. +.IP "\fB\-C\fR, \fB\-\-vcount\fR=\fIN\fR" 5 +.IX Item "-C, --vcount=N" +Similar to \fB\-c\fR, but the per-target statistics are displayed in a format +designed for automated response-time statistics gathering. For example: +.Sp +.Vb 2 +\& $ fping \-C 5 \-q somehost +\& somehost : 91.7 37.0 29.2 \- 36.8 +.Ve +.Sp +shows the response time in milliseconds for each of the five requests, with the +\&\f(CW\*(C`\-\*(C'\fR indicating that no response was received to the fourth request. This +option overrides \fB\-a\fR or \fB\-u\fR. +.IP "\fB\-\-check\-source\fR" 5 +.IX Item "--check-source" +Discard Echo replies that are sourced from a different address than the target +address. This avoids spurious reachability results on busy monitoring systems +where two \fBfping\fR instances with the same lower 16 bits of the process \s-1ID\s0 may +be running at the same time. +.IP "\fB\-d\fR, \fB\-\-rdns\fR" 5 +.IX Item "-d, --rdns" +Use \s-1DNS\s0 to lookup address of ping target. This allows you to give fping +a list of \s-1IP\s0 addresses as input and print hostnames in the output. This is similar +to option \fB\-n\fR/\fB\-\-name\fR, but will force a reverse-DNS lookup even if you give +hostnames as target (\s-1NAME\-\s0>\s-1IP\-\s0>\s-1NAME\s0). +.IP "\fB\-D\fR, \fB\-\-timestamp\fR" 5 +.IX Item "-D, --timestamp" +Add Unix timestamps in front of output lines generated with in looping or counting +modes (\fB\-l\fR, \fB\-c\fR, or \fB\-C\fR). +.Sp +Subcommand: \fB\-\-timestamp\-format\fR=\fIctime|iso|rfc3339\fR +.Sp +Allow to change the timestamp format of the \fB\-D\fR option to the following format types. +.Sp +\&\fIctime\fR = \*(L"%c\*(R" (Example: Mon Jun 10 07:50:00 2024) +.Sp +\&\fIiso\fR = \*(L"%Y\-%m\-%dT%T%z\*(R" (Example: 2024\-06\-10T07:50:00+0200) +.Sp +\&\fIrfc3339\fR = \*(L"%Y\-%m\-%d \f(CW%H:\fR%M:%S\*(R" (Example: 2024\-06\-10 07:50:00) +.IP "\fB\-e\fR, \fB\-\-elapsed\fR" 5 +.IX Item "-e, --elapsed" +Show elapsed (round-trip) time of packets. +.IP "\fB\-f\fR, \fB\-\-file\fR" 5 +.IX Item "-f, --file" +Read list of targets from a file. +.IP "\fB\-g\fR, \fB\-\-generate\fR \fIaddr/mask\fR" 5 +.IX Item "-g, --generate addr/mask" +Generate a target list from a supplied \s-1IP\s0 netmask, or a starting and ending \s-1IP.\s0 +Specify the netmask or start/end in the targets portion of the command line. If +a network with netmask is given, the network and broadcast addresses will be +excluded. ex. To ping the network 192.168.1.0/24, the specified command line +could look like either: +.Sp +.Vb 1 +\& $ fping \-g 192.168.1.0/24 +.Ve +.Sp +or +.Sp +.Vb 1 +\& $ fping \-g 192.168.1.1 192.168.1.254 +.Ve +.IP "\fB\-h\fR, \fB\-\-help\fR" 5 +.IX Item "-h, --help" +Print usage message. +.IP "\fB\-H\fR, \fB\-\-ttl\fR=\fIN\fR" 5 +.IX Item "-H, --ttl=N" +Set the \s-1IP TTL\s0 field (time to live hops). +.IP "\fB\-\-print\-ttl\fR" 5 +.IX Item "--print-ttl" +Displays the IPv4 \s-1TTL\s0 value from the \s-1IP\s0 Header in the output. +If \fBfping\fR cannot read the \s-1TTL\s0 value, \*(L"(\s-1TTL\s0 unknown)\*(R" is returned. +IPv4 only, requires root privileges or cap_net_raw. +.IP "\fB\-i\fR, \fB\-\-interval\fR=\fI\s-1MSEC\s0\fR" 5 +.IX Item "-i, --interval=MSEC" +The minimum amount of time (in milliseconds) between sending a ping packet +to any target (default is 10, minimum is 1). +.IP "\fB\-I\fR, \fB\-\-iface\fR=\fI\s-1IFACE\s0\fR" 5 +.IX Item "-I, --iface=IFACE" +Set the interface (requires \s-1SO_BINDTODEVICE\s0 support). +.IP "\fB\-\-icmp\-timestamp\fR" 5 +.IX Item "--icmp-timestamp" +Send \s-1ICMP\s0 timestamp requests (\s-1ICMP\s0 type 13) instead of \s-1ICMP\s0 Echo requests. +Print \s-1ICMP\s0 timestamps for originate, receive, and transmit, together with +the local receive time in the same format, in addition to normal output. +Cannot be used together with \fB\-b\fR because \s-1ICMP\s0 timestamp messages have a fixed size. +IPv4 only, requires root privileges or cap_net_raw. +.IP "\fB\-k\fR, \fB\-\-fwmark\fR=\fI\s-1FWMARK\s0\fR" 5 +.IX Item "-k, --fwmark=FWMARK" +Set \s-1FWMARK\s0 on ping packets for policy-based routing. Requires Linux kernel +2.6.25<=, and root privileges or cap_net_admin. +.IP "\fB\-l\fR, \fB\-\-loop\fR" 5 +.IX Item "-l, --loop" +Loop sending packets to each target indefinitely. Can be interrupted with +Ctrl-C; statistics about responses for each target are then displayed. +.IP "\fB\-m\fR, \fB\-\-all\fR" 5 +.IX Item "-m, --all" +Send pings to each of a target host's multiple \s-1IP\s0 addresses (use of option '\-A' +is recommended). +.IP "\fB\-M\fR, \fB\-\-dontfrag\fR" 5 +.IX Item "-M, --dontfrag" +Set the \*(L"Don't Fragment\*(R" bit in the \s-1IP\s0 header (used to determine/test the \s-1MTU\s0). +.IP "\fB\-n\fR, \fB\-\-name\fR" 5 +.IX Item "-n, --name" +If targets are specified as \s-1IP\s0 addresses, do a reverse-DNS lookup on them +to print hostnames in the output. +.IP "\fB\-N\fR, \fB\-\-netdata\fR" 5 +.IX Item "-N, --netdata" +Format output for netdata (\-l \-Q are required). See: +.IP "\fB\-o\fR, \fB\-\-outage\fR" 5 +.IX Item "-o, --outage" +Calculate \*(L"outage time\*(R" based on the number of lost pings and the interval used (useful for network convergence tests). +.IP "\fB\-O\fR, \fB\-\-tos\fR=\fIN\fR" 5 +.IX Item "-O, --tos=N" +Set the typ of service flag (\s-1TOS\s0). \fIN\fR can be either decimal or hexadecimal +(0xh) format. +.IP "\fB\-\-print\-tos\fR" 5 +.IX Item "--print-tos" +Displays the \s-1TOS\s0 value in the output. If \fBfping\fR cannot read the \s-1TOS\s0 value, +\&\*(L"(\s-1TOS\s0 unknown)\*(R" is returned. +IPv4 only, requires root privileges or cap_net_raw. +.IP "\fB\-p\fR, \fB\-\-period\fR=\fI\s-1MSEC\s0\fR" 5 +.IX Item "-p, --period=MSEC" +In looping or counting modes (\fB\-l\fR, \fB\-c\fR, or \fB\-C\fR), this parameter sets +the time in milliseconds that \fBfping\fR waits between successive packets to +an individual target. Default is 1000 and minimum is 10. +.IP "\fB\-q\fR, \fB\-\-quiet\fR" 5 +.IX Item "-q, --quiet" +Quiet. Don't show per-probe results, but only the final summary. Also don't +show \s-1ICMP\s0 error messages. +.IP "\fB\-Q\fR, \fB\-\-squiet\fR=\fISECS[,cumulative]\fR" 5 +.IX Item "-Q, --squiet=SECS[,cumulative]" +Like \fB\-q\fR, but additionally show interval summary results every \fI\s-1SECS\s0\fR +seconds. With \fIcumulative\fR, show summary results since start instead of +for the last interval, unless option \fB\-N\fR is used, too. +.IP "\fB\-r\fR, \fB\-\-retry\fR=\fIN\fR" 5 +.IX Item "-r, --retry=N" +Retry limit (default 3). This is the number of times an attempt at pinging +a target will be made, not including the first try. +.IP "\fB\-R\fR, \fB\-\-random\fR" 5 +.IX Item "-R, --random" +Instead of using all-zeros as the packet data, generate random bytes. +Use to defeat, e.g., link data compression. +.IP "\fB\-s\fR, \fB\-\-stats\fR" 5 +.IX Item "-s, --stats" +Print cumulative statistics upon exit. +.IP "\fB\-S\fR, \fB\-\-src\fR=\fIaddr\fR" 5 +.IX Item "-S, --src=addr" +Set source address. +.IP "\fB\-t\fR, \fB\-\-timeout\fR=\fI\s-1MSEC\s0\fR" 5 +.IX Item "-t, --timeout=MSEC" +Initial target timeout in milliseconds. In the default, non-loop mode, the +default timeout is 500ms, and it represents the amount of time that \fBfping\fR +waits for a response to its first request. Successive timeouts are multiplied +by the backoff factor specified with \fB\-B\fR. +.Sp +In loop/count mode, the default timeout is automatically adjusted to match +the \*(L"period\*(R" value (but not more than 2000ms). You can still adjust the timeout +value with this option, if you wish to, but note that setting a value larger +than \*(L"period\*(R" produces inconsistent results, because the timeout value can +be respected only for the last ping. +.Sp +Also note that any received replies that are larger than the timeout value, will +be discarded. +.IP "\fB\-T\fR \fIn\fR" 5 +.IX Item "-T n" +Ignored (for compatibility with fping 2.4). +.IP "\fB\-u\fR, \fB\-\-unreach\fR" 5 +.IX Item "-u, --unreach" +Show targets that are unreachable. (Options \fB\-c\fR and \fB\-C\fR override \fB\-u\fR.) +.IP "\fB\-v\fR, \fB\-\-version\fR" 5 +.IX Item "-v, --version" +Print \fBfping\fR version information. +.IP "\fB\-x\fR, \fB\-\-reachable\fR=\fIN\fR" 5 +.IX Item "-x, --reachable=N" +Given a list of hosts, this mode checks if number of reachable hosts is >= N +and exits true in that case. +.IP "\fB\-X\fR, \fB\-\-fast\-reachable\fR=\fIN\fR" 5 +.IX Item "-X, --fast-reachable=N" +Given a list of hosts, this mode immediately exits true once N alive hosts +have been found. +.SH "EXAMPLES" +.IX Header "EXAMPLES" +Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to +each host), and report every ping \s-1RTT\s0 at the end: +.PP +.Vb 1 +\& $ fping \-\-quiet \-\-interval=1 \-\-vcount=20 \-\-period=50 127.0.0.1 127.0.0.2 +.Ve +.SH "AUTHORS" +.IX Header "AUTHORS" +.IP "\(bu" 4 +Roland J. Schemers \s-1III,\s0 Stanford University, concept and versions 1.x +.IP "\(bu" 4 +\&\s-1RL\s0 \*(L"Bob\*(R" Morgan, Stanford University, versions 2.x +.IP "\(bu" 4 +David Papp, versions 2.3x and up +.IP "\(bu" 4 +David Schweikert, versions 3.0 and up +.PP +\&\fBfping website: \fR +.SH "DIAGNOSTICS" +.IX Header "DIAGNOSTICS" +Exit status is 0 if all the hosts (or the number of hosts specified with \fB\-x\fR +or \fB\-X\fR) are reachable, 1 if some (or too many with \fB\-x\fR or \fB\-X\fR) hosts +were unreachable, 2 if any \s-1IP\s0 addresses were not found, 3 for invalid command +line arguments, and 4 for a system call failure. +.SH "RESTRICTIONS" +.IX Header "RESTRICTIONS" +The number of addresses that can be generated using the \f(CW\*(C`\-g\*(C'\fR, \f(CW\*(C`\-\-generate\*(C'\fR +option is limited to 131070 (the number of host addresses in one 15\-bit IPv4 +prefix). +.PP +If fping was configured with \f(CW\*(C`\-\-enable\-safe\-limits\*(C'\fR, the following values are +not allowed for non-root users: +.IP "\(bu" 4 +\&\fB\-i\fR \fIn\fR, where \fIn\fR < 1 msec +.IP "\(bu" 4 +\&\fB\-p\fR \fIn\fR, where \fIn\fR < 10 msec +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\f(CWping(8)\fR diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.pod b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.pod new file mode 100644 index 0000000..7709225 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.pod @@ -0,0 +1,345 @@ +=head1 NAME + +fping - send ICMP ECHO_REQUEST packets to network hosts + +=head1 SYNOPSIS + +B [ I ] [ I ] + +=head1 DESCRIPTION + +B is a program like B which uses the Internet Control Message +Protocol (ICMP) echo request to determine if a target host is responding. +B differs from B in that you can specify any number of targets on the +command line, or specify a file containing the lists of targets to ping. +Instead of sending to one target until it times out or replies, B will +send out a ping packet and move on to the next target in a round-robin fashion. +In the default mode, if a target replies, it is noted and removed from the list +of targets to check; if a target does not respond within a certain time limit +and/or retry limit it is designated as unreachable. B also supports +sending a specified number of pings to a target, or looping indefinitely (as in +B ). Unlike B, B is meant to be used in scripts, so its +output is designed to be easy to parse. Current statistics can be obtained without +termination of process with signal SIGQUIT (^\ from the keyboard on most systems). + +=head1 OPTIONS + +=over 5 + +=item B<-4>, B<--ipv4> + +Restrict name resolution and IPs to IPv4 addresses. + +=item B<-6>, B<--ipv6> + +Restrict name resolution and IPs to IPv6 addresses. + +=item B<-a>, B<--alive> + +Show systems that are alive. (Options B<-c> and B<-C> override B<-a>.) + +=item B<-A>, B<--addr> + +Display targets by address rather than DNS name. Combined with -d, the output +will be both the ip and (if available) the hostname. + +=item B<-b>, B<--size>=I + +Number of bytes of ping data to send. The minimum size (normally 12) allows +room for the data that B needs to do its work (sequence number, +timestamp). The reported received data size includes the IP header (normally +20 bytes) and ICMP header (8 bytes), so the minimum total size is 40 bytes. +Default is 56, as in B. Maximum is the theoretical maximum IP datagram +size (64K), though most systems limit this to a smaller, system-dependent +number. Cannot be used together with B<--icmp-timestamp>. + +=item B<-B>, B<--backoff>=I + +Backoff factor. In the default mode, B sends several requests to a +target before giving up, waiting longer for a reply on each successive request. +This parameter is the value by which the wait time (B<-t>) is multiplied on each +successive request; it must be entered as a floating-point number (x.y). The +default is 1.5. + +=item B<-c>, B<--count>=I + +Number of request packets to send to each target. In this mode, a line is +displayed for each received response (this can suppressed with B<-q> or B<-Q>). +Also, statistics about responses for each target are displayed when all +requests have been sent (or when interrupted). This option overrides B<-a> +or B<-u>. + +=item B<-C>, B<--vcount>=I + +Similar to B<-c>, but the per-target statistics are displayed in a format +designed for automated response-time statistics gathering. For example: + + $ fping -C 5 -q somehost + somehost : 91.7 37.0 29.2 - 36.8 + +shows the response time in milliseconds for each of the five requests, with the +C<-> indicating that no response was received to the fourth request. This +option overrides B<-a> or B<-u>. + +=item B<--check-source> + +Discard Echo replies that are sourced from a different address than the target +address. This avoids spurious reachability results on busy monitoring systems +where two B instances with the same lower 16 bits of the process ID may +be running at the same time. + +=item B<-d>, B<--rdns> + +Use DNS to lookup address of ping target. This allows you to give fping +a list of IP addresses as input and print hostnames in the output. This is similar +to option B<-n>/B<--name>, but will force a reverse-DNS lookup even if you give +hostnames as target (NAME->IP->NAME). + +=item B<-D>, B<--timestamp> + +Add Unix timestamps in front of output lines generated with in looping or counting +modes (B<-l>, B<-c>, or B<-C>). + +Subcommand: B<--timestamp-format>=I + +Allow to change the timestamp format of the B<-D> option to the following format types. + +I = "%c" (Example: Mon Jun 10 07:50:00 2024) + +I = "%Y-%m-%dT%T%z" (Example: 2024-06-10T07:50:00+0200) + +I = "%Y-%m-%d %H:%M:%S" (Example: 2024-06-10 07:50:00) + +=item B<-e>, B<--elapsed> + +Show elapsed (round-trip) time of packets. + +=item B<-f>, B<--file> + +Read list of targets from a file. + +=item B<-g>, B<--generate> I + +Generate a target list from a supplied IP netmask, or a starting and ending IP. +Specify the netmask or start/end in the targets portion of the command line. If +a network with netmask is given, the network and broadcast addresses will be +excluded. ex. To ping the network 192.168.1.0/24, the specified command line +could look like either: + + $ fping -g 192.168.1.0/24 + +or + + $ fping -g 192.168.1.1 192.168.1.254 + +=item B<-h>, B<--help> + +Print usage message. + +=item B<-H>, B<--ttl>=I + +Set the IP TTL field (time to live hops). + +=item B<--print-ttl> + +Displays the IPv4 TTL value from the IP Header in the output. +If B cannot read the TTL value, "(TTL unknown)" is returned. +IPv4 only, requires root privileges or cap_net_raw. + +=item B<-i>, B<--interval>=I + +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 + +Set the interface (requires SO_BINDTODEVICE support). + +=item B<--icmp-timestamp> + +Send ICMP timestamp requests (ICMP type 13) instead of ICMP Echo requests. +Print ICMP timestamps for originate, receive, and transmit, together with +the local receive time in the same format, in addition to normal output. +Cannot be used together with B<-b> because ICMP timestamp messages have a fixed size. +IPv4 only, requires root privileges or cap_net_raw. + +=item B<-k>, B<--fwmark>=I + +Set FWMARK on ping packets for policy-based routing. Requires Linux kernel +2.6.25<=, and root privileges or cap_net_admin. + +=item B<-l>, B<--loop> + +Loop sending packets to each target indefinitely. Can be interrupted with +Ctrl-C; statistics about responses for each target are then displayed. + +=item B<-m>, B<--all> + +Send pings to each of a target host's multiple IP addresses (use of option '-A' +is recommended). + +=item B<-M>, B<--dontfrag> + +Set the "Don't Fragment" bit in the IP header (used to determine/test the MTU). + +=item B<-n>, B<--name> + +If targets are specified as IP addresses, do a reverse-DNS lookup on them +to print hostnames in the output. + +=item B<-N>, B<--netdata> + +Format output for netdata (-l -Q are required). See: L + +=item B<-o>, B<--outage> + +Calculate "outage time" based on the number of lost pings and the interval used (useful for network convergence tests). + +=item B<-O>, B<--tos>=I + +Set the typ of service flag (TOS). I can be either decimal or hexadecimal +(0xh) format. + +=item B<--print-tos> + +Displays the TOS value in the output. If B cannot read the TOS value, +"(TOS unknown)" is returned. +IPv4 only, requires root privileges or cap_net_raw. + +=item B<-p>, B<--period>=I + +In looping or counting modes (B<-l>, B<-c>, or B<-C>), this parameter sets +the time in milliseconds that B waits between successive packets to +an individual target. Default is 1000 and minimum is 10. + +=item B<-q>, B<--quiet> + +Quiet. Don't show per-probe results, but only the final summary. Also don't +show ICMP error messages. + +=item B<-Q>, B<--squiet>=I + +Like B<-q>, but additionally show interval summary results every I +seconds. With I, show summary results since start instead of +for the last interval, unless option B<-N> is used, too. + +=item B<-r>, B<--retry>=I + +Retry limit (default 3). This is the number of times an attempt at pinging +a target will be made, not including the first try. + +=item B<-R>, B<--random> + +Instead of using all-zeros as the packet data, generate random bytes. +Use to defeat, e.g., link data compression. + +=item B<-s>, B<--stats> + +Print cumulative statistics upon exit. + +=item B<-S>, B<--src>=I + +Set source address. + +=item B<-t>, B<--timeout>=I + +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 +waits for a response to its first request. Successive timeouts are multiplied +by the backoff factor specified with B<-B>. + +In loop/count mode, the default timeout is automatically adjusted to match +the "period" value (but not more than 2000ms). You can still adjust the timeout +value with this option, if you wish to, but note that setting a value larger +than "period" produces inconsistent results, because the timeout value can +be respected only for the last ping. + +Also note that any received replies that are larger than the timeout value, will +be discarded. + +=item B<-T> I + +Ignored (for compatibility with fping 2.4). + +=item B<-u>, B<--unreach> + +Show targets that are unreachable. (Options B<-c> and B<-C> override B<-u>.) + +=item B<-v>, B<--version> + +Print B version information. + +=item B<-x>, B<--reachable>=I + +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 + +Given a list of hosts, this mode immediately exits true once N alive hosts +have been found. + +=back + +=head1 EXAMPLES + +Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to +each host), and report every ping RTT at the end: + + $ fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2 + +=head1 AUTHORS + +=over 4 + +=item * + +Roland J. Schemers III, Stanford University, concept and versions 1.x + +=item * + +RL "Bob" Morgan, Stanford University, versions 2.x + +=item * + +David Papp, versions 2.3x and up + +=item * + +David Schweikert, versions 3.0 and up + +=back + +B> + +=head1 DIAGNOSTICS + +Exit status is 0 if all the hosts (or the number of hosts specified with B<-x> +or B<-X>) are reachable, 1 if some (or too many with B<-x> or B<-X>) hosts +were unreachable, 2 if any IP addresses were not found, 3 for invalid command +line arguments, and 4 for a system call failure. + +=head1 RESTRICTIONS + +The number of addresses that can be generated using the C<-g>, C<--generate> +option is limited to 131070 (the number of host addresses in one 15-bit IPv4 +prefix). + +If fping was configured with C<--enable-safe-limits>, the following values are +not allowed for non-root users: + +=over 4 + +=item * + +B<-i> I, where I < 1 msec + +=item * + +B<-p> I, where I < 10 msec + +=back + +=head1 SEE ALSO + +C diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/Makefile.am b/ci/tmp.VwGIuQgZdr/fping-5.4/src/Makefile.am new file mode 100644 index 0000000..c58e474 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/Makefile.am @@ -0,0 +1,11 @@ +AM_CFLAGS = -Wall -Wextra -Wno-sign-compare + +sbin_PROGRAMS = fping + +fping_SOURCES = fping.c seqmap.c socket4.c fping.h options.h seqmap.h optparse.c optparse.h +fping_DEPENDENCIES = ../config.h + +if IPV6 +fping_SOURCES += socket6.c +fping_CFLAGS = $(AM_CFLAGS) -DIPV6 +endif diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping new file mode 100755 index 0000000..dc0098d Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping differ diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o new file mode 100644 index 0000000..564be54 Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o differ diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-optparse.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-optparse.o new file mode 100644 index 0000000..75fbf33 Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-optparse.o differ diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-seqmap.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-seqmap.o new file mode 100644 index 0000000..72bd0f3 Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-seqmap.o differ diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket4.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket4.o new file mode 100644 index 0000000..c770f1e Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket4.o differ diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket6.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket6.o new file mode 100644 index 0000000..4760776 Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket6.o differ diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.c new file mode 100644 index 0000000..6779175 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.c @@ -0,0 +1,3201 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "fping.h" +#include "config.h" +#include "options.h" +#include "optparse.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "seqmap.h" + +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ + +#ifdef HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ + +#include +#include + +#include +#include +#include + +#if HAVE_SYS_FILE_H +#include +#endif /* HAVE_SYS_FILE_H */ + +#ifdef IPV6 +#include +#endif +#include + +#include +#include + +#include +#include +#include + +#include + +/*** compatibility ***/ + +/* Mac OS X's getaddrinfo() does not fail if we use an invalid combination, + * e.g. AF_INET6 with "127.0.0.1". If we pass AI_UNUSABLE to flags, it behaves + * like other platforms. But AI_UNUSABLE isn't available on other platforms, + * and we can safely use 0 for flags instead. + */ +#ifndef AI_UNUSABLE +#define AI_UNUSABLE 0 +#endif + +/* MSG_TRUNC available on Linux kernel 2.2+, makes recvmsg return the full + * length of the raw packet received, even if the buffer is smaller */ +#ifndef MSG_TRUNC +#define MSG_TRUNC 0 +#define RECV_BUFSIZE 4096 +#else +#define RECV_BUFSIZE 128 +#endif + +/*** externals ***/ + +extern char *optarg; +extern int optind, opterr; +#ifndef h_errno +extern int h_errno; +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*** Constants ***/ + +/* CLOCK_MONTONIC starts under macOS, OpenBSD and FreeBSD with undefined positive point and can not be use + * see github PR #217 + * The configure script detect the predefined operating systems an set CLOCK_REALTIME using over ONLY_CLOCK_REALTIME variable + */ +#if HAVE_SO_TIMESTAMPNS || ONLY_CLOCK_REALTIME +#define CLOCKID CLOCK_REALTIME +#endif + +#if !defined(CLOCKID) +#if defined(CLOCK_MONOTONIC) +#define CLOCKID CLOCK_MONOTONIC +#else +#define CLOCKID CLOCK_REALTIME +#endif +#endif + +/*** Ping packet defines ***/ + +#define MAX_IP_PACKET 65535 /* (theoretical) max IPv4 packet size */ +#define SIZE_IP_HDR 20 /* min IPv4 header size */ +#define SIZE_ICMP_HDR 8 /* from ip_icmp.h */ +#define MAX_PING_DATA (MAX_IP_PACKET - SIZE_IP_HDR - SIZE_ICMP_HDR) + +#define MAX_GENERATE 131070 /* maximum number of hosts that -g can generate */ + +/* sized so as to be like traditional ping */ +#define DEFAULT_PING_DATA_SIZE 56 + +/* ICMP Timestamp has a fixed payload size of 12 bytes */ +#define ICMP_TIMESTAMP_DATA_SIZE 12 + +#ifdef FPING_SAFE_LIMITS +#define MIN_INTERVAL_MS 1 /* in millisec */ +#define MIN_PERHOST_INTERVAL_MS 10 /* in millisec */ +#else +#define MIN_INTERVAL_MS 0 +/* Set a very low limit for the per-host interval, even if safe limits are + * disabled, so that the memory allocation of the event storage is not + * unreasonably high. 0.001 ms would mean in theory at least 592 mbps of data + * sent to a single host, which probably doesn't make sense in any scenario. */ +#define MIN_PERHOST_INTERVAL_MS 0.001 +#endif + +/* response time array flags */ +#define RESP_WAITING -1 +#define RESP_UNUSED -2 +#define RESP_ERROR -3 +#define RESP_TIMEOUT -4 + +/* debugging flags */ +#if defined(DEBUG) || defined(_DEBUG) +#define DBG_TRACE 1 +#define DBG_SENT_TIMES 2 +#define DBG_RANDOM_LOSE_FEW 4 +#define DBG_RANDOM_LOSE_MANY 8 +#define DBG_PRINT_PER_SYSTEM 16 +#define DBG_REPORT_ALL_RTTS 32 +#endif /* DEBUG || _DEBUG */ + +/* Long names for ICMP packet types */ +#define ICMP_TYPE_STR_MAX 18 +char *icmp_type_str[19] = { + "ICMP Echo Reply", /* 0 */ + "", + "", + "ICMP Unreachable", /* 3 */ + "ICMP Source Quench", /* 4 */ + "ICMP Redirect", /* 5 */ + "", + "", + "ICMP Echo", /* 8 */ + "", + "", + "ICMP Time Exceeded", /* 11 */ + "ICMP Parameter Problem", /* 12 */ + "ICMP Timestamp Request", /* 13 */ + "ICMP Timestamp Reply", /* 14 */ + "ICMP Information Request", /* 15 */ + "ICMP Information Reply", /* 16 */ + "ICMP Mask Request", /* 17 */ + "ICMP Mask Reply" /* 18 */ +}; + +char *icmp_unreach_str[16] = { + "ICMP Network Unreachable", /* 0 */ + "ICMP Host Unreachable", /* 1 */ + "ICMP Protocol Unreachable", /* 2 */ + "ICMP Port Unreachable", /* 3 */ + "ICMP Unreachable (Fragmentation Needed)", /* 4 */ + "ICMP Unreachable (Source Route Failed)", /* 5 */ + "ICMP Unreachable (Destination Network Unknown)", /* 6 */ + "ICMP Unreachable (Destination Host Unknown)", /* 7 */ + "ICMP Unreachable (Source Host Isolated)", /* 8 */ + "ICMP Unreachable (Communication with Network Prohibited)", /* 9 */ + "ICMP Unreachable (Communication with Host Prohibited)", /* 10 */ + "ICMP Unreachable (Network Unreachable For Type Of Service)", /* 11 */ + "ICMP Unreachable (Host Unreachable For Type Of Service)", /* 12 */ + "ICMP Unreachable (Communication Administratively Prohibited)", /* 13 */ + "ICMP Unreachable (Host Precedence Violation)", /* 14 */ + "ICMP Unreachable (Precedence cutoff in effect)" /* 15 */ +}; + +#define ICMP_UNREACH_MAXTYPE 15 + +struct event; +typedef struct host_entry { + int i; /* index into array */ + char *name; /* name as given by user */ + char *host; /* text description of host */ + struct sockaddr_storage saddr; /* internet address */ + socklen_t saddr_len; + int64_t timeout; /* time to wait for response */ + int64_t last_send_time; /* time of last packet sent */ + int num_sent; /* number of ping packets sent (for statistics) */ + int num_recv; /* number of pings received (duplicates ignored) */ + int num_recv_total; /* number of pings received, including duplicates */ + int64_t max_reply; /* longest response time */ + int64_t min_reply; /* shortest response time */ + int64_t total_time; /* sum of response times */ + /* _i -> splits (reset on every report interval) */ + int num_sent_i; /* number of ping packets sent */ + int num_recv_i; /* number of pings received */ + int64_t max_reply_i; /* longest response time */ + int64_t min_reply_i; /* shortest response time */ + int64_t total_time_i; /* sum of response times */ + int64_t *resp_times; /* individual response times */ + + /* to avoid allocating two struct events each time that we send a ping, we + * preallocate here two struct events for each ping that we might send for + * this host. */ + struct event *event_storage_ping; + struct event *event_storage_timeout; +} HOST_ENTRY; + +int event_storage_count; /* how many events can be stored in host_entry->event_storage_xxx */ + +/* basic algorithm to ensure that we have correct data at all times: + * + * 1. when a ping is sent: + * - two events get added into event_queue: + * - t+PERIOD: ping event + * - t+TIMEOUT: timeout event + * + * 2. when a ping is received: + * - record statistics (increase num_sent and num_received) + * - remove timeout event (we store the event in seqmap, so that we can retrieve it when the response is received) + * + * 3. when a timeout happens: + * - record statistics (increase num_sent only) + */ + +#define EV_TYPE_PING 1 +#define EV_TYPE_TIMEOUT 2 + +struct event { + struct event *ev_prev; + struct event *ev_next; + int64_t ev_time; + struct host_entry *host; + int ping_index; +}; + +struct event_queue { + struct event *first; + struct event *last; +}; + +/*** globals ***/ + +HOST_ENTRY **table = NULL; /* array of pointers to items in the list */ + +/* we keep two separate queues: a ping queue, for when the next ping should be + * sent, and a timeout queue. the reason for having two separate queues is that + * the ping period and the timeout value are different, so if we put them in + * the same event queue, we would need to scan many more entries when inserting + * into the sorted list. + */ +struct event_queue event_queue_ping; +struct event_queue event_queue_timeout; + +char *prog; +int ident4 = 0; /* our icmp identity field */ +int ident6 = 0; +int socket4 = -1; +int socktype4 = -1; +int using_sock_dgram4 = 0; +#ifndef IPV6 +int hints_ai_family = AF_INET; +#else +int socket6 = -1; +int socktype6 = -1; +int hints_ai_family = AF_UNSPEC; +#endif + +volatile sig_atomic_t status_snapshot = 0; +volatile sig_atomic_t finish_requested = 0; + +unsigned int debugging = 0; + +/* all time-related values are int64_t nanoseconds */ +unsigned int retry = DEFAULT_RETRY; +int64_t timeout = (int64_t)DEFAULT_TIMEOUT * 1000000; +int64_t interval = (int64_t)DEFAULT_INTERVAL * 1000000; +int64_t perhost_interval = (int64_t)DEFAULT_PERHOST_INTERVAL * 1000000; +float backoff = DEFAULT_BACKOFF_FACTOR; +unsigned int ping_data_size = DEFAULT_PING_DATA_SIZE; +unsigned int count = 1, min_reachable = 0; +unsigned int trials; +int64_t report_interval = 0; +unsigned int ttl = 0; +int src_addr_set = 0; +struct in_addr src_addr; +#ifdef IPV6 +int src_addr6_set = 0; +struct in6_addr src_addr6; +#endif + +/* global stats */ +int64_t max_reply = 0; +int64_t min_reply = 0; +int64_t total_replies = 0; +int64_t sum_replies = 0; +int max_hostname_len = 0; +int num_hosts = 0; /* total number of hosts */ +int num_alive = 0, /* total number alive */ + num_unreachable = 0, /* total number unreachable */ + num_noaddress = 0; /* total number of addresses not found */ +int num_timeout = 0, /* number of times select timed out */ + num_pingsent = 0, /* total pings sent */ + num_pingreceived = 0, /* total pings received */ + num_othericmprcvd = 0; /* total non-echo-reply ICMP received */ + +struct timespec current_time; /* current time (pseudo) */ +int64_t current_time_ns; +int64_t start_time; +int64_t end_time; +int64_t last_send_time; /* time last ping was sent */ +int64_t next_report_time; /* time next -Q report is expected */ + +/* switches */ +int generate_flag = 0; /* flag for IP list generation */ +int verbose_flag, quiet_flag, stats_flag, unreachable_flag, alive_flag; +int elapsed_flag, version_flag, count_flag, loop_flag, netdata_flag; +int per_recv_flag, report_all_rtts_flag, name_flag, addr_flag, backoff_flag, rdns_flag; +int multif_flag, timeout_flag, fast_reachable; +int outage_flag = 0; +int timestamp_flag = 0; +int timestamp_format_flag = 0; +int random_data_flag = 0; +int cumulative_stats_flag = 0; +int check_source_flag = 0; +int icmp_request_typ = 0; +int print_tos_flag = 0; +int print_ttl_flag = 0; +int size_flag = 0; +#if defined(DEBUG) || defined(_DEBUG) +int randomly_lose_flag, trace_flag, print_per_system_flag; +int lose_factor; +#endif /* DEBUG || _DEBUG */ + +unsigned int fwmark = 0; + +char *filename = NULL; /* file containing hosts to ping */ + +/*** forward declarations ***/ + +void add_name(char *name); +void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_len); +char *na_cat(char *name, struct in_addr ipaddr); +void crash_and_burn(char *message); +void errno_crash_and_burn(char *message); +char *get_host_by_address(struct in_addr in); +int send_ping(HOST_ENTRY *h, int index); +void usage(int); +int wait_for_reply(int64_t); +void print_per_system_stats(void); +void print_per_system_splits(void); +void stats_reset_interval(HOST_ENTRY *h); +void print_netdata(void); +void print_global_stats(void); +void main_loop(); +void signal_handler(int); +void finish(); +const char *sprint_tm(int64_t t); +void ev_enqueue(struct event_queue *queue, struct event *event); +struct event *ev_dequeue(struct event_queue *queue); +void ev_remove(struct event_queue *queue, struct event *event); +void add_cidr(char *); +void add_range(char *, char *); +void add_addr_range_ipv4(unsigned long, unsigned long); +void print_warning(char *fmt, ...); +int addr_cmp(struct sockaddr *a, struct sockaddr *b); +void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time); +void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time); +struct event *host_get_timeout_event(HOST_ENTRY *h, int index); +void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency); +void update_current_time(); +void print_timestamp_format(int64_t current_time_ns, int timestamp_format); +static uint32_t ms_since_midnight_utc(int64_t time_val); + +/************************************************************ + + Function: p_setsockopt + +************************************************************* + + Inputs: p_uid: privileged uid. Others as per setsockopt(2) + + Description: + + Elevates privileges to p_uid when required, calls + setsockopt, and drops privileges back. + +************************************************************/ + +int p_setsockopt(uid_t p_uid, int sockfd, int level, int optname, + const void *optval, socklen_t optlen) +{ + const uid_t saved_uid = geteuid(); + int res; + + if (p_uid != saved_uid && seteuid(p_uid)) { + perror("cannot elevate privileges for setsockopt"); + } + + res = setsockopt(sockfd, level, optname, optval, optlen); + + if (p_uid != saved_uid && seteuid(saved_uid)) { + perror("fatal error: could not drop privileges after setsockopt"); + /* continuing would be a security hole */ + exit(4); + } + + return res; +} + +/************************************************************ + + Function: main + +************************************************************* + + Inputs: int argc, char** argv + + Description: + + Main program entry point + +************************************************************/ + +int main(int argc, char **argv) +{ +/* Debug: CPU Performance */ +#if defined(DEBUG) || defined(_DEBUG) + clock_t perf_cpu_start, perf_cpu_end; + double perf_cpu_time_used; + perf_cpu_start = clock(); +#endif /* DEBUG || _DEBUG */ + + int c; + const uid_t suid = geteuid(); + int tos = 0; + struct optparse optparse_state; +#ifdef USE_SIGACTION + struct sigaction act; +#endif + + /* pre-parse -h/--help, so that we also can output help information + * without trying to open the socket, which might fail */ + prog = argv[0]; + if (argc == 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) { + usage(0); + } + + socket4 = open_ping_socket_ipv4(&socktype4); +#ifdef __linux__ + /* We only treat SOCK_DGRAM differently on Linux, where the IPv4 header + * structure is missing in the message. + */ + using_sock_dgram4 = (socktype4 == SOCK_DGRAM); +#endif + +#ifdef IPV6 + socket6 = open_ping_socket_ipv6(&socktype6); + /* if called (sym-linked) via 'fping6', imply '-6' + * for backward compatibility */ + if (strstr(prog, "fping6")) { + hints_ai_family = AF_INET6; + } +#endif + + memset(&src_addr, 0, sizeof(src_addr)); +#ifdef IPV6 + memset(&src_addr6, 0, sizeof(src_addr6)); +#endif + + if (!suid && suid != getuid()) { + /* *temporarily* drop privileges */ + if (seteuid(getuid()) == -1) + perror("cannot setuid"); + } + + optparse_init(&optparse_state, argv); + ident4 = ident6 = htons(getpid() & 0xFFFF); + verbose_flag = 1; + backoff_flag = 1; + opterr = 1; + + /* get command line options */ + + struct optparse_long longopts[] = { + { "ipv4", '4', OPTPARSE_NONE }, + { "ipv6", '6', OPTPARSE_NONE }, + { "alive", 'a', OPTPARSE_NONE }, + { "addr", 'A', OPTPARSE_NONE }, + { "size", 'b', OPTPARSE_REQUIRED }, + { "backoff", 'B', OPTPARSE_REQUIRED }, + { "count", 'c', OPTPARSE_REQUIRED }, + { "vcount", 'C', OPTPARSE_REQUIRED }, + { "rdns", 'd', OPTPARSE_NONE }, + { "timestamp", 'D', OPTPARSE_NONE }, + { "timestamp-format", '0', OPTPARSE_REQUIRED }, + { "elapsed", 'e', OPTPARSE_NONE }, + { "file", 'f', OPTPARSE_REQUIRED }, + { "generate", 'g', OPTPARSE_NONE }, + { "help", 'h', OPTPARSE_NONE }, + { "ttl", 'H', OPTPARSE_REQUIRED }, + { "interval", 'i', OPTPARSE_REQUIRED }, + { "iface", 'I', OPTPARSE_REQUIRED }, + { "icmp-timestamp", '0', OPTPARSE_NONE }, +#ifdef SO_MARK + { "fwmark", 'k', OPTPARSE_REQUIRED }, +#endif + { "loop", 'l', OPTPARSE_NONE }, + { "all", 'm', OPTPARSE_NONE }, + { "dontfrag", 'M', OPTPARSE_NONE }, + { "name", 'n', OPTPARSE_NONE }, + { "netdata", 'N', OPTPARSE_NONE }, + { "outage", 'o', OPTPARSE_NONE }, + { "tos", 'O', OPTPARSE_REQUIRED }, + { "period", 'p', OPTPARSE_REQUIRED }, + { "quiet", 'q', OPTPARSE_NONE }, + { "squiet", 'Q', OPTPARSE_REQUIRED }, + { "retry", 'r', OPTPARSE_REQUIRED }, + { "random", 'R', OPTPARSE_NONE }, + { "stats", 's', OPTPARSE_NONE }, + { "src", 'S', OPTPARSE_REQUIRED }, + { "timeout", 't', OPTPARSE_REQUIRED }, + { NULL, 'T', OPTPARSE_REQUIRED }, + { "unreach", 'u', OPTPARSE_NONE }, + { "version", 'v', OPTPARSE_NONE }, + { "reachable", 'x', OPTPARSE_REQUIRED }, + { "fast-reachable", 'X', OPTPARSE_REQUIRED }, + { "check-source", '0', OPTPARSE_NONE }, + { "print-tos", '0', OPTPARSE_NONE }, + { "print-ttl", '0', OPTPARSE_NONE }, +#if defined(DEBUG) || defined(_DEBUG) + { NULL, 'z', OPTPARSE_REQUIRED }, +#endif + { 0, 0, 0 } + }; + + float opt_value_float; + while ((c = optparse_long(&optparse_state, longopts, NULL)) != EOF) { + switch (c) { + case '0': + if(strstr(optparse_state.optlongname, "timestamp-format") != NULL) { + if(strcmp(optparse_state.optarg, "ctime") == 0) { + timestamp_format_flag = 1; + }else if(strcmp(optparse_state.optarg, "iso") == 0) { + timestamp_format_flag = 2; + }else if(strcmp(optparse_state.optarg, "rfc3339") == 0) { + timestamp_format_flag = 3; + }else{ + usage(1); + } + } else if (strstr(optparse_state.optlongname, "check-source") != NULL) { + check_source_flag = 1; + } else if (strstr(optparse_state.optlongname, "icmp-timestamp") != NULL) { +#ifdef IPV6 + if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) { + fprintf(stderr, "%s: ICMP Timestamp is IPv4 only\n", prog); + exit(1); + } + hints_ai_family = AF_INET; +#endif + icmp_request_typ = 13; + ping_data_size = ICMP_TIMESTAMP_DATA_SIZE; + } else if (strstr(optparse_state.optlongname, "print-tos") != NULL) { + print_tos_flag = 1; + } else if (strstr(optparse_state.optlongname, "print-ttl") != NULL) { + print_ttl_flag = 1; + } else { + usage(1); + } + break; + case '4': +#ifdef IPV6 + if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) { + fprintf(stderr, "%s: can't specify both -4 and -6\n", prog); + exit(1); + } + hints_ai_family = AF_INET; +#endif + break; + case '6': +#ifdef IPV6 + if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET6) { + fprintf(stderr, "%s: can't specify both -4 and -6\n", prog); + exit(1); + } + hints_ai_family = AF_INET6; +#else + fprintf(stderr, "%s: IPv6 not supported by this binary\n", prog); + exit(1); +#endif + break; + case 'M': +#ifdef IP_MTU_DISCOVER + if (socket4 >= 0) { + int val = IP_PMTUDISC_DO; + if (setsockopt(socket4, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val))) { + perror("setsockopt IP_MTU_DISCOVER"); + } + } +#ifdef IPV6 + if (socket6 >= 0) { + int val = IPV6_PMTUDISC_DO; + if (setsockopt(socket6, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val, sizeof(val))) { + perror("setsockopt IPV6_MTU_DISCOVER"); + } + } +#endif +#else + fprintf(stderr, "%s, -M option not supported on this platform\n", prog); + exit(1); +#endif + break; + + case 't': + if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1) + usage(1); + if (opt_value_float < 0) { + usage(1); + } + timeout = opt_value_float * 1000000; + timeout_flag = 1; + break; + + case 'r': + if (sscanf(optparse_state.optarg, "%u", &retry) != 1) + usage(1); + break; + + case 'i': + if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1) + usage(1); + if (opt_value_float < 0) { + usage(1); + } + interval = opt_value_float * 1000000; + break; + + case 'p': + if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1) + usage(1); + if (opt_value_float < 0) { + usage(1); + } + perhost_interval = opt_value_float * 1000000; + + break; + + case 'c': + if (!(count = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + + count_flag = 1; + break; + + case 'C': + if (!(count = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + + count_flag = 1; + report_all_rtts_flag = 1; + break; + + case 'b': + if (sscanf(optparse_state.optarg, "%u", &ping_data_size) != 1) + usage(1); + size_flag = 1; + break; + + case 'h': + usage(0); + break; + + case 'q': + verbose_flag = 0; + quiet_flag = 1; + break; + + case 'Q': + verbose_flag = 0; + quiet_flag = 1; + if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1) + usage(1); + if (opt_value_float < 0) { + usage(1); + } + report_interval = opt_value_float * 1e9; + + /* recognize keyword(s) after number, ignore everything else */ + { + char *comma = strchr(optparse_state.optarg, ','); + if ((comma != NULL) && (strcmp(++comma, "cumulative") == 0)) { + cumulative_stats_flag = 1; + } + } + + break; + + case 'e': + elapsed_flag = 1; + break; + + case 'm': + multif_flag = 1; + break; + + case 'N': + netdata_flag = 1; + break; + + case 'n': + name_flag = 1; + if (rdns_flag) { + fprintf(stderr, "%s: use either one of -d or -n\n", prog); + exit(1); + } + break; + + case 'd': + rdns_flag = 1; + if (name_flag) { + fprintf(stderr, "%s: use either one of -d or -n\n", prog); + exit(1); + } + break; + + case 'A': + addr_flag = 1; + break; + + case 'B': + if (!(backoff = atof(optparse_state.optarg))) + usage(1); + + break; + + case 's': + stats_flag = 1; + break; + + case 'D': + timestamp_flag = 1; + break; + + case 'R': + random_data_flag = 1; + break; + + case 'l': + loop_flag = 1; + backoff_flag = 0; + break; + + case 'u': + unreachable_flag = 1; + break; + + case 'a': + alive_flag = 1; + break; + + case 'H': + if (!(ttl = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + break; + +#if defined(DEBUG) || defined(_DEBUG) + case 'z': + if (sscanf(optparse_state.optarg, "0x%x", &debugging) != 1) + if (sscanf(optparse_state.optarg, "%u", &debugging) != 1) + usage(1); + + break; +#endif /* DEBUG || _DEBUG */ + + case 'v': + printf("%s: Version %s\n", prog, VERSION); + exit(0); + + case 'x': + if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + break; + + case 'X': + if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg))) + usage(1); + fast_reachable = 1; + break; + + case 'f': + filename = optparse_state.optarg; + break; +#ifdef SO_MARK + case 'k': + if (!(fwmark = (unsigned int)atol(optparse_state.optarg))) + usage(1); + + if (socket4 >= 0) + if(-1 == p_setsockopt(suid, socket4, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark)) + perror("fwmark ipv4"); + +#ifdef IPV6 + if (socket6 >= 0) + if(-1 == p_setsockopt(suid, socket6, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark)) + perror("fwmark ipv6"); +#endif + + break; +#endif + + case 'g': + /* use IP list generation */ + /* mutually exclusive with using file input or command line targets */ + generate_flag = 1; + break; + + case 'S': + if (inet_pton(AF_INET, optparse_state.optarg, &src_addr)) { + src_addr_set = 1; + break; + } +#ifdef IPV6 + if (inet_pton(AF_INET6, optparse_state.optarg, &src_addr6)) { + src_addr6_set = 1; + break; + } +#endif + fprintf(stderr, "%s: can't parse source address: %s\n", prog, optparse_state.optarg); + exit(1); + + case 'I': +#ifdef SO_BINDTODEVICE + if (socket4 >= 0) { + if (p_setsockopt(suid, socket4, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) { + perror("binding to specific interface (SO_BINTODEVICE)"); + exit(1); + } + } +#ifdef IPV6 + if (socket6 >= 0) { + if (p_setsockopt(suid, socket6, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) { + perror("binding to specific interface (SO_BINTODEVICE), IPV6"); + exit(1); + } + } +#endif +#else + printf("%s: cant bind to a particular net interface since SO_BINDTODEVICE is not supported on your os.\n", prog); + exit(3); + ; +#endif + break; + + case 'T': + /* This option is ignored for compatibility reasons ("select timeout" is not meaningful anymore) */ + break; + + case 'O': + if (sscanf(optparse_state.optarg, "%i", &tos) == 1) { + if (socket4 >= 0) { + if (setsockopt(socket4, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) { + perror("setting type of service octet IP_TOS"); + } + } +#if defined(IPV6) && defined(IPV6_TCLASS) + if (socket6 >= 0) { + if (setsockopt(socket6, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos))) { + perror("setting type of service octet IPV6_TCLASS"); + } + } +#endif + } + else { + usage(1); + } + break; + + case 'o': + outage_flag = 1; + break; + + case '?': + fprintf(stderr, "%s: %s\n", argv[0], optparse_state.errmsg); + fprintf(stderr, "see 'fping -h' for usage information\n"); + exit(1); + break; + } + } + + /* permanently drop privileges */ + if (suid != getuid() && setuid(getuid())) { + perror("fatal: failed to permanently drop privileges"); + /* continuing would be a security hole */ + exit(4); + } + + /* validate various option settings */ + +#ifndef IPV6 + if (socket4 < 0) { + crash_and_burn("can't create socket (must run as root?)"); + } +#else + if ((socket4 < 0 && socket6 < 0) || (hints_ai_family == AF_INET6 && socket6 < 0)) { + crash_and_burn("can't create socket (must run as root?)"); + } +#endif + + if (ttl > 255) { + fprintf(stderr, "%s: ttl %u out of range\n", prog, ttl); + exit(1); + } + + if (unreachable_flag && alive_flag) { + fprintf(stderr, "%s: specify only one of a, u\n", prog); + exit(1); + } + + if (count_flag && loop_flag) { + fprintf(stderr, "%s: specify only one of c, l\n", prog); + exit(1); + } + + if (interval < (float)MIN_INTERVAL_MS * 1000000 && getuid()) { + fprintf(stderr, "%s: -i must be >= %g\n", prog, (float)MIN_INTERVAL_MS); + exit(1); + } + + if (perhost_interval < (float)MIN_PERHOST_INTERVAL_MS * 1000000 && getuid()) { + fprintf(stderr, "%s: -p must be >= %g\n", prog, (float)MIN_PERHOST_INTERVAL_MS); + exit(1); + } + + if (ping_data_size > MAX_PING_DATA) { + fprintf(stderr, "%s: data size %u not valid, must not be larger than %u\n", + prog, ping_data_size, (unsigned int)MAX_PING_DATA); + exit(1); + } + + if ((backoff > MAX_BACKOFF_FACTOR) || (backoff < MIN_BACKOFF_FACTOR)) { + fprintf(stderr, "%s: backoff factor %.1f not valid, must be between %.1f and %.1f\n", + prog, backoff, MIN_BACKOFF_FACTOR, MAX_BACKOFF_FACTOR); + exit(1); + } + + if (icmp_request_typ == 13 && size_flag != 0) { + fprintf(stderr, "%s: cannot change ICMP Timestamp size\n", prog); + exit(1); + } + + if (count_flag) { + if (verbose_flag) + per_recv_flag = 1; + + alive_flag = unreachable_flag = verbose_flag = 0; + } + + if (loop_flag) { + if (!report_interval) + per_recv_flag = 1; + + alive_flag = unreachable_flag = verbose_flag = 0; + } + + if (alive_flag || unreachable_flag || min_reachable) + verbose_flag = 0; + + trials = (count > retry + 1) ? count : retry + 1; + + /* auto-tune default timeout for count/loop modes + * see also github #32 */ + if (loop_flag || count_flag) { + if (!timeout_flag) { + timeout = perhost_interval; + if (timeout > (int64_t)AUTOTUNE_TIMEOUT_MAX * 1000000) { + timeout = (int64_t)AUTOTUNE_TIMEOUT_MAX * 1000000; + } + } + } + +#if defined(DEBUG) || defined(_DEBUG) + if (debugging & DBG_TRACE) + trace_flag = 1; + + if (debugging & DBG_RANDOM_LOSE_FEW) { + randomly_lose_flag = 1; + lose_factor = 1; /* ie, 1/4 */ + } + + if (debugging & DBG_RANDOM_LOSE_MANY) { + randomly_lose_flag = 1; + lose_factor = 5; /* ie, 3/4 */ + } + + if (debugging & DBG_PRINT_PER_SYSTEM) + print_per_system_flag = 1; + + if ((debugging & DBG_REPORT_ALL_RTTS) && !loop_flag) + report_all_rtts_flag = 1; + + if (trace_flag) { + fprintf(stderr, "%s:\n count: %u, retry: %u, interval: %.0f ms\n", + prog, count, retry, interval / 1e6); + fprintf(stderr, " perhost_interval: %.0f ms, timeout: %.0f\n", + perhost_interval / 1e6, timeout / 1e6); + fprintf(stderr, " ping_data_size = %u, trials = %u\n", + ping_data_size, trials); + + if (verbose_flag) + fprintf(stderr, " verbose_flag set\n"); + if (multif_flag) + fprintf(stderr, " multif_flag set\n"); + if (name_flag) + fprintf(stderr, " name_flag set\n"); + if (addr_flag) + fprintf(stderr, " addr_flag set\n"); + if (stats_flag) + fprintf(stderr, " stats_flag set\n"); + if (unreachable_flag) + fprintf(stderr, " unreachable_flag set\n"); + if (alive_flag) + fprintf(stderr, " alive_flag set\n"); + if (elapsed_flag) + fprintf(stderr, " elapsed_flag set\n"); + if (version_flag) + fprintf(stderr, " version_flag set\n"); + if (count_flag) + fprintf(stderr, " count_flag set\n"); + if (loop_flag) + fprintf(stderr, " loop_flag set\n"); + if (backoff_flag) + fprintf(stderr, " backoff_flag set\n"); + if (per_recv_flag) + fprintf(stderr, " per_recv_flag set\n"); + if (report_all_rtts_flag) + fprintf(stderr, " report_all_rtts_flag set\n"); + if (randomly_lose_flag) + fprintf(stderr, " randomly_lose_flag set\n"); + if (print_per_system_flag) + fprintf(stderr, " print_per_system_flag set\n"); + if (outage_flag) + fprintf(stderr, " outage_flag set\n"); + if (netdata_flag) + fprintf(stderr, " netdata_flag set\n"); + } +#endif /* DEBUG || _DEBUG */ + + /* set the TTL, if the -H option was set (otherwise ttl will be = 0) */ + if (ttl > 0) { + if (socket4 >= 0) { + if (setsockopt(socket4, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) { + perror("setting time to live"); + } + } +#ifdef IPV6 + if (socket6 >= 0) { + if (setsockopt(socket6, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))) { + perror("setting time to live"); + } + } +#endif + } + +#if HAVE_SO_TIMESTAMPNS + { + int opt = 1; + if (socket4 >= 0) { + if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) { + if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) { + perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option"); + } + } + } +#ifdef IPV6 + if (socket6 >= 0) { + if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) { + if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) { + perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option (IPv6)"); + } + } + } +#endif + } +#endif + + update_current_time(); + start_time = current_time_ns; + + /* handle host names supplied on command line or in a file */ + /* if the generate_flag is on, then generate the IP list */ + + argv = &argv[optparse_state.optind]; + argc -= optparse_state.optind; + + /* calculate how many ping can be in-flight per host */ + if (count_flag) { + event_storage_count = count; + } + else if (loop_flag) { + if (perhost_interval > timeout) { + event_storage_count = 1; + } + else { + event_storage_count = 1 + timeout / perhost_interval; + } + } + else { + event_storage_count = 1; + } + + /* file and generate are mutually exclusive */ + /* file and command line are mutually exclusive */ + /* generate requires command line parameters beyond the switches */ + if ((*argv && filename) || (filename && generate_flag) || (generate_flag && !*argv)) + usage(1); + + /* if no conditions are specified, then assume input from stdin */ + if (!*argv && !filename && !generate_flag) + filename = "-"; + + if (*argv && !generate_flag) { + while (*argv) { + add_name(*argv); + ++argv; + } + } + else if (filename) { + FILE *ping_file; + char line[132]; + char host[132]; + + if (strcmp(filename, "-") == 0) + ping_file = fdopen(0, "r"); + else + ping_file = fopen(filename, "r"); + + if (!ping_file) + errno_crash_and_burn("fopen"); + + while (fgets(line, sizeof(line), ping_file)) { + if (sscanf(line, "%s", host) != 1) + continue; + + if ((!*host) || (host[0] == '#')) /* magic to avoid comments */ + continue; + + add_name(host); + } + + fclose(ping_file); + } + else if (*argv && generate_flag) { + if (argc == 1) { + /* one target: we expect a cidr range (n.n.n.n/m) */ + add_cidr(argv[0]); + } + else if (argc == 2) { + add_range(argv[0], argv[1]); + } + else { + usage(1); + } + } + else { + usage(1); + } + + if (!num_hosts) { + exit(num_noaddress ? 2 : 1); + } + + if (socket4 >= 0 && (src_addr_set || socktype4 == SOCK_DGRAM)) { + socket_set_src_addr_ipv4(socket4, &src_addr, (socktype4 == SOCK_DGRAM) ? &ident4 : NULL); + } +#ifdef IPV6 + if (socket6 >= 0 && (src_addr6_set || socktype6 == SOCK_DGRAM)) { + socket_set_src_addr_ipv6(socket6, &src_addr6, (socktype6 == SOCK_DGRAM) ? &ident6 : NULL); + } +#endif + + /* allocate and initialize array to map host nr to host_entry */ + { + struct event *cursor = event_queue_ping.first; + int i = 0; + table = (HOST_ENTRY **)calloc(num_hosts, sizeof(HOST_ENTRY *)); + if (!table) + crash_and_burn("Can't malloc array of hosts"); + /* initialize table of hosts. we know that we have ping events scheduled + * for each of them */ + for (cursor = event_queue_ping.first; cursor; cursor = cursor->ev_next) { + table[i] = cursor->host; + cursor->host->i = i; + i++; + } + } + + init_ping_buffer_ipv4(ping_data_size); +#ifdef IPV6 + init_ping_buffer_ipv6(ping_data_size); +#endif + +#ifdef USE_SIGACTION + memset(&act, 0, sizeof(act)); + act.sa_handler = signal_handler; + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask, SIGINT); + sigaddset(&act.sa_mask, SIGQUIT); + act.sa_flags = SA_RESTART; + if (sigaction(SIGQUIT, &act, NULL) || sigaction(SIGINT, &act, NULL)) { + crash_and_burn("failure to set signal handler"); + } +#else + signal(SIGINT, signal_handler); + signal(SIGQUIT, signal_handler); +#endif + setlinebuf(stdout); + + if (report_interval) { + next_report_time = current_time_ns + report_interval; + } + + last_send_time = 0; + + seqmap_init(); + + /* main loop */ + main_loop(); + +/* Debug: CPU Performance */ +#if defined(DEBUG) || defined(_DEBUG) + perf_cpu_end = clock(); + perf_cpu_time_used = ((double) (perf_cpu_end - perf_cpu_start)) / CLOCKS_PER_SEC; + printf("[DEBUG] CPU time used: %f sec", perf_cpu_time_used); +#endif /* DEBUG || _DEBUG */ + + finish(); + + return 0; +} + +static inline int64_t timespec_ns(struct timespec *a) +{ + return ((int64_t)a->tv_sec * 1000000000) + a->tv_nsec; +} + +void add_cidr(char *addr) +{ + char *addr_end; + char *mask_str; + unsigned long mask; + unsigned long bitmask; + int ret; + struct addrinfo addr_hints; + struct addrinfo *addr_res; + unsigned long net_addr; + unsigned long net_last; + + /* Split address from mask */ + addr_end = strchr(addr, '/'); + if (addr_end == NULL) { + usage(1); + } + *addr_end = '\0'; + mask_str = addr_end + 1; + mask = atoi(mask_str); + + /* parse address (IPv4 only) */ + memset(&addr_hints, 0, sizeof(struct addrinfo)); + addr_hints.ai_family = AF_UNSPEC; + addr_hints.ai_flags = AI_NUMERICHOST; + ret = getaddrinfo(addr, NULL, &addr_hints, &addr_res); + if (ret) { + fprintf(stderr, "%s, can't parse address %s: %s\n", prog, addr, gai_strerror(ret)); + exit(1); + } + if (addr_res->ai_family != AF_INET) { + fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog); + exit(1); + } + net_addr = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); + freeaddrinfo(addr_res); + + /* check mask */ + if (mask < 1 || mask > 32) { + fprintf(stderr, "%s: netmask must be between 1 and 32 (is: %s)\n", prog, mask_str); + exit(1); + } + + /* convert mask integer from 1 to 32 to a bitmask */ + bitmask = ((unsigned long)0xFFFFFFFF) << (32 - mask); + + /* calculate network range */ + net_addr &= bitmask; + net_last = net_addr + ((unsigned long)0x1 << (32 - mask)) - 1; + + /* exclude network and broadcast address for regular prefixes */ + if (mask < 31) { + net_last--; + net_addr++; + } + + /* add all hosts in that network (net_addr and net_last inclusive) */ + add_addr_range_ipv4(net_addr, net_last); +} + +void add_range(char *start, char *end) +{ + struct addrinfo addr_hints; + struct addrinfo *addr_res; + unsigned long start_long; + unsigned long end_long; + int ret; + + /* parse start address (IPv4 only) */ + memset(&addr_hints, 0, sizeof(struct addrinfo)); + addr_hints.ai_family = AF_UNSPEC; + addr_hints.ai_flags = AI_NUMERICHOST; + ret = getaddrinfo(start, NULL, &addr_hints, &addr_res); + if (ret) { + fprintf(stderr, "%s: can't parse address %s: %s\n", prog, start, gai_strerror(ret)); + exit(1); + } + if (addr_res->ai_family != AF_INET) { + freeaddrinfo(addr_res); + fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog); + exit(1); + } + start_long = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); + + /* parse end address (IPv4 only) */ + memset(&addr_hints, 0, sizeof(struct addrinfo)); + addr_hints.ai_family = AF_UNSPEC; + addr_hints.ai_flags = AI_NUMERICHOST; + ret = getaddrinfo(end, NULL, &addr_hints, &addr_res); + if (ret) { + fprintf(stderr, "%s: can't parse address %s: %s\n", prog, end, gai_strerror(ret)); + exit(1); + } + if (addr_res->ai_family != AF_INET) { + freeaddrinfo(addr_res); + fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog); + exit(1); + } + end_long = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); + freeaddrinfo(addr_res); + + /* add IPv4 addresses from closed interval [start_long,end_long] */ + add_addr_range_ipv4(start_long, end_long); +} + +void add_addr_range_ipv4(unsigned long start_long, unsigned long end_long) +{ + /* check if generator limit is exceeded */ + if (end_long >= start_long + MAX_GENERATE) { + fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog); + exit(1); + } + + /* generate */ + for (; start_long <= end_long; start_long++) { + struct in_addr in_addr_tmp; + char buffer[20]; + in_addr_tmp.s_addr = htonl(start_long); + inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer)); + add_name(buffer); + } +} + +void main_loop() +{ + int64_t lt; + int64_t wait_time_ns; + struct event *event; + struct host_entry *h; + + while (event_queue_ping.first || event_queue_timeout.first) { + dbg_printf("%s", "# main_loop\n"); + + /* timeout event ? */ + if (event_queue_timeout.first && event_queue_timeout.first->ev_time - current_time_ns <= 0) { + event = ev_dequeue(&event_queue_timeout); + h = event->host; + + dbg_printf("%s [%d]: timeout event\n", h->host, event->ping_index); + + stats_add(h, event->ping_index, 0, -1); + + if (per_recv_flag) { + if (timestamp_flag) { + print_timestamp_format(current_time_ns, timestamp_format_flag); + } + printf("%-*s : [%d], timed out", + max_hostname_len, h->host, event->ping_index); + if (h->num_recv > 0) { + printf(" (%s avg, ", sprint_tm(h->total_time / h->num_recv)); + } + else { + printf(" (NaN avg, "); + } + if (h->num_recv <= h->num_sent) { + printf("%d%% loss)", + ((h->num_sent - h->num_recv) * 100) / h->num_sent); + } + else { + printf("%d%% return)", + (h->num_recv_total * 100) / h->num_sent); + } + printf("\n"); + } + + /* do we need to send a retry? */ + if (!loop_flag && !count_flag) { + if (h->num_sent < retry + 1) { + if (backoff_flag) { + h->timeout *= backoff; + } + send_ping(h, event->ping_index); + } + } + + /* note: we process first timeout events, because we might need to + * wait to process ping events, while we for sure never need to + * wait for timeout events. + */ + continue; + } + + /* ping event ? */ + if (event_queue_ping.first && event_queue_ping.first->ev_time - current_time_ns <= 0) { + /* Make sure that we don't ping more than once every "interval" */ + lt = current_time_ns - last_send_time; + if (lt < interval) + goto wait_for_reply; + + /* Dequeue the event */ + event = ev_dequeue(&event_queue_ping); + h = event->host; + + dbg_printf("%s [%d]: ping event\n", h->host, event->ping_index); + + /* Send the ping */ + send_ping(h, event->ping_index); + + /* Loop and count mode: schedule next ping */ + if (loop_flag || (count_flag && event->ping_index + 1 < count)) { + host_add_ping_event(h, event->ping_index + 1, event->ev_time + perhost_interval); + } + } + + wait_for_reply: + + /* When is the next ping next event? */ + wait_time_ns = -1; + if (event_queue_ping.first) { + wait_time_ns = event_queue_ping.first->ev_time - current_time_ns; + if (wait_time_ns < 0) + wait_time_ns = 0; + /* make sure that we wait enough, so that the inter-ping delay is + * bigger than 'interval' */ + if (wait_time_ns < interval) { + lt = current_time_ns - last_send_time; + if (lt < interval) { + wait_time_ns = interval - lt; + } + } + + dbg_printf("next ping event in %.0f ms (%s)\n", wait_time_ns / 1e6, event_queue_ping.first->host->host); + } + + /* When is the next timeout event? */ + if (event_queue_timeout.first) { + int64_t wait_time_timeout = event_queue_timeout.first->ev_time - current_time_ns; + if (wait_time_ns < 0 || wait_time_timeout < wait_time_ns) { + wait_time_ns = wait_time_timeout; + if (wait_time_ns < 0) { + wait_time_ns = 0; + } + } + + dbg_printf("next timeout event in %.0f ms (%s)\n", wait_time_timeout / 1e6, event_queue_timeout.first->host->host); + } + + /* When is the next report due? */ + if (report_interval && (loop_flag || count_flag)) { + int64_t wait_time_next_report = next_report_time - current_time_ns; + if (wait_time_next_report < wait_time_ns) { + wait_time_ns = wait_time_next_report; + if (wait_time_ns < 0) { + wait_time_ns = 0; + } + } + + dbg_printf("next report event in %0.f ms\n", wait_time_next_report / 1e6); + } + + /* if wait_time is still -1, it means that we are waiting for nothing... */ + if (wait_time_ns == -1) { + break; + } + + /* end of loop was requested by interrupt signal handler */ + if (finish_requested) { + break; + } + + /* Receive replies */ + /* (this is what sleeps during each loop iteration) */ + dbg_printf("waiting up to %.0f ms\n", wait_time_ns / 1e6); + if (wait_for_reply(wait_time_ns)) { + while (wait_for_reply(0)) + ; /* process other replies in the queue */ + } + + update_current_time(); + + if (status_snapshot) { + status_snapshot = 0; + print_per_system_splits(); + } + + /* Print report */ + if (report_interval && (loop_flag || count_flag) && (current_time_ns >= next_report_time)) { + if (netdata_flag) + print_netdata(); + else + print_per_system_splits(); + + while (current_time_ns >= next_report_time) { + next_report_time += report_interval; + } + } + } +} + +/************************************************************ + + Function: signal_handler + +************************************************************* + + Inputs: int signum + + Description: + + SIGQUIT signal handler - set flag and return + SIGINT signal handler - set flag and return + +************************************************************/ + +void signal_handler(int signum) +{ + switch (signum) { + case SIGINT: + finish_requested = 1; + break; + + case SIGQUIT: + status_snapshot = 1; + break; + } +} + +/************************************************************ + + Function: update_current_time + +*************************************************************/ + +void update_current_time() +{ + clock_gettime(CLOCKID, ¤t_time); + current_time_ns = timespec_ns(¤t_time); +} + +/************************************************************ + + Function: finish + +************************************************************* + + Inputs: void (none) + + Description: + + Main program clean up and exit point + +************************************************************/ + +void finish() +{ + int i; + HOST_ENTRY *h; + + update_current_time(); + end_time = current_time_ns; + + /* tot up unreachables */ + for (i = 0; i < num_hosts; i++) { + h = table[i]; + + if (!h->num_recv) { + num_unreachable++; + + if (verbose_flag || unreachable_flag) { + printf("%s", h->host); + + if (verbose_flag) + printf(" is unreachable"); + + printf("\n"); + } + } + } + + if (count_flag || loop_flag) + print_per_system_stats(); +#if defined(DEBUG) || defined(_DEBUG) + else if (print_per_system_flag) + print_per_system_stats(); +#endif /* DEBUG || _DEBUG */ + + if (stats_flag) + print_global_stats(); + + if (min_reachable) { + if ((num_hosts - num_unreachable) >= min_reachable) { + printf("Enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts - num_unreachable); + exit(0); + } + else { + printf("Not enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts - num_unreachable); + exit(1); + } + } + + if (num_noaddress) + exit(2); + else if (num_alive != num_hosts) + exit(1); + + exit(0); +} + +/************************************************************ + + Function: print_per_system_stats + +************************************************************* + + Inputs: void (none) + + Description: + + +************************************************************/ + +void print_per_system_stats(void) +{ + int i, j, avg, outage_ms; + HOST_ENTRY *h; + int64_t resp; + + if (verbose_flag || per_recv_flag) + fprintf(stderr, "\n"); + + for (i = 0; i < num_hosts; i++) { + h = table[i]; + fprintf(stderr, "%-*s :", max_hostname_len, h->host); + + if (report_all_rtts_flag) { + for (j = 0; j < h->num_sent; j++) { + if ((resp = h->resp_times[j]) >= 0) + fprintf(stderr, " %s", sprint_tm(resp)); + else + fprintf(stderr, " -"); + } + + fprintf(stderr, "\n"); + } + else { + if (h->num_recv <= h->num_sent) { + fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%", + h->num_sent, h->num_recv, h->num_sent > 0 ? ((h->num_sent - h->num_recv) * 100) / h->num_sent : 0); + + if (outage_flag) { + /* Time outage total */ + outage_ms = (h->num_sent - h->num_recv) * perhost_interval / 1e6; + fprintf(stderr, ", outage(ms) = %d", outage_ms); + } + } + else { + fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%", + h->num_sent, h->num_recv, + h->num_sent > 0 ? ((h->num_recv * 100) / h->num_sent) : 0); + } + + if (h->num_recv) { + avg = h->total_time / h->num_recv; + fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply)); + fprintf(stderr, "/%s", sprint_tm(avg)); + fprintf(stderr, "/%s", sprint_tm(h->max_reply)); + } + + fprintf(stderr, "\n"); + } + } +} + +/************************************************************ + + Function: print_netdata + +************************************************************* + + Inputs: void (none) + + Description: + + +************************************************************/ + +void print_netdata(void) +{ + static int sent_charts = 0; + + int i; + int64_t avg; + HOST_ENTRY *h; + + for (i = 0; i < num_hosts; i++) { + h = table[i]; + + if (!sent_charts) { + printf("CHART fping.%s_packets '' 'FPing Packets' packets '%s' fping.packets line 110020 %.0f\n", h->name, h->host, report_interval / 1e9); + printf("DIMENSION xmt sent absolute 1 1\n"); + printf("DIMENSION rcv received absolute 1 1\n"); + } + + printf("BEGIN fping.%s_packets\n", h->name); + printf("SET xmt = %d\n", h->num_sent_i); + printf("SET rcv = %d\n", h->num_recv_i); + printf("END\n"); + + if (!sent_charts) { + printf("CHART fping.%s_quality '' 'FPing Quality' percentage '%s' fping.quality area 110010 %.0f\n", h->name, h->host, report_interval / 1e9); + printf("DIMENSION returned '' absolute 1 1\n"); + /* printf("DIMENSION lost '' absolute 1 1\n"); */ + } + + printf("BEGIN fping.%s_quality\n", h->name); + /* + if( h->num_recv_i <= h->num_sent_i ) + printf("SET lost = %d\n", h->num_sent_i > 0 ? ( ( h->num_sent_i - h->num_recv_i ) * 100 ) / h->num_sent_i : 0 ); + else + printf("SET lost = 0\n"); +*/ + + printf("SET returned = %d\n", h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0); + printf("END\n"); + + if (!sent_charts) { + printf("CHART fping.%s_latency '' 'FPing Latency' ms '%s' fping.latency area 110000 %.0f\n", h->name, h->host, report_interval / 1e9); + printf("DIMENSION min minimum absolute 1 1000000\n"); + printf("DIMENSION max maximum absolute 1 1000000\n"); + printf("DIMENSION avg average absolute 1 1000000\n"); + } + + printf("BEGIN fping.%s_latency\n", h->name); + if (h->num_recv_i) { + avg = h->total_time_i / h->num_recv_i; + printf("SET min = %" PRId64 "\n", h->min_reply_i); + printf("SET avg = %" PRId64 "\n", avg); + printf("SET max = %" PRId64 "\n", h->max_reply_i); + } + printf("END\n"); + + stats_reset_interval(h); + } + + sent_charts = 1; +} + +/************************************************************ + + Function: print_per_system_splits + +************************************************************* + + Inputs: void (none) + + Description: + + +************************************************************/ + +void print_per_system_splits(void) +{ + int i, avg, outage_ms_i; + HOST_ENTRY *h; + struct tm *curr_tm; + + if (verbose_flag || per_recv_flag) + fprintf(stderr, "\n"); + + update_current_time(); + curr_tm = localtime((time_t *)¤t_time.tv_sec); + fprintf(stderr, "[%2.2d:%2.2d:%2.2d]\n", curr_tm->tm_hour, + curr_tm->tm_min, curr_tm->tm_sec); + + for (i = 0; i < num_hosts; i++) { + h = table[i]; + fprintf(stderr, "%-*s :", max_hostname_len, h->host); + + if (h->num_recv_i <= h->num_sent_i) { + fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%", + h->num_sent_i, h->num_recv_i, h->num_sent_i > 0 ? ((h->num_sent_i - h->num_recv_i) * 100) / h->num_sent_i : 0); + + if (outage_flag) { + /* Time outage */ + outage_ms_i = (h->num_sent_i - h->num_recv_i) * perhost_interval / 1e6; + fprintf(stderr, ", outage(ms) = %d", outage_ms_i); + } + } + else { + fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%", + h->num_sent_i, h->num_recv_i, h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0); + } + + if (h->num_recv_i) { + avg = h->total_time_i / h->num_recv_i; + fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply_i)); + fprintf(stderr, "/%s", sprint_tm(avg)); + fprintf(stderr, "/%s", sprint_tm(h->max_reply_i)); + } + + fprintf(stderr, "\n"); + if (!cumulative_stats_flag) { + stats_reset_interval(h); + } + } +} + +/************************************************************ + + Function: print_global_stats + +************************************************************* + + Inputs: void (none) + + Description: + + +************************************************************/ + +void print_global_stats(void) +{ + fprintf(stderr, "\n"); + fprintf(stderr, " %7d targets\n", num_hosts); + fprintf(stderr, " %7d alive\n", num_alive); + fprintf(stderr, " %7d unreachable\n", num_unreachable); + fprintf(stderr, " %7d unknown addresses\n", num_noaddress); + fprintf(stderr, "\n"); + fprintf(stderr, " %7d timeouts (waiting for response)\n", num_timeout); + fprintf(stderr, " %7d ICMP Echos sent\n", num_pingsent); + fprintf(stderr, " %7d ICMP Echo Replies received\n", num_pingreceived); + fprintf(stderr, " %7d other ICMP received\n", num_othericmprcvd); + fprintf(stderr, "\n"); + + if (total_replies == 0) { + min_reply = 0; + max_reply = 0; + total_replies = 1; + sum_replies = 0; + } + + fprintf(stderr, " %s ms (min round trip time)\n", sprint_tm(min_reply)); + fprintf(stderr, " %s ms (avg round trip time)\n", + sprint_tm(sum_replies / total_replies)); + fprintf(stderr, " %s ms (max round trip time)\n", sprint_tm(max_reply)); + fprintf(stderr, " %12.3f sec (elapsed real time)\n", + (end_time - start_time) / 1e9); + fprintf(stderr, "\n"); +} + +/************************************************************ + + Function: send_ping + +************************************************************* + + Inputs: int s, HOST_ENTRY *h + + Description: + + Compose and transmit an ICMP_ECHO REQUEST packet. The IP packet + will be added on by the kernel. The ID field is our UNIX process ID, + and the sequence number is an index into an array of outstanding + ping requests. The sequence number will later be used to quickly + figure out who the ping reply came from. + +************************************************************/ + +int send_ping(HOST_ENTRY *h, int index) +{ + int n; + int myseq; + int ret = 1; + uint8_t proto = ICMP_ECHO; + + update_current_time(); + h->last_send_time = current_time_ns; + myseq = seqmap_add(h->i, index, current_time_ns); + + dbg_printf("%s [%d]: send ping\n", h->host, index); + + if (h->saddr.ss_family == AF_INET && socket4 >= 0) { + if(icmp_request_typ == 13) + proto = ICMP_TSTAMP; + n = socket_sendto_ping_ipv4(socket4, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident4, proto); + } +#ifdef IPV6 + else if (h->saddr.ss_family == AF_INET6 && socket6 >= 0) { + n = socket_sendto_ping_ipv6(socket6, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident6); + } +#endif + else { + return 0; + } + + /* error sending? */ + if ( + (n < 0) +#if defined(EHOSTDOWN) + && errno != EHOSTDOWN +#endif + ) { + if (verbose_flag) { + print_warning("%s: error while sending ping: %s\n", h->host, strerror(errno)); + } + else { + dbg_printf("%s: error while sending ping: %s\n", h->host, strerror(errno)); + } + + h->num_sent++; + h->num_sent_i++; + if (!loop_flag) + h->resp_times[index] = RESP_ERROR; + + ret = 0; + } + else { + /* schedule timeout */ + host_add_timeout_event(h, index, current_time_ns + h->timeout); + + /* mark this trial as outstanding */ + if (!loop_flag) { + h->resp_times[index] = RESP_WAITING; + } + } + + num_pingsent++; + last_send_time = h->last_send_time; + + return (ret); +} + +int socket_can_read(struct timeval *timeout) +{ + int nfound; + fd_set readset; + int socketmax; + +#ifndef IPV6 + socketmax = socket4; +#else + socketmax = socket4 > socket6 ? socket4 : socket6; +#endif + +select_again: + FD_ZERO(&readset); + if (socket4 >= 0) + FD_SET(socket4, &readset); +#ifdef IPV6 + if (socket6 >= 0) + FD_SET(socket6, &readset); +#endif + + nfound = select(socketmax + 1, &readset, NULL, NULL, timeout); + if (nfound < 0) { + if (errno == EINTR) { + /* interrupted system call: redo the select */ + goto select_again; + } + else { + perror("select"); + } + } + + if (nfound > 0) { + if (socket4 >= 0 && FD_ISSET(socket4, &readset)) { + return socket4; + } +#ifdef IPV6 + if (socket6 >= 0 && FD_ISSET(socket6, &readset)) { + return socket6; + } +#endif + } + + return -1; +} + +int receive_packet(int64_t wait_time, +#if HAVE_SO_TIMESTAMPNS + int64_t *reply_timestamp, +#else + int64_t *reply_timestamp __attribute__((unused)), +#endif + struct sockaddr *reply_src_addr, + size_t reply_src_addr_len, + char *reply_buf, + size_t reply_buf_len) +{ + struct timeval to; + int s = 0; + int recv_len; + static unsigned char msg_control[40]; + struct iovec msg_iov = { + reply_buf, + reply_buf_len + }; + struct msghdr recv_msghdr = {0}; + recv_msghdr.msg_name = reply_src_addr; + recv_msghdr.msg_namelen = reply_src_addr_len; + recv_msghdr.msg_iov = &msg_iov; + recv_msghdr.msg_iovlen = 1; + recv_msghdr.msg_control = &msg_control; + recv_msghdr.msg_controllen = sizeof(msg_control); +#if HAVE_SO_TIMESTAMPNS + struct cmsghdr *cmsg; +#endif + + /* Wait for a socket to become ready */ + if (wait_time) { + to.tv_sec = wait_time / UINT64_C(1000000000); + to.tv_usec = (wait_time % UINT64_C(1000000000)) / 1000 + 1; + } + else { + to.tv_sec = 0; + to.tv_usec = 0; + } + s = socket_can_read(&to); + if (s == -1) { + return 0; /* timeout */ + } + + recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC); + if (recv_len <= 0) { + return 0; + } + +#if HAVE_SO_TIMESTAMPNS + /* ancilliary data */ + { + struct timespec reply_timestamp_ts; + for (cmsg = CMSG_FIRSTHDR(&recv_msghdr); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPNS) { + memcpy(&reply_timestamp_ts, CMSG_DATA(cmsg), sizeof(reply_timestamp_ts)); + *reply_timestamp = timespec_ns(&reply_timestamp_ts); + } + } + } +#endif + +#if defined(DEBUG) || defined(_DEBUG) + if (randomly_lose_flag) { + if ((random() & 0x07) <= lose_factor) + return 0; + } +#endif + + return recv_len; +} + +/* stats_add: update host statistics for a single packet that was received (or timed out) + * h: host entry to update + * index: if in count mode: index number for this ping packet (-1 otherwise) + * success: 1 if response received, 0 otherwise + * latency: response time, in ns + */ +void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency) +{ + /* sent count - we update only on receive/timeout, so that we don't get + * weird loss percentage, just because a packet was note recived yet. + */ + h->num_sent++; + h->num_sent_i++; + + if (!success) { + if (!loop_flag && index >= 0) { + h->resp_times[index] = RESP_TIMEOUT; + } + num_timeout++; + return; + } + + /* received count */ + h->num_recv++; + h->num_recv_i++; + + /* maximum */ + if (!h->max_reply || latency > h->max_reply) { + h->max_reply = latency; + } + if (!h->max_reply_i || latency > h->max_reply_i) { + h->max_reply_i = latency; + } + + /* minimum */ + if (!h->min_reply || latency < h->min_reply) { + h->min_reply = latency; + } + if (!h->min_reply_i || latency < h->min_reply_i) { + h->min_reply_i = latency; + } + + /* total time (for average) */ + h->total_time += latency; + h->total_time_i += latency; + + /* response time per-packet (count mode) */ + if (!loop_flag && index >= 0) { + h->resp_times[index] = latency; + } +} + +/* stats_reset_interval: reset interval statistics + * h: host entry to update + */ +void stats_reset_interval(HOST_ENTRY *h) +{ + h->num_sent_i = 0; + h->num_recv_i = 0; + h->max_reply_i = 0; + h->min_reply_i = 0; + h->total_time_i = 0; +} + +int decode_icmp_ipv4( + struct sockaddr *response_addr, + size_t response_addr_len, + char *reply_buf, + size_t reply_buf_len, + unsigned short *id, + unsigned short *seq, + int *ip_header_tos, + int *ip_header_ttl, + uint32_t *ip_header_otime_ms, + uint32_t *ip_header_rtime_ms, + uint32_t *ip_header_ttime_ms) +{ + struct icmp *icp; + int hlen = 0; + + if (!using_sock_dgram4) { + struct ip *ip = (struct ip *)reply_buf; + *ip_header_tos = ip->ip_tos; + *ip_header_ttl = ip->ip_ttl; + +#if defined(__alpha__) && __STDC__ && !defined(__GLIBC__) && !defined(__NetBSD__) && !defined(__OpenBSD__) + /* The alpha headers are decidedly broken. + * Using an ANSI compiler, it provides ip_vhl instead of ip_hl and + * ip_v. So, to get ip_hl, we mask off the bottom four bits. + */ + hlen = (ip->ip_vhl & 0x0F) << 2; +#else + hlen = ip->ip_hl << 2; +#endif + } + + if (reply_buf_len < hlen + ICMP_MINLEN) { + /* too short */ + if (verbose_flag) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf); + } + return -1; + } + + icp = (struct icmp *)(reply_buf + hlen); + + if ((icmp_request_typ == 0 && icp->icmp_type != ICMP_ECHOREPLY) || + (icmp_request_typ == 13 && icp->icmp_type != ICMP_TSTAMPREPLY)) { + /* Handle other ICMP packets */ + struct icmp *sent_icmp; + SEQMAP_VALUE *seqmap_value; + char addr_ascii[INET6_ADDRSTRLEN]; + HOST_ENTRY *h; + + /* reply icmp packet (hlen + ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */ + if (reply_buf_len < hlen + ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) { + /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */ + return -1; + } + + sent_icmp = (struct icmp *)(reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip)); + + if ((icmp_request_typ == 0 && sent_icmp->icmp_type != ICMP_ECHO) || + (icmp_request_typ == 13 && sent_icmp->icmp_type != ICMP_TSTAMP) || + sent_icmp->icmp_id != ident4) { + /* not caused by us */ + return -1; + } + + seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), current_time_ns); + if (seqmap_value == NULL) { + return -1; + } + + getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + + switch (icp->icmp_type) { + case ICMP_UNREACH: + h = table[seqmap_value->host_nr]; + if (icp->icmp_code > ICMP_UNREACH_MAXTYPE) { + print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s", + addr_ascii, h->host); + } + else { + print_warning("%s from %s for ICMP Echo sent to %s", + icmp_unreach_str[icp->icmp_code], addr_ascii, h->host); + } + + print_warning("\n"); + num_othericmprcvd++; + break; + + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + h = table[seqmap_value->host_nr]; + if (icp->icmp_type <= ICMP_TYPE_STR_MAX) { + print_warning("%s from %s for ICMP Echo sent to %s", + icmp_type_str[icp->icmp_type], addr_ascii, h->host); + } + else { + print_warning("ICMP %d from %s for ICMP Echo sent to %s", + icp->icmp_type, addr_ascii, h->host); + } + print_warning("\n"); + num_othericmprcvd++; + break; + } + + return -1; + } + + *id = icp->icmp_id; + *seq = ntohs(icp->icmp_seq); + if(icp->icmp_type == ICMP_TSTAMPREPLY) { + + /* Check that reply_buf_len is sufficiently big to contain the timestamps */ + if (reply_buf_len < hlen + ICMP_MINLEN + ICMP_TIMESTAMP_DATA_SIZE) { + if (verbose_flag) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + printf("received packet too short for ICMP Timestamp Reply (%d bytes from %s)\n", (int)reply_buf_len, buf); + } + return -1; + } + + *ip_header_otime_ms = ntohl(icp->icmp_dun.id_ts.its_otime); + *ip_header_rtime_ms = ntohl(icp->icmp_dun.id_ts.its_rtime); + *ip_header_ttime_ms = ntohl(icp->icmp_dun.id_ts.its_ttime); + } + + return hlen; +} + +#ifdef IPV6 +int decode_icmp_ipv6( + struct sockaddr *response_addr, + size_t response_addr_len, + char *reply_buf, + size_t reply_buf_len, + unsigned short *id, + unsigned short *seq) +{ + struct icmp6_hdr *icp; + + if (reply_buf_len < sizeof(struct icmp6_hdr)) { + if (verbose_flag) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf); + } + return 0; /* too short */ + } + + icp = (struct icmp6_hdr *)reply_buf; + + if (icp->icmp6_type != ICMP6_ECHO_REPLY) { + /* Handle other ICMP packets */ + struct icmp6_hdr *sent_icmp; + SEQMAP_VALUE *seqmap_value; + char addr_ascii[INET6_ADDRSTRLEN]; + HOST_ENTRY *h; + + /* reply icmp packet (ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */ + if (reply_buf_len < ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) { + /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */ + return 0; + } + + sent_icmp = (struct icmp6_hdr *)(reply_buf + sizeof(struct icmp6_hdr) + sizeof(struct ip)); + + if (sent_icmp->icmp6_type != ICMP_ECHO || sent_icmp->icmp6_id != ident6) { + /* not caused by us */ + return 0; + } + + seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), current_time_ns); + if (seqmap_value == NULL) { + return 0; + } + + getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + + switch (icp->icmp6_type) { + case ICMP_UNREACH: + h = table[seqmap_value->host_nr]; + if (icp->icmp6_code > ICMP_UNREACH_MAXTYPE) { + print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s", + addr_ascii, h->host); + } + else { + print_warning("%s from %s for ICMP Echo sent to %s", + icmp_unreach_str[icp->icmp6_code], addr_ascii, h->host); + } + + print_warning("\n"); + num_othericmprcvd++; + break; + + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + h = table[seqmap_value->host_nr]; + if (icp->icmp6_type <= ICMP_TYPE_STR_MAX) { + print_warning("%s from %s for ICMP Echo sent to %s", + icmp_type_str[icp->icmp6_type], addr_ascii, h->host); + } + else { + print_warning("ICMP %d from %s for ICMP Echo sent to %s", + icp->icmp6_type, addr_ascii, h->host); + } + print_warning("\n"); + num_othericmprcvd++; + break; + } + + return 0; + } + + *id = icp->icmp6_id; + *seq = ntohs(icp->icmp6_seq); + + return 1; +} +#endif + +int wait_for_reply(int64_t wait_time) +{ + int result; + static char buffer[RECV_BUFSIZE]; + struct sockaddr_storage response_addr; + int n, avg; + HOST_ENTRY *h; + int64_t this_reply; + int this_count; + int64_t recv_time = 0; + SEQMAP_VALUE *seqmap_value; + unsigned short id; + unsigned short seq; + int ip_header_tos = -1; + int ip_header_ttl = -1; + // ICMP Timestamp + uint32_t ip_header_otime_ms = 0x80000000U; + uint32_t ip_header_rtime_ms = 0x80000000U; + uint32_t ip_header_ttime_ms = 0x80000000U; + + /* Receive packet */ + result = receive_packet(wait_time, /* max. wait time, in ns */ + &recv_time, /* reply_timestamp */ + (struct sockaddr *)&response_addr, /* reply_src_addr */ + sizeof(response_addr), /* reply_src_addr_len */ + buffer, /* reply_buf */ + sizeof(buffer) /* reply_buf_len */ + ); + + if (result <= 0) { + return 0; + } + + update_current_time(); + if (recv_time == 0) + recv_time = current_time_ns; + + /* Process ICMP packet and retrieve id/seq */ + if (response_addr.ss_family == AF_INET) { + int ip_hlen = decode_icmp_ipv4( + (struct sockaddr *)&response_addr, + sizeof(response_addr), + buffer, + sizeof(buffer), + &id, + &seq, + &ip_header_tos, + &ip_header_ttl, + &ip_header_otime_ms, + &ip_header_rtime_ms, + &ip_header_ttime_ms); + if (ip_hlen < 0) { + return 1; + } + if (id != ident4) { + return 1; /* packet received, but not the one we are looking for! */ + } + if (!using_sock_dgram4) { + /* do not include IP header in returned size, to be consistent with ping(8) and also + * with fping with IPv6 hosts */ + result -= ip_hlen; + } + } +#ifdef IPV6 + else if (response_addr.ss_family == AF_INET6) { + if (!decode_icmp_ipv6( + (struct sockaddr *)&response_addr, + sizeof(response_addr), + buffer, + sizeof(buffer), + &id, + &seq)) { + return 1; + } + if (id != ident6) { + return 1; /* packet received, but not the one we are looking for! */ + } + } +#endif + else { + return 1; + } + + seqmap_value = seqmap_fetch(seq, current_time_ns); + if (seqmap_value == NULL) { + return 1; + } + + /* find corresponding host_entry */ + n = seqmap_value->host_nr; + h = table[n]; + this_count = seqmap_value->ping_count; + this_reply = recv_time - seqmap_value->ping_ts; + + /* update stats that include invalid replies */ + h->num_recv_total++; + num_pingreceived++; + + dbg_printf("received [%d] from %s\n", this_count, h->host); + + /* optionally require reply source equal to target address */ + if (check_source_flag && addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) { + dbg_printf("discarding reply from wrong source address\n"); + return 1; + } + + /* discard duplicates */ + if (!loop_flag && h->resp_times[this_count] >= 0) { + if (!per_recv_flag) { + fprintf(stderr, "%s : duplicate for [%d], %d bytes, %s ms", + h->host, this_count, result, sprint_tm(this_reply)); + + if (addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + fprintf(stderr, " [<- %s]", buf); + } + fprintf(stderr, "\n"); + } + return 1; + } + + /* discard reply if delay is larger than timeout + * (see also: github #32) */ + if (this_reply > h->timeout) { + return 1; + } + + /* update stats */ + stats_add(h, this_count, 1, this_reply); + // TODO: move to stats_add? + if (!max_reply || this_reply > max_reply) + max_reply = this_reply; + if (!min_reply || this_reply < min_reply) + min_reply = this_reply; + sum_replies += this_reply; + total_replies++; + + /* initialize timeout to initial timeout (without backoff) */ + h->timeout = timeout; + + /* remove timeout event */ + struct event *timeout_event = host_get_timeout_event(h, this_count); + if (timeout_event) { + ev_remove(&event_queue_timeout, timeout_event); + } + + /* print "is alive" */ + if (h->num_recv == 1) { + num_alive++; + if (fast_reachable && num_alive >= min_reachable) + finish_requested = 1; + + if (verbose_flag || alive_flag) { + printf("%s", h->host); + + if (verbose_flag) + printf(" is alive"); + } + } + + /* print received ping (unless --quiet) */ + if (per_recv_flag) { + if (timestamp_flag) { + print_timestamp_format(recv_time, timestamp_format_flag); + } + avg = h->total_time / h->num_recv; + printf("%-*s : [%d], %d bytes, %s ms", + max_hostname_len, h->host, this_count, result, sprint_tm(this_reply)); + printf(" (%s avg, ", sprint_tm(avg)); + + if (h->num_recv <= h->num_sent) { + printf("%d%% loss)", + ((h->num_sent - h->num_recv) * 100) / h->num_sent); + } + else { + printf("%d%% return)", + (h->num_recv_total * 100) / h->num_sent); + } + } + + if (verbose_flag || alive_flag || per_recv_flag) { + + if (addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) { + char buf[INET6_ADDRSTRLEN]; + getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + fprintf(stderr, " [<- %s]", buf); + } + + if (icmp_request_typ == 13) { + printf("%s timestamps: Originate=%u Receive=%u Transmit=%u Localreceive=%u", + alive_flag ? "" : ",", + ip_header_otime_ms, ip_header_rtime_ms, ip_header_ttime_ms, + ms_since_midnight_utc(recv_time)); + } + + if(print_tos_flag) { + if(ip_header_tos != -1) { + printf(" (TOS %d)", ip_header_tos); + } + else { + printf(" (TOS unknown)"); + } + } + + if (print_ttl_flag) { + if(ip_header_ttl != -1) { + printf(" (TTL %d)", ip_header_ttl); + } + else { + printf(" (TTL unknown)"); + } + } + + if (elapsed_flag && !per_recv_flag) + printf(" (%s ms)", sprint_tm(this_reply)); + + printf("\n"); + } + + return 1; +} + +/************************************************************ + + Function: add_name + +************************************************************* + + Inputs: char* name + + Description: + + process input name for addition to target list + name can turn into multiple targets via multiple interfaces (-m) + or via NIS groups + +************************************************************/ + +void add_name(char *name) +{ + struct addrinfo *res0, *res, hints; + int ret_ga; + char *printname; + char namebuf[256]; + char addrbuf[256]; + + /* getaddrinfo */ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_UNUSABLE; + hints.ai_socktype = SOCK_RAW; + hints.ai_family = hints_ai_family; + if (hints_ai_family == AF_INET) { + hints.ai_protocol = IPPROTO_ICMP; + } +#ifdef IPV6 + else if (hints_ai_family == AF_INET6) { + hints.ai_protocol = IPPROTO_ICMPV6; + } +#endif + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + } + ret_ga = getaddrinfo(name, NULL, &hints, &res0); + if (ret_ga) { + if (!quiet_flag) + print_warning("%s: %s\n", name, gai_strerror(ret_ga)); + num_noaddress++; + return; + } + + /* NOTE: we could/should loop with res on all addresses like this: + * for (res = res0; res; res = res->ai_next) { + * We don't do it yet, however, because is is an incompatible change + * (need to implement a separate option for this) + */ + for (res = res0; res; res = res->ai_next) { + /* name_flag: addr -> name lookup requested) */ + if (name_flag || rdns_flag) { + int do_rdns = rdns_flag ? 1 : 0; + if (name_flag) { + /* Was it a numerical address? Only then do a rdns-query */ + struct addrinfo *nres; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(name, NULL, &hints, &nres) == 0) { + do_rdns = 1; + freeaddrinfo(nres); + } + } + + if (do_rdns && getnameinfo(res->ai_addr, res->ai_addrlen, namebuf, sizeof(namebuf) / sizeof(char), NULL, 0, 0) == 0) { + printname = namebuf; + } + else { + printname = name; + } + } + else { + printname = name; + } + + /* addr_flag: name -> addr lookup requested */ + if (addr_flag) { + int ret; + ret = getnameinfo(res->ai_addr, res->ai_addrlen, addrbuf, + sizeof(addrbuf) / sizeof(char), NULL, 0, NI_NUMERICHOST); + if (ret) { + if (!quiet_flag) { + print_warning("%s: can't forward-lookup address (%s)\n", name, gai_strerror(ret)); + } + continue; + } + + if (name_flag || rdns_flag) { + char nameaddrbuf[512 + 3]; + snprintf(nameaddrbuf, sizeof(nameaddrbuf) / sizeof(char), "%s (%s)", printname, addrbuf); + add_addr(name, nameaddrbuf, res->ai_addr, res->ai_addrlen); + } + else { + add_addr(name, addrbuf, res->ai_addr, res->ai_addrlen); + } + } + else { + add_addr(name, printname, res->ai_addr, res->ai_addrlen); + } + + if (!multif_flag) { + break; + } + } + + freeaddrinfo(res0); +} + +/************************************************************ + + Function: add_addr + +************************************************************* + + Description: + + add single address to list of hosts to be pinged + +************************************************************/ + +void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_len) +{ + HOST_ENTRY *p; + int n; + int64_t *i; + + p = (HOST_ENTRY *)calloc(1, sizeof(HOST_ENTRY)); + if (!p) + crash_and_burn("can't allocate HOST_ENTRY"); + + p->name = strdup(name); + p->host = strdup(host); + memcpy(&p->saddr, ipaddr, ipaddr_len); + p->saddr_len = ipaddr_len; + p->timeout = timeout; + p->min_reply = 0; + + if (netdata_flag) { + char *s = p->name; + while (*s) { + if (!isalnum(*s)) + *s = '_'; + s++; + } + } + + if (strlen(p->host) > max_hostname_len) + max_hostname_len = strlen(p->host); + + /* array for response time results */ + if (!loop_flag) { + i = (int64_t *)malloc(trials * sizeof(int64_t)); + if (!i) + crash_and_burn("can't allocate resp_times array"); + + for (n = 1; n < trials; n++) + i[n] = RESP_UNUSED; + + p->resp_times = i; + } + + /* allocate event storage */ + p->event_storage_ping = (struct event *)calloc(event_storage_count, sizeof(struct event)); + if (!p->event_storage_ping) { + errno_crash_and_burn("can't allocate event_storage_ping"); + } + p->event_storage_timeout = (struct event *)calloc(event_storage_count, sizeof(struct event)); + if (!p->event_storage_timeout) { + errno_crash_and_burn("can't allocate event_storage_timeout"); + } + + /* schedule first ping */ + host_add_ping_event(p, 0, current_time_ns); + + num_hosts++; +} + +/************************************************************ + + Function: crash_and_burn + +************************************************************* + + Inputs: char* message + + Description: + +************************************************************/ + +void crash_and_burn(char *message) +{ + fprintf(stderr, "%s: %s\n", prog, message); + exit(4); +} + +/************************************************************ + + Function: errno_crash_and_burn + +************************************************************* + + Inputs: char* message + + Description: + +************************************************************/ + +void errno_crash_and_burn(char *message) +{ + fprintf(stderr, "%s: %s : %s\n", prog, message, strerror(errno)); + exit(4); +} + +/************************************************************ + + Function: print_warning + + Description: fprintf(stderr, ...), unless running with -q + +*************************************************************/ + +void print_warning(char *format, ...) +{ + va_list args; + if (!quiet_flag) { + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + } +} + +/************************************************************ + + Function: sprint_tm + +************************************************************* + + render nanosecond int64_t value into milliseconds string with three digits of + precision. + +************************************************************/ + +const char *sprint_tm(int64_t ns) +{ + static char buf[10]; + double t = (double)ns / 1e6; + + if (t < 0.0) { + /* negative (unexpected) */ + sprintf(buf, "%.2g", t); + } + else if (t < 1.0) { + /* <= 0.99 ms */ + sprintf(buf, "%.3f", t); + } + else if (t < 10.0) { + /* 1.00 - 9.99 ms */ + sprintf(buf, "%.2f", t); + } + else if (t < 100.0) { + /* 10.0 - 99.9 ms */ + sprintf(buf, "%.1f", t); + } + else if (t < 1000000.0) { + /* 100 - 1'000'000 ms */ + sprintf(buf, "%.0f", t); + } + else { + sprintf(buf, "%.3e", t); + } + + return (buf); +} + +/************************************************************ + + Function: addr_cmp + +*************************************************************/ +int addr_cmp(struct sockaddr *a, struct sockaddr *b) +{ + if (a->sa_family != b->sa_family) { + return a->sa_family - b->sa_family; + } + else { + if (a->sa_family == AF_INET) { + return ((struct sockaddr_in *)a)->sin_addr.s_addr - ((struct sockaddr_in *)b)->sin_addr.s_addr; + } + else if (a->sa_family == AF_INET6) { + return memcmp(&((struct sockaddr_in6 *)a)->sin6_addr, + &((struct sockaddr_in6 *)b)->sin6_addr, + sizeof(((struct sockaddr_in6 *)a)->sin6_addr)); + } + } + + return 0; +} + +void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time) +{ + struct event *event = &h->event_storage_ping[index % event_storage_count]; + event->host = h; + event->ping_index = index; + event->ev_time = ev_time; + ev_enqueue(&event_queue_ping, event); + + dbg_printf("%s [%d]: add ping event in %.0f ms\n", + event->host->host, index, (ev_time - current_time_ns) / 1e6); +} + +void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time) +{ + struct event *event = &h->event_storage_timeout[index % event_storage_count]; + event->host = h; + event->ping_index = index; + event->ev_time = ev_time; + ev_enqueue(&event_queue_timeout, event); + + dbg_printf("%s [%d]: add timeout event in %.0f ms\n", + event->host->host, index, (ev_time - current_time_ns) / 1e6); +} + +struct event *host_get_timeout_event(HOST_ENTRY *h, int index) +{ + return &h->event_storage_timeout[index % event_storage_count]; +} + +/************************************************************ + + Function: ev_enqueue + + Enqueue an event + + The queue is sorted by event->ev_time, so that queue->first always points to + the earliest event. + + We start scanning the queue from the tail, because we assume + that new events mostly get inserted with a event time higher + than the others. + +*************************************************************/ +void ev_enqueue(struct event_queue *queue, struct event *event) +{ + struct event *i; + struct event *i_prev; + + /* Empty list */ + if (queue->last == NULL) { + event->ev_next = NULL; + event->ev_prev = NULL; + queue->first = event; + queue->last = event; + return; + } + + /* Insert on tail? */ + if (event->ev_time - queue->last->ev_time >= 0) { + event->ev_next = NULL; + event->ev_prev = queue->last; + queue->last->ev_next = event; + queue->last = event; + return; + } + + /* Find insertion point */ + i = queue->last; + while (1) { + i_prev = i->ev_prev; + if (i_prev == NULL || event->ev_time - i_prev->ev_time >= 0) { + event->ev_prev = i_prev; + event->ev_next = i; + i->ev_prev = event; + if (i_prev != NULL) { + i_prev->ev_next = event; + } + else { + queue->first = event; + } + return; + } + i = i_prev; + } +} + +/************************************************************ + + Function: ev_dequeue + +*************************************************************/ +struct event *ev_dequeue(struct event_queue *queue) +{ + struct event *dequeued; + + if (queue->first == NULL) { + return NULL; + } + dequeued = queue->first; + ev_remove(queue, dequeued); + + return dequeued; +} + +/************************************************************ + + Function: ev_remove + +*************************************************************/ +void ev_remove(struct event_queue *queue, struct event *event) +{ + if (queue->first == event) { + queue->first = event->ev_next; + } + if (queue->last == event) { + queue->last = event->ev_prev; + } + if (event->ev_prev) { + event->ev_prev->ev_next = event->ev_next; + } + if (event->ev_next) { + event->ev_next->ev_prev = event->ev_prev; + } + event->ev_prev = NULL; + event->ev_next = NULL; +} + +/************************************************************ + + Function: print_human_readable_time from current_time_ns + +*************************************************************/ +void print_timestamp_format(int64_t current_time_ns, int timestamp_format) +{ + char time_buffer[100]; + time_t current_time_s; + struct tm *local_time; + + current_time_s = current_time_ns / 1000000000; + local_time = localtime(¤t_time_s); + switch(timestamp_format) { + case 1: + // timestamp-format ctime + strftime(time_buffer, sizeof(time_buffer), "%c", local_time); + printf("[%s] ", time_buffer); + break; + case 2: + // timestamp-format iso + strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%T%z", local_time); + printf("[%s] ", time_buffer); + break; + case 3: + // timestamp-format rfc3339 + strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d %H:%M:%S", local_time); + printf("[%s] ", time_buffer); + break; + default: + printf("[%.5f] ", (double)current_time_ns / 1e9); + } +} + +/************************************************************ + + Function: ms_since_midnight_utc + +************************************************************* + + Input: int64_t: current UTC time in ns + + Output: uint32_t: current time in ms since midnight UTC + + Description: + + Return ICMP Timestamp value corresponding to the given time value. + The given time value must be in UTC. + +*************************************************************/ +static uint32_t ms_since_midnight_utc(int64_t time_val) +{ + return (uint32_t)((time_val / 1000000) % (24 * 60 * 60 * 1000)); +} + +/************************************************************ + + Function: usage + +************************************************************* + + Inputs: int: 0 if output on request, 1 if output because of wrong argument + + Description: + +************************************************************/ + +void usage(int is_error) +{ + FILE *out = is_error ? stderr : stdout; + fprintf(out, "Usage: %s [options] [targets...]\n", prog); + fprintf(out, "\n"); + fprintf(out, "Probing options:\n"); + fprintf(out, " -4, --ipv4 only ping IPv4 addresses\n"); + fprintf(out, " -6, --ipv6 only ping IPv6 addresses\n"); + fprintf(out, " -b, --size=BYTES amount of ping data to send, in bytes (default: %d)\n", DEFAULT_PING_DATA_SIZE); + fprintf(out, " -B, --backoff=N set exponential backoff factor to N (default: 1.5)\n"); + fprintf(out, " -c, --count=N count mode: send N pings to each target and report stats\n"); + fprintf(out, " -f, --file=FILE read list of targets from a file ( - means stdin)\n"); + fprintf(out, " -g, --generate generate target list (only if no -f specified),\n"); + fprintf(out, " limited to at most %d targets\n", MAX_GENERATE); + fprintf(out, " (give start and end IP in the target list, or a CIDR address)\n"); + fprintf(out, " (ex. %s -g 192.168.1.0 192.168.1.255 or %s -g 192.168.1.0/24)\n", prog, prog); + fprintf(out, " -H, --ttl=N set the IP TTL value (Time To Live hops)\n"); + fprintf(out, " -i, --interval=MSEC interval between sending ping packets (default: %.0f ms)\n", interval / 1e6); +#ifdef SO_BINDTODEVICE + fprintf(out, " -I, --iface=IFACE bind to a particular interface\n"); +#endif +#ifdef SO_MARK + fprintf(out, " -k, --fwmark=FWMARK set the routing mark\n"); +#endif + fprintf(out, " -l, --loop loop mode: send pings forever\n"); + fprintf(out, " -m, --all use all IPs of provided hostnames (e.g. IPv4 and IPv6), use with -A\n"); + fprintf(out, " -M, --dontfrag set the Don't Fragment flag\n"); + fprintf(out, " -O, --tos=N set the type of service (tos) flag on the ICMP packets\n"); + fprintf(out, " -p, --period=MSEC interval between ping packets to one target (in ms)\n"); + fprintf(out, " (in loop and count modes, default: %.0f ms)\n", perhost_interval / 1e6); + fprintf(out, " -r, --retry=N number of retries (default: %d)\n", DEFAULT_RETRY); + fprintf(out, " -R, --random random packet data (to foil link data compression)\n"); + fprintf(out, " -S, --src=IP set source address\n"); + fprintf(out, " -t, --timeout=MSEC individual target initial timeout (default: %.0f ms,\n", timeout / 1e6); + fprintf(out, " except with -l/-c/-C, where it's the -p period up to 2000 ms)\n"); + fprintf(out, " --check-source discard replies not from target address\n"); + fprintf(out, " --icmp-timestamp use ICMP Timestamp instead of ICMP Echo\n"); + fprintf(out, "\n"); + fprintf(out, "Output options:\n"); + fprintf(out, " -a, --alive show targets that are alive\n"); + fprintf(out, " -A, --addr show targets by address\n"); + fprintf(out, " -C, --vcount=N same as -c, report results (not stats) in verbose format\n"); + fprintf(out, " -d, --rdns show targets by name (force reverse-DNS lookup)\n"); + fprintf(out, " -D, --timestamp print timestamp before each output line\n"); + fprintf(out, " --timestamp-format=FORMAT show timestamp in the given format (-D required): ctime|iso|rfc3339\n"); + fprintf(out, " -e, --elapsed show elapsed time on return packets\n"); + fprintf(out, " -n, --name show targets by name (reverse-DNS lookup for target IPs)\n"); + fprintf(out, " -N, --netdata output compatible for netdata (-l -Q are required)\n"); + fprintf(out, " -o, --outage show the accumulated outage time (lost packets * packet interval)\n"); + fprintf(out, " -q, --quiet quiet (don't show per-target/per-ping results)\n"); + fprintf(out, " -Q, --squiet=SECS[,cumulative] same as -q, but add interval summary every SECS seconds,\n"); + fprintf(out, " with 'cumulative', print stats since beginning\n"); + fprintf(out, " -s, --stats print final stats\n"); + fprintf(out, " -u, --unreach show targets that are unreachable\n"); + fprintf(out, " -v, --version show version\n"); + fprintf(out, " -x, --reachable=N shows if >=N hosts are reachable or not\n"); + fprintf(out, " -X, --fast-reachable=N exits true immediately when N hosts are found\n"); + fprintf(out, " --print-tos show received TOS value\n"); + fprintf(out, " --print-ttl show IP TTL value\n"); + exit(is_error); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.h b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.h new file mode 100644 index 0000000..f50710b --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.h @@ -0,0 +1,39 @@ +#ifndef _FPING_H +#define _FPING_H + +#define __APPLE_USE_RFC_3542 1 + +#include +#include +#include + +/* this requires variadic macros, part of C99 */ +#if (defined(DEBUG) || defined(_DEBUG)) +extern int64_t current_time_ns; +extern int trace_flag; +#define dbg_printf(fmt, ...) do { if (trace_flag) { fprintf(stderr, "[%10.5f] ", (double)(current_time_ns / 1000)/1000000); fprintf(stderr, fmt, __VA_ARGS__); } } while (0) + +#else +#define dbg_printf(fmt, ...) +#endif + + +/* fping.c */ +void crash_and_burn( char *message ); +void errno_crash_and_burn( char *message ); +int in_cksum( unsigned short *p, int n ); +extern int random_data_flag; + +/* socket.c */ +int open_ping_socket_ipv4(int *socktype); +void init_ping_buffer_ipv4(size_t ping_data_size); +void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr, int *ident); +int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id, uint8_t icmp_proto); +#ifdef IPV6 +int open_ping_socket_ipv6(int *socktype); +void init_ping_buffer_ipv6(size_t ping_data_size); +void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr, int *ident); +int socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id); +#endif + +#endif diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/options.h b/ci/tmp.VwGIuQgZdr/fping-5.4/src/options.h new file mode 100644 index 0000000..229975c --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/options.h @@ -0,0 +1,52 @@ + +/* + * Interval is the minimum amount of time between sending a ping packet to + * any host. + * + * Perhost_interval is the minimum amount of time between sending a ping + * packet to a particular responding host (when count is > 1) + * + * Timeout is the initial amount of time between sending a ping packet to + * a particular non-responding host. + * + * Retry is the number of ping packets to send to a non-responding host + * before giving up (in is-it-alive mode). + * + * Backoff factor is how much longer to wait on successive retries. + * + * + */ + +/* constants */ + +#ifndef DEFAULT_INTERVAL +#define DEFAULT_INTERVAL 10 /* default time between packets (msec) */ +#endif + +#ifndef DEFAULT_PERHOST_INTERVAL /* default time between packets */ +#define DEFAULT_PERHOST_INTERVAL 1000 /* to a particular destination */ +#endif /* in counting/looping mode */ + +#ifndef DEFAULT_TIMEOUT +#define DEFAULT_TIMEOUT 500 /* individual host timeouts */ +#define AUTOTUNE_TIMEOUT_MAX 2000 +#endif + + +#ifndef DEFAULT_RETRY +#define DEFAULT_RETRY 3 /* number of times to retry a host */ +#endif + +#ifndef DEFAULT_SELECT_TIME +#define DEFAULT_SELECT_TIME 10 /* default time to wait during select() */ +#endif + +#ifndef DEFAULT_BACKOFF_FACTOR +#define DEFAULT_BACKOFF_FACTOR 1.5 /* exponential timeout factor */ +#endif +#define MIN_BACKOFF_FACTOR 1.0 /* exponential timeout factor */ +#define MAX_BACKOFF_FACTOR 5.0 /* exponential timeout factor */ + +#ifndef DNS_TIMEOUT +#define DNS_TIMEOUT 1000 /* time in micro_sec for dns retry */ +#endif diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.c new file mode 100644 index 0000000..63a9f40 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.c @@ -0,0 +1,266 @@ +#include "optparse.h" + +#define MSG_INVALID "invalid option" +#define MSG_MISSING "option requires an argument" +#define MSG_TOOMANY "option takes no arguments" + +static int +opterror(struct optparse *options, const char *message, const char *data) +{ + unsigned p = 0; + while (*message) + options->errmsg[p++] = *message++; + const char *sep = " -- '"; + while (*sep) + options->errmsg[p++] = *sep++; + while (p < sizeof(options->errmsg) - 2 && *data) + options->errmsg[p++] = *data++; + options->errmsg[p++] = '\''; + options->errmsg[p++] = '\0'; + return '?'; +} + +void optparse_init(struct optparse *options, char **argv) +{ + options->argv = argv; + options->permute = 1; + options->optind = 1; + options->subopt = 0; + options->optarg = 0; + options->errmsg[0] = '\0'; +} + +static inline int +is_dashdash(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0'; +} + +static inline int +is_shortopt(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0'; +} + +static inline int +is_longopt(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0'; +} + +static void +permute(struct optparse *options, int index) +{ + char *nonoption = options->argv[index]; + for (int i = index; i < options->optind - 1; i++) + options->argv[i] = options->argv[i + 1]; + options->argv[options->optind - 1] = nonoption; +} + +static int +argtype(const char *optstring, char c) +{ + if (c == ':') + return -1; + for (; *optstring && c != *optstring; optstring++); + if (!*optstring) + return -1; + int count = OPTPARSE_NONE; + if (optstring[1] == ':') + count += optstring[2] == ':' ? 2 : 1; + return count; +} + +int optparse(struct optparse *options, const char *optstring) +{ + options->errmsg[0] = '\0'; + options->optopt = 0; + options->optarg = 0; + char *option = options->argv[options->optind]; + if (option == 0) { + return -1; + } else if (is_dashdash(option)) { + options->optind++; /* consume "--" */ + return -1; + } else if (!is_shortopt(option)) { + if (options->permute) { + int index = options->optind; + options->optind++; + int r = optparse(options, optstring); + permute(options, index); + options->optind--; + return r; + } else { + return -1; + } + } + option += options->subopt + 1; + options->optopt = option[0]; + int type = argtype(optstring, option[0]); + char *next = options->argv[options->optind + 1]; + switch (type) { + case -1: { + options->optind++; + char str[2] = {option[0]}; + return opterror(options, MSG_INVALID, str); + } + case OPTPARSE_NONE: + if (option[1]) { + options->subopt++; + } else { + options->subopt = 0; + options->optind++; + } + return option[0]; + case OPTPARSE_REQUIRED: + options->subopt = 0; + options->optind++; + if (option[1]) { + options->optarg = option + 1; + } else if (next != 0) { + options->optarg = next; + options->optind++; + } else { + options->optarg = 0; + char str[2] = {option[0]}; + return opterror(options, MSG_MISSING, str); + } + return option[0]; + case OPTPARSE_OPTIONAL: + options->subopt = 0; + options->optind++; + if (option[1]) + options->optarg = option + 1; + else + options->optarg = 0; + return option[0]; + } + return 0; +} + +char *optparse_arg(struct optparse *options) +{ + options->subopt = 0; + char *option = options->argv[options->optind]; + if (option != 0) + options->optind++; + return option; +} + +static inline int +longopts_end(const struct optparse_long *longopts, int i) +{ + return !longopts[i].longname && !longopts[i].shortname; +} + +static void +optstring_from_long(const struct optparse_long *longopts, char *optstring) +{ + char *p = optstring; + for (int i = 0; !longopts_end(longopts, i); i++) { + if (longopts[i].shortname) { + *p++ = longopts[i].shortname; + for (int a = 0; a < (int)longopts[i].argtype; a++) + *p++ = ':'; + } + } + *p = '\0'; +} + +/* Unlike strcmp(), handles options containing "=". */ +static int +longopts_match(const char *longname, const char *option) +{ + if (longname == 0) + return 0; + const char *a = option, *n = longname; + for (; *a && *n && *a != '='; a++, n++) + if (*a != *n) + return 0; + return *n == '\0' && (*a == '\0' || *a == '='); +} + +/* Return the part after "=", or NULL. */ +static char * +longopts_arg(char *option) +{ + for (; *option && *option != '='; option++); + if (*option == '=') + return option + 1; + else + return 0; +} + +static int +long_fallback(struct optparse *options, + const struct optparse_long *longopts, + int *longindex) +{ + char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */ + optstring_from_long(longopts, optstring); + int result = optparse(options, optstring); + if (longindex != 0) { + *longindex = -1; + if (result != -1) + for (int i = 0; !longopts_end(longopts, i); i++) + if (longopts[i].shortname == options->optopt) + *longindex = i; + } + return result; +} + +int +optparse_long(struct optparse *options, + const struct optparse_long *longopts, + int *longindex) +{ + char *option = options->argv[options->optind]; + if (option == 0) { + return -1; + } else if (is_dashdash(option)) { + options->optind++; /* consume "--" */ + return -1; + } else if (is_shortopt(option)) { + return long_fallback(options, longopts, longindex); + } else if (!is_longopt(option)) { + if (options->permute) { + int index = options->optind; + options->optind++; + int r = optparse_long(options, longopts, longindex); + permute(options, index); + options->optind--; + return r; + } else { + return -1; + } + } + + /* Parse as long option. */ + options->errmsg[0] = '\0'; + options->optopt = 0; + options->optlongname = 0; + options->optarg = 0; + option += 2; /* skip "--" */ + options->optind++; + for (int i = 0; !longopts_end(longopts, i); i++) { + const char *name = longopts[i].longname; + if (longopts_match(name, option)) { + options->optlongname = option; + if (longindex) + *longindex = i; + options->optopt = longopts[i].shortname; + char *arg = longopts_arg(option); + if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) { + return opterror(options, MSG_TOOMANY, name); + } if (arg != 0) { + options->optarg = arg; + } else if (longopts[i].argtype == OPTPARSE_REQUIRED) { + options->optarg = options->argv[options->optind++]; + if (options->optarg == 0) + return opterror(options, MSG_MISSING, name); + } + return options->optopt; + } + } + return opterror(options, MSG_INVALID, option); +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.h b/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.h new file mode 100644 index 0000000..7a555ed --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.h @@ -0,0 +1,103 @@ +#ifndef OPTPARSE_H +#define OPTPARSE_H + +/** + * Optparse -- portable, reentrant, embeddable, getopt-like option parser + * + * The POSIX getopt() option parser has three fatal flaws. These flaws + * are solved by Optparse. + * + * 1) Parser state is stored entirely in global variables, some of + * which are static and inaccessible. This means only one thread can + * use getopt(). It also means it's not possible to recursively parse + * nested sub-arguments while in the middle of argument parsing. + * Optparse fixes this by storing all state on a local struct. + * + * 2) The POSIX standard provides no way to properly reset the parser. + * This means for portable code that getopt() is only good for one + * run, over one argv with one optstring. It also means subcommand + * options cannot be processed with getopt(). Most implementations + * provide a method to reset the parser, but it's not portable. + * Optparse provides an optparse_arg() function for stepping over + * subcommands and continuing parsing of options with another + * optstring. The Optparse struct itself can be passed around to + * subcommand handlers for additional subcommand option parsing. A + * full reset can be achieved by with an additional optparse_init(). + * + * 3) Error messages are printed to stderr. This can be disabled with + * opterr, but the messages themselves are still inaccessible. + * Optparse solves this by writing an error message in its errmsg + * field. The downside to Optparse is that this error message will + * always be in English rather than the current locale. + * + * Optparse should be familiar with anyone accustomed to getopt(), and + * it could be a nearly drop-in replacement. The optstring is the same + * and the fields have the same names as the getopt() global variables + * (optarg, optind, optopt). + * + * Optparse also supports GNU-style long options with optparse_long(). + * The interface is slightly different and simpler than getopt_long(). + * + * By default, argv is permuted as it is parsed, moving non-option + * arguments to the end. This can be disabled by setting the `permute` + * field to 0 after initialization. + */ + +struct optparse { + char **argv; + int permute; + int optind; + int optopt; + char *optlongname; + char *optarg; + char errmsg[64]; + int subopt; +}; + +enum optparse_argtype { OPTPARSE_NONE, OPTPARSE_REQUIRED, OPTPARSE_OPTIONAL }; + +struct optparse_long { + const char *longname; + int shortname; + enum optparse_argtype argtype; +}; + +/** + * Initializes the parser state. + */ +void optparse_init(struct optparse *options, char **argv); + +/** + * Read the next option in the argv array. + * @param optstring a getopt()-formatted option string. + * @return the next option character, -1 for done, or '?' for error + * + * Just like getopt(), a character followed by no colons means no + * argument. One colon means the option has a required argument. Two + * colons means the option takes an optional argument. + */ +int optparse(struct optparse *options, const char *optstring); + +/** + * Handles GNU-style long options in addition to getopt() options. + * This works a lot like GNU's getopt_long(). The last option in + * longopts must be all zeros, marking the end of the array. The + * longindex argument may be NULL. + */ +int +optparse_long(struct optparse *options, + const struct optparse_long *longopts, + int *longindex); + +/** + * Used for stepping over non-option arguments. + * @return the next non-option argument, or NULL for no more arguments + * + * Argument parsing can continue with optparse() after using this + * function. That would be used to parse the options for the + * subcommand returned by optparse_arg(). This function allows you to + * ignore the value of optind. + */ +char *optparse_arg(struct optparse *options); + +#endif diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.c new file mode 100644 index 0000000..31bf725 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.c @@ -0,0 +1,124 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * seqmap.c: implementation of a mapping between sequence number and (host, ping_nr) + * we can't just use ping_nr*host_count + host_nr, because it can + * overflow the 16 bit of the icmp header field. See also: + * https://github.com/schweikert/fping/issues/48 + */ + +#include "config.h" +#include "seqmap.h" +#include "limits.h" +#include "options.h" +#include "fping.h" + +#include +#include +#include + +/* description of the data structure used: + * + * - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in + * the timeout interval (SEQMAP_TIMEOUT_IN_NS) + * - we store the values in an array with SEQMAP_MAXSEQ elements + * - current sequence number % SEQMAP_MAXSEQ gives the current index + * - when entering a value, we check that the current entry is expired + */ + +static SEQMAP_VALUE* seqmap_map = NULL; +static unsigned int seqmap_next_id = 0; + +#define SEQMAP_TIMEOUT_IN_NS INT64_C(10000000000) +#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX + +void seqmap_init() +{ + seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE)); + if (seqmap_map == NULL) { + perror("malloc error (can't allocate seqmap_map)"); + } +} + +unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t timestamp) +{ + unsigned int current_id; + SEQMAP_VALUE* next_value; + + if (!seqmap_map) { + fprintf(stderr, "fping internal error: seqmap not initialized.\n"); + exit(4); + } + + /* check if expired (note that unused seqmap values will have fields set to + * 0, so will be seen as expired */ + next_value = &seqmap_map[seqmap_next_id]; + if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) { + fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n", + SEQMAP_TIMEOUT_IN_NS, host_nr, ping_count, seqmap_next_id); + exit(4); + } + + /* store the value */ + next_value->host_nr = host_nr; + next_value->ping_count = ping_count; + next_value->ping_ts = timestamp; + + /* increase next id */ + current_id = seqmap_next_id; + seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ; + + dbg_printf("seqmap_add(host: %d, index: %d) -> %d\n", host_nr, ping_count, current_id); + + return current_id; +} + +SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now) +{ + SEQMAP_VALUE* value; + + if (id >= SEQMAP_MAXSEQ) { + return NULL; + } + + value = &seqmap_map[id]; + + /* verify that value is not expired */ + if (now - value->ping_ts >= SEQMAP_TIMEOUT_IN_NS) { + dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d -> DISCARDED %ld\n", id, value->host_nr, value->ping_count, + now - value->ping_ts); + return NULL; + } + + dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d\n", id, value->host_nr, value->ping_count); + + return value; +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.h b/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.h new file mode 100644 index 0000000..a1780b0 --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.h @@ -0,0 +1,21 @@ +#ifndef SEQMAP_H +#define SEQMAP_H + +#include +#include + +typedef struct seqmap_value +{ + unsigned int host_nr; + unsigned int ping_count; + int64_t ping_ts; + +} SEQMAP_VALUE; + +#define SEQMAP_MAXSEQ 65535 + +void seqmap_init(); +unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t now); +SEQMAP_VALUE *seqmap_fetch(unsigned int id, int64_t now); + +#endif diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket4.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket4.c new file mode 100644 index 0000000..c408c6d --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket4.c @@ -0,0 +1,166 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "config.h" +#include "fping.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char* ping_buffer_ipv4 = 0; +size_t ping_pkt_size_ipv4; + +int open_ping_socket_ipv4(int *socktype) +{ + struct protoent* proto; + int s; + + /* confirm that ICMP is available on this machine */ + if ((proto = getprotobyname("icmp")) == NULL) + crash_and_burn("icmp: unknown protocol"); + + /* create raw socket for ICMP calls (ping) */ + *socktype = SOCK_RAW; + s = socket(AF_INET, *socktype, proto->p_proto); + if (s < 0) { + /* try non-privileged icmp (works on Mac OSX without privileges, for example) */ + *socktype = SOCK_DGRAM; + s = socket(AF_INET, *socktype, proto->p_proto); + if (s < 0) { + return -1; + } + } + + /* Make sure that we use non-blocking IO */ + { + int flags; + + if ((flags = fcntl(s, F_GETFL, 0)) < 0) + perror("fcntl"); + + if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) + perror("fcntl"); + } + + return s; +} + +void init_ping_buffer_ipv4(size_t ping_data_size) +{ + /* allocate ping buffer */ + ping_pkt_size_ipv4 = ping_data_size + ICMP_MINLEN; + ping_buffer_ipv4 = (char*)calloc(1, ping_pkt_size_ipv4); + if (!ping_buffer_ipv4) + crash_and_burn("can't malloc ping packet"); +} + +void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr, int *ident) +{ + struct sockaddr_in sa; + socklen_t len = sizeof(sa); + + memset(&sa, 0, len); + sa.sin_family = AF_INET; + sa.sin_addr = *src_addr; + if (bind(s, (struct sockaddr*)&sa, len) < 0) + errno_crash_and_burn("cannot bind source address"); + + if (ident) { + memset(&sa, 0, len); + if (getsockname(s, (struct sockaddr *)&sa, &len) < 0) + errno_crash_and_burn("can't get ICMP socket identity"); + + if (sa.sin_port) + *ident = sa.sin_port; + } +} + +unsigned short calcsum(unsigned short* buffer, int length) +{ + unsigned long sum; + + /* initialize sum to zero and loop until length (in words) is 0 */ + for (sum = 0; length > 1; length -= 2) /* sizeof() returns number of bytes, we're interested in number of words */ + sum += *buffer++; /* add 1 word of buffer to sum and proceed to the next */ + + /* we may have an extra byte */ + if (length == 1) + sum += (char)*buffer; + + sum = (sum >> 16) + (sum & 0xFFFF); /* add high 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + return ~sum; +} + +int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr, uint8_t icmp_proto) +{ + struct icmp* icp; + struct timespec tsorig; + long tsorig_ms; + int n; + + icp = (struct icmp*)ping_buffer_ipv4; + + icp->icmp_type = icmp_proto; + if(icmp_proto == ICMP_TSTAMP) { + clock_gettime(CLOCK_REALTIME, &tsorig); + tsorig_ms = (tsorig.tv_sec % (24*60*60)) * 1000 + tsorig.tv_nsec / 1000000; + icp->icmp_otime = htonl(tsorig_ms); + icp->icmp_rtime = 0; + icp->icmp_ttime = 0; + } + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_seq = htons(icmp_seq_nr); + icp->icmp_id = icmp_id_nr; + + if (random_data_flag) { + for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) { + ping_buffer_ipv4[n] = random() & 0xFF; + } + } + + icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size_ipv4); + + n = sendto(s, icp, ping_pkt_size_ipv4, 0, saddr, saddr_len); + + return n; +} diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket6.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket6.c new file mode 100644 index 0000000..84a84ea --- /dev/null +++ b/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket6.c @@ -0,0 +1,136 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "config.h" +#include "fping.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +char* ping_buffer_ipv6 = 0; +size_t ping_pkt_size_ipv6; + +int open_ping_socket_ipv6(int *socktype) +{ + struct protoent* proto; + int s; + + /* confirm that ICMP6 is available on this machine */ + if ((proto = getprotobyname("ipv6-icmp")) == NULL) + crash_and_burn("ipv6-icmp: unknown protocol"); + + /* create raw socket for ICMP6 calls (ping) */ + *socktype = SOCK_RAW; + s = socket(AF_INET6, *socktype, proto->p_proto); + if (s < 0) { + /* try non-privileged icmp6 (works on Mac OSX without privileges, for example) */ + *socktype = SOCK_DGRAM; + s = socket(AF_INET6, *socktype, proto->p_proto); + if (s < 0) { + return -1; + } + } + + /* Make sure that we use non-blocking IO */ + { + int flags; + + if ((flags = fcntl(s, F_GETFL, 0)) < 0) + perror("fcntl"); + + if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) + perror("fcntl"); + } + + return s; +} + +void init_ping_buffer_ipv6(size_t ping_data_size) +{ + /* allocate ping buffer */ + ping_pkt_size_ipv6 = ping_data_size + sizeof(struct icmp6_hdr); + ping_buffer_ipv6 = (char*)calloc(1, ping_pkt_size_ipv6); + if (!ping_buffer_ipv6) + crash_and_burn("can't malloc ping packet"); +} + +void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident) +{ + struct sockaddr_in6 sa; + socklen_t len = sizeof(sa); + + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; + sa.sin6_addr = *src_addr; + if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0) + errno_crash_and_burn("cannot bind source address"); + + if (ident) { + memset(&sa, 0, len); + if (getsockname(s, (struct sockaddr *)&sa, &len) < 0) + errno_crash_and_burn("can't get ICMP6 socket identity"); + + if (sa.sin6_port) + *ident = sa.sin6_port; + } +} + +int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr) +{ + struct icmp6_hdr* icp; + int n; + + icp = (struct icmp6_hdr*)ping_buffer_ipv6; + icp->icmp6_type = ICMP6_ECHO_REQUEST; + icp->icmp6_code = 0; + icp->icmp6_seq = htons(icmp_seq_nr); + icp->icmp6_id = icmp_id_nr; + + if (random_data_flag) { + for (n = sizeof(struct icmp6_hdr); n < ping_pkt_size_ipv6; ++n) { + ping_buffer_ipv6[n] = random() & 0xFF; + } + } + + icp->icmp6_cksum = 0; /* The IPv6 stack calculates the checksum for us... */ + + n = sendto(s, icp, ping_pkt_size_ipv6, 0, saddr, saddr_len); + + return n; +}