From 7b6f26e25a9ce501555ba3f1ad6541774c65dec0 Mon Sep 17 00:00:00 2001 From: David Schweikert Date: Tue, 19 Aug 2025 10:05:27 +0200 Subject: [PATCH] Fix changelog entry for the new -p lower limit --- CHANGELOG.md | 6 +- ci/tmp.4rIIEYCP9c/fping-5.3/CHANGELOG.md | 299 ++ ci/tmp.4rIIEYCP9c/fping-5.3/COPYING | 17 + ci/tmp.4rIIEYCP9c/fping-5.3/INSTALL | 177 + ci/tmp.4rIIEYCP9c/fping-5.3/Makefile.am | 3 + ci/tmp.4rIIEYCP9c/fping-5.3/README.md | 50 + .../fping-5.3/ci/build-1-autotools.sh | 61 + .../fping-5.3/ci/build-2-test-command.sh | 6 + .../fping-5.3/ci/build-3-prepare-macos.sh | 13 + .../fping-5.3/ci/build-4-compile.sh | 28 + .../fping-5.3/ci/deploy-bintray.sh | 14 + .../fping-5.3/ci/deploy-coveralls.sh | 16 + .../fping-5.3/ci/deploy-coverity.sh | 25 + .../fping-5.3/ci/prepare-linux.sh | 7 + ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-lcov.sh | 9 + ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-tests.sh | 8 + .../fping-5.3/ci/test-01-basics.pl | 55 + .../fping-5.3/ci/test-02-help.pl | 46 + .../fping-5.3/ci/test-03-forbidden.pl | 63 + .../fping-5.3/ci/test-04-options-a-b.pl | 218 ++ .../fping-5.3/ci/test-05-options-c-e.pl | 365 ++ .../fping-5.3/ci/test-06-options-f-h.pl | 231 ++ .../fping-5.3/ci/test-07-options-i-m.pl | 94 + .../fping-5.3/ci/test-08-options-n-q.pl | 187 + .../fping-5.3/ci/test-09-option-r-t.pl | 149 + .../fping-5.3/ci/test-10-option-u-x.pl | 48 + .../fping-5.3/ci/test-11-unpriv.pl | 95 + .../fping-5.3/ci/test-12-option-type.pl | 27 + .../fping-5.3/ci/test-13-unknown-host.pl | 11 + .../ci/test-14-ping-internet-hosts.pl | 106 + .../fping-5.3/ci/test-15-netdata.pl | 35 + .../fping-5.3/ci/test-issue-56.pl | 18 + .../fping-5.3/ci/test-issue-58.pl | 10 + .../fping-5.3/ci/test-tarball.sh | 31 + ci/tmp.4rIIEYCP9c/fping-5.3/configure.ac | 129 + .../fping-5.3/contrib/Dockerfile | 17 + .../fping-5.3/contrib/fping.spec | 74 + .../fping-5.3/doc/CHANGELOG.pre-v4 | 627 ++++ ci/tmp.4rIIEYCP9c/fping-5.3/doc/Makefile.am | 6 + ci/tmp.4rIIEYCP9c/fping-5.3/doc/README.1992 | 43 + ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.8 | 420 +++ ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.pod | 345 ++ ci/tmp.4rIIEYCP9c/fping-5.3/src/Makefile.am | 11 + ci/tmp.4rIIEYCP9c/fping-5.3/src/fping | Bin 0 -> 147200 bytes ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o | Bin 0 -> 197824 bytes .../fping-5.3/src/fping-optparse.o | Bin 0 -> 19304 bytes .../fping-5.3/src/fping-seqmap.o | Bin 0 -> 13288 bytes .../fping-5.3/src/fping-socket4.o | Bin 0 -> 21736 bytes .../fping-5.3/src/fping-socket6.o | Bin 0 -> 16832 bytes ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.c | 3201 +++++++++++++++++ ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.h | 39 + ci/tmp.4rIIEYCP9c/fping-5.3/src/options.h | 52 + ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.c | 266 ++ ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.h | 103 + ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.c | 124 + ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.h | 21 + ci/tmp.4rIIEYCP9c/fping-5.3/src/socket4.c | 166 + ci/tmp.4rIIEYCP9c/fping-5.3/src/socket6.c | 136 + ci/tmp.VwGIuQgZdr/fping-5.4/CHANGELOG.md | 299 ++ ci/tmp.VwGIuQgZdr/fping-5.4/COPYING | 17 + ci/tmp.VwGIuQgZdr/fping-5.4/INSTALL | 177 + ci/tmp.VwGIuQgZdr/fping-5.4/Makefile.am | 3 + ci/tmp.VwGIuQgZdr/fping-5.4/README.md | 50 + .../fping-5.4/ci/build-1-autotools.sh | 61 + .../fping-5.4/ci/build-2-test-command.sh | 6 + .../fping-5.4/ci/build-3-prepare-macos.sh | 13 + .../fping-5.4/ci/build-4-compile.sh | 28 + .../fping-5.4/ci/deploy-bintray.sh | 14 + .../fping-5.4/ci/deploy-coveralls.sh | 16 + .../fping-5.4/ci/deploy-coverity.sh | 25 + .../fping-5.4/ci/prepare-linux.sh | 7 + ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-lcov.sh | 9 + ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-tests.sh | 8 + .../fping-5.4/ci/test-01-basics.pl | 55 + .../fping-5.4/ci/test-02-help.pl | 46 + .../fping-5.4/ci/test-03-forbidden.pl | 63 + .../fping-5.4/ci/test-04-options-a-b.pl | 218 ++ .../fping-5.4/ci/test-05-options-c-e.pl | 365 ++ .../fping-5.4/ci/test-06-options-f-h.pl | 231 ++ .../fping-5.4/ci/test-07-options-i-m.pl | 94 + .../fping-5.4/ci/test-08-options-n-q.pl | 187 + .../fping-5.4/ci/test-09-option-r-t.pl | 149 + .../fping-5.4/ci/test-10-option-u-x.pl | 48 + .../fping-5.4/ci/test-11-unpriv.pl | 95 + .../fping-5.4/ci/test-12-option-type.pl | 27 + .../fping-5.4/ci/test-13-unknown-host.pl | 11 + .../ci/test-14-ping-internet-hosts.pl | 106 + .../fping-5.4/ci/test-15-netdata.pl | 35 + .../fping-5.4/ci/test-issue-56.pl | 18 + .../fping-5.4/ci/test-issue-58.pl | 10 + .../fping-5.4/ci/test-tarball.sh | 31 + ci/tmp.VwGIuQgZdr/fping-5.4/configure.ac | 129 + .../fping-5.4/contrib/Dockerfile | 17 + .../fping-5.4/contrib/fping.spec | 74 + .../fping-5.4/doc/CHANGELOG.pre-v4 | 627 ++++ ci/tmp.VwGIuQgZdr/fping-5.4/doc/Makefile.am | 6 + ci/tmp.VwGIuQgZdr/fping-5.4/doc/README.1992 | 43 + ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.8 | 420 +++ ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.pod | 345 ++ ci/tmp.VwGIuQgZdr/fping-5.4/src/Makefile.am | 11 + ci/tmp.VwGIuQgZdr/fping-5.4/src/fping | Bin 0 -> 147200 bytes ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o | Bin 0 -> 197824 bytes .../fping-5.4/src/fping-optparse.o | Bin 0 -> 19304 bytes .../fping-5.4/src/fping-seqmap.o | Bin 0 -> 13288 bytes .../fping-5.4/src/fping-socket4.o | Bin 0 -> 21736 bytes .../fping-5.4/src/fping-socket6.o | Bin 0 -> 16832 bytes ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.c | 3201 +++++++++++++++++ ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.h | 39 + ci/tmp.VwGIuQgZdr/fping-5.4/src/options.h | 52 + ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.c | 266 ++ ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.h | 103 + ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.c | 124 + ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.h | 21 + ci/tmp.VwGIuQgZdr/fping-5.4/src/socket4.c | 166 + ci/tmp.VwGIuQgZdr/fping-5.4/src/socket6.c | 136 + 115 files changed, 16607 insertions(+), 3 deletions(-) create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/CHANGELOG.md create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/COPYING create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/INSTALL create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/Makefile.am create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/README.md create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-1-autotools.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-2-test-command.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-3-prepare-macos.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-4-compile.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-bintray.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coveralls.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coverity.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/prepare-linux.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-lcov.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-tests.sh create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-01-basics.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-02-help.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-03-forbidden.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-04-options-a-b.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-05-options-c-e.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-06-options-f-h.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-07-options-i-m.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-08-options-n-q.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-09-option-r-t.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-10-option-u-x.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-11-unpriv.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-12-option-type.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-13-unknown-host.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-14-ping-internet-hosts.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-15-netdata.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-56.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-58.pl create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-tarball.sh create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/configure.ac create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/contrib/Dockerfile create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/contrib/fping.spec create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/doc/CHANGELOG.pre-v4 create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/doc/Makefile.am create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/doc/README.1992 create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.8 create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.pod create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/Makefile.am create mode 100755 ci/tmp.4rIIEYCP9c/fping-5.3/src/fping create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-optparse.o create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-seqmap.o create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket4.o create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket6.o create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.c create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.h create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/options.h create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.c create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.h create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.c create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.h create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/socket4.c create mode 100644 ci/tmp.4rIIEYCP9c/fping-5.3/src/socket6.c create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/CHANGELOG.md create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/COPYING create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/INSTALL create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/Makefile.am create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/README.md create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-1-autotools.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-2-test-command.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-3-prepare-macos.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-4-compile.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-bintray.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coveralls.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coverity.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/prepare-linux.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-lcov.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-tests.sh create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-01-basics.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-02-help.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-03-forbidden.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-04-options-a-b.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-05-options-c-e.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-06-options-f-h.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-07-options-i-m.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-08-options-n-q.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-09-option-r-t.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-10-option-u-x.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-11-unpriv.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-12-option-type.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-13-unknown-host.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-14-ping-internet-hosts.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-15-netdata.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-56.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-58.pl create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-tarball.sh create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/configure.ac create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/contrib/Dockerfile create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/contrib/fping.spec create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/doc/CHANGELOG.pre-v4 create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/doc/Makefile.am create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/doc/README.1992 create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.8 create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.pod create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/Makefile.am create mode 100755 ci/tmp.VwGIuQgZdr/fping-5.4/src/fping create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-optparse.o create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-seqmap.o create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket4.o create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket6.o create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.c create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.h create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/options.h create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.c create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.h create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.c create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.h create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/socket4.c create mode 100644 ci/tmp.VwGIuQgZdr/fping-5.4/src/socket6.c 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 0000000000000000000000000000000000000000..b2aeb58113dbbc5919dae269e6c3a0d9e78ad926 GIT binary patch literal 147200 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..682a6a51bbc8ca9620ec0445e0857cd212cd910f GIT binary patch literal 197824 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�e=X1V75zp$A|` zt>`aS^gqr*|CFNtvZDWW7W%gp{UwV2Pg&?cSM--E`q*TgU<=!Eki}{Dui#%`_hDJ+ zv09>Rq`yqjW8F&G!u%I1`kjh?Sr+1S^5V< z_*#oU{eMb3^LU%8|NkHJ%*{OJl1!PWL>VekB#J^AGnILaG+aU&NJ$}6GDamKlp!Rc zQn@80h0LNsK2rVG`|Q{I_UiTR{PkOp$GzvA=XveddhhpMd+oJ{v$ybG;D>}q&v%RN zNo8O8{0@UY4v3Egw|fX!as3$ZWa0k&Lc8{x_5Qr=M#7(ik6nw!`WL~w2%iQ%Q249h zDZ&?mPZs_r_*~(uz?TbO3%*JCCh*6?OE|1&5g&wcI$H~pOO=iJVfTTy+F2*)}1Z+48riunvC z|3PsY`3xa$`;t~nKa{xbLs>EYTln*MY>aKi{r&uf_Z!Cf`kAS5byV*#^0&U-is?CT zuf=J^=Z5!Q?-Js_5`Poi@-v+L*OI<@;C{UQW8x2y-uoqsX9V$INdIbh@9|s&w|YmC z{!ii$6Sr#-t(bp?@aH~u%+`u=J0I$C+BJ|?jN5Tb=hcYw^+k5f+=}V>x~A)ik0Kwt z2Gxqi|44Z6@eCyXC~S^Y6|Z6CWM8 z$J30stqaa?2e){}kp4c>KSBP(Nzd^=LV7;G^E7cguI_P8CvMk2`}#hYxLyD3`nQSm zdcB7De44K<#JiHuUgFlqJP(J7k0brx#21i%MqAlJ(Y%!hx5?fLf9_w4I3M4;jeIzt ztw=wf;_O76`%k|wqSed&*l5zT&lIZnFvS@?A3j>&7ZP7gdS1WYA%8oc;>+s;;(UH& z7x7k<=jgfaQN6a@y*>OudTS@{A3di%(ibLvg)NX!?1l5`&n36~aQlp&mmc|W`@9A| zrY}nV^@w*Q-X=l49Z3IV(0hC6OM2eU4kkS>-zSLk@|{aQP04>f@xx&ryxv{pvxxZT zr03^nC1Sxg4c>t6-dEd0tGsCb(6@@%a9S>6=jgZzrG1 z#G~gzNAYmK(Vg@*2Jrm!A^tk?!4walxAOf1i<9&7H0ik=P9}fu=U*dk+bNG{wQz6$ zJBZt0+4XygCsX|2f?J%tpL>?{?DHG(rQ~yoeE9fhMvRL!581(OdD+;&<1b122^4<~ z()0P#JBTl%c-tHzn=lR|Q`o~Gnc^*gnDT;F{ z@tdhV&mn&vpD#(kmlJ=Qd^V83Ef?Ru?<8*hp7XuLdAoU%xb^d{x91OAvE^mkap&=y z!h_rR#Cg_i;X^2<=j}os;w!>;zTC?a=kZ&8;`>Q|GjVRucM<3Dc`xGJ@AW5sfczgJ z{w;BPZm<=buWXcuX~Zo*K3}tmTYj7`BX0eb=WP{nyS~WV`4-~bzwIDy%gg;gCvN*M z&JPf`e$4B&=Mr17`QmziAF?z6XM*i+7ajVw-a$&kKCsRaqcIF5$Aq#6miziB+mM!;MPx` z2!FnOSCIZR@ioMG{oO?T8p_W%#5tdbiSz#53F3TxV7eS3h)`@fj-&jP2e2$q-P&{uCEoVcTM>7db^RH$4kRVZ^sN>|8N5R1k&^Pa~5$vez=Hy z__)*Cq<)y_q=Y$M2hM z@$mfKMfGw#et&H9Ur+w`lb-iq`cu94(Qo)2ur z;^%so5kDBd^1Qu6d?WEq#5WQDh∾8(ibuN1Wq4NVv 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..2d9e14adb00326fdb5761c57169c1002d5cdbc36 GIT binary patch literal 19304 zcmb_@3v^V~x&Jby_18PB{ z0m?L{johlO7esAqtlrO=Htp&rG6>ov7#;&)~xuY%t4aRq=DFd#BIXd_Hya zeSjaQy{W@zu;8{0?lGbGu~7Q~Ep_h(-+7S4J_>b~(cUNh_*#)V96aL(LhVPj_HHe> zE$Yrs-8*^4<}YF&wVx|ne|7voRVT1h8N_d!FVz0D7HU7DwV#_F9hdbuJjr}KxNo{=jJLj&t zCV2J1u26?bNGLw}=&V)tXqG#4be5mSM`qGmPtZhm`bb3d*o92JSJlI*0r-kBwjhClz zy*eUbIISZ7U-82yM#9SW>r&vdLuv67Tv_sC>fVsn_GLkI<>qIie+)I&tg7v-aBEfZ zXM(9uvUqt~FmZwfbpD72TSCiLM_gb5~W1j}w4{4#!x;!7G9;wJnWfk$p z6zpN4&WlOiZ54UG6DPifgAbqDLh{;faIw@aAt*yziTVkQ&!23<7hk_wD~XN^B1?j8 zH)t%HS`n{V1zqw_mV;tN7wxJneug%ldLRC4yV+I3&5jm@I_gT?N6Wd_;Q_usHa@iF zrDzd$xkB;zep@>*`{G~c&nu+S537(sp?JCf)Z4ZN4zrx*WOH*){vIr#&!XVMs`#tH z1y%8HgLPH$&ncXrg>L!#6l8u?{BO1KbEmw}bIZrEXsG>QTBv;*>$uJxI}M=m2&K-y zYU8JQv}SMlBAOCBYLP$M&z+A=2;FjsxKONu*94aYmmXZv1#3=_pMp~tq{Z}LJkWkv zt3pVt+Dr3Tu%j-|9ee-On>{HuV_SZxGo*Etr)=rIIX8az$r3~*6n`NU|A-3>bsG66 z8@cn_C}23EC+qmsJ|CgRD<~;tGIwM?ONSU*SU96`By9XeXGV7g7x0X3|GOJUhBA6~ zN9Li~TV6`tjA*i8TS)=3y(<1nD1JCv-Z9@zD@(A_S*g{=Ke`}y;~xc)yDPs*U?&u!mw%g`n`|RWr#3>gjGeUhvuM&T3a` z`mC(l4y&^GEpg7`Yf@%!>5kUXxddNVZT#ul_zTGM5vNwB4(I+UEsN$&IS})w?wy6B zbQGVbHHZ$O0HO9A$MQ_BS8c~-i1m@QVEaK0JY$b^T!v#BJ5d{dR^$>X3wwp8hrSZ| zU&3MsYvVOpv$uR4H7euRu!@c_jJ}Re;!GEG=}#w-^a~>J2S~V4S{6Iqu`mT)V9QIf zp-@}MICVEng;hcOknM*%Xb<@NPdXy}Zg5&|OWL$?@B)`xnqEi_ z;o~xgEz^hm8E^_4@)bJo!}!X?hrObaxw0Lnt!Ubg)nH)I@D)D|W#iDRHh>mCf*f}TdYsrJu)!+(JB@D2DHL>!W~J1CR>-7&#p>IaTF_u<)ruJaDe^|@ohSlYmZ z&35{;x6>#qU85X0OZ%E11zUgE#MoccE+ML9C)GH6ow4s@X(2xFt^RXu0UU{LE*me` zujSt5Ye=2|U@s+{mwf6cqJvKFzD@|5wj&7DdCDBTFpCadm_>(sWzhuA<7hH5(QohC z$g|}cp3z7kngB#_yVhG;)O(5X)^7xU;nKkR>W@h^LM9ITI-qXD`8f zoH(&s17FfP+Q?}(VUbrN%JKkJBEQD4ANSvM2sFxUF5~e`ekl0TZt}23p5jZpbLb4& z!-+IZX<&PJDM|^mJ;MlLBk^H7$pxHlXEBu#dl)3fDQnp-yRxPtXB%V2W3 zcadD(0|WTZyT%a{Uo*RF3J*CiYMn`3PZEcgXLm?PGCP}QoujCzX$yEtb@eJ#c3G@8 zoeA`$2$i-kY&8FA{BKt9)dv>-HsytPxd!SKm4h9B4O6 zu-ljPq_KVZ!rBXx)yDq+pR6t{a`V#8f?Mw*mwQ2xBZYW)&@V_IL;CkBc&Rrz$|4c7 z#x&PY9GENanAoR!rvt$Teo%-FzhsMZQpOL%uYvNUEaMjxUn46U^$Tp_7nuq>?juR) zr1vD{q`{O%eAA>c#Dvpck~jsE#bt}9et-ycGTKL%s6ZCaH@=k5m*~>Km-4fFmU8)0 zv0TcvmkLP_Z4l2Z8s^d$8d4mT{E!S1hs2&-Ot(l{9rF{Fn|R8$PYkpjbP?w6cMrMX zbhwM0r^BYIbVBa6EZIl*I0>{`*ucRMdV}IE)@f92UR=Qla8gNXB-n3-4Vz( z;$<;Odc}c4al73CPB=F{T>jktJhy-JMS1I3E-GnSZ)Bt!Y2QD>faXlhNx_}%`N0?E zjU<+%B(KDPX;sXXb#oS!G+A+mYtW-Jkz0B{ru#}pxTblhdaE*~c;P#fBbto}GP4(m zQZT6xqNGVZeBB^$myGDm#S_vtYMXHDm>keZDy@#t#$;Dz_`MonZz}VSa93fJ(rY`8 zwO32m`X>>Q532NV#=Xl>tvF+z_Sj7Cfe0|yoB+uw{ZImy=s}CPCoS3FT%oyQ4`mOw;}bK+CU6(>eN`DGzknuzb5`yT``2dw!P;{CCOwl7a6_-k)sa`;+hV0>9IHA3|^3=RJ;@JZ^~| z(vG>cI^&ovrjEpbf1TtHV7uoq0f#+ZUN8pGMI7rmM-C*IT`+(_5U|Is%{BJ8Uv_KP z7%$s$=8~Mv9^jijogUzwWYt_L70X=eTu6N=8OsmZRsr9i{3-#jCUb27ba`RsT$p*B z)SD~rX7t1*S14uNL55ywn|CGHKjFdb3D0XDZL#s1=MD1d8zgKo7pC9jB3U2M`~%2x zMY3$WujF=PiqdC1Mlo7Q5;R!$x?7uLyiU+HjGiNmZn#Xl%69!#OxzeTqs`mp)o;{x zVd0nd;FsRtdLihyu)$Tdi#WfT+y;a=qrnS8&2|d${^Y~x>?K-*?)A_eYjf?jxp<_7 z=esFzR~bJ^zBgIB$^q4J$PS&Yl<~0pH@0)Wq;9)sC!7NtT!!(b`&)u`+K>>+j5FpP z7F4;zdc#6A-mu=azz<3Ku5~O4=F4W&)q(CgOS{^5&f1#9fT1atl?>GLE!naXDDalPk4%-(Z7sG}}CsPES8nC;d-F_qE)+S_!v;x?NIhkm#I z76EVRI}F>oJB?A!orRX#=|`?|POC7DseoNA$Z4B5%^EKlk*bjS*$Mq)w za2im(te@7AL;GPEx{u)qq>|n2HS#&u>g=^TJNyKZ+lbx{KUgt3qSijm_OHxEmWjQY znRq6OvfSdFT}Eb}6=kg~cbAbDz-TRvex*H%8#yl4U}2aa2AjDgORy0t3EN0mCdtpt z)LSF&~oyHfe1OOMm+k*P6H zqNolw&5R5)MKd)k%}kkIYI-d92y>XFnJLyHD{9?mrd#P|N(}gK%seY#4z4zbmC~X) zVYBHGw4(y%1gpv{#05*Uy3E1UFE%GoH_bGyT63_a1u$4i1N65;T!uM#uj$io{D(RC z#sKE}sHkaXLI!jxG4qN{EmUvjO*ae5OfNAhGm|xQhz1TdZht+13^Si-7gt;Q5-`s& z2Lj575NU=v0ONtJ7}wI6WVV}GL|$X*6W%9k4R(#)V-Be{v!-IXhPK>-K`g@@3&Ihl zruSBkyD>|#wwszh2YfP#T|L~PPb63?HTzlZ8DF3MB&?vxa4p01WWx+(N>vma=5YP`S--XoA6jMRlyT7u>&S@+GGXs4;5Rn|PgvYq&pr5ar z3k0vLyP%3bv~MQ;z;rZcqOZRv!|ab?W=*}>f0~)O*z6zS95X3;@ZmAmg=N#)N12dj zn);Pd#9?%)r7xm9%s{qb-J4!&nq|;(G1qdURRwSWJg({MdB}1xFRnIoO9MP|K8>7) zJ(ixUaRp4A8;TUMfNX9!8LTZi7BF-5S%^crrC$t90S>?k@uM%n$#Gfscd0p)A1lbD zUay8+8f2Qe9EW`B>+NYhjbDYOy2qBEN(owH_Sekepak#XrRKmIGsErwhnbp2o>=`4 zIu2vubZ@mefR0*B#H$8qy6LvutxLyT{tGc;tEITmMy%&*~=4$z;yxr;LU zG3^-qbmV64D4d!AjMtykE;u%2W=<27>^U~K(5&~dfj1}Uci-#|n4{|{*>zl-!2B7T zIX^gHzL!8tABTL>7gm>oU|gx6#`Q?{LpRs&R(D#UK8#I+txPj3#7)Sw2AV0;%)udK z@q?SHQKH^vrRIRikO;RTetH%+4|`YDo9X%>>@2J9g5fnh zfkvZBQuOnx&9QJc5~)8vh>>Z{HV0W+mpReW4=_58`Y*tEB7_rLO1K_D^~g|5KLawJ zNxN_=O|8strYs`-;Z0q{s-BYI5NIexDFtxok!lII@`F0GnlEYk6SftZHp|RB;mxs?bL&rSqALYeGzjU25Sw`oo#{VOn3u|mvXWPnR7=m>ZKh{HF%m^m zv8~HY%``JJNn2=kyEz4YPOUkk)hsGCXH=Ux)6EejSg9eWyL`B~;qB|{HQ|-vhL$Eq z1I!~!=?BIO(WdZnw!9(Qz#7-Y@cOc)DH3T|*~FS7OCzh+v_`R$T`{L_PH^7*%B7cI zad{=J2$u9BcWpy!q-kk$xH*~-B;M~vSW|0jOJpU3+~|#Ko7mE&%VN!|qs`%^Eln+v zCi^`wq$dXA0Da_)kvd6gAxZBuJYEZPL!_%@>V$HI~3mEor4etPFR>+%Ku z^5V(<;)#KYfg*oFOEea4DqGnUZfb3A#I&KcaaGw3Q!XjEWRkyNrN7{ciT;8W4Urqe zjjLMMgxAC(1+nn@=J4`@Xv4DAO%c|MdBRBYU*oEVRls;V55u!1UB8kc#P~}LK0cn;|I9E>Wa&QwTycayVvzNUiy}HEM3vC zdiAn~#_MPqzF)&NwRL0RrW>LZy5$X#RrC=-Vm!!P2PvIJV#_dQVR$C-E}w@v(8vl` zt!Zg0T)sY1c* zl9J@^!aZObupDvoCx7?O$Gk{j{3q#3U)pW1N?+Diy~5{jH(GpIL0{TTAKir0e)$VQ zuGm9+*NQQJ(=?Oz2Wfwh_RsPaxvow2`O77rN-qn6{ug4;>(pbY?%Y6X2$+LNk%XI!q!l6_NxzM`Nnf2Pk5Qfz@zc9 zryj(e#Q!$ZX{!My?Zn@;DA|_}E1|8;?lSLOAhR4urPsAXA*#YpuYETXWw1}r_q9sD z|Mb;#`~69;r4-Cu4tg0Y{*u2BdipC0qVE=5cpNbv%jb!=Bw`gmmGY5kzn4p(j9nyf zTTaiy6by;~8S#+7V+QOpK`-CF_3Xg=0ft{z`)GR48@*nuy8X_!7e*7E;Wzg_n$A-D zK#4y6JMjJ&;59%ff7C`l%JwJ!i;&4&ZxDEqz~!6OYk~L0=Xyc^qIgc0`FXSCFP_GD zjsjCkfL+)EwdFqS78w55QNYQ4!X+3nHjaPW^v=BFuSKyYR**CA@n4xI8Q#!<#14xIRG z7x;Pwm+{`-Dd|%s^!ZY(OMJ1w2MW6> zujp!c8$Q&=IB?SQ6S051f`26NA_q=<OK99Q4Hh6h74O=kvUgy~Ka4m~T*UY5xx#IPrOr?`G_0-+|xnz={84 zF@He8i^cpA1)neGzgO_tV*ZrqrM=xEj>jDIr00D?&;NAbq>uE=YYN^h=I<$Zo0z|^ z;L=~G1upd&FZ4O*peKD+3w@HrbyoWSr-II_;M)a0K;V-9je`F$2R-q>Mer|h;AHRb z1fOCB|E<8~{ea}ZUGQI|$SoClwZXxM^7&KRh_*$cm-o3l6na@dA8_EL=QBc|hZOvP zz#nnoBv;nY#~nEF`Bcz9q2MP4{~PF zXRe?xQSjLUFIVv80-vSeQvZ1Zm-_S*^jA6PNuN@#4epB^IQeappbsnfjRIe<;P(jp z`wIS3fwwtur`)&$C%N5%zEi>fAn-dKIPs|!`tNe!#7D;U=L-Ib;Imuc(m#HI|M5HU z7ZpBbV*av%PZRTZ6#Q~AKd#`lVtz{WQlGnoKJpP-=HZos4u8SMo5U9i+#_(wXOG}B zM#1H|nD5|2=S$v4EmLrL-x5~v-`HxfjS4RB8@DOAD1)`1Td zJlAH!&MLU%lWf@p;j1xb&N>N8=TGSy!hhxU_4g1E)M}5plUp!LJi|tpg{0 zBL&|n@PBjQ#7FvJ zrvoQGCk6d|3NFvd0}h<{$otMc4xISpin#tk!3PWcaR*L(`itwuK?hEJWZoZD@N&WD zIe|<6ZxnfQ+(A$L<^A?42TuIo7JN=C_?rU%M!`=AT>ca#&-MEPH|a+TG^tOg&}XQE z%jbs@1wSq5uTk(U;h(4jr;;JmV_O_JkscBB4=VWI1pbr*Cq4u4q4u%^C(;(7&pQGq zd#Rq|PcV7=y8|bGek=TNM#29n@UIm9{2!XJPZvLYNWV#Zn82l<2MB|66+A=W6BIr# z3;i#4(3AdSxb}?AaNwl>NWrH;Rp1L9xKr*@2TpPq3;IR{xBnvp z&z%mO@>xE=|4_kYy}d`l>F+qGJ*41&wqf=M1()^eDFv73=vf7q&u_;ST>iHIje^e< zatDb&G?#ULkjT%83cga%PZhY#6MoRJHb-@bv;8t>7_%7dmh{r}F-4iUTKqZWHvS3QqqeL@g+AY42GZW}Oatir1?Gzg@xa z5cr)6-X`+%ZUx^a@Joe!n#x;JVkN@H{VZ)FT>i!@^(2g1uHA8Z`aOBNm`_mf>&3iS z!8eHcB?|rnF`uU3^7p+;fvfuX1x{r_lm?E-dM5F1LH9k;OI+56sDjJ;vivxJ` zBBqUz=oCz72j0QPR^lbgiZ$5B#|_JtwKlEmwY+*ws<@AAHEQ zGG8Uz8DgORiKfh7NjC%o3dIZwh(2w+J@AXT(R~XI#pQ^PE+x>Koi04FnoK4EFae^32`LdrOFgml&wpQpb?UieCF8g^{kh~-f^*4z9 zyF}fQYbxz*EcE67B2hS|477KW|EW|-x%3W=+7f(Jo`esgVu|)P9XLl*X{jEm7?FQQ zFB8%37WL7dT}Znc3w`OoYNowI>Ph;OD^&fr0_#hDCnY9Yk=-S}RoYvy(wF=;Az$t% z`6>9Q^69#v@&v@55c0pKiKD5s4`EHki2Sh}dy{+)vS%04{t^p)>Ay$l-z7GZ{&am+ z_1_DOm-{4sTI^TMWXHt*?2L&PdpPu#Pewo+AUX@K- x@`d5`Vv*?SNU8hjHczd6fLPl&`tEs;WX~?lA3ElJ?LQ&(|59!gz2Xk`{{Z{mgqZ*U literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..a586164f20ab24476e9fce927d33f8f96ed09300 GIT binary patch literal 13288 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 IMYH|?17eFlb^rhX literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..57976aa9c2aa256dab570c4ad627af7576d48a2c GIT binary patch literal 21736 zcmbt+3w%`7)$cho=gbUw%mgNo@Q_Rp6wo9DBJw671SbJ`1_>&Tc}!q5nZ%h14_kqX zSfYZ^`hC(?#W($Ktx~OpQmavXfRC#5t6Kf6*w%`omTDEWRqy)mz4pw>Cj9RG-MfFx ze*E`ZYp=ET+WS2AAscGu&2gEgp^|CLFfuKL8pcoOXX=%rT4@Y63XQ7z+U|dcw@wGN zbjeW^;qGU`n|lJ+{etRM&sihgRNlBW?{Sn*xF{1;-3K=JtesqbSis%yl=n#V8A6-8 zKP>Ng+#<^EcQ*dcCprkO=zimp6;+oW2o%khf*}inQT7(RZuf7#rF872?W~#7eilF~s2FYm6^aYA4seg?xyy+v~6L3sTN`{ zZiGCiy~iGE?d7jD4@ z$)#VG_Z)jU#fa)Qx)M&-}qLSR{hpT#7ckZL@8j_ z7Hcds)^2*nteyOM;z(8ZKggKCwto`O?5%UYDL>3^sNFhk&b;p9fxQ$SJ!Jp$;mIe3 z{TFPVSM^QRrZ1%jywd2v-orKB@78u7h4mEuhoobqSI9-5&g=f-#4AE|snMpV3o&g~ zE2=K5iX6zqWVrip<=?W>IU~b2rbhb0`<9Ja^t(F`))dx0Hzx<42%q>M+_rcxY&|=s=ulq##;SWk^VL-59#G2bXMK&eW6~8jxu_hksOmw6=nmgKz*5-Js z&1i0npPdS|H@3BPG>1B4@s**@#^x)dDRjg;QlX|;yd{+E=t?w4LyavhiD)uOawXTw zXev}&ec?jt2TLf{5{;)~sddJke#5X06EkO=jqD6$&h!HqBYu= zCAqU)qMc>Q!W6V3v(75027^m1Yzd7XR!7hn%Z|lUhJ?lrS_CSegX+#9I|!29|8>Ut zbp5HJ8T^@I)XkT`D+l$WE}0G&K&GhMZNWXN?(q)1m+IN{GxEIIzEQLZVK*_nc{w{# z%ErKfk5S#HOm(W}D<1eq>KhAUuZ2Md6?$$WF##Z^$Xz0Li`){qEpm^@v(5n}#GlKh zP_y4K;Tfr#Z?CUMspk8&4f#?v-~Oy;M2B}L6?riD4^-)oiODrgfHnXTwcdBAW+Jmc zNMoM?LuP-S#=K;Joea#T%Z*F+e3?In z8kTJQJ9vm1KEqo^Z4;TjnzEsgF)Yh6|C<^VizLuvN{O=NHKj<|@|phrkSSaJ%z+O= zsBC4)zCy#h5knxe|45m%<1fIF*&nB|6Tpz!CIz{q%ch!%%pRD=ihv=r$E2|dz>wL~ z)7S;TklBkU6VsW!Fl!~%hb=HMk#-Cee?={c+DX)|K`jSbd>^$CYCBMakL{nJ2ItuK zp>`Cthfw=BYQIJ;k23oJYPdzPUqWpXYOkX<54CqGlls(WouK-#C8Cv67>tn1Wqojd zB3&Pnzgg9@h7W+t#mrk-MLsdX)M;cD2hN}lX3zT00GnEa^0MBx*JDxy$vat@`jPBy zY5d*nJHVRvCFufG1a82{g9!A9w%5qR$e3c$cB}Av%ZFGZ`$>sE_ghGH5>-vv9~G(B zC=uY`9BdlqLCQp=73R)1N6-c%A|`i^*$+M3y1>kOkN9OY<%Uf!So6sFRFuX#jeP%= zz9)!R?2vIRd0Fj1RYtkLD;E}-LN)*DeC%;@G5FVr29vE74UZ(dM)3G#W4&nflZ_36 zEK4>viq(WTA%!;%!_vx=4)F#4!}mTZCb|N*=D=y(*eMzo&tBl(oB++Wq`O}@n;W}D z!=>mR$T>ev_n?#Rq26>4=d`8iei?x2Ebmd#kbVgKikSvkfjixg6N8A2z}-PinXKO< zjFa`BdSQ&L|Cdos?y{x~=@`yWdI1jusk{hTdB9)iRu)t4z zyVC>Sp5t)P9iqVw+LeR2mw^)4XTztg`R{Eg>@&;(jz7fwbj<2r_N-goxTGh=b-Js*rw1ro4o6W(M1mP!#Fh8W3D+a-4!G;>8ADgl?Z~HpSFh(Se&Be~{T=Z@}4_9cF zBs51%2V)Yt7_p&}ggQ@!t`o7vWQDQjPUHInFtkb&P%*a*#QeE;?Ab6F?d~khw@QU^ z8 zOQh(ohYQFiEZFnWZ>I9WTVkoh}$FAj)kMzqH&`sfS7RYn3uL2>*;r- zXvXgEQhkwGnQ_fd^4>8fL1(==F4I{-`~ezMcDc|5C%e?Fo`6Oup#MQq@ak+Agg4d*qmAIq7WQV=g_@XG~VKSf<*b#ps*h zbo0ARZQh2+62nahIXx^Q|GYt!>0u3{FlkKe75QR{A0TEyT$k${AkBw;rk-fhZlv2m zngxfWL2*?tii(W2*uJ*QPKO)Q(TZ-(*!0NQm0mc7HQkM^?tR&9j>p_j$c&0UH#vqx z%f9iMN$tbGXTh80n<>LyAXbK}ybx_ebd5+*ZE3n|L?PP7ROi;P5(p*pHUwp_4WZXo z(R*WG$MPcL*V+W>)mz9>9{9CY-6 zc9uYWPHu|3uz8KSA!rg?)<`2edqy@KlN~hO{_Jcy2>Nn@Bx@Q4Laq&=#iktHRj_v! zT@(B)(^eVuAp=UynS+)7XAiCoP8*B?g0@i}WO4aYCvvqI zj4h>`lmgSKQ$bo1jhm5FSYfz*x`u-ZJVosxXPD)|#pb?Q*-Hx=ip}NO%d(-$(6sUP z6X(vm)cNk-hjytdo0GZ;y}`XO+_YPAPU_ zFcX7?irvuo?EdB`e=yr!G_(i;@@Q^HQ{0hpV>mcy<&3q6c}8|NMPDXB&Jimy&0F&M7Rz`WaVha73i%k(OKU$(3FjPpTUeoO0pP3WSbfoR@7b zC4DD`4Foh@($W%Wp$Hqr>`oHSNXOJ<#M-syU~o)<1h`>pDFuepgVUhmw83$|3|!LU zY})5-c_*wEsbL+lw%g`X%0BX#ORSGPUwEv0%%!`mFFap)%_V6%TBw4uo+v-|m={?e zOUimsZt|M-)+R48q%R)CC>a(J!{0sTrPkji!y+(rd(A~wHyAEWk08kx6S+`fG1Dy; zbfnYbT^ebFB5h#O21VMSlP*`J%b9e!B3&*?txfi49`iD3^<{L=WZmHX#5JjtVwd$}&u(Y)6ZoZ`jg>5y5zB6pWQjiLmrhg_ zG_G;GB+(-4m!AC|^6!4n(_neQa~Q>8DmA=L2;ExN+psHo78&Pe8iOPN6dE#aBx|J zipUQ|i)irVE|cEpl zO>}6P;GnmWhI|18TK5Fgwu8Zew&}^W2duEo4tu}^+jp&Pdv37<^sdzQY_j`_(l_1q zQKg^9on4o25Av7~G}t+%)V|Qp^_Z{OISqBTS(sJU^xDLb^%JV7Db(XmO!W4Lr|LbS)K+m*fU=#VCT_Dxpf515Y^$+?7V4q zKLFENZ!+1_-_DtCn`QP8_v!}QKMkJCJqRBJgZXG&O*7?tn3z`E`6Lj`UQyo1?d3G! zAbVhw<+8Kf+cuP1CcTpW)POUV6K1+^*kIc3fdo(WxK9|S9qdGxJwQmgSg1RdTqvxf z*f>*|W!l9k8|+1*`7?W}uu?Q0ApRA00rBT~+)Jj}Lkeua=b%00Ael2=*jhkNA_sZM zIl?i-a6S8F<*9xluei@7VeS>Jb)xECaf+ARBc|Co?no<1au=s)Ah_aUa!{}#R7zYP z_Z0^{(>z^4Ve&3z@<@;SZ8Ev8&K}ud55ChLxzVok4X{VvVb|SZk5AckDLa@Fp1Ws5 z9b7lq{U@UD=b0O{hj`r46io@eS~Ja9A{A+iwMJ91_NbAJ#V1B^c4ov{Vi9`h8;Jnv zqK>Phk(41%&$x&rqw$thM+8T4M7z3zsJrMmYZ3^VA<-Cb>1d~prmk39Di)8lN86Kh zWEbmM>tNJ1#tOy_@BM(9LOw8ZF5 zU9GLrgj9m%G_Pt*7^1WD%2Y(CBXo?lL|PhCjW9KGbu`goNEHPbX>Ds~M-#DTYBnaCS503#X=2I5icrbQP|1Svp_10d z6tdD%4&)`$7XVy{5C#=;i99oNg#lJ`rxF zW7tUZm3Y-dla^d7E$ziZaywdE4VnPh7H_1u!Q{y4z#*)WTt)WNF|K1u;cgjNosrc> zY*l3C8qpNm&0jEo);#hqWQs%IrgcIr&0A6CR3pwF{w1 zgQf=u(3xnbFyawqq>&Y!G)YEkbtImQHp{7JQG@}a5L%aPrX%Y}5@9YJ+(JE9372(< z2qtY3jV-G)3dd>gFb#5e;i1{p)eGq;yR8`$BXByuHfRD8v6aFC5pl`J2oI0BThrJX zDW3=x$c<5QnDnGrJ~XCSgb*hdeX_ZuGa8AtU}|D5Lcv5MX%MA#6^%DXGf^WJRywL< zNpg^wNjd3Q4hX!Cq=X}Qg_oW_QU@j{JIOUfMedZAuA(_gi)_S75e^UFjOoBxwctQ8-9$QW9(KXrWcp5@~NtUTKi$ zDW2tD%x+<-V^O``VhMpT#aR-qJruwE@&O`PAtN! zdftMXhMH<}VtU;{Wo-VWB|=RNBe#>;7c8bt5OLi>VXriZ#f9&&|6?PC+i9UuNYON{ z?w|@SxOhiITZ|6&#)SL?1PcTflICKs7CJ7jT88QC>`amA%BP}dNzEdTj7)4tdT$2A zC^S&J5C)B=DoUG;vQ-`J(Xy5`$+9c1C~L(mlr_i7Qth3k6^Yu~n&s6CCpSyHH(yOHjL>LsSmG(!fiTR=uqNzxx5;T9J z(n6k;l~@Or;tL|Q#lT`Kq}DWXS5gv-&oGP&s;j4jM$e8m#Tw&$2`(wGIHx7rR6f3| zd<;XG;}rAi#fG^y&m5ZL^=+r;mPz!iG7Jwal-@-)%b$0XYp%cWdUusSw8?TcX88-N z{CTtdzB$=z9CacEUjuk3iQ|H>Kaa?LRoP)by>%1ElWRq73d@)r^ZSumGg3!Wz75zaFH@oit-Zs!{p2Z38YAUY5}K<)#F zU3j2WzE(`)-8|vqQB#3b4iR4P3*Zlmv~X?Nz_ zp_eqbL8o?oB)2@TIi<%fztHFdm)_7j+(v&LGR6=xz~O%pqlC?*Utdz@p9aS(mcHmO zISqd3GxRmo z(XTH#drpJzJq>=~H252Y3%ht+wf2rMez|-fls+Lpc^WzWh`%pA^G<^ooCbI7;HC4b z#~GB3M^=t(0nptx7viu26Z#cJNhZlqNhC8@uMi;#PxoNq&ZM=gXzH=t$*XYZ%X1@MaJlSAdR0#btKT@ z&{EOQ1xN`v_9TV30Hmbj+a!F7oO>9DKG@TgoS!=A2RZQHFs{@0oQD4Q4tl(WQ}PkN zNYIncRMNQGIv^jX!it_=)`~hYpihuZkzClPQI!6}?IQF9( zm|uLVL~Y>Cs|{ijN#Q7wa~r{RC+`Tm854`n&O)$q%h{uK?+X8CVwcoE}&({Od-^Qnfvzl-%*t>L@bZ{O8$bxXQg!__{uRm1NpT*-&*KmBnj#Q`N_%0l2nTD_A zc8iANehle*8lKPNZqx9&EdMqQU&wZ;{a@KNp6wF@TXahI`UNd%x8KJ>!on{ zQ8?X0YxrSq57%(DZ;sXQPgwr>8vZToU!&o_U_CF^@Wnh|ts36K?SzKk$8sLh@JG1) zn1KpMV!Q6s@O7-`!y3L?ns2E6M)_d{ z)2aPT;g7PP-_+y`X8A`oJdg3uHT+VR}$Hz1cKQ4zgmTUMZ zo|je)zm?}Vso`q9ZPf4p>$z3KH?o``YxsMNKd9k7tml5lp&p)JR63y1zs(&lJLvIT zqtY81{W3D?5~+?c1P`&4l)dkn>AeNbAtni9Ch8j#eqXk2g}*1;ZeqKci@n-o&CSt zfkTeE|NohW|0m1Y;3A)ep;4jgh0G5zBj{v_iE9603sC$IOH9603slj&d8@Q)Zj zqT%W}?ynk-_kKtpIB<;n7?1myp8k#u(37PlL|07{zAe>7Het>)qD<-n_(9mk_!12dGv1)#>ON|PhO7IoCJk?7IV&|>y$@{DaCPo* zm4Xr_?3M6#aE59w@ph(we}B%K!f< zL?YmFzU-z2R&q_f=T;qR-&1Y86TvM+r2@F@Q5zWVyMqYFIO-m*km;~50%tNt>3=Xn zXdj8gBi(Z@)gV*nuVj8*Up2lGP)-%dRQsyJ75_yF;8KmR%1Xlf;@`>R%kQr;Le%(* zzn=Ls6tcFL`S0cHlImA{s*U>`kX9;y%N`g;Da?+B|M3b+jj#NFIbpg?f{aV}hUI3> zu{v%1H2fc8KuYJZ9kO-mSevLrmkHW|{IYGFV&qb%T~Byl_WSB2gW`uexPI&Q<9-sM=0p}KSCH}Dm$qv(moEn zFSLcN##iOzMBNwvgM7oHp37Nm+E&H?yVLMLFk literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..52db65d6f5abfd5060411b14f6fca29c33d7efe2 GIT binary patch literal 16832 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..dc0098d732e04a3c05a966d4e3094b5963c5b124 GIT binary patch literal 147200 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

34#&uhFbbDG4T-(nT#PF^j@mqq)+P zdI~+}YkuRgDhc_=Jp`@hH=#!+*Q{UjbC}d5By%iWCKqB~^JNiS3-~hPDkWb}+Bp}d zpCN83`ia;4p?m@V1MUa7j7IT>pUJk>*FiPGWy}|E`f{mxE}*Hz%oT6>av}L|fbN2; z{8cMw%0YAi+XC^4AE#p6w($&H*d3$tz)4|I%8uY|jj>W8yhF(=7zv&MDWOr|dJ~af zhYJk=@HGNo66gisHw1oxYc&agAHX6uocEiS%C3ba@1jV`6h5#(bZIT@4Vpqt`{)>pWJcUtVZV?@J>d{)-dI_Nf-T}~ zMfIHDZ&XNOx6)*`#~TcJuX!}s9n;904SAa(dxxb7NAY2u*^oq02xd0ZZ_pfTU{SoR z=KFeRTb-$FwF=e5y&$pDB$nR%Tu#V3P5T#R;GiwQC4^^yK7~9_OP)$@196&GoEbeo z2McJ*CeH=^9JuJmK9;$Bxm{x&;F}rmia3^?e4lAMO&iaQ{Taq0QVKo`6K|MR>yF6J z7YK2MpUFqiHbi_Hu3{00-*j;*M6r!5LaOI! zrUO%jKEl3Rr^@ypp7o|we+w78 z5F@VTiqC0Uxh%@vo-4d;E~)(q`X6w`IKtyxPi{%XczbCve)lfUGw_c~WBU;0d?nUt z`e|wGeu%ul!26fRxKHIGPj2XQntopzy9KTIVgs*O7F&g<>`DV)uq?V09ZJBL16z&< z`8V>44^f(HdjWU>&>ByE+}8=gj&NSLiK-&*?w@Yd?h4rsOv&;&PtQouZO$3E=@MFAVc#T&`W+X5v1G zz$Q3v{}jcw2<%YEY1+1oUD1+qScKI8n$+l2T|<@#!QwvmGV2c48u2H$PaCN}An-Mu z)adkSN-}l?=n$SN@-iCn^MMRFnVSj(xLd-zNOS*BjY|2ZHu6Lz%Swe%>+%ZttxlqL zpMa|#0y{8;cLDT6KyH)F;cMn;DFG$OQpopiVWb*RMuG2WMk)lr?H9A)R5_fj&BYQO z5vjc&>(mE)tQmeed^IDnW}ZUeF*sQc$*Ec~VL}I&!!EFXXyWpdsqf*uS{?6ymO~EL zbv{aIGzc1X^J1+eaU|yNZ1!?Bds0?JwawY%NK|-?8o@*QfT=w*F#SZYLBr`NBrM3BUMsg=so1xtk!Kn56Djg@n%o-2w^Wf?d>gd2 zG0kQZ>-tozXVb`!8M1w&P?!BLP3An-8;Z;^l-+KcVxZI?O|*McQv0QmGaGa{Y)z4m z)?^lQog!m6iFbswXhTf2w@ozf&NMPi-E)pNBsECk149m4mMfTcE#da!sA+iM7RtfL zb~F}Vk6X&On%DLRjf0LNFPHC))}+GfLOcRJ`AxAkvG5~|%S${t=C;NauEz+qRMU>_ zg@HktM+w&WUK|yaD_}zJxzii*HA~)KL8=^jq)H1TPI=V=Dd$tFJ^h$lyIfQ}0NVMW zwElxibn=QAH^$LOXD^SV5$o94NI+e@4E1bWyS(=t(bdc0YizBBHgJ_r#}fa9tN~tC z`#7+gSe_!j4^*QU)kJ?KK%ZZX95ouHvvJjI8db<)Q*#R9plOX8XTsJo zg&Z>7oPs!Dy2U`nEbCj{tQW{RDfSYi+~&&4wnkMxuX9o+^MhDNV2?1qX!)y~dmnFy>@S?N9s_HT4^V5VlB1JzD^h~ep zV$y#CMM(O{6n#EWSzg(lDS9pAPfXF5fu8M^skp-DY_`wuJA8gMQvVI8m$~ecF$sE^ zTSE&J_56X@@h+c6z#i`ww@h6g@3x{<6`YJ#W*zT#kibsJ1Ry6tMZ39ZR=z9WDt7e& zFD`jN34E)$ZjgSf@Ll;0mUB63?hDO@_cL(ycXOTrTWA9))ezDe zE_4fkZU}UN>q@Rxj{q|m5O?~udLF=W2#h801^|BZKLZZM$|3QNR0<}9vX|FDx3wG& zp8@6tGJ<`nX6}oe#Ngx*^s42;Tc-(|*`MKE9l7Q}#Vto&oC|5py6m)Tgx`!}X?H7% z?1Qkhi!Hi=WLYX*t9kHX)EW2ee-N(XhQcPKelc9M6?FSBEc<}x0Q39iSRCR$3P-sQ z(P`SgEczmPlwFGFebC>98+rk3XHVGjwFOobBc<=4QpV)TbH$h8;3~j>fbloD=yVtm zaNN_F16dI`5#FbjQ1I$h28y(mOlTH|6Q1GupRZ0_Ygx-CBd;D1^h(&fkAkv0VgLalHE^L2 zfZho3qu$W(h%*X-5pZ1@rByk|lL1YF^R{bo2Tq(WWCFIMY0ap>tw@EhO^blXxtj7C z0Q^T9zaU?PM`*mP@L|U)Cb>%$b;8JG8msY~jQ38`Kxz(V#RV!Bh9KvnF6M=|AFUAb z2pt5i=Dx$A!e<)IA@WoyT@I1OaK+6*_6n7#=ai-faYbq5TMW5firhVo{0~F!nIex) zBkwfip(*k-O{PjeNwQRFXuiOVuar+{JR8Oh5|6h} zFI5}zUr7*4^4}F%zK0y4wPGsUT2fi3(PZDH+0kj+JJay{HGUbM1U|yNq!CqWfRS6H z>ZD=(XnOZ>r*z&U(|C_kyzGI(qtlsYrZLTLVe;-z!^=c=nM6dFTB`8~+Dp>-n-$)3;-*OKJJQIH8FEdEd~cf6H`1iOnilOx6RmeDn#nko z@kgpmQJI;C$?_1)Y@Nd6`?(bgDeTiUnbC$A^0pLtX&QO9A@50%H>C-`$dHdo>GXUW z`EQ0iRg+;Tfu_yNL&E+bjqN4F)|ir#uSYk`!Pkbo`dpKP)|xCc4x^G|n7t`-eHyvW zkju|Au@6rp4>9CXDe~g9v}YS~!U*>+NQ*7gZ8RiNl29nRqY7T^BZf#cx~peWWj{fa8EbM&tjp43 zovC8UUhIuD{B=fJqj}bZ|I}pJJLTcYZBl;P@V4|$)tW4Md#CY!q0?J}-f2)e)A4Cc zQ4}%^j04>8h3QN;q%n1BVY1)Qcy6;hR^s)_p4wsFS$Oqn9s5C@+_2>sl}`=r9ieh` zI4X&k)yxTh)b(^#*RxR%li^TfGgOUT0q9b=@E;>o6h^Se!^nBj;NQ}^KrMTo#&f#u z8-?c}<1&qAk7_@W7B?Tlq*c0RtY<%~$=n0cQIWAUYQLQpYlMmQ&5cS8VgHgAYo?CX zN!Vc|$cuVjU}80-(#q6irgc*)RybFq`TAg2rSUwec~I8v($F;2dOUjnj376|Lm{iE z2)%gk&=xifTy2$y()Pw+x@e3f%Aa3i)5oxAA=+MW%QVF#kIzHUYR(^zdYHFRTpW~7 zmB&#D8{wk+@hY=Y;mYH9BZiA|v(zO)xiWSN;F)l!!b^klYy4(FSHlfmnU5_O!QkyP zRZ_=T?E&agjN%P83t%DTrF2UOvI3k_&Jt_xZ*JjFmx1@Zk)8e-^ z*me@kw8w#y+fX)ui~k#u+fbfC;3)#!hOz^Jx8b@nirkCx1t9*1$xFX^W4jyOF;WAy?@;z>a1~`4uM)AllyUT1PpN;q^h4-9~ zZc<1Qo}kIH8$KzG_YA|^vJ`P+8hMo=w=6}h(`0sE_b4*DFFQU*rA5V_QE2Xr2$yKQ z)P9f#sO9%Y^uJSDPSRwq8F}Y5;N+ zKE1Vtrfe+@=JON0*4!{)EemFRjc2Xh9x-|Sfl>bogjoUDDnCZfr|7jWYarIfH6Qnp zfrmqBw57JW_>n@8@pyHxly5cPd_3k&ZbLeQg1Ow(^$X14d$@*~^Jf6pinxwhm~()O zJ(0wdI+&w&>|j2x4dNXY)Vq9EFOM=`LxXZYYXbPk!bO?AVG4H!;8Wq`Y|GI>InG`W z_+~gcU%OMQXNlEFc49DV@&sDwY1k?TmhEtguM}urmbeFe^MZ+s4d1um`I3D0(^?j{ znQR1^MIrZPs{K52n~t=?h!#f1cQs?$#-9{pxQ%Ayh7-HH2H2VVD8rO^cahl~79Nxy zVVVXw+UYJMV6=19g)$$IH&2uK#2T*TS)D|9fkw-nH`k_#ILnA=Oo_N9O~h3#BJM~N zA&Oo?-TJ}u`6}JhQGC3tW_IqGi(zMeQ0_X6Wn*^_T=WDy)S^MT&d~>O7vk=Q9mEuF z0pL@JyAsdH3{}t918yQNiCbLZ9!Ky2I9c}zRrlN^mQPW%t4w2886V&{}y^bq$Y*2xorJ%5x!fqN+bJR12nQ#Dqg1CdFYle5XJ7Fg{_xhx3)E=^blmH6h~#J zVqyQ0Cg>w2DEp8&_)g*fMO0^qsybDbCha%?qd^>e=Xi}ma&a2{jonc*(VB}S6SiXt zdstfB-X?BK8yK4wYji4Bc%nwjHn1#B#Q8=<&$Q&1Ao-PPf^JL+@~+nC{;gyMK_fAw zmj^o!=5gi>Ec86%cPqD-3S-mje*@qR_0|$cQfDz;IQ(tK zu^-U%c3V08#Mx=uwWxUN^o8ORE0>>@16~|^56v~xE~F;dKzVj-FxuCVc7*@pahg6@ zRJpOEQo675#J^5NB8#TZ6U*%!s!SpFTbhaA_r3!L)TcIoR3p`FLa6aSR)GMrta$Kz~-SDO^t39q}x^Mhw;u5Yyn>XCw_j2w z#DD$|gR}Q(J?0_3Dnz4s^c3E(9x4UyVC=+CS+vwbUJmydyy>r zJ&^M`WnH1!57Db5@|f4gl$Qyi@0VBDDOpTe4dD6(a(11mMa-&5FYG{8RdotZjE-BUV!qRCexq2CmluV2_V zX#O52?9sYOu*0gEC9B4BUe_WdulWg{uw8BPA)hC?)ZE}` zwGq&5jmL}U%z0ZC0>3usicN4j5_58^iiA(tOb25(YNKY2ZdPOt&emx(KV^Acp#x3Z z7GaY7DNUgg!P&}~~gmj!Qm<2`eo1Fvgscqnw4h?`#+kC zQ?9R=gm!85*hTXRZo5^eCf(AQ%x5|oXgXP=X~5ArvPc3bjF3#uoKPn06`GCBu*<=0 zV^eu~PqWb$CP+3kheK>(rXI$SYx)1=dL)hO4#O4Im5*FWHHH1NVS{F`DK<44v)uux zOPv{x{Om|ORc)-xy^EsXm&_f#Q9Vte^I5sp+*lI!(?iM$XEV%Cj_?7Q9c9TMYe#RC3GG*osd+s69+h zvE8HD*oihMHvUZlooM4bstiQ<3(dn8Z2zDEme>p(0VO7XV2%jP{P_xvKis71G#6FP zi?MFhvAT+|JX#89juq|Unup0eFL}`B_Fp68fqYz=h@CA7&(>)9H>P<9<U;qg=td~2HU-bxDX;LWsHXPQ{6b*?OHT4Y@tSLwGGKc1Q10wx=T{b8ESD_UfJ zr_ogSL4|IqzlEk^!W}y+!LrGnr~z36b2PxR{Jcf(rD;6TQ*^7JlG1g&p(xkniq^Y-F{(R&RVaKHj`|(g=XK6BXP=J{h47OTwV2&#k;okby79xkqt$&Q?=|;cyQjFa9Vm+(`rcnO?Z32Dm5|?xz8+ zJ%>kWfV0l_#TrjC9qs*~gGOs>G(Z{_oZxM)5;GJ(tdAeT6~b+-%PR>W*xuQLz>9BgBfu#N@pNVw=JIcSG!-sc*? zm%(95bb)wC&HFqG_PA{b|NAolKYJj%CvQZiszI?$yfcORdXjCY?V_>-O@H3Y2 z@Fs}xU>!*gZcj{;@SKt$O@YhQh>vkKqU*0ymZNTFr$yeW`T6?%7ma7L`d#7C@vhKi zYu}hgEqv%Hkpfm>LS9&1JsDhbb@e?cy#r2ohAVw_HT^TZ zDy|MTNUbr)qeWTG+bN0be!oJ>Ubs502wG$0Dq#ndPaC*8t{+;*KxfKmP?1q@^0J!$ z1sQeRt%jBEDt@_FKT45~NwHi8gOT5n4Td;*O54TYn+AY~9mtQ$8g(RmprJ!qI=cC| zZaG+aaEBChI|6Iq4m(eC>yOHU_zbL-i{^m97zWfge^pyM;3E;uTAb4BLFiS-FX^nY zb^N-{8iSKZpjpFc#nLmyS+)=fb0K&u66HZQa*6mW1bAqNTs)2yp|Qfr)#3IC)WIFL zSc^Jzb-0S#dsiHi(j`oZyLbm9dVe^%zxN~rW)R@c-^&rW7*1~O{Tl*z!5y~wf2YJ% zgI&j|%v_zy)3P%luN6qIBKlKsp?UyWC>|GXRv!QfI9~dVS7ac{@V-DgO&gXEA0`7E zm&-3G467qnqV+5fmdbUJ21x2F3%oOxI9khV3012EupSzcx*QAU;c!xyGZ9z-XV1~` zI1ZT$9pqD>;X)nPJ6)4aZ_b6WwI`*`(L9$MH(h+W6Uci0Ix6I>1PSHQ^?_syE! z7XLsV%!>QnAm0HeSKOaQ;2&^EfZGrD>KI3)5|CS)_@O0is)pVe(T!8fRdC(TLnpKt zt{eZ1d?{QvbbNw6Ubp25AUdXI9T)4WQ(gnFBD!6j2W5n-PI(RRlvlg9xEoNp>bTj!$56*^lY2N&0Uq{hw=1}k zG1Q^7ffZ1~UM*1pp7UzoP(*T`Yd=UXbs%ey;lO2x?G$C7&+u!!`I# zFpq!?6eiC^IKnTz62Wky8ij80l%b%PLp5+X2DpO01OgUM845;n*tNPM@F4n!V9fae zP~a;h7xBC-KHG+5o<-_D54-T zO>Gez56@#pu0_D7&=|HuA?y$lx&bXEcnd-{Z_ZuBJweML>zC<6U0>!N7J==b6z8^ z4{_XnYxCxOM%=l?eNP;3&M(CMl{g*^WAo<37-F?Kc?_*%h#%2mZ5bFO=4&>LpLE-F}osR#EJ9h z&fO9ICq;NK<3^;kxVZ2bpA-p)g~w!BJrZ_AM4sH~z3iADH_i^qgX~3j-L0Lq~a~^S?tYjeBAB1?|oSg}5XapqKMF>g8 zZiX>i*pDM6hX|XM?DRvZC?7=|ZOULc>z`;*y>j`(eb3pk1I)N=cDPxmgVI}ev7WPC zQ?kE^BP#w|-3Yc@5h*&5Hy-#}EK2wz=oo$k{Qz;~5T*RPbF{S++e#GG5ZU}Ac?^Ff zXBmA$G|NZcg#3a3oH(`FBI9FDlwxq8@E9$hf9jclx;+JGPq7dm z!zK8is*|!QA&B9-1t;V`?FVNt(ymi+!}YrIAoU1XeI}nR)ueX;e;r&VA24$F^*lfm ziQy@AqnOkSfF6TO+>Zh}DvQywOThq_=nT|QnR*pKe%q9BuFl8>Q0ZG_Aeh(yV=;Vd^Z~-GA`56SjYkB7?v+X8S6FrMxZ(z>wKt&dn+hD3zzmOR(bW%#76euoZlP(p%wwZL-~3|s7Wk?5_gGKNDuPCoE@9%Y7jVtjC3_C|(zVtgo^ zvku{iJgq$(ajPt}BCha;6VcTm2%D$1hjVfsN7!XndE7d_?&V-4^dh9W6*=#M)@B~6 zC>&rSx%r{LKur807@ie>1$x+VdE$Cpp12;DC$7gY1WPEsBoorwniJRC=@ZvO9OZb$ zvSd=DoGnyMk8&s6J#anO@ZbfpG;|DDMb25X293P_`DKUei93R6R zDKdk@93SJHOv=pQILF68=UxiUkOLizbV$R;iYu4|Z^3tQi*lqB{)9N*g5MIykxrN= z*ju~>Ef{%}Bb{&rA&a+Q4sjgmgt;w@N597j6gF2wN`>_Z$!I^n^@@fIA7TWCWu z3T%|mu}SerixnB1OAdah7F@v4eukDZ6r~myGgQt{6GJTH;7ts%aDp5%T6-9}k0EYd z3qHb70=FRl+h?_A=w*g_GV~5ZM>Dh=w@?S_Ge!$qO0gNXakFVzH``l3(V^+TcjZuZWkx0~<$5{yAAeK)DHjXK)z;E=NlKN4^Ym zsO0a8TtPg?O8)K$fBYsA{3Rf<(s1K=dq9{J35P|3DYJ?tYz9mI`z~$C=3vSH*c*i~ zL=C|0UBem{?QcNYCJLhLG^}m76^%po^J4?8N<3IIt^p7mWO<~Bj9G*RTmEN=?`8}l zG{g!sY6681uLFL#kjyyQeG+j?iNx-u?9g(qIvibJK5Rba@r_|B z?=t21!(l2YN~6zx3tx`%<6EV*2>Uq@;@cz;uz7-L`~?ZPqBQwWoBc8vMEvE<8YBaY zO~#*bcnF0XV2Uq>rG{5C-m76scX@tje0u@w-hB;-_-jfY&kv2io?u*M$>R}{mWt*g z&kv2?=hY5sk1^IhbUmFggdlR4MrNH08;-0_d2dGPcj0*f3 z`3-bIGZFPWAtU>0E3*ke9?t~IEVpFS>Bz`GFbYG$`UAJD3<_T;>0?sDPoOmZs{-93 zyERhE`3Km%`Q+IKg2*al%tjgW3Sy;NEqY|}c$BO@8U4X~FX;>@CaNv+I2g^wV3hb5 z$slthX`MKBO=9f2lXy0A{2T+xcg8Tmp_iJ zBV`-myfVm&O}7dffTB}LSYM&ADtKtqg^V_30eP`Ti4x#tHU9yvDi??gD@a~ligy#Z z7|$uaup6JyPXpXc6i+L?a1e{`UjV-(YAuqy@Oat=HxC!W#a0s4NYrqEM-nxFs0(OY zivc#m<@0|s7iTf)TL9h!*JU!etd%*eKW2wGN7k)KV0BJ!$m}`qe$l zZGo8xXapQH1zDFaWDqUjc`#gEbO)uh2mbnUOy0nW?r-UIXv^Mg&HfI|`D5@pax0XB zwXkIfA7j-!_#4F{1SeoEL?n%L{&NMaB+K7+pgh=MdyHVoEKCeVI#y38mm@#YSXe8= zXG>yN7E8|sXPhFeMcKU(78coC^Tege^?YpN+N?a(`B2m@>U?r5Mtingh{xe#L(y?h z?oQesfS(d|BcxA0awJf81t#x-s#-8rOwH%;$Zi@{HE-s8F)dD;u$zwd&e937J-q@& zTk^dG;n7xu@UGGWhsaE6mo~GjT&~dHiCm}D!6GX?g>HuUdvRn!0d0Hr2JipLp zC3S+%!P~hAAbQnkI-99Xv~McW3Z8z{g^3EC-0oCzw5-^MEYQnY!XuH?0Jwr7DD-Z* zY{KUQJPR&=f#@zR{{aBE!S%idhPVL(n1a#JX=scI>;wK=IB%p*iT%tN@IWPd0q$ck z9F!}u-kda!(+=Rkwrl>X~LWosIHrGJ{J`%F}?mnO5T z`$Cbe&QdSoU7bdAP%sd!Xq`p!15Hbn@1I7bsFtf@7eZb31vy+5vpeMz7S(c9j8(&_ zA4RInmsNEbyN12G)@G9#m(@(8lpR7=C5A9?va6^=paM>I3{w#p2`3Kcli*W0JRfgD z8|ORfZ;)Co-%&rdrAW-QD}Of(j@S6^=us-6WMhXL0Xi?i*g8fT6war()yw%Q*XfO? zdnXx=I&1N??JUCy=O^I1L~a3RzEcf+R~asM`oPM%`40nM>pY6I)J)qPA<2<-z-Ovg z&mx9v)LU&9!&~8sdFzMYH-)DnH?=EK4B^1PfU|pr=w-i&42ta8cmP=0=b>(Gk*VII z3wc;t;;=Rr^#2*U9iG_{LE-d87S)uT>oh@J-=bH5j*6mR;YIGjO&+uMmc=(-aTad^ zA08;*YMuw{4t#@V@K!m4Z=k>*gA4HUgSXqB22}r6C?L2%_Y&-#OfCZIHh>qwg&Ki+ zSLVD;Yd&$&%6jS~s#FRh2lW%;zk5E(qz22tvjomPU3?}Hmjbv5uH+~ku`6`r%aGaC z%JpmEP0-XmCKc+=<#O*gUfmxjK3GyQ-Rw7;@fbTr#J=Rt)N&x z$I327xNHe-dBlXTM(A^J?Sc#61i-F>1OT|=ocG(JbK#s0_IaVUlJkupCHMz;oB5pzj!EQdbG7E+ zJoq>`lr8oV$lvp0kAY}=xX$uPh^1*To(_l_p}|F1rsWN&>}MF-dnRtU^Z*mhxqnbw z(KFJD79&xf?Io?~S!qRU0j?&BR`i^-qHO@Tz_mLLC~K=vA^0oV(hz&=7i2U13gkU- zu_=pHlJ&|H!%-fn?U!?@&rjg^5l$BIV$ErF2FuH(vWP`BssRkLh_eC2;ZS&g4MMc$ z7cuZ}3swVVvt4%pOD&vzAAsQq42H`iQ}{VxP6ad_uHqE{CB(jpz@5OXfvaR?mm5t? z08L6>YjZzG1gY6KVEzhDYW4>Lzrl(2I}rVP9lcJ+3Ue0Nt3m$<=WW!~zo5Us(y8ro zryW{_yu8CSby!H&r`!QDhW{cFvL~XIcVJIcj^pDWL*svhjliO12ic?_NfH+RPathz z30o|wAiJFn#cV^8YeQ!Sqf^C3*%d|Si;bnkh*k;6Si>R+vKv{`iQPz$wY;W31!IEw z7S*#x=VI283FJe}?Xoff_}h@~^+Y=!G9ZOq--bf)4aW67Nf1c~;w}$U+;*MW*2Lqo znwjkac50Vbu~W0g%8u$PnPxFcuMkco`EVE-q_lcnZd@YfWi_9KW+l7Dp=FfN4iQ?z z1(=DUU75@A0FQ=~qDM;6s{#InsBh4Wrb`2U4d4qzy@JGMNG`h;)(TW?sZQ1C%~^8U zQywQf#>>EW2^@OL2@-KVfNS7NF4qy6&0<7SJtYpJ(0J2FE=lVnW8Z6HCzVBU0V1|u zu<&#-Cxe-_n@;rdb-UKR0Qy$BD8J@56@>=YbRragUh_d0dA({xEzL5bzWDE=HXI~M zc50=W6AWe318zBDP;O( z?1$Xx340ZAuY>v$oP7y^?-1Anmq&*18em*Bwt#AIvY}9nd}O1Y@Zs8r)?(cStTg97 z@_~X60Q*#}10mOk>H}rHi&mck(RCL&X^345X+}Xl2fNl#NbV`Hr0%I!&_lKY&W3@x z0~s74*9ZG`EP+#D@lAbNK$QqB29&`N=fQuNR^7zk;jl)c_E<-qY|Qd!NkES z8%dsSBn2EI<#oG})G?xb1Z29DX+~C$F^tPq8z^D)IPJKSb`*dXcDv zy(bRD$PGtX3k0ymor~4UAYEE>i=wD9gQa(N`ga4>CoB&e51R+C39bwC7{I)Ys42vy`f2uiD#rH-up5C?4k-b?YlXm13t z(m|v{gwK_Z&_xJYyg5Ae+viG0h;uO(Zw@yc_+04--Af#A&Sv7c(h+)^INqF>aLbbW zIoy4DsJk#9Ywpilt1ak(-Tm<|p{X6_LWlcH@>KwVFc&)9-?QhTmvTkuZOY@#DF!}A zE_Ap7>udmWH;0Rb4w+B6ox{aKhZL#yb6}z4Vak*nI$$3;Tvm4Fjt(riNm{-LF+sVB z#95Az&xMZACB*UOTtgfeIznrRQB$rTrWQa>BK`wN7WBfG;=N=n; z4VL1og^nN>I()Uz5#&OLuNFFjTxo4%u=tw1TkcYAlEtEbF%IM zl$UUKR)Uz|GKc$-FT-5saCb#G2u*OA!`&U>t`58=A_lS2YU6lA15Ap9v9W{cvVtY- zh%C7$#C@NJ6y_?2`?0qVERZw+wp;tqs~nMm)^lKrag`&2RSr_{ zDKH_da;yZ&jd7JD(z43IPTzVJl$yLiwCx`VB%Z)6+CD17O-Mf4AsRzNNPLf3uV}|; z3BpQsVx{VUnKe=*Y^kibH!!kx9C}eVT0I}A@aG=*YBO0nBFsIZ(K-oO;hRu;(KeYB zW`|dit=`)Xbpj%P5Mp)+uR|1k-LV56uKY965qH#c;CnSPlXKwS>cmrE*osJMhWABE z;Y*GJnXkb6lu^q$@VK4>&*T)hr>401il&&kN*MSBps*OlA*Dc0ac97;0@O)la*Eqi zQ`{Yh<=j!AC7Dblf$-;hd<;@XHzPH}r`iu;iRXfi!fAg8!rAVsQP$SLj!rnq+jMW>RmE=NK|pXB1a z49eZL1UFnw%EJSiM?@4a5U0y2?i1QzLI^H{Q{1O_W7m8(z=cF{iu?3IEV>&2UPBb8 zxKBTx_52XP`-$Qd_vwv9y##O@T$1zI3-g%HE`T2rHD8<|r|k9u*aO#gs}Cbus+6+$ zu4SE_`&Yzhw*v&xzMCe|60+xLU^M_6(|1d7=a&>VXOC^n9xp|30;ZE8g~nSl4kkaT zT<3hVN(4Fo5yp(1Pm&Y8`E5}-{||X@9%n^ywE=hE>T2$teV7@RVVl7LWE&O{P(VRN zm|=%O2NkcwEHFBobMLSi6$CV96b?t*<@@vdh99@PPn|kdb?R(&s`_61FJPi~^AI%ts6QoSY5rxm09nCf?z9k+w`&A=FPXAsx#b%#G? zN~VO2Sq+sfV5+xHQoWaBz-#e8`d5od$)5)t5Oyb^(;A5h#8=gQZKD)dX*8AU9q>Uv zY>snZz*O&q3i9|aG<6I94`HhJq&^hoLwI}v|4S42!2uG9jzMk+fN`&2 zEOn?qgsI-SlIpEN*)05zo^HEKefzuVu9*k-q==+?qxESR{Xr$1DZC01z0DRw0OtE_^C;ucTx;d@vf%LM8PRaAO zEadOU0ZC^(^SP0seEY#sl&T4m?X@Z0i9y_pc*m`ABK@w!Y((a|SGXHXT)HW2pdb@6ojIyK> zgBpigrPc1~{euCI=wDMZy+657Hprb&vebS2486Q>eWklXpPNf?pAZ|(rm*{#xT+vG z*Kmz^{e%b5sQ%K6T*EZ@gv?H1Yy&JsVQi&8qJOd5yVuNqmq{-MW)2+agQm!23=X?T z^t28Rsd932Ps`=TKt+k0-lfW1cX?m-ZD_8`O1wQ`QfmIHgzaHZhgE|C>3tbKTv{H1 z5v1k<&Nl2x$SABGMJ~|YQGGM|Fd86dO!|n0iRsP2NKZh|s)d2jiE$xo^(mE6c6xkz zeR8a#(j|OC_S{s+luZmfn8qp?lMp-i6cRDhK8Z}i4nehZIv^bdl=wl@D$(o7o_ktl zuiQ$nrX)4ZQ!LL!S6BnqL8MSB8TC0O#jwh64dd zmboKD0?z{bqgIRz`)8X04u^rL>|IlmU+G-}H9FfsT|!GRaESgK+buCAL8sd3bfzIpHFBC#gastLn3G}HFYhy)=m(| zaYYQ$oJS-y{mNJ_FU1Y=N*k-<2U6cF@JP{=A&Uh@J0~#OxhW2xB0SDBJ}TcxVa%9Y zGO{4$*o?!dj2X`cf03bJRzE_oQTYRhelGAEnYiG8Nyv^2PY}2hm~+dfbm=Th2_L}} zzCJ18>uZFsUpP2WCRh7s8qx9;2jM=XW0v8@0u4m(oI#o03#WW=Cfo?l5U~`N2!*R6 z17Q4nW#G++h9oe;^wFIV$_w&oX%-ZODH@?9M6!iM1(P0x8b(z7)IcdJy^N?t(`$!8 z2Kkhe5}Bg~BoHvHaMR4HonHK4yI4gq+!*b`AciRlWUn}oz251=Pw7}mS}0T+u&ON6 z+V;tu$i5+^3=!%lx^Dz16u|zO0%)eBJaBEf#`or$AZ0+B02!M-urC9!Q!6>em56=^ z89gcBW6FjPmVlwMkWfvA;@6SWcxB8`h3#}@5z#`&Ss8%E1Eg7S6Ug8Ymx&r6GU1pq zqK}OFSz*wyOpZW6hZ{2=VIR`X{D`9!>_nqgBU5@dN}OJ9E_#wO!J~tKV@wdbjg`@7 zs8%&N8+b!e&2cp6`@?;caecFt|*Rm{Yoi{8uW1EyxfocnFy)JS#%b}5(5VB?T-yY3M>PH2xVNRGNcb2>w(ObO1i5F zq&$c|>{>R{v-oBXdZl|71`pBHT*Okck`uU++`u>F1(Rpu4;!{g_>rM0R((>=CA~q& zW9ArxrD*TaoI^ik1yo}Cg~e;;+!?P>7UBmhraspEGxVYP?;H9dW9R8{Bq$gCGIqXy zV36}O?0k9H#|)p9wu(g)N16YD8Cq)D5QHeAAlWP5!I>kY4rFxF(x^CEE-Q__ADR-+ z6OJXGRe`-97TEjY(m;m2A3^he;<3#8$V@&M^F9jQbVi5j7YIKEevHxJv4L@~PE&w! zfiZz3V;-ajsQ??_HXZ;O1x-v-PGF+J$Hya##x~U$m>hgf@ZS*3;DQIo0ES>)gEc1p zUx@#g;Qx*I{}lfJ4F5mG|A;#zQaJu3+&S{$vtl7X%JC67fp>gYP|d=JSIb9!=%s{R z$PexmxjnpF$B)hYxPc#E!H1STx+iew9>9nH0zRBq`1me9)SvhfLHbk`Fo()5B=-b- zcw_M4Ou>gbjURk1!&!ij$Z|e5@bO}Nxa;xZZ{o+*{NNG&$SwSkccQ<_JB~(gT+|*C z9j|l8;BmYjg2#dN+Fg=lt!nllS^vg9(D_0viW<_m*7N*By07}?6==CsSD;SyZoKC7 zY$U1O9$(!|+9jnWCHNL@m;Ksskc5gN6Ww1%E2EWLbsnn3{5PVL^@+UOtmm;uEjq@_ zHhg&X{O}L)6X^25DsM)|=>k;A+bp;d|5|(%dBltOYT0xHQDbWbaGu8Z6M7N#hX^{! zyHb9XXu0_K&TuLH+2w+*b}Dd|5PzRRE0YI{{UVyHyl&gC4a@UYS&sGa3^VaIz zCUkSYj4zb86Q^&nYFyeCy#G>IFn zQ6s5~F-&*oW=zY==HAEm2)qx*mX!1*Q`ftC?8kd`;dHIn>w>e;>RO#o*3@Gva<*NJ zifT;@bKsDsc2?awRG1LbDB1*{OM)Bg2+Y-d+cbl=~B&dt+EBI#3h=$X-4RJ|4; zl6Y1SwSS{7!gB#TL%Xva8Xc~Sb2G>jUWPto;oqN9SH64J9 zKpHq#;r2AtheY}6b+nXU%Ek_;OCben$n?$7?gLu)0q+WQ-dVb675d*Joa{Xdw`+Aj zkjbmo{i@}2x{jU;uowcrk1pyG^xndXb-FLEG%|hU8A6L||D=HW32425`Wn!`z$y{! z9+3y_uhXS?b{BwNs2<+}0KZ$BZ;E;eS^l3A+ zuJu=d{t{*+L0whX(_4Z|y7Md(FI2v6KltV`9V*Z07 zeHc`1wSPPdmFscw#iW^E`!a z?dX6&lwrp6eD$+p7qA?4M@K!vg`aUu5ad{y9uGoLLAJe3YVDF*8gI9v<{#VGAS)p)6u0yAFepMlc65ba zz)OuTQWrztWB%{0S>9O^{QyJCi6)OnqYAVjo~I$!(I-Hf3#)Z$k1mFtxe5kl9=^E-KZkrs^dld7 zjS)5wU6t-F(Z#G%#45#WebtSxY0&x6*T9M?Vp1uxg%H^VDi==7Z!#f4%pWgQYTJQ&&pOpWjE*u>AhIUIdZ;}mkVvup6XVEHq^I9e#=CAP? z68RSjSHO?f0|ub_Ac6v;0J^l^f(imqodKL5V6+Dqy#ox@6M%9A1i!x)?O--J)A_p3 z>!5tdII3u=e-Q2-;a;)-9leM=hcI1ecwfxRG<mH$Yt&}sa@HkL7*7VoAEWAY<<3# zX7L+JXjbE!lGyMiy0_fGff{(RzePg7VbgVSj~(ucUWJR1}1{XsJ*=4E3&1FMMixD&Pg~ zZ``CVL^;B7Kf2jJpS%N$3ZpG*ZPJHdS%xliUYdA?Nb{0DFB1$~KmsC@d(cF<^u3=! z2dKdL@YTNh218lck7K&Utw6JJ>4S*NCAlRY|bn#||su$O7w zlaLzoH&GX$&lDU9#VG+>5Yf8&1jKti`UFI@Y4caC5|Pn}I5`7L59(r>fzx5Vw&1Xwzu>f+qN)KXLz&XHdz}3$~7#iJa|E2CqC0;>DtZ(s?(I+G0OCwd}0wU!Ee&+|D zeq(@tVoX!)AM&@s_b~n`_U|w=A^iZ~LXpKB7H>9&4GOF; zwBf@YXu#Fz5QA3+O?l8nf8HS|b{kx+8u-2-=J?kG%wZjZqORX@2*z&R4pp#2>pQ{A zHxQhFk^I_=azuYv4q-T4L=58X9n$RrzZKX1x>#+f)@}#LskJ-w=|Do)HoOnAIZ!Cy zt*wQd@UcJ*z9Uf$1&W!aG2=8$z?h_l?!tJw^DrnePi4Y93A(ZB3?5?sY8wb{vDX>G zF^-k%3tnYC>VE~DKmbLv%pT9Mj9wwZ7oDPExM5K~%8UC5CHD-DBhg~ZXB>@J0-MH` z)aru>4dk|`1i^1HU|ieIlelpz3UEqm>Wm6q(xRs(^@QoV!~|kwBLXsnczwHZGXtVm zI!z$7Bj8i;y^a0JrD=xHG(%`wQcwEN3GH8kyaN8zwOHTL=ELaw>VC7*hT#4$ZGd{{ zirOUl9X?<(QxBN-z-W;%m`T{Iw=b)O%}S!=c08A<-B&=JeDzWUmXbm>1;UH9JO_#y z%<=EWEcDg+BlT1os~vhQFO<+Nf<6n8M?QITk%(sA0xS!wVfkpR&h=komT6cACiStHC)R+AH!2&$ zfWw3XQKzMtHNRUM#T72x^2t zdKgB}D}~Y*>HO<;?ickeELduFF1Q1xme6|L;77Rz3H);3yR^GZ_q_z46}s<9Xl#Wr zr|<^cw$MYY(D{^_6}T_P`UH=+2aj080A7S{M%U@yT-~EEDEOfKgzn2LJ&6L{80MI!lnJM?xDJ4wVOPgOm*BZIin(GL421%eZD~a2 zzWRrQJGib=2t_efNOb8o+yoP1rxCb+gX?AZR4@eDr0Hx^EvZl^?tK*Isb{ah*J#|# zb$9YPqt-GLSrmM&DH zGI%d0oWQRglxYyEHDieRy8`W1U4}FoFL)p5;PnSRSQCP6E|jEVymq@8O851ni%lwS zCxfd{PhfV2Q!IGM&SVEMuAWi>T*ws(~g@^+?bAgjFNnqH~C-=fG4!^O-7) ztkBiG;CL-aOc#bRCUpHc_yse93{`A5gsri3JyI`1mzyZ$Vb zGJ3guHtPN`i2fER6@egQg!vk<2__P1cnP(P>poY#%t3J_pX;lyp`-mD;6T(*dp0w5 zq}2mC`1un;Uhb*qkOZQOmV>|qN+ctTV>F@tON9LQ0`gemJf35gWe0j{4ecj#-1CL@ zGdQ_V`R2T2?ld7o2k3M+2nZdv1A$ov|p_Gd%pO54e z1sJmmPt5Gwzy-R`Dd^s5mIHwaSs_lfU_QAZMYJ;Xvp|)M4L#H)Vwhn!>FQno3N!|y z(7_s@oexiqTbjiGn5cHwQalsYB9`oxrNKDEG@^QQB;aeQgsAS9_3)M2ZP3F{((Y_M ze1q=YqlYs&wt`C-uHa@syNjdMlKnDO=YpG73@`hB($(pB%* zgGte9Q9SkfWemLRAEgT>s6ds{C%3^M;PxHRM@*{y?VRlbs58Fs!Wd4IoZKoCK*Pg{ zNL{byGkZ809OjxGX+-s?Bp#1Sz$Z1{;l~a@nR`Iu)eo-(>rAMu@*=YX8*sH)JFJdl{?%f0^8Kf1II59_N0h)m=S5Cn zhD9NlFRN;HTE+H?c}dGI-^Ag&%zO@9i~b@^>;(n`m;Q?*H`lV6CSwWF6XTg~ z8C?do{H!8D5(A+$B1P&05J8@%1T&A^QGWD#JvgPF?}c>0Y&Bw$dF(Iulm1M&1< zsgneOpU2op3zQ4qkvlFi=)z+DtJK$GU4fb2q6baWv7LToL}_%FOyi)<+=$^?a0nDR zf2hdfHm6a7dGE7#6kq7^b_uwCN|csa6MKxI8qi(o8-iVSfR z;Z?lghDeW?1z0)y?% zyP>wAC)aYa z+4fHaTxNOo73&xI-mtm5cNFhTc4q6h2%T8}wI2AYM2B&y%WnNsiAR%qz1 zOIk}SnJES=T0M*QUG>2=wpjMgL_BdIiIN5pN4)+p+N3Tt*>P7b2Dr%_da3% z=CXrQJBHd64r%J3mV6kz0b<7)(i>z9bkzlz^5|-G9+JVyukxpXW$L{v>ovLN->OIW z@1c%*!vO~8GaosPVmJ|wbz^F*qYsjDB~jP|Ghm22yRQmp=DS-YK*T+Jg)Jo{BFF`# zE#HTKihf3%J(NY=w-Kx4BENVi>fQ)}xtV*@rKM#@MF!YNgu#*E!0dSZr+&N;o+iOg zeG>_UeDz|Y7WaGdYQ@xDOk<8-{~Q?eOLcykF_FyuVI6upE|DF26fflXXHAe&p^$RV zQ=QZGbS!nS!L&%1cfx|Kdk0Q%s;?e~ycDY!lCsA9MlKw7DZohep!66E{p=+sLd@C7 zF-kD=LK3Mh21cnilfFX00I@^2v2~ZH5=l%Bv$9qcM>B3P(}SBs6aZ);up8WxKECQl zVyIK3E}hQ3)f+?@Q2e!xKr2)){F@n=1JnKAg=d(78)ODv(zWVKy}=EiblZvm5tRSdh}%Ea;E|3 zJN}(uArjE2G;lKjALx;|E!_rE&q@dS!zgek2bts#G5x=HVA5mirQG)cao@)#QUdEl znnOQ2l-m1R9v)c4srduKIO?R`n`9sOw6~7OEjhMR{0?#wVsUrsSJm9^6@hjPcen*xpk04ExyFlyF zvLM>1bGUpt9p_aLnQiiS{;OroowAI%8mlf@C1Dx!QOqo3u3cM;?IpO4zanz&Z5A?H z*UHkSfJp3>4g35yJrUi6qK&&iPpm`91WZ$*9ye1LFy@&dM`ze2h8>c?RWU9J?FtA9 zFuHN(8;v_(m?~?Z9z6u_?nhhv6<_v~eq?BgO6>4=;3$)v({ZY7vf*V$UgffeT*sZh z7^B1$y5CjoKuKv|5k{P#U|xgWVDbdcpNn8>Jhw=Y2w>7F0;3BfhwT8Z?t-_(6fk7U zSL+y)T_SSZcQ0-)mf4A&uk(M3r&bI=LU;z6JS&7_68`wP{+e~tp7w7>^zd2GT#xuf zod$hWXC#4&pq`W9t1n$%Z)Ty~SHDwc7H+&eTES`Pt=?5GyxVP5LU=&!ug0{}U!WB= z33e}Ey@CGEQgbfR!e9`uXDhu7m7t#p3pv+tU7#<4n$Vf zi{6vo9UB9Bw7u7hMJF8l-;{2iT}q?Y9}e77yE-KCG`hr$T;BvJNQ8i%twxV7##Ay! zBfZyw#6?QJ|0MVQkPZ^?58%Sdpdy5#Y@Q2a>Fjf|@70H4^OI^P@&fG5y=H7!dC1tx z)xltFSIZVCkq0eSjV(ey@+9(eEd#TYN|hzIYE8ZUNZ=6Ek1B1#;b0F<7S&Onumj1 z9H-Hj0oshMy93yA!A_`pPu)&!o_qCo5sX%Z1>?6E;7T*~3cpe86V4_sRph4H=^x5c>>TUGJGWdK?W5%wBD}(%C z#`Z!Oi`4Jn7YEhqqFOy*x-R1Es;93+e}<7}y&krMMTL}!?Z!*h>yZe1YjsIII#0ia z8e5Qkhg1R@oBpJC4hRuX%Nw30GlCM<3MJ}LOt$Qjg?uk|1C*q z1QGHu>g6^)l9yU7Pr_QmrK!u;^$t83AxP=9;{CvIKVQ3lY;a41}CWt2ai6 zHd5sy&kg+HG_1@$zko`zFw*|FtzmpYt`hSiE+ZF^dgkS2;A4ZD__Z465Tf*rH;E(x zP!7rlz!AXQYk$8%-mFh#bv7667d8U(jJ$wC3Whml+D@21n`7REa31VpCg@eEKxbr7 zb{-2w=%WUg<0cWZRk%C~XYyL~DC{a-pz}t7+QpJ!zC8vF!`NCad>_AwL=L9l8J zF&(E@`RXrMK%V$qte)7o_gKcGSX~E&g_-yPXl0m*V)aAV*mU!$X5iTfEG_01Ebg9W z1GFUl--p(34Q@+NXf^dlxNjr3l*xHk(O`TzKwrHI>u5zxAUMH^9k&)tV~JX|Lx_Oi zuSee52fOu4cL#QU=3+|+O8D9p^~f)ks^46(LsX{k`=Gx9OF?o#y&HK4S=_-pA}3*Q zO?`ZM8qW1LqW-hEnqp)T7`$>>%r)v<_DlUAdOe$WbkAENBTDY%K^xiOLrQgrIl&=i z=iUBZ5B-dS!*{#kf1QeeJy6>c%^bG%~xAD0>^S)Kric=>R$Lc z>Iz2fnFa7>CWg_IWRSb!+{gSV5_A4FIGjaZXn{L-&mn9k_=j$oH@Iclhe7 z8?C8~RIyidJ{w>eOa+c&3u3Rg>5fX(W1l*34F0|48TmmiZVtg9PvRwMp3Ej>gnD*aSJ$tVPtIt6ziqR+Y_osfo+m}_G;Aq@@GUEzeHQJO=-%Afd=R%1 ztV$B3*4RsKFY&zFH=(*tttKtY5A2eU#lqgajw2TgJO zcO9)!zFL&T3QJw&GB4j*k1ay1%=UgtROZ(nzRm}ekApb9{piBrHd2PzzLV$j@$SM# zME5u+ee}BvKEr;#yTErA_`U+)U*LNT^3Fmbf5^;{4|yv=UPF)<4dm?rzOE3Fmk;EP z2EKft_&$Nh_X#|{N}&0IgO(Q!WSJ5CK#w{d5jPhZ#n|oDMck4!%L(^<@ZlU3U=w68 zF40+B=WzqBK*ttxt5-u5Xn>2bjgBP|%I{%;Yx;Yj){-G8bcy%0Nt z3acaSk1IivhsSzGPuDn6wU1d6dyoxWt*$??yV^ewCr13e^;}c9*b+sHXrCs4Tf*Ff z?stclbBODxWbhQ1)$Zj%@4{*vgK^zq_?8s1T)rmiSS-gk?W9=F*F?y2vOZ*cKlx=L z`H;6ngwNq?A&ResczpW<$CWUxG6Ceh=A)A7;p-Xl%7*4E8(LoN;M*EL-`4OsDL$vi ze~lmVsz_>%g6{`cCvlEsah5>}V(BkhEx83f_p12ys zWNfK87k926f|#9~Ts`8Ourdi{=sb`=7j&>efgN@n*1#}uEz%_?@c=_?31({p4ghY@ z`dnQM>~Xqq3aW37R$|9mMueluxFQhK7=szx3LHuTERX8FKo|hi&lD`3hkKgYg~VZ_ z{J-efzM$Ooe}mS`pa<}N1<1cbJr$Q)ay83mh0*e{*1G>`;$#uH5BIUx%Ple60Z1RL z7v=agxy2##B5VT_fU`mob}I9U);z|*E01!+#8DI{Qqa+9wgC$!!3V79=?PdKC;<} z>v_`MX*7Wx6=dTCJJ?EI>-7?Od_ePnpgnhibR|wvaQ%VQ30`z5=bqaEUCza~$tL#& zlfWRPkIRKIsBn$t%j%=~06x$W^|26GKKSw+hkJE?u=r*TN50?a(+9 z313UZgTn|JxkdO)r2$4z{mxhuH}H;58Oq5?v6oZKaxN|cA?q^lN#PASPT5>yijc4=|8nAai7 za3GIIMrTNic$2B@Iy{XFj_J)~Z`C-2GGo-2H*VI$kxRx44igAnCX}c6OnS*)3Kuol z0-$#AG~OVdAnGv|42O_WU|dVzeR>iW1AWbgTwil0XgHRbs9rQ*7hFYC$EbpP%SE^( z-f1ern zpc*}JhDiQ7_1Mk=F$J9)r4sd=bTycpikt$RjaP*bY&rsM8f>tsJJ>3frRO_K?4(0({1}CGZC@h19Fhu2^Sj0D< zSSnJF*e0($eb01TO~`^-aztm1uL zSVT^=y-#%*38v@bGzwJ>$J&8N*&hkngCS<;Ia}0VXf8H8Sa6sObayd#F^7HA26+G6Wv6 z#L4gSxsc*}H`c;Lz2QvPW%TnsJfvb=omitXcHvGKcxWR80lS^DV?{~nr`BNotKfag zX4GL5gNdaZG(uZ@4)Q$^VQuTJQ0nPECnvrP(7nr zbp&Xng}gLhJi(dTJcc#ufsNZpN>+}~0EZ$<5nvF&6?1S{n2L(T9E)7_lo>^-Az50F zbBmlqyh+I;qP6G%rx!c0>|9iRdm}vsEgB?kKR|}KoIsY)E6yQM+UaBq5!I-w-F#iA zFW%YM2rDPmw&_Bw*3BVyrp%_I#=!Y{X15+cUC*r515eYHr=riIwUGjNJH9GR-}fcB zu4DSXjCD!yE_E0nm+~8R9r-v`fSef?OO%`ni#18E4kb)PS?DTq65%E7{rMB$_*taiS#?PJ44A(XhJN zS+HzQ{Jhyq7oE9i@d~Fao@h=cIvX$P>`FSVcS=LWx|^HXt=5i~PN!z^;-!n~7R8q?J7=-enoPvIldbK|=wwf8M{;UB86wmzcDkCo z+k2AD>@N|UK{F1l=I*r(ZBBb)b-beiRXcjx(7j8@pmJhOXLpkQ?(9io@Sx>zw8Gd{ z@TVc(($L=8wgG)zw&=`x@w3i66C)x2I+C4TPIp5`Q)hd;sUZnOHnq07dsSz`wj}e_ z13oo0u8}EgUK?*}zO<*g2Rul$uI}n=Yhx3v?lksvcgK_M&YDgzw4pWL)!muwZ0u}v z8asP1NkTo~=kl`_JDq5%rLA*a96v;W|IG~;a7X;I=I%~sT|;X!PEN-=n%5`6%PtI( zvzP2lp!0D)Vn6__X>&Lh4%g{!UL8*~tZg>L8XMZ$IvX84G_C=UJ6l>%qrJHuY){D{ ziYbAsz{!@T&MtgCt_-=GV@#ll4PD_3pS7%R(c-#gGJ%vj87HetN5TDg^IC!-T&;;F zuz=#yX~YE`xx{G&W^lv~&K7>O@}teUw5Js# z6*fwz8xoDJt&rSH+Z(##kTK3ls61;M;%%+yL>J^3<4Crdik!5@HEm5Y%*jwXnYsy+ zp?_VFU$8I%CWG;iqCj#)o|==Boz^w+wVjYl>eu4gv**dpnRQE-FFaFj7cN>>GiTwf z`J5MyhtmU9YKBx`+Cuq^x1yPbCa4FcL}sp$42rLAP8xRcv)k!v?N}Xf?5sr#>&P{X zuu)WLeR2(EJRVPMNN}R#3EBrtaCdWKb1OuktD*4{G>~FQ%ewAXDrW;VGuhdV2B=2@ z6-|P;u157Ps0x*f1870N63v;sI%%SlFrB72CfnGD1e$AVLU-|C86Sr-LPbpP9H>oK zck^1AZL8>^TrF5Ue;J9iuBO3&*mOYlW$fri3z*m1wRX}mp_6TQWxkRPG_46}L#Qw^ zkxu&th=`Sg)oq=t8o(@CCGbjFJqY1@mj~8Ama%gMKfD*0H4Kb^b zjkSg+wBOK1dZ2`G04;Nr#;#A8%xOpoFD99mDX>9nM7Epa?G1@boP_N_f(9E3($${q zagv=$G)Y-%g(At=&`xJJ?Xws|G_<;-r!f!~XBDKC21=Bh?hKYYE^;kAZ*N#H)HXP+ ziFk8&cPD;X2SyfRo9y0T*tKxc!ZYT>zB?QajggQtoIGoR({79*6sQ*U{WmVLUCgkluNcs66kW^i9UP2Q$84R=ss3bC%9pfPu7FPEeafjZ;qX%tZ?p z%S><-^ih!TX7Oxrf&qI(pV^jZM{DO=vKOKvh?o>n#0HF3yimicHc?^@53T^ld~%$Y zzyt|0m#vLWaZW}!fntQ|7%}XIwyre|&T1GQ2#R4P4EAN69nDrn;7!DvHMcc%As{h) zG*c*kPgK)Mu8kvHY0R2i%X_vXVj+`(os=Ypa2#ri}6uLLt3`Zh7gk@&b7#md;9U)xeNsh565l?hLxYl$gp?{%N8xaZSzh(|p zhbkoj&8h~vAp}f~GEvJ`EOc7C8;n7QD8o>9c1YXM*6xO;wV@=`EItP+3{d|<)B3u+aT@Y)>>E7a$?dGHik6(Z|!JmUQdfS8C~vNC*x}C?6fkDF?V#v z8@n44YvPD4;Y+*m8wy=uGi)Cs#K4}@_KL*Q0HK*RKyHIm4j3SDY8(MHq7;Z-TXQ2s z2ErneAQQ-nP$3c#2hOnMj9GPO&gGOf!Zac@6g$(nRt!DRJ0a7EhbB+LsDNZ*9^)VY zCKjcN3Il7Lib4avFhrwd!X%L`(tQN6iPp{zGkc5$7_=vyQ2sgN%_2IT9Z(0U1DR~@ zFj4f}Ma$~qaAiwZ7-IodM^*0!y4E!b1r=5rPB`z=ky;L3)6maAn6( zaOtAub+c3I!G#d4IC_tvb;t_J*r}FgEFrCFm545!7Q`81r|7b!0;Uz=7c>ccYG`uS zKptSSS_8>PN8weS7Lg3jMY=4<;aW_Pl5|#w7z_%HpYGt2ZZ+nD717ZRO${6DAjQ7Z zLpWG&_Fx>GF?0c|Su6@UDP}!~zM(Q#uObh|=1~@pQ83w&MPWtg+$r0zLL@EPN>f31 z%*Gk)!ZH{KDv|;D?PzXp!W>KZu&i$BY&d#Zd2;~^CFz1)4fJ#YR=)JO3^LcY*l5W3 zWxKkV>cm%ZXsP(E=FA1OOW?#hazYkoqLXP0VNN>jA7>*j_RmOuz=5y>v*#=hSG*xm zOmZst$8rj66eALEfb++?7_1Xk+qf)Pim+J-357DX2qm95`>+dK*u~pvBpTN=!$&1L zd%7Fb*5zhBA^q)QkSTJBJjI-a%PY>DFr{L`#OjIF<15A@Ozdc$A?y0qMm%zrI%ECR z$zvx^su;VvV(g-c6=Pc(5*s=i*K~JwboM01_H@A1HjPbEHDRfH5VSWWxzrKAY4o?1 ziIP@GJvwYX)g&{Ei)WoVZ+0D*Ka|AABurMQ)3TZ+uhEN3LahxYGv3nK-QHjXw;A~u zur1!$3e_hD%?|Wi!cmA>knBJ!a5d1#rVdz|WSq-chKh;!D(XKi3#(8NMK1$sqGH!9 zoWm%d86q)MrnjMkpqW2YKISi)T|fIwE2XoS*dfL#o?_n@i8XIro0O5JxmuD>cGCLb z0<#GdRsr>9Xvx43q9L|n+3Y0?W-X4NGi(0x+2VK4p2Zx%?1ku;cuE=$cxAiTZI{@Z z@jpUhYPu}2Z1jPNS=ZGN%ID&m1r9i2mJp0Z85Yn;G`Dvpv0#IcbzRa-)c`Dx<$rr? zqwy*<^gR@~PE1Lhs{y!MwiHfjM<)e4bODJ*DM)McgQjry+%|=g<-?=`7{YBg{H-Z>FrKR zw1Uo#m$I{K=Fbit$>fw1<(imzA2w>Ib{#rrRwkH5F&4=5Kw=WDEv?OMFgBqVMRvn@ zz>xd1=9=(MoIR}28Yr>DgcXy)l9Ysv-AUoNE8;< zptHT5=`&0b7|W2cNsLd>$JxskqmRk>YWx@!rqbkBnG5SO9h@9*yd;5G$}Xctf8Ze- zO~A(x8GOAA+R+VngpajOvb(jRjgEX(&+64O<&qLTX(FaaR`h0_o3f#4%XcLI=GVY~ zi+efKYH{G1#k@$?0MgTL5>DdIB)&Da4q`w?n-~Mq)npcBm<8qqLo;O7=1fU~xKuY% zifoi&FC=jFI#CJQlSPZpFfo`}u!+$NreRfLz0@a&qU3#4GdqNUbU)+|gPR!Vs>q83TCLhn|$Bg5HZC@xwW z_G0mJN-GQ!!U2YuuyMh%mx+>|E@O$p=zwOJCdt?t2(g_CG2$W1B^@gA2!DpK0*OAu zo%~!ssJ_}qyhxk>>*K2Ql5o^Eq+&{Q61F9hv5L}7)56`NRT~5r zkHe-ctBcb?%sT6=rSVxy=NLySSPn9yjbybvA-HfruDf+L_WIx#kt#t-N&rl0AT(H= zT*DXyX4w#d=wn6JWm0hx;}|$b#)5ceyOd$bCl-T9O@|K>z#x&s-8YmnF>A{x%!sa; zU$+$zJYy9Ku*ry#4hh1ABGc8uG8phqX$4@}#jyIrOX_i$u&g3GCBR{sa7Rv{(s) z*w(sg-0H^0qX|!#7&Q8CC^F(q@4z@%R_=6W0--4gl^}l2$?7%Estw6zIyl^7iH|;n zH)AElmdEa%MuZhiznRje<`&#Y-*J_l2Zl_9F__~Gh{1r2#s3aGNf-~6uth?TsL*f0 z4FOE`5+X}g-dOb%ETPDaXOe8?2c}tM%3`tsFqBVes|Gwu`)JIxANUr7hvb{NG3zYe zBLm*O8aLBLp)rWlxKtt&7@(uTNQ7Xvc1jI1f_C1Ei^L6-8vTRq?PiZ8CBQ3L&2<4R zFz&=>;Yue+-jgf180El?tZ#7TJmS)WOjfdq2&R=rJClVp6i!CrPw*3+ zJTnvg`7f?9w;q0)V7WKunH={V0HQ}M`0gBcS%527f982Xg=$o&-r%0&ZMe+C4~p*e zE_>L;)5Go~u6cgMeG7n$>gFMh$P~BEo3h?r=B+1@IuN2%aBtpCaHX_xq#@ z!1vvk33wUA1rXBrKNWWE1b4A_!X*4~>gg+Sx8W|=U2M_(L-x*d3Q=BIhVrtR?ouhv zC=_^5Eo>yb@wc6A?medijObWz#=QP!{N%lNv%AakV3&(?Xv@7v-TfA@A3stKz(M!0 z1srz&Ou(PrO%X$4Q{-m+{-}3zWS0SiP4dRSKWw(%ZSXGK6Mq(FiWz2Wed1 z1wpsLR`w6iGryF#QWaH7-0x%a!mlD;VEI~1%NIyP0) z(Du8mtawg2u*zpa8fN{EGNbw*b&taHJ?c3FFjeF;tzIEIRaoz?^y;M^rd#T*4C>YG z4C|%Us&tolmA5MQLhn{3^_H;Sa{z?cyveAs)T_LXa&(=0i>ogGlIz{#O4X&d$z?&4 zOVgUXJ{({PGS4$v9x+Y&D?=L7(85pLH;o)eKepW%3+-~9=s}BC6;she zrd4zz1P_ah-^E4u;yIPMmpjpls`1s)f0pm`KJR|s%>vx!Vgh7r{;xyIMQHVf z$ZsRIRlnkVGkVWy#%P*vEzA~fh|jel4yt*PMHpMlH6A_>dE2A7Je_lMJ}$52KU9G6 z%E@~W^&b_fpd_3g>2kc&7eje&jD9DI%hNe8=D_w~4qvsRI!JAQk3W|kebLtXO|FqD z(>=$3JEZnN1bXs7|8993jxEzl4DNZ7SL>hgX&z1MnuAu2c5 z=G>gan_vuSh>#$n;X)*lpy)dn8N^asCj}6BXQAK8;o;A7Oj{qsZj&awr*fV%Z5jTj zBcc(a;X)+SR`)7HCu}PONL$fG!MuQf7=G$eB+>CN4Y@Z1Y`dw~gJc_ie(~n?0Thzl!c()yI_zEBFc+wCt5TfBiBr~4UhOF^~0FFmRe`ecp+~CGP zJR@kj8=~L6$%O=Ma$m}DK50nz(Q(}8{*yN65(iK7Jik%LAzTQczd%p{t2k-XX!14R{oE8jn4CZOf z8~ux|Uj<=^ zc+sEQN5|iVd|$?&zkhnrF^Q*+(9|7qKd`~U2kv$BG1o<|Pn!<^4`Cf2gK6JjH1!P& z?OmF5dcz`K>hvkaW%P-z)29TzcA`0UrVHp1@S30PNgBO@nACyareFNF`#sm&{^FH8 zVSf?EE%V-T-!Xu&|9fB`#e z#mAp*qA>Op!@4H&xzIYRuw)iWJ`;JEC3r^?I+50iuSMu-zZSvQ=q>fwI_*AwIoD0Y zx!R3P-HF0CBDkV{^fmic(tR=wT6C9favW!rGy;I<6rc|UX2<~gG%mZQEwc7DVCrmGT&1is^b9I(mP^8?HgV9$ur?s8JWpMP;!QaNGc zEAEZn#y9XW5c3RAKsoqDf>Xk+BiF6ZB3jhyq} zlQzBkRXD<1TsQ7Lcu zw$rbnc#ub`qFw#0_X=Vh7Mq|hUK5}WAnJfqG1ya2QyVdj^VV96>VG^p zKpKI@(RziAVm6NgO)rKbgc)bN_qNroWE=Nyv#c;PDps6$qyH8}&G1 zoB-vra0oe2`Du0dsH^X_(K)HA%Na^xHH<1=6!0LQjLJVBgwBtPyg%&z0P-)z{^$_x zMCjCsV+s=>q>fl;=??{#k$bd<6CJ(lvhHPC5RdunkAW{<+gDYQYHKiTpkSclP_p z-3)y1rq5mCU88qvLHR)c0B=|U_XqxApF$bIKmPgao8^iQ|IWqYRc#9{kpKHG4$ra$eZY*X%5juM%lL_Z?XHY z>)+rf>!^kg+Tu(#M5p~}VUK6zsKa5<@+h=U-B>YGmH_$6rs zrE=P{8R0u&XGVbSBSuG(MJR{{;EG;XR@~@eF@@<1fnyl=y3tQ;)e_oa4(!?%p$S$m zO^d#~x73F!?b!@0h5LDhDcG&{d!Q-?KJUYJ5fC_(}b23PM*}XSVa!?r;mPKM~oxFeI z4@21#5b5%~0YmNT z%O4!Jo2z^J`6qZDehXd9xoM=L!!+qRrQk^^GEWyE^K_k!U#^S1kJ!s#82pn%{K4qL z;Ky9GcH>TOulv8|=En$%1@cpb7ZQ`Pnm;?Nbr0Ehzl+x%&jIfcrUZTQk))PC&$%4j z+vMKB`MAaXGF+Z1Afe|%r1C;xVz=dG)lRRxqPKve6$xjc;V__86OKZhFy$DCwhjN9 zumvv8?_)k`vG*e;+%gkk{v#n`1$b650qn~ljJ0^x>)1C4S#t! zF48Ttn)jCvGad1qJP6*i1ur1f7KlHhDkwps$n)+Q5$5*%L8F7B7>Z)~stcl(-w&~K z`k%jXQh?SEX#E)Byy^aidiE0}Z~!`}f6mm$&-L4gFo8=a?jJchsKwz7pMj4bMP8>` z2C+^CQa@Vke#7ByhmY#j?TCBwM%Cb%wP?oSz+5}ZK4QS4AKS+wwSCh%kd3wuH*JQ1 z86&a)-icX&IoW_KMrL939c2Ky(hBeWBU25?bE+V>RgYk?zRyI^25vqx(CWM@$?7gZ zg#`k~fj?x1X*H z1!@@5%Am5;tC|gGJbMASEL4!fUHEARPoG9I5Pih6P%%Ol63OgKy;n5{vC5nU@T)?l z9#oKjywLlMp@L_jlI~SWE2A$fys8@LV9f&LE`-VoQ289!M4vNM@GMl~VK@A;aGk>- zc;p0pOjrpyTh07*3T;)0CK>=o<`tI%cgz{IU@H2wEzbz*!s?Dc^K|pzIRi0y1Ak;p z`ym?w9CCj}z^~ko4M1?y>M+KPeToHFEidAwwa^t;^gCn~T#i}R3u}z?nnKsn*oRJvJ$SIMoe%_R+sa|BDj6+l7fKp*l zQoTu0@i9Dq3Z`C&1c|B(!&b0<_4=1{!61MBrm*C=?Wa(V+kOh=*zNBKTghtQcEj-x zpKESC2e|@obUnnT{sJ+87qsBMEdgj^i>tdfZvqpyxYwu6t{qA`i8^m|D-^P|O(w)^ zyNbEKt4uAhO*zqA8*BA977#T2`C<6g3$69)Ya8o3+)Rf!*Az|}D3-AZ^rYzVFi2x& zZtP?jMX|j934A&6mpk`^Q2MSWqR?H;0@Zonjl9Tc4zcQs5o9dQ{CVGw{0Q+GO!AA7 zK0P*unpCA;dBw71s1aq$+L=(5<%og~GckJD{jJrQ-@044O}8Z@HD{^>6=6Q=U_QR= zM!G$O#80}#T~0rMQtZdRag4$@ zFp44SMa#zH-Fk9(zA!2q)k zn7>EL+xxx21jGL9Z|MbwZRv#yL0nC48PZ^t{y!hG{ePwcc=2cdGrhoz&#*!&%s1#u zfi7Ku?-0DDf`>k(Z3i0E`T!LULQv}iRGYO5qRPUjly0K~iBz6yY#``JW6^n)CKV zKBDG*6!|9eQ{Pli*p102)O$fD6*vc}{|6)QrDd2|9VPpj4cQ-glo`H9O>KyS)D8p( zDR`s~v90M|8xbFMZRDP;wXqO$@_>}r4Y}%07=cYZ#8u=&!Nxj{L;O55e)0MY0Uw4e zLE{Oec+SCo{p)nSuM;t7Uj}MFylJ&4u3dy$mx_zlnRP%f0VJ-{dCjo6+A!%}o3@dTk7V zYh(Dmr{&)E*!3|3zdrU5PPKRsL}>f1@r;9KK4BVz8Bk;3&H?wBgHzQD1f7gh5!r*4eW`6M|+|#MWMql znRaNpqgxq-ZH;{)2KW~^swF|ID3(^2pw;`i5q!TH72x}F4ia!MM|uOmwp4OnoZ@{s-@_$UhQ8OM?~=5*W5744{x$juLAM)Fz)|mrzR5>d zZt`D6(${;{f6Mx}xBLUWn6eCdCwO(hd!EkfdH>xLd? zSLktx;ysDFV)OyS9l4G%zU9A1xA{>P$TUKz8K&uu_XYf1ueW{M6}0Jle5_)m8*!N} zH1T&1ik(H-1*Yr*TXqZrz>OPRZ0_~C1)cM5>Gkzq2qvE3;FcnFh?$g%X!s_dR^%rC zHb0thE_Vh_8n)BB&EMtc*eB+XcA?=^Df<>aajd)i2UEoX08C_fiKh3^`AFN8A%NcQ z^&tWR({n!Wi5#Y%IUKo{e&$}a+xnT^3JLs7(*RuLitD`38zdFy^-kp7=$U=S5PK7UOL>X3bu_8(>mRZ3NBSok)8Y3xLr;i$Khf{%91e`Foe-tU zeiFGOI5FjYN!`Yw-lhOD`8f3S_e{Vp1{U5QzIJ-|xQ`)Rmv(s|aEaFeGWe3xP^4{_QuE-Hvi(y0<`nXrrB&$r*)_6q ztLea?JJ!kly328Y`9{?PX*c=rE$-E>6y56HV{X_qNj;Vx$9vVM=BQilG_CIRPHn=- z9&?{SOk?`E-^EFTB?xo=$>ofA0jxp(!BB;k5Mck~hp~-p1PDbI{ZAIX3?s`7;^Fxr z;IOvd-#u7^zk63v&ch|UDdt@K1G_2skm7J%gW??w4R&~&u#1EbDYo7Tg`aSaKT!g; zA-JJf4~hbnXxqEq`#62a*82vE84~aFe#DbnKk{DlWEb)yR0?GXQ@sVCZ1K-E%xIXSAc=oo)oubCg## z(a}FVE%iKTiKB;~5j;Ddj(JyJiIl~sDRFnX9=@aAb@Uk_hUdj{9gUaO_r{j9v*ur_DaV(Iym0I&Zsg+?+^1g7=Nx;SnQRRdxOV&Q%-YqaPEY-ULUk&jh2TX zqG+b057>aka}wUO?u#y#I|tCE<#vVOIla8RvEIa!z5l`D-q8&qyb?!RZv&(#Ov^;P z-ldLC?UFfONguCbsH0Q+W9UOK^v}_0Sr>2oWJiB7Jo8xL4aX1 zRWKpFZ~**IXnuj+%J!Th@4m=W5$|XEXWG$SA-JEnH}d0%cL=`RJET8CS!$1atT*9g z@01zd@AW5uA8HPWN4)$~FeBkE?O1QhG;emTcNnKt9sQjU?t3{!UjP2ykh8pRt3xPC z?ID4oQLh+mcWri`^V}Qr{ISi$drpowc$uR=T^+Pq>AfENGDP^?NdW}%dUfOr5$`?k zpPu&*{aGKgcyds92F?cjA>#DfKh;2f(%viBi2C0V&e;G4YUrKb=Iw&^c#lJl930fW zQ+xO5do)+v=26bpAOJO|JG zn}Pqtudwh<1mcg9a;$b~yCP1Z<4h%1>W_gh;p4O5)C$78vf!5k&UWV>G&F)h^jd+J zIj_86;KAqDaYH(LvgkZ1_@&N^S@^F3eyslgLh#F-AghaDM*jX_;X#%%;O8fRAB#>e zbof~C-hc~#dJJ9mkADL!e7}XCZotkc3qP{X0A8{1smGyzym>hT_%5Vn`W{Ol?Q*Ps zE*AVg&fzS+tpMC{dOOqaN+W>VHo@=by!WF__-4S1F^}608F;|Y>n(h@g$Mk+6Y$=d zB;;uf5Q?4t&iAGX-Ag1V2ME!F0!2WZ}Wf6Sw1;fAzRl$X(_~5^(af!s)b`cnn?vF2;aao`ID4tru( zj9YEHD=hp)d$P7a`oX_83wJh{=bu~tTn0G%b9YvMJ}3AFH~sVW%abjD=SdHOi` zFI)UavgZ947Jge6oj(Fz1o`P_@q<2nWbyCKq7#82ael|IHJIPBaT%5}-JlISP z+{O*Zq4QP1X&-)CE=6_yWs1;5-mF>Aa(I1c@I?y=?bHA|<<(kZh2f5*Zn zWzql8!mrJOyV}gx9-Hm7ODHGL!e`n=N5F>)f!oH?E+-!czR=PMPKP{V>zofb=e;Vc zKW!F%k%b3#Z0&LAf5GB!%94k2-^|NlJ1+s9FIoJTvheQ``h`xge|^2}=VKQCk*t1x z%fi=Z(fN^uZ_R=q7W!!nv$r2u{KvECe|#ML0vT7i6TAWx%==Ia-=Ed)Sip~E-)0KD z&^cn~{S4cmS_^m98o*EsuMg;F&CAN;(C@MM!C~ou|648nnKLu#fB86c9##mb2)DuhyMQoPC0xgi*J8F4t@drDe;3-<-xd0ExbO9 zKZ5~37XK$${C!#NP6M3wHrrp%wfMoQ>0sVh9EX0J#eY7F{yGcalLa3GJHv4m+5QLg zKQHtPo#1e5x8?tZ$FWN{9j8AJS~`b6W#(y$xj5eiyu#k6Uw#5O`_q-x&z~QM{)fbm zAWqAQb6iZ&vG`vi@IvRs^`_M-+js@wZ1*DDZZN+i1zzkpn+zh%sr*f~bdFqVo`Z2M z6u3o7yEF-%a%ZdMb3muv!mrI5@0R1xxmoc0J0E8Gon3;Db(ZbV&u!a}TKZG7+TCyQ zgI|>h@DB<+t>gCg*FvYib0DkTKU(^ZrH@DX`}=X|6k_4ZI3ajlu+GZWV8F@$yR-N( zTJSB=w99OZ|6&&YITn6f7JQY3U!Da|0$zl6ombO{<93$F8|1`JY+w&JSUR82;^!3> zz9$QQ9pDldEjIL*+Gf5a@XR*(^suEfJ&Vp$0`Kn}$>RU_Ec~M^_zTCOe;9C%H#@HT z-Er_AvikUuU1$dL>mVV(afQhuCLZuN!^*>ZS@_!G2j3KN7W^FlaxFYaa(>;)LmA+V zuYz~df_8@szNwr3IpsL;sZccbvumco9&0PjKMwvy0xxuebB-Td{EIDoo1Mpj7Je1r zl-mPYa`iSyoc_=RBt$GYhhQ-8d)G+P&Mt z4`<2qV-|iS3;sh3f93z_?A$`Es=_$F5h5Qf@}bh`a==6b+l+aw7sv5Bp(#3a5n?+t zj^l`P>C6aDN%Yb~QdCb#7cis?6cGi{Ly?|L_gdS1Hot$C&kwM3ym}whO1?Nx!{5xle_F3!wfTSD0;X?27Q@c@){~9z zvM%Y@iyh_e)4YDREO%KxyDcB@hsV3*GsX1SXY+OAxaD&(YwvTgH`=RToVN5cS^AG) zXaCIcMIVlrH7LHd^v`GMf0Xo=C<%VGd>WR|rxphl9?8GQ?iaV;DfT1-J6+qw-VZzb z|72F5hs}N}8<+dLJkLL6&!1N;AMgMDme2cH{)b`rJt(d19zL(mL!%q1wJ4rN`cCub zB`J4talzIfFZZ=B=|8agEYIq5R?=g}_|Ll=9ocepvTvLwTNa0rM!@VcGMCFDa&ILu6!t5TJb^1fo|=)tmw ze?fUJR~E=)dIlF@A_2WUG76p&sOo?*0%J7+7FSh)@@G0BAf`3JJv(}gfYGTV&}2A( ztU9KEGSdWr?#<@ltjSUw1iT-F)}!O&#MmZR0CYm(Bu(0aIVoOI*m8QB^6N%shK#8VJOcUMk0?n}eufq@^kAix8-)f^x{tE#R$huBxKi{MbVqclK|B8Fc1q%XW+1 zzIjhkZQHS{Z{v z1k#W^GsTmI#3U(3EiG`v0Co011LzBCEM%whGeDk& z(OS7qz@)U1=}OGuSgc)?G>H8DYDB~-1nDS{Qm>T>6NL(NQkl`2kZCbwT4HP)ackft zhWsMXS@_avAAg0O~YM}=qwmFo>dlrPniCWk|kmM96f zEMZu4#Z0lp%8llX9G?oV3Fq4u{RrmfKnnvO?Qmp!$UycuPAQ_EO~s4!-_dbsh3Lv% znLI`<&L)f3k&q24K0Rq1XA!TPnyuqkuCDh&VUyMh4Fn?#f07zS;H-BM6vGfwLb1+I zHVC`lx`42iOBp@verIJmVUT%iDXqLyJS5CSfG}i9#woeb+D%+M0sL(nUAtF-QWvE+ zb8=vJ5HYKBU)L_UlWL!JkaQsDl`3!TvP5#9W8P%&+PW-uCmXLCN%j!pxJpwS42g-E z22ob#DEYu(UWa&r9;*%t?{1yDZQ2Xu=>|8v9ET^7AmKhnv)hL0B#c&LOt@7XOUBcBnw$qD7HEc+oE4+?JZ@1!);0#0KS zrUsihOWn9rq05`KbV1| znmpD`aX1*N!&%l6eV|TPh_-DQw-H8|Qe-CQ5k%@#9x?b;6&?lcSs9CQOBJ-@17pX> zMJvkr`kfmA;g?ojs5*qrB;Va?&nS6=hYE}b7B22T{#dDGX^a)`$hHj(g9|;t&@g)( z(`nFBFyJuz@-ci2Q)~=qTs-UsUp|P6j!(3TTuCrtkHzc^ChZ-Y!PpBDUVEKxl{}ZT zC0zc3R#+-bTc?*rTSSziNxCVTIy^)a<@D@0c2b0RaF+0ppUL(UC;&n2D{ zaKp{aCMNQM58OL;z)Tza`k_xVT1fIkL{XOqW+zaDhPcfn#&-5_Q6a901%?iGHU(vb zlABji;Z-Z|^pD&BAoLW!#}!s`MdExnumv1AdPvU>l{5_m9|GfTYE?&S1`_%KpSLAYd*lP{W`_J3|iuw1cTe1BXJ@N3A z{eD7!`sDrhCT#3i&%bEkf=5IC7Po3p|INq$b;P9pjfN)m@Vt$uXK<69c=!&kQ~%3L zG=Ya+U-$QG4?oQO{dXo0pRn&2+~3Rf>rXO&|31h={M;3ey#1ej3u}50c($0 z>;CuaFLA>5yT5-Q>ET62CP!ZW_lQgV7rmv4JzUP4D>=O1+;kBqoN_)){=Mt@&oxD! z-mg8pgk<=2ulD!vYcKpq|3Bc%x##8kccXLWKWFXd{lmk{^>KU;HYRcZGv}D9D9(JL z;c^Y?zwYnh--t>5{X5i4=6}V?_YB<6L(tHIzkio8cUC?4yJC7Y(hHm~fIsu{`Zw%- z^`fse;hawl^J`e>!9pv)#|;*`|FX=Ef(R%arM8x_uBru%s=nH+wDW56L)m>*W8O@Ul;$k`N1%b zzq0XjKM&bVKTk_~!*2Yc6{)p7?UP;nug=$kf6wM$UKX#jDoTNuZ&2%$Z2(JQy$k<* n-uwQ;_0i|9ING26OVxj`?PngBm(Sttf)d`$K!PV4-UEV&81e#$TR>YH!1%Mmq5eXYMhN32$yL^N;N%H0?I< z={5Gwpmh0Zu4S}v$F-;Lnr$R<(g@3~=Lzqj2&49W;J@W@2rzg_t+W?hRVze-D{J?b z618C6N<&gB%3mgF415CUZ8eclp|>`Cy1bto3q~F&dc_Y8SkL5%R*j2p=X zSnGSv-}@@G!h}@+tg1g}V&xz7oxVOJxVg8G2sM7?O3BJJ#3l@0}cvq!0m0 z-*-U_6^))lI`h-)f4je8H1Sk(q?a2u)9+9MSJ0o;TX-A^|1BZVHzM3zWC)ejMhai* zd&=K;;?vWoYa(@pna&Oo>30qPIgEdRZ17$G<(v@}Ih5>F@xa$Xtl2*nc4;)cQxoYe zBu*5D@fG9br!|l_kubtlgq!PD$2<^CCRUr<13i4_k{Hs`Yv48EqhW^0uPb@y| z@k)cwHCT3`gM-KO%3xhh_@66R7&pAN2jyb#VtPjSPZckOf8$^Dx9al0_B^Sd7}b0m z>!W9;$KUr;!e$edIuB<8V1!?-4Zr!G@x8w1w&#YAJw~bwKYQ?0vhn;I#+^oZ&J%qf zpx~WHxZv+x@EQtIbDk)Fs{FY{;p0a56=nZ@{oD72E*Bd@Ixl=!Y8^cIDagHMG<;x; z&-q99I16K1Y>dzdWy9z>?cdsML~6lM z-&3K@H9XqJQ#Jk9wG}~ccaDswmSCp1#9*EgPBbD}M);U<@}-{RDMn9!rqT0}e`}c$ z{?sV>l~HlHbG%V<*r<4+b0k;;!fU4t{aL1V_{2|{UUm6XFvu&a!bjI0a!B~LVEC9A zQP1ulfeCc$RL^emkb3xJ-*YEl^xyvY!MDd2d{j+NYd5hOIna+=&#ngusb?3tJe@?E zWK{fmM~V^NL&d;4PPd9*Uzdc!Zh|u)a^R@IcUo`;L=KRsfN#SYpzk?GaD5MXmfq*O zhaVDugJfY3>tC07D6;DmA;Kub>F*GdOgM%GSJ=i8&pZEwwJAEr5$-LjYHVpoc2h%i z`LlK($IU4%*dxzhFc%S8dA||i`A80`5;eR@uMTzZzq)X=J z!d*lrvNDtNJx@$EJ-Qj6Jwmc5?;ltXlcIQtTG#x2$EaG&)-eigB9Ko^BCW{(wA3@3Cjx)({b-lRJA2fDi$Flei^#0+xzOu1;XjiR z!y#0c_g|?$T!t#O;lG6cRvUhU^+=glVA+mIzc&2ViT^a4{+4Rm+kMxG9?OVs`Crl< zpicT9+MaC4G}e6Zh}Zv+3Jt@D4DvfufKn5FJqFwF+H42?4_2ci|Cp1sZONR(ZI}4_ zPGNeFq^WU6#jvrQr;W(+%sKw8&9&hV+(C#tr`*NB{UEY;>HE7r(*3)?<0Poih2%vT z9IOH(GX3$|@VhF4Iq^MXFGpV%^7Mm7_}TJ)ps=h@+~gQ7Y(E$;HQ`Ta$ovCAfeaR- z=fjk(D|gMh!3h5*RD|64t-f8?jPm+>VQjEIw~es={SVD2%hzy+;rEl_>x9PBjb+5m zw^{mo*oa{lM))r>vpYIWUiI-DK;HQlf*55g`+P2t6J)*rQeB7n6LUixPD0Z zosy%Q`?2o&G>FMmW-S_m&Pmy{bIdn1gY;1JLW``g;qGkLK%C8OSCpaz3#l%kn+qw{ zTy6Mo=FAuw^(I=0T%5@@s-z8yl=_}T-AIHQiQG?fZpGjIw=9DZgWc542S0;Vleyjo z)G!*38j&8FPmIXVj?xY5st;?zPjH(iCt?;x_;KZUY8w7oySE6~B1nZ+3m-?4#Fis9`4|%)(7}qs=YB4GRD+}ZG!{wH@$jp0w=bNMQI;4nJdvf|st8;*m)iFI zKH2xnO18?rm9-Ci86CFb*)!QYEK|s`okC}Qi$OLR*-bGzS>?}gcN)83v)Hf!G_J-S z3nTjuD$s?Eh26(-r@aW-g7DumfAGL~-L$jFoR`Y`Ya&ZzU<4z#5(mM^Llk8q>Y&kZ z?ioe{JUX*xv))@RL!l-VBLp4_hT5WvHx!J9Pt?W`(=^dAimjmla>qd~ZutPs z7Gm#Ui8>LS#6taFS>R?Nru;QFxg2&b`(uOrAS+aH9_82m)kTBt<6qr^3g5*~yL&UJ zaZ_7;SX)0u8kbrwO-1`Y<*ms$=AsH#D6$MUX${6_w6mef`kpk%&p2mg)8{C1Gl&D8 z(GY!kdDB(a_p(vM{0&NyH#BVMzz`U}+6P-%-p@0qBG0Udxu{)JIEV&pfXY^A^KGUu zBA%Bbdw9}&s{4Eu5{V+xSid1eZ5^4|ZZusJL;IfVZnmdmd-U(TSLV7jZa8WHWBQsfTruAUSkl+8%u;z+qLqq%z9V|I!uH%|}K1>J=E$_$O7aHN1Z!YvqTIjL! zM$cid(R0N6NG6EO9=g4|jd?5l&R3MxMRt41Lt@>!H|LASUJo@@2?M^+i#1JXqY+t^ zY0O@ldEI#9$U-mMK{(k6cVMZ#&Fg3nC_Ba(;e$p58(00^ZyQIF1$i+r%Z>2)AWQqN zR9S&K9QDa!{aMM)hQIA_v%eMT6z7h{ZQ*yY9u2jE2@4}mt)tbb(tBjt~46{riKq~m0)T`Sjb9?%!Z3@Vat(?FislbFWrm&8)42d zqW_^4dCff^CHQ+!qon*Pq<#Lr*O3-y0pGEQe0JnZcjC9o{}9`f|DmJC-Y(g>=6Z z15717OTs-a2~9s{gfGtvw?VXvWv;Xak&`^ApMIE~LZpX!ug0(AISID)*0FsluliKq z>FsZne;}g>mVQ(^U+KRcPbL=RnL?=ATl*l)=rDJF;C<+YQ%0l<>sjSI&5&~7A1KCt zPEGg)TB5%HXeKzKr!L`7c=W9ZKO>cC#oj@76n@(bQ?anC!9Ee1lE+Em-_`8Bt}qYt zJb^Q7tSMal84ElZ-d{)xqlXz_Z%h z?Kxbnt*3GCpRUBCm05MQoAf~cbnSpvB=iXO$Y~HBq(jy0){YLN-@(^lG2368? zh}9k#y$q5P+HuDZZTsaVqIIY%hX7N1PGP{6!NvBR^7(sLLf?dfn^wEGwJ@_Bn=7@X z@VBv@#7$EG`U;svCZ)g5ZnZ1ode@s?NNWAF>T-ler9GqA~9mLc;Xl6Ul31qcYk_X zCr?9x&rCe+=vqaCl&p+QEgd^$M#ZO{=dnG9UwSwP+$4GJ(Ei$~^<#}B!|_sc(^DGW>+wR;CKGq|@mqRm;i?i(SXPw*R5|es#iJ<{ z{!BKo5H=$455tYw7kWbhdKiY>G5}Ek|DI@seGw5_!94lV{ZK!2kyW9g$Zw_m1WUHw!%31 zHlBdtapS>L7pNz)#=(z97$uJzn6S`{`LquaSyFkM+=%)T|mgyhTU5 z5Kp>S1m>eq3h}C-^}UzTgB6*T!mmEs2n8y2nSNhcp!E<{;z&om6Nl~b?4)<%2Y9}4 zN$}xapvgbA^2F5IfxF=?YKlhE74*=OAD9*cLc<4!nuC#h8uvVPABB=#$OqKDknYTE z_)vL&-^>xtv42*x5Klk-s8tiWo#T<3hQmhBoX0i)p8Eimv5UaC?@Op< z21k6xA{c(D3UiiV)PxVZok4W-uVT)k=0lZacvER2ay?iw!oM>WB@$3xL#za}!@pzr zn#%_*{Rd8AhPZ7}g?e~-^8m7NhkOR1Dh$skPpixYE_g_)t$1@sN^O`UFEfOyc$1ze z_jgCbb-_}CHUrBlYyC#2SzNKY=NLJcxrS(%+?2ofHb~zBARnUq89Z6A=jVmA2-o2= zFo~NHh`;x4Qi_TU{C(*lL+u|U1vcEwRiGrb-Gw-sWyb1)uAnhla6?;G)Vic^XbxZd(i^3l%i#86tJpI8JzwpY)1oI_EPG>R zV93Yj{vtU-fA1I+voq|QjI#AD$OG(f+LBGU_NBa;^41f(pgMLdi8{u=VtR8(jBZ@Gz`#r0TqNDxtS z1dmtzx1?b(uQiIg@6PRpQK$|K=IWYk|bFOd28;ANg-C zgh?%e! zS~!RRgONof;A(XeG}v<^J@C}wmyvvlk_b?}I5-t1r>}f9oWs{pWX@UszNxI=Rhi;B z-99fExse|P^!so50G057xh8TWg&HcpP)|z+M+|pJz;FvOMDao~F%UOiu%|cEGW>mI z@Sn~Ibqw+%0P0@_ch%qHB`Dh^9w8KvXx^*wpL63qX!bq-8Xhn28UD%rHDQJYBi#Y> z+3~=C!LyRS#QHw~CAH3y4da2aY-*KJ^Z3A6YnD-V$Ms1U13!fYIQ)g8Gg;Y1P2^G8 z?t4~Lf!*L2VGelE@9!Oo`@kkf)PkFDj5{qp$0)t%o~B_6;GWZ36v1>KEORu$4S$u~ zMVJ&ho2Nfsu_bMUfBQ%lu=#nq(z>`q6ioSC1&_?6R>QBlgEMNNCLWz7@d}K11q)*p zJn|{Fdt$a+7Yp4Sy7rRdRXozLdVN96I)aQw$hv5i&Q>LBcGt;w^q2GzQ=pUM6-k&-(v1J@ryCwfu4U*x+Rv!xH#Uzb_%Gd=_7M~d#>$i`@ zl`5TijH%MNCLGgJsZ()zZ;sanZRdWz#^dT_bv#nl@d_@BSFk)@L2{Zpgo<1t&ajh?^BVKnU5 zR#HTW{mh=fCE)pU6gX-#Hay_=+V&Q16r$-fSt>S`xoa!&1fHrWA3ON0I%FtQtz8+A z7#F!j=XIVlgLHjVJ{XnXfIKy3Uh|P~<{P5&3!?IkW<_*Tb+eSZ;8s&JmI|BoEfASN9Eh2^5poO?R7-uuZqH7 z7FFIEl_z)NytgbcHMC&-88M~mmHVTd`e^4c~NmgeOp_5DA3f}w6#9e6zJ$|+1k?Dw6Uox z(A?e`=xPdewKr^T@1XAU)m$H{Zw)kccD8rU3N*BLw>Ac-eq(2QhqH2hbEwHxeSr~N zUKeQYXldJ6R@Ak=qrPD?Xa^=v3`|_O6u`hzflLfoMMYf`RRt5&+S1k(C@-Hnb=uTG zQQ6dHIK`@(Mb(Q})GS#X*uEtMe%nHU`VC#}t=;HMd7#`;-r2A<(Am_`)Uvgy(TzhL zi{kI9?)ui2(A5t9mI(y>HFY+infi@Qfr&PYW`+9Brg~eKR10#6QbKdsJ%VVwW+-`#CBJ+VA0Y*aZzJn!_^@&#m@FE zfugPw=$lJcwn54bo9Z{THU)}n+O|Shje!O2jZGycs!gT3VG}5mU4+^}!|Y#?MfJ?6 zXTfJ(%a*3DQ2myU!1AV!)~jRlP3AcTCOD<2NDLq_H&E0#h5r>5X-w=>gs53>uRFz3myxBJ4P+GKtd*)gu+*#sC-)4xy|T#L!h{+wZ5YZ z76+-dawANN@v7U}yEkqMY-;a9vks|tHeJ=-(%IBF3tUdN3nN`8@uO|QHEN|KhO|S0? zwUha+Ct}=7_H*&^l-y0egeFA4t-iCdw6(o`b9YCezOfOFLp5TD#D6K+t?#Vg(nP*) zV^bS!o~)Hjc}soU)n=6@>I~rvT~z79$WY`6PQ6w1wzYR|?h3TG!Hl-Ggf<0gmTsMH z;wn0US%JoGXr1Lj_OZ68aouF-MFtB}UGNR6+n~z|XZu7`OFCONwzPrGxkcSDSN4XK ztm~|A>)O&1qI4}p-Kq=Pfn!4&00M&14@5Tsk zZ)W=mG-8sX;Z8<1IRJkrZlt)esky$pHDnnvx<>To6TJb^0FD$fFgPgL=SUgTS%w{XrcsrTi~H)F;l2cy(3!*kS7a> zBm?zrG)Ozh4MJlf*agvRCVI^nC36?n)K&vRu0($rWo8Or8rgMM0DU_)>; z=vF=T7YxEK6@zRdgQ_r~cq3+I>M}Y`GJxJ-DWtj3rY0v-lLHWcePBUN)pFA+q;GNP zHf=8>o5e^iub5U=e%{Qo^0KLp^t2f>h~glWDbuD~bW07AS18nKYE$fkI0KJ$b+rLZ zK;4izO$33u_CPIlW>b3yO<3Tow1w)ow82XNaqglO)e8dXnq&hTnnK%}n%Z0r(29X< z8>4Us!`f0L(XC;+u*s&mH4B3aU>O@)AUF~}Ii^rcLw9R^r!+-aqyVb7nd&uf+fv`T zdG5kX76q4I%mz;#>csRz!<5QQeU-KnKHOjjD$B(ghdGNe!x_Qcnx$}Z7_6P`TU#1oFEstM!I8qfHkEBGQ(l6NVC#7$ler%I!_pvAmwqfF`i<>v zp=Nk{ZiL1yb)%}CW`%_SZ=spLxwU?yquvs#7i#Ystk2NZ9Zkeo7gW{K0F?p@F$Jo_ zB{5~5dR071B++bX2hl@V*wWq@PrK~P%rF)Tf@d+!x|rfIOR=`BoGHR#nbY8~ok`c^ zfbG)U210yw5?_cmI!B$`U2TC+M zgeJl-!-z_;qG6>5F#V&q(-6U0no`u@=QlMqY%W!uX>93gK+HfsoWn9&8gcMy`gfW2 z!J1XSrD014cUD438X;_BIJzTSTd_o1a8;cU_~&(FNvtMbgOe>>%y1~)Wg4G%2V?e3;37z;A&zG?8zTsTLltqdP=qOR@kmU5@&t!s6V8OO`JR*1^}aOe|7r zPNE5`P4y;FTv`S8Bw#KPMxiO5`Qt9XvO0wToCdtHz&N8CY#dYUmGG4KEvSJQ8T?e6> zMveA1z)}#Z+tYPd_ZG~JR|jaKyE;I%F5T&!!bEK!<{FxiFT6{Co6m9(Guut zX@j+IXhNLchN)NynD~af2j3JIn$*S4n-S5sngOFjAKirCEo)_|;j$OYFDMjRPMhk~ zsJ*RJAN?eU?x?RIf=YPX3C~(P(p*FBbOjJP&O=VtmgIme9E!Q%A3%cYucrFV^<5zs zk*4h}=xC@DkyXoEz!%3)?GiiX2?evVMNe;<_bO)vIb2RO8Xx=fj_j9Xk za7IU7?F}Ie^O~jWp)4}#&%#@E-uk))wZRpP%=p-zd!yj8m=)dG-9}SkXM20-f)ds% z`&C+}2C%B8>5w<7CW~EA9=3r1eIxXQvDgMI(NENBv#6|`)?n`H4zuENvI0st?Et(| zHEfi%q2p0jMtlL;lq(ckhpp5Vb-_hTF~Jf!Cnz9`{?Ch#-MOU*;2}3|-L-FLM(3Dl z;9eFtHDMu85(96A#EHu>Z8QZIvYtS2Fuf{F|FpFs)IzkA5?I-`xvhO$+h^h%Gz;0t zG5J+|Flr5Um}xGH#qWalEnB+VXnTe@VQ0S>4uIHM+S$ITWdp5{NhEv??njLJ+@`zo z;Cf~wP9ZOZ+1JsUW=V5kg{)~*%Y*AH8Q4BLX63>4-24U`X>YkJgsm{lrWiwRwqxi` zbq;$`jo9jL3an}&*+O>A>EQO3k{=h;hVBryY$&{JYHn_72$g8_t1qlsJm@ilPg_x4 z#}5c-(^YcxI6!jMi>spRsoi{qX>QmHdQ=l?<6Tf`Zyi{zstwu-cVuZNU1huQz@;I? zUc%h{!ybgVUpRrXX&do#ZZoCmr<{JK($Bd~T2bjaK*dgQmli1192?7srMkFJ*0wUX zOE?@W#sZT|Gi>8%LYnxal zuIXsQlHsgG+ONiT6g;bfV*Y~X<1%wz1#9VtAuhD{6pfu+^y*ttl>}tg;!+z|$scfwgl=!RR_}js>Pv7H6lHTEY_(?8<3HjYUOR+;nwe0->ZV z1xhsREg@zpg4>W(x9QiA#r~5jK*~|Tq5>VZ7S%L~kppnhSzNzZwTdB%=^I-dvavhM zr!A2+k_{-`q?ML#YHID!cuqZ!L`QQArjPEHMvdt5;!7=_G+qK}SORHk38XpK$(no7 zt68y{nF_Vi#H1cQQWUVLZsq!_niUI{tg2q_F2cm`DlEb%>DKJ%TANWe9qODFSfv74 z8gH`s6`(z8NBTUisD)9n*GE$}#tv_l(DW%Yvl)Bw&Zvs5u=-Z>cC1n?j9aB{X^RyQ z&Vv^~V9$I09nny8M&|Vq!Y^91Yo%JJ*4*CF)TS-q2OeAaiHJM{As#WbLR|=ET3Wji zXH(FIxTLFPBP|Rt{WrEYb!yyO{G6wWQPLv_jluv;1sobL?KN59YqT)86|1RLsz%$( znz?zbu}MH&nz>@rT4<+H300##E40?CnY(lvEnhXYpwz@UX$aCa*=f;uQKre-OyjL9 zP4=ENUiWC&MPi;%Q&S^ZQ|l3+t7n3cgL5q*b54xuQ3|5xJ%M6OgxVY0TM-r5blF!e zrQP{KQ0r;j)lz>Df(jp&bz_p-Bsj~lsDbATNscH;s*W}Ss_MRJ6!UDp9IBG@QIZyV z<^6IZKf!-{zd!^>4hNaXRk>*?Ks)M<5ek;^NevvQl8XKkMysa7v2;F)UX#VqUA%1k z{lb2nw7@|t_2vUpQoL{{9;O2wIH2{O@ooB?o&83No$^1VnvupF1vn2}{v2LIFb|3M z(5G4}Q}FKkn|P1i*oJS}dU_1~rPIf`$vzwtug5_S&Zx6cIG^nAqqqE=r)mdg18|c2 zgk!~cn=WyP`GsGcqt{N{Wb-g^E!D-lFO}-GBm3(l)ZBd#l>?bxdZDvqm3%I(T)u`R z-6HHopzgp90NatxGAq*|uw3wgGj1$H?oZE~=t#Poz^gcbe1_&;fodG|={*Ydl7B)@woQY3S@7kDmn z_%Z-?f2zx$t5T=MuXhy;v?Cisf~x@@c-SqID!}5ZCUl|Qnw=WRbhoCTiG;uJH5^yB zPw$yB2~RKdhhIy!#X^8R4+6Iq?>SZ0hL6xUXyxTXf_U+s5+sCA9Y358VcC)*d)rpc_iRd*p~A@V&G*TZh%k1z75gSXLl=OAV9c%zXDB1`#;7j7IwB= zIo*M~0A@?AE`QlQfUClzsbh8>8A9ZUdSIJTBf5h@m*N8h=;EVv#{OOP(g)7zPwrRa z+va{8wYzt_?(`PKwa>-oz{ejd_T0SLtek?yM6vQ`207k1F`df~h!|c9$Lnxl(h{2o zUj#Qlm&1PcTOeQ=b@&q4vz6O(B{P&>sLY%Wtg@LiM`Y7A+=y)q12X}zg*Z^c1jr8h zgz+ju{@!d@O|ax7f?M6+JI#v>!d!pf0v-chG7p)^eXGH-Wc2*g zJx3B`kc%z(!#im{bU4}n#f0_-Y~M-3_S5AbsPRnh|4cJhCUNfIV&F7ro=wzIcQUHt z0s`P2ORH(plI2Ar7|E`7t|34Kf4smE6q38?L9H0@zT+S-E&!uW8@T@;RNWEBQb$#5 zp&hob7`O?DrX9G)Z|^AfNURTKH?{zU0!{J*1~ugnk^NH(4!VC*Lp3-4i$ z{%kh5Dw&vv|nqD(n+?x?3H{V%@kcjsuT9P_skmtKY?YllT(VA3@d}%f0k^ zzw$`jQ2FUFb4niXn1BA`;$jA-0!`K7*b|@BU^`a|5Mfjt^xwLN!1M{_y-W3hYmrgo zbv)##-e%g*u_a#avO3D|sdBS|O)q|pHY-?Ir#KQ}G=>el0l?Xir-(|7?M&n&(d4fI zAkGL|OB4TBDEg3|!=LgOM`&vH^RQyYnr}Q2co~$TG-!su;X}21)U3|$13*i8ip=T5ZM5DtzaWorsQYREgA&5yk5)W7XME@pv-uN03LjB& z$|R{$w6DIl&Vsb&qTW!H*OZchbpTuLk9>!-HaWNAsCom#37}q~9XLdpD3{1R`X5-N z!$2Q;+td?2uQ*DHUL-8vw&Ra?`~uxq91q6&GYT2&2_%dLHkL=d#Id~R%l)Oz3Z=LH z?%@OH6KdpQ1e*p0L`uiUKAc0WE zm#gtPLTeF4N`+SCo#IEydzl&DIeCmAn9lA+E4btXg!rmXwvY1(i`$}Nd16?#nOXrxb`P~4}&v5^hFgPiZmAP~iA8W=V zj_HF54ZIjNeMb4JCN>oIG*0I?FbO^kdQ*Y+0TKef8FTE!?_z}B1BLOBsoMX${+|T? zH4qXqIX=A-SR+o5^@JK>SBT&i9IP(cukt{P8fazl_YTE+^V;D6d_Cc zoME?H>B;%!R{D$iHvCQp{3|1EoV)U8TKM}N@OwtsIR8G@PJef_jsLg<|H%Tv@vVi6 z9K8%bivI}&5H6n^ZgcbE5Q|FclC0mN=7gOlVrpx4g_-uHNK)$W0c3FxNy(+OrVYIqKW`zKO$onL8RAWR(yX45l0(I!F~8S48Gf8e z_%qU}A(ioG6(HkPc$sP5IukE5(}9c25Uru zK7r3+gP-bv^?cR%6bB%-e}kNBnnnxIWc#BC^Pvl0nre2B2gbun@4q1Zkcim$gNUtyOcr#&GeLW*=A-wAr%*eY33>W! zR-+>XU9m7$&{d-W$)yXaae4t&%hZP604je+av2F<^L>Ei0v&$DLrsaXX6I%9yOqw* z`Kgs2k#o>Y=ZqPek6LUko}97XT4Y$QIR*YAc1x_roRY*u_$^jWJY|Yiib~TNGmC$R z@$YE_oT}VnUMHiZq^XeI7 z6&}f@>bbPe*Q<_YITd+$rgl7WQ+e@(A!Uley)bNtett z&SXmF+%%eE_>g1$LS=tD+?&@0z;ZHDK1b@!%S-t> zGHf+@BT`5{k{+4L5d&At8#8P>kOJQPnF+r_f?Lg>mGKF%Rc3YuO`skvkePo$!f6X9 z=;I+S73OnBw4c8qi`w;4g$om=;+c)$)HsP=Bt)g;VzWXZe@Vi%R)uBG3d@}pR&aBo z$NakNRCHWam%oxTdDM1&;@uXhh9P#4l;6l1F9ufr<;e$u!(z#AN};ADy)ok;2_O*2 zUz6~zMP+TegUY(h9{@w~u*pYlWm2=P3B#~!Cmn0crD;=x;|d z^-SPbClk}!P*UkZq}YB(BEZNmOihQONOvZ%F{(^4XOzm%ahPeoj4~Nm`PZgWS2M*( z^RG)H>TG!2kh!+egMkW`4Y%9LeN7$$leDPw+*piNKzPoUkVO=!YxrSJRrrE1!!;*pOcv5L}1 zkQn+Re&|0-Mbj>!g1pgMI<^OS43L`aluUiZrI$-7rTRarA@3)k!z{lvrrdiscF>rY zG3WC5RGITq$)gC%W6tM{nD>~OoDt77rh+p8Aux+G#gduL8H%hlZOk0b%#_Sr&QwaK zk~4;6f}B|@nfaVqEt#re2f*hQl3AGZ3uHD)#$c{HBvZo~`bsYvy(sO^xNVorqM>_` z*(I69{;wkQ1<5S&J`QRV4lsT5w*pQh!8>5kEE&vo#;7b~FLbCyE8PW!UL`oURIO(PoZIIgp`DU|g!h1jhL| zBcp3v8fU!B{kU|_$mkk3gfp2^lEIlA$@n>wCz(vnjFLe z38TT3?^YDBrDl##$vkPYIX*R)&7EtE_i;wp9G{j;e@8_vQN|BRd>nPS_l4*4?Ci_O zL_XS&pEYAMG4wI`Jw=m}mH@zmzo<0bPM4*xx8PIK+mV*gg`i3q9NJI`=XD8vcA9w= z+IWj5cn<=`{1z2wQFx>>C7jWvr9;b^uz5Aut0sQixa*v3 zr=)azLiZ4&DugC%%^_nKLKC)eMxkxzOft7OVF%X{oldx(GpSOtlhJ&V*~MX%XnVr0 zQ50ikidMW6|IND#j4|HCFQ-$aq%wDM#v^#1iQh`U*TVacOzNh>`wnLkOuX->AG7d& z;Kci(8}BFSNm(X|2mH1`C;pT(B8Q0&s!Hd0Cf<{H2`YfLrcM0!>>F^C^f$S4lD;>E zIwR@ta@Z&7AEglUl71+K7}Nsk6Q4}lW3g}~)6w;#oDqRfe2Oy&L~pg#F%;qRl=P@44Sp@aoFRO9XY2U5xak&!{YV59~U$uCGx zr>t-xT}qglx_&(K_8k1#mljR`qa$+BU*m{ghMxW>&WH!q|7Ub1xDltR|CtxvGU@2A z4uoApHc_>6enXICE4of91?E$-K>VUXsi^ zocX+7l zpbyov8C!DMk`qnqIXbr>y47>_ylm{@i*EH{vM~_Qd|v@A1UG2#w6dNae1+xljkaDXh}@yBt3=9 z%%;V-ll3Sz8Cn_>S{4&JB_?!gOz8BO&>1nI=f#9p=)=1(oTGX%D<*V~o^iWN1>Cm_ zVnQqRR5Fh!y1|&x`7xmj^b`*~piN<{hi7_jv?^w!)p4M_yKEC;3JYW6UKq{FWpt`v zH)0~!#FXeodM3@SQO(uH#9gFk(MCiR?y_hmnBnCyp(|oS>taGz#^hmDOz0&sp{rv; z*TjTg8WXxUCiJqH&~-7P>-8+!0FRQ{6)}5U9}~JECbS_Yv@s@hV@%FA#ertK9T#hJ zlRh>kbW%*{+!)Z7n60(wv07`<3u00zjR~C@1A1l5)~?iZV&a|?6FMU%v@#}iaSZ6@ zm^^IOd9NYL9yaTN7!+D#QrHp`+7=C6M_Y}0yPg!)R7W%-EBLCI(9W39u9(nJOlWsZ z=(RB&)Q;#W3iBL-)kZ(9XIn=hLRw|GR8zorETovjN#E4D>(i(b^S}};EgCY9 zkO{)A1PYTWy~RZHP;4!|q2+^zmvn+TmNECA3Dd)i5k?mtR>4ZS50;RgIC2+lq&3X!ayJ++(0<-D!&sNIr!jI;ob{F3WTLEghZtbE@oNKnd;aQQ`MxpuCGD==;? z0WP4l07kc30M>_RvJA;RCfJEQ{+k44EpUo#O!HABBgDoWvdTFn0GARTHHlRjcr zndO>00Si*AX`S+sd^9am( z=I;EQJ3W%xsAl0(s*2}mOy~RGo~&uK`GUesW`xqXGU(mf3)9osKm~-u1?nQ*d=Jg& z`pSeZ{MOkafsK^9Rnv|Nl0FMKz_bg8qVS{?+I4}Xm+Sg6J*ex;2cb_a}%Pm6^=D?a|BSol}Q$G<2VpX}sT!H>2RTa$$JaBL(R z$LHFZB<_Lu&Bq)z`NeU?Q4)*Yd4eCGU1FjwKG8weO!!}qk3TP(3BvzXeEiC2d~%T| z1V6Tm98nTS0{S3Y)b>U3&=b5d?dO{K_+`<&68-z)*`=kX`>0OhzIU$Yye~cdUQGXq``)~s$)}}f(vsD@63hgxbMHY#Fig0% zo2S*lV^Uy`V!QZ4>}UKzip5JOcpEiK1XMX%-9W>$Dmu>UFH;Y+8t`Bp*E?x501?T& zlUC@=RPX~BA3e*U#j2*ilIACnzR{}jN?IA!Kwt*&@icj4!-D-m8o}u5l^XJk)omMu=sxLhAC#gs+jpZ2u<9ieKlmklg4|VQn@E>j$OG= zRThDDr15hc{fk7SUh7C3OFJbKHz0K`rSO3(To#cYSR(yYu#WGtmn(Dz+bcdh%B zJGPin?o6Mqco=5!fZ@-VzQ1^y>f*4pkxm|5E#&|yx+UtO?KYyDde&$5;Tg*y{~LU; zG@te5I-623mk1PWCfm6prC=BF0$jl|I<)6~Sv0oHE2B;OZy!HuwjeFqZ+!e9*@QrN za+z|_&c$lGOZ$`0?_|spJ#7kWW5^Mhmu(DKL-CcAmedU@$x9tr$qSsB3P)!AI!DG* z7`aBW*lvwsJ?j#qQFz zaZ71LTqC8nZ?Y@Xc>Kzliw_JcwxmnM(G3S-8JhN|mcOP1r|UcHSc{L3Ye+3s?@FJK+D_c} zqisxQvz5OZn$Wb|^XL#Qu3LOr&QO92-=3kU?DLHi4u5p5Wec?Z{6`>=CRs1~RN7bB z0l;!JcdhMdXoK4x+E>Gd2=O{b^x;=uO;y+E@Sxmm01QJAA?-ihJdGnh=>pGu-G>DC z>c_rek4Z0W{^*g(tw13D$Qohdi3w=f)))CV;$n5eP6vPF!K^-^ro+sM_2-%7GE|{{ zy4kk|IPKV5f})ur3Ea7Cg~rI%xUGU8yFLl}BB>uk(5JTAn8f-fCnmaQmy#NGsnRaT zL_o}1MorAdVpJwM5;9M6rzL+3`TC2A*#wCmwx)87!P>#kT}mSQ{>Dl*0Jf%%a)u9V zd)rf84whAVb!ryXv9-m}Yf||TQsTb;>*1KMb=S+lr#1oO-C2`^j7{2gsV;}kE$&F= zLpvrG!>)Hz6DX8zqBOrl4~ zChq%(82&-GRqaCXq^&7&!~4zbV>#BXw8^z{GvGU2hpV4UG@M zg*|e(5svVdCwQ@xvIe=u6a^g^2eyjIEx zP3Pp7Q{fQjVC99Z_S`aOaz@JD{m(O3b0VpOt^8%ud{1^=~ny)b` zcVSdIN8cKN?D?X%5-)a0b(wd#Le%^@$ZuG4;F{5nxrf%A|5UVgIN;<0Ce9-k9m9fn zqZxZOIRmRVw6QvmQCI4-Z1BJW1W*Fz$y|k=6x1$H=ycR47IrE`CkwPgai74QvWUe3 zk$6T>)Aqf&<93fXQ0NUzu$duRe~G5$E>69G6=FB#E-pTE@r7qDZjN7E2=VQZVyF0s z7t=o0^HNMPl%*@G_HO)YRGbCtf?>vz1Btmrid}02s%8wTX1O#fc2krf zg(eIRT6RjF?3(kXT8)Nlge&;?xlS-p+J8?_Z4ix29Y*U$eccEu7?sNJ6zi99ZgeWg z-1;icjZtMQDi9cqO(hEY>I#Yq0+LxXtEHhs8<#r#+bDwV%Z0FwuVMgshMkbArn!4| zN=V#;64?+cPaR2hIkcFTI-H^reFf*vP0f(G@t&QtHfhsSb7>h{tYZwAm(Ga=sYRuJ zhQ=uDNKIFTzCFP9(HkQyrQ79wEk&vzQ4;$8CoulF@Bii%DT!R}@QRc~E?@SFlfrMo1vhS9$2_0gkveJSVmyK-Oi`l(@kIhTFimAl)_jUrip!#ngT!d%BP z`gboYTVHC)eyr-z-SahV7T#$2wm0Wjz_*oypoXs}fxyan$Qz}c0^l?CL*8NB)>6(r z;dN@~Nv~5ohrRK%^P<<(j>RG-D!wj6JIsO448UL>xq}t#Nlo7fRMBJZ>sP7jxQPK| zrH zO&W$}ijfkZbTKST%uyf;HdGAO1bXZF7WJ*Qe+zQk(FUvYGm+|$FYSTr`^XAhT zv)sK`naHMV4tjGB0WJCaj*{fN9U1I);854Y4#@b!&dl?UjHXR94yx&HcFB4dZQ@d)zR_`$h`C zrDyinwTwz;=r>c6D)A63*J(4tCzeiQQR220tIu(lPV}tBef=sW^@l_#8v%rQB_}&G z|8&$5TMsyjtv1~ory-(c>1;m~cm%D`vI#Mj1z!O8s|wzgXYYQw6waqqp%bd?M54`j ztMx&9FlxWO)iR=d)vCUK9(G?W7AQonXX>sHnS$(H(x~lo>{?WO_nC_yJ#+CN;ujN3 z|KQ?5EM;Rjb)B;w<~`Z;jZpt3Xc z`{^c2@KW7p`GF7y7COo_l_F+;5x zXD;3tznFS@zn0nxYQMqFnOBqyLa^_+qelc}$ z8@QJv)T`~M`TZZ4K7}58)BNB&+e<#YsuLQ*9LfPoQlk9f}Qt33(zLU&vk(q-I z1L0oxKwzxzx`&G;2XZha%a~o~UJVUhgTXP~71dfFyVf?T=g?T$gz;yaVaKL_p` zsy(>D_yp4-WEdC)xbcz7Z6r%PbgXa%!_|{LIblA{j-X;VIZQzajx1fz(M31FD`w|Ed4O5G)4?GEID=J%D4}T{E94A zJ41kVHt`T_NXwm7rYhp5bMk0X?w5!{t)pZ*m5g8GfD}8QdWcM4$D^V6Pdw0;^GFIe zr9GFFm9PqJo!v1M;o>aLqJ)TgjIQlV%59_O{`Fm>O)2vdY21-C==X z`P5nGAC8Reu;>Z6HC!n6wuTFp{0;Omx}C$9z)6>wV5_QY9Y@<2=Ln9=Wz*2F5x65h zuxPk~M8fSJgllm}#ka>VCinF{DR$04#MmJL)5!>{Wf%8E`t3oaEnIqLU`@(|>vn&# ziP)8N2L?YsK-9aEipfQonfa7yC?t*PJCgF~6+FpYpOitLuCluL38Ma8ph613QTaOF zPf^dl^eUSNI!6W^3Z>P$ivFmITxGi4_5EMJRBb6OOd94q)K%Hk)~GE^8t;UG3(V9> zxpHDh?dR1bsZ&08%6{HONxYvW^py*`*bU>|mf9p&oE>Ao_Ohg*>({`Lc|X^r7Xz;~ zDRcKAJWE`3%;ZNXCQn9l7NVtTI&fl)pd z*cE6FKaVTKjCN?+StRuIa@!JJCvS+v)n_JgTWk^%8u~0d=(OyBwy&~C$i5`ksY9MZ z(vw^#uoyNZ1}wv^XU6lpVXXU1x9-`lvP`@Bk?a!>HSOwNv8!x19j2Y*hK<>Bm1!nW zh?O*FsL@I3zg!D@+UdZuMrnm4_Mkd=PvJ92O>>YUBlN&%P{(%K^l%#f#u5iv^GHU*aZDRbb!SD_wTr3N zGOLy~j0TN?o@f%({B=>y-(?Z9bR8Ve3Ia#+`a)9Da5}q{_%u*)f;=f{I=|6AnJnlx z@(~Bqn0}QlDV+RjR|DoZdd5t%7!|vMkoG5i7`;}G{B{{O2_uLT9H6|0^VJDy^evvm zeZSudDatiZ-QT+$58AfYw`w~Ra*1UklAy{odcXHYAV8nW{2@)kpd(Jx?P(>(UcJ>& zP!U_VUNv-MoQ8rxKtl;$yd1YozwoSE!sx<_4XDiWdnIAGb9%D6LWA&&W($*T*6D?3 zm$_>46#AYkz%KrDw6@B_$IJ%F#+o{dY?z+Vl_(g8wNroKYlY*~DJIuVp zT1b=$AY!>p+XvX=m|p*%AV_3V4nJYzyb{1EP(?^N%wBp_)a4k)^!|OD3x`hQQpjV| zp=jquh2w-D1^urpxRd5-zz)_nauq2w!P&)1pzI3aQ3 zpZ`^~W+s-GH=eb;rZ^;F%Zoi6q?eL7dOOjobYNNX`u13{C~Q(#(sCXF7DVrOth zud+NRV9&mzTOFI^#6;3YF(!WXAZcI!*4sTKW;&LrJ!vnZXmhMK&fi^JmqJBa$Tp zPT#~L@jw{K?ujJ9v`!j^=YBRC+07b8b1{t<px;(F`IV3DByTj&?Fj5 z@GgLuRA(sivpPY#e1}n;Gon>YY>jF;d!wHp1D89RVoEIt-ePCy<3UylZCqO!+F!9U zq%?~^nreT@ZN_Au%>F4UjKTV3AW={=m6fie*)`R@U z_)U?1f5^pZR;7^|PrJX0Plqh{eJTDdLm##IGsgot(Mmz1uSqzasHHp_!Itt!lZ~o^ zWB8Ft_6RthobOV#rrTygv7$wpnmNokjxlE!Q^S84+%SKQsr57aNyNu9T3q6@go@J+ zsMfaVTDra=?OW$~Wo*2I56?8%*_=u@!?z5kNeur~z%le^2|WljD>Fy~uMeh6IO$sk zjr!GzKK#Mc1al;l6vs0b?E_d1P-_+rad?T~#Ng0EBZIzC8dS^2N?5e5{TS=5Zwpl$ z$8MCUJulQ`)k_~Au@PesdpABY>Op>6JfpCBy*A*G@kPj3eVdNV#X`Wf0LlS;lLewZI3 z^)tTiXPq2Wulpt8HL&qs3T32li49YGo6fMB204ft11oE z^&0MFb^$sy1+{X@^b7LM4o}Rl$)1x>Qpg>xmuD~656n+mIec}2z9#7s{4q@IwOiO| z*2W&5ttV!rrHRxCFOOxA1ZU4&q>0dQTF1>4`ZiKgWWg3BPt4EKho)5KUBg_Aa(5i) zqt9n$jIr1wbO(cD3$?Vgd1;9mnij~`oh%ik=_`j5Z{yPN=QxI@P;&fqTYrTtc8k-Z zG6=xQ%Y+Hs@Pf0K4Z5ckwU@AZ@a<$1Fr=Go@5j)5=(Y$vCuS zi8iUCz)MU|b=D_|1qyV6mq+U+z$%+&G3XE#HbyM$vC^*)UrogwM3dcvHlw;yjCK2xExJ^aaE%;ZA{>6=aH8YFee;Fb1p|06{iDHM;Sq zcs(#&SHB99NtO$8^@(hORS>^dnURRUS~@rZ4x(UaP4d7}#4=enz}2?T!$uoTLYFc^l5Iz8odn63UB(uo2BY}eb0|1enT3>+-R945oxlB zpg~)8&1uR{5RUd70-hxG*GG}X%k=8T5g*weI#@bH9$<{rUsCkemb_aE?9@u)!)?hr3%e~a+&QpD0Bb}L))4$^qV(#k ziQh>?{yT}!2q1PnKbZ2b*4KGfb3Le=>#Z~E)!l8?bF@~VFY^@Km8f6txhs+DEu(tR z0AOKL!c}9rr{Gqyqg(Ya>xtLhse8VxbJgYlhqyO^ucNBs$LGCyGkHmxG-=Wm3Tf#A zbW73|X@M@GZMuannzq1enysPP$b0F+*3y<$kQP}4u|-e;1w*jzjB;WE$%THOh;aKk`O-Mn=o`K&bRxBO#`%PkXlT z9(q~}JFeYD!|igfwU)frz0C!DoBMVQ_}j71VmSLO_6^UrbtU#iQE2#w(Wl+sJn0bB z=@s__D(|bY>tek%(TgHb@XsTka`)Hh!&ESo3k9n(hUK5-U}=i-@p$uTPwbM&C6N$t zT?7W8BJ^EFDD|o6pQ5%@#jg>yX}q>?*tvV$joV_;C8%4|`7!+NkL`+M_i)}-1=zh< zaAzUvOE2K2SRWtlbYjQXpz&N0e<+UK!+B5VA@(R64#je$c$}Fr>bv>ItAtk%Zr_Wd zoqR9)T^EeL>)w%vvpe$c2fx_;c`xKg@Y+&_%iH0 z4eqQx=uTW+8C+et$Kgzay7#*g#60wFKMOj3b!{x{H1;gag(8sXd)7dfH4w;&W?~~! zh#sdg)Mk$pQv}gnH9Dc<4Nm6r2slGDmQlKYy;XX8rv#IH>H~(l4&g{*(Vi6mI(j zC=h3@`zSHusMh(>FZU9iXX465(YtshMgwXK-X3L7dwcX}QJ9jYGwvgMjwsIOMWWO8 z;Nr_s>~VkEHUo5{RFQK6E!vYuA!H~lXM4+7x|}^+=ClY?JrIt6(Ns%#G~M#(A5fh? zh};u#lgI=fiu^NBlag~Z)H8Yvrcn=S_QNW+yb!q}w&i8~9BS5N3JmG^huvIp^U?N! z;MN`EXC89%w3{7d8%GWAOq)9^)lqZ*ch=$zO75#8kwomy2zq?Rm$Y^VGb*a+qm`{v zli|24U>59Q=i{liBY$D3hsK4WwGN_4x&c%3oN7}ck$ za>`gv*+!`T!pO&rs~5*!K#oJE;iT>mk{L7_Cl-zuy&k6#g&#l&X$In>uoAU#^Cm@n+2MTK^}xqRvGK`J?-x zixrGB)Q9egedyj3!=-y-55@*$E@X~C@@@YyA0)re{TrAFd(QAi@Slsn)UC>J+}zLi z#EP0w!#AUUj-osJbM#wGe80s$_oUeQ-mRXHeCR#u%fX}mYd)PaYM){%X75EXIC&#_ zorfgte(x{b?eL%Wk)$Dt$-f@;tHkw__TX`qx#v`K&#C4fGpJF_b0N)b(N`cM)r2i{ z?WfV-QT&&@cRi3~ZHCZ;y0J&n@(1q|Pd8ZvRZV+K6tyD_k|eUwY_eZb4CQ8Z&Pr%5 zqoMZEW1^`d!0DJ$mUB+o6)_B^V7@dsmU(aHw1jcEXT_GPa$>)8Kf+46QXGDyx6tKY z;=%;Cx(~*{HB_;sxWc=8xuO^zRDh3#r|HIi?SX11sNnTL(hT-A~MWhgP$$ikHS$&3EQ?6-s4lIJ+VPUg?#8pxYWoo|B<}%&>m?+Ul<|eMSZNZ^eGL*lTIydh|qyj z#v!QeA#cZ#6?_nXrayMi^uKI?zr{&8=y@(1aMOSsOq9yWO#{9+AP*F7)*-hZ#@%6W92VU6#$gYZ0eZ0PcVz+eyRx^+a<@3ay?+??G7_iQABXQc0=wr& zemXKBd}7qEMx~2MWP)oMNhT3aWGK063-ydrIu8A-4{}naGSV z37K&w;+_I=KQF_Xh<1t*?UdL9BcB-wkP>3|#Hi;+VJBj7vZ9Ci`@r!YD|`y6cK8Y= ziej;wMyKcYl)SmPlw06-!nFzpA$QiBA{zvD>2jodiXA;4=e&zyTy^pIk>P@K z;i7w0^6DYW%GikcXoK??VeUe>tOS=Yb4>JQ!v*KUC6N|G-OnWWs0#d4oB}^<=KOST zWYPlAk;RIKfOhOGMzAbntMu(!%tK+kLw{vL`+l1O?2r6`z#k(2G=SWwL}QMb`%g^C zgfB>ZUkWX+pl|n3#~he-4lngKKg2veR_vxWVQ#!%78-d9QS5dHG`5Hyg&c*-95prC zIVd)DT1JW|l# zF|}};+LI*!p4^1v)+Es6_K4THZ7YnGP{{ zkBY5w_UkFKOaBDl>81gDupJ|S;HfBwHnPQ>SS)W0=Z}JOH#VZO=lRf+^f}(d$&HolZy_T~xF3%qHeFNk{fjlPA@C=!~*T{g_`Irrm`F9PwvAojQ zA!B1xS86l|53T>!qxhoOEzzGuW3PIzdYW)hY;W|LXl#GEXig*Yl#6Mq}^9K99xz?Op6^@>!VA_)9eN7V@v#(yuiCaBwiegoq^|39%H!!pvlq(8;NgWKM-xm}Y*2B=jR<2qxN#dJ!jAPNj&weIlM$ z;^ltJ8|+8CTz`)j@k_CHH}Ca^1c>{$4Natq_{H&Cy`c*{&tF;U#c|p5&j;$}M!bA? zW3?A?b9eHnj7PO)b)M}%^1ex8hqqLq=i;=|&@c6fboORoQNe2RA@kG6RWC{dG_%iT`=#A^BD@8>Vb z<%GAq5})7|;+8(!gf{A5=#}7N)OVLnH;6l~T7Xp^K6i{o-M>U3B#%n@Q{u_a#}XuR z_0_Y4+TG(qvqb#+4OxFVvE=vKYnKZc@rKFXedVl(VFSsUMU#Ctc=-(wbD`9*z~3G% zFS*Yh9&ak~M)}2F@pP|XyH}j_3RZf>=i=Azj!$sAqr)SlyU%Tnr*PnTxFh8iqneRD z+hCUG%(3tOBys?XEh!mDrEZFNpR`^HhG0}Q0fM+fU2p5De`unh8x{=_=B{O zi2poZKNCO6_2D$}h3a^bsMGV~h5+~ERolxGy#8d@Juf)xzd%{}>yM0n#$qH}qYH#Q&Z%C(C zlJxp5hxj*ubSOmd`~@Z6p>nXx0xQMqJpb|mR@jwv-2=NJ+yW18+j+?+?Fa9OK5(xYOUQwrz_Y+lY^af(jATvPD;k4KfP6;$fpiKe|G|+#b zDiP{#@dwY}=#}C;vIvaaQ&NzKr7RLK*Y9?R*5ak|h&LeR9X8#IETm3P-R%trG$iGf z9_J130{ITOhdVMwSAi;uA@=QPg*fQH&@26})HLElN9TEOf(8mGhLvX=@bANIMbMBy zW!`Z!Jg?S|9z||_;QzQWx*9AQEh9IgoSXgayT9be_pbztQr~^!40;Pg78M+iZvx4F z<8`_IZQ^~XRPL=FRan^M9d-gZHd&uSbMp>CydH_R57$TYXE9Z9D0iDTY!?vsVdqwH zo?M3A1u++5?QVxd^oPa!`0lI45ny@lH`{CR^60Cq6C63WzgG@MXo4(zr`&bD+~wto zuMBlxDXx|qZ{&?|*H?-ev?mDZo}hrCzWX~{zzvq}cg19C=+c6KE+fb`;rA-&B9&gQ z`{gb1ZC)AMhVZXGG0<>$?u#V(z>E05rn70)1mf{V*+Z7!J+2Suk6;mao(q;R?Wf!^m z=*0X6lM>|meMfJnyx0@S_1F1KiTqPVE6_*FJ_EP|kU>FFfKIQqP+IB=h59G-7EGV@|IBNaHdm@?u)rQ7C*5j{`m10 z$$nzSxBEOVv8<>G)xx@@zPoBKyl_-Cx=(jiEi<>=`=l4h?e_BjiXs=>E($y5!ZQ9u3#?+_lapN{&~xZ^Pd-H2C;)YD(>$EQPCZW)pv z1Q#@HZ#-IA&0eqn0&jfMn=#(&zul`zdi@{s4j%`Qnsxu|n0%^-UcGoJ;?ou9uy;pR z6r{N*sjqt%ns=G|)S1&W2`^~hjikK3xQ=w(k8kr=Q+H5N-*}U|A?2fASq715mj>?P z(%fmgR2a2@1zaZod6VI?@4W~DumKmKulC&^FqK98=(Sti0WzDH-iEwf(%V2)x#%6) z#VboPi9Q^b?DqN`EB4%$mQsl)DK#9Y(kq0_bR0>==>gl3(MG%@kneSSMK7mljqkDlWsXWEUqMRj zUG1mh_eIM~qa&yVWXee_8;D;&I+8ZL&-3O}g{j@RN@d=b-kXf)Hc3=q`8UswO9GtR8EGH&QnJx2tcNu>(vZb|8(E%#0hO@4J#7$XqymGVQ2=n~Q z0kc~B(NH(--j86nakpEz+w*RKE?-7+0!1P*@P;7!!*B@I;UHot55Fm57y2#O5B7@P z&EvgDJJ`7!c6-Nz2%>F10JeE(P=2Jk8r_7i2dKkAVyrZFf`BgutILY;!Z6dhc?q`U`SXYiOxR>#$|7{3?1d3sq63?)TUMa~JJ4K^#qoM*_ zFCHMABC}YJWRtx<<6ycH#59)VHb0NlKn}Z0ko*<{T^jJX{N0gohQ%lDhM#maP$ELhV|2rf1LX7Vi^AYrY z_q%4K4afZ@V}N_-+0`k?oj!pvGbb>65VWWmSQ0VojWendvr@Q%SH9s`x1NpWSm3&W}ihE7LG^c zW3c*?{~|NjKG0Sv2gBVm%;4UHvIUaz7rc#2r$JZl&vIZJ_a~diV~FHFl!Mi;OEF?O z7URH_*PHSr8gTH&#>Op47NnbL^ny|}`XaC3axecY-b@Tws=a(@2TCnr^!lnF=NKgDmj~X6 zN08pY_4qCG22Mm_D@8edzly^q_7E$*0(#9#92aAJg41sVrx?QkFM^oyjb1+v?zW?Y zMO*kW4^2u}H};4G4d z=FgD{hkm9R#D|H-2Krx>UdfH`lAhWH(QxR&^^@K}?%9*L;F}8@Gn8_|X&m;4AkI+K zacE2ExjkIwh~+ReD4;CMLuT%~|8{VMuB#MIQOqVJZRt831O~BY1nsBjdYL{I9*)_h z=`7Pdsmwic?++24y7&5fd$u_DBlgs6C>RZ(fw0+3fpIof!^`vIWu8~>4ZNPczc<%k z2`Z5)5Ay&fmR>1I1pONBkLXX22_$zh&BP920MuUK9un`zUWY+H{*kD^05JTwV(7v~)E~VUC!CI29NrCdECh`meYPw_sP8R zAQRNRyZZpK@yNH>IYeE&`fr%}oGOg2^u}{{Hh<7t&_|gQM*IZyg)o8{sN4a5>iO~T zd^B(74#q`be+a%I<0ScP^AQ*A-Mg5RGTsXLt@j2aAo|vY-y~qZ-XL7u_C8e@F zm}i(m+o7B z#cPwjDz=Zi7pX1M7pvIZ`1h@Y?ZO~sD`RD;1eF5!-xzfdbGOAX_{8yUdyH{N=JZx? z>~1-goG1RV1XhlnIYjHrDT7^J?kiG2K2RA?R3jNnqvAt+i11tYrYJH!>Yxx~CzJnU zv<2=6j&S|>boxG~;{O9htvAB`!P)Hh#39`^NSZl)+^5;=*ND4!$=x#ep={edNm|k4 znq1AzeO@%k4i~{`1XX;QkEzTQ{LQqMm%#G7Qtq3!6b8D>QZ~}c%oGzA&wUK# zN8BHslfsi+^=+i8D%w zcxd;QVh<_IQ%brcWNh+g@!1h{&NDXb3(!8M(joU`##i#}a~onVpM4_y&7**FcP{Rx zb4XFodomw}-T=Ad43P#i2HuF1Ve)u0gokI)_#^ydp)&WKb80wwM@Y%1rq#5(c;(#Kxn$K5jAv<8W5iy5bn-4aPh;*iQ#QD+G02q-22a4k9z$ zQ{<_RC7yGkOM@J46d?X$WnoFY*{`!yeMt6HtFqeBQ zXdd!!fC@1IjhhbL2H->QC>)mV1gpnHfWZg~e3FBi#GUy#PJP1Mt^Ql4~(*k51_w>Waly-expDp1aOGS z%;6jl9nlSi#7q3W{>sPV+vUHNcE3H&qdoEM(W6S^=f!uVVE`p^O%CLy;9kSwKmMX= zfBAG&Bb||&VR4Ga!sFox-sj-aPRJFEX}-$237pT6P8~T|EC#x#P=8k*Lcb|Pmb)=c zlfTIG#>jwZiF`U%#IB*v?(MJrLt+C-|AIDOf<9!CwrC4ais!g>g!E7!7F6WGecgTp-4$uOTvq z+{h<=xy%w*dV|iT041dZ#ToGi1?M#=1_!3-{5c3_i{~Q}OayS!DT<(rAcw~Ro_iyD zOPGKuQ-QmYIoW#g+kty=c$!!zcePjWEY4a`0ZHMRX!2blye8q7&-2%9l=3|PDr65A zgXbpXC+=}*kM67#NRiaj2)_HZvuceMhWPG#uCc-uXT{5ChJNnbZUnvCb!>#_0X@GN zW@UeYQrt<1dj;;xkbkE8E#v~!;>>-JXBWbwWKQn=Tb}p&vaakecc6j@hMddZ<^G-> z7+Y$A|99KdT$0R8SF8Q5MgEu?YKwJog&FwD~@F59S3Z z&CRB67(FttOsUOX!69C!@y-C+h(~w(@W>61?ELNbf&7AV6!}FNa?X>LaKg+y%_+qn8-zj% z+&|F8g4&Na@0zfB{cGd5Z4@=%*;B${?vsI<-M#1R!}BUD+mqHqZ*;#Et&Kkxzt4RG zvRDPLj(M=y<><=bKd{(dIAf9f9{Rzs7?-)P;#qDJMWL3=U}wT6qxW1_z5_KBFR-5YQTz^=Oyw2C{*Q4sIr+0S|$# zsf+tc5XUZ!nxYXPO7SEBL%`VptO3Hk=RatOw|PhMb`}>Olr99}8S?@zreHXy z%-D(WXXlu&M>-F6aVF@uasxXfL$aqg65)?KI2<<2m~=f+_fF}GuI_b>}!BpG}Ft$s&vSb~eTrCx#V+xRVga)E7V z2)?YK@BS9i(Ylx*c!Lv9+?rs<5_j!xVFG=>6n*o4#I3g?yYb{_9v z-FMI4ElpzEk;Z{x%;BuNExSG0YuAIHR; zf4KfX9PjP^%v-_p>MXz6rX>f1UKsm+~@iDatF zY247*o^p~ciMob{u0(5ct&`|(?@l&0R62>o+U}OtR7-oJvpZG4uCB{Trs}#&rMhTLol1^J=GFjK$=qy?`H?gW}>5|z?YF0X(iDY9c z*-^iqf3dCwXI=G9stsVh)6SLTn_9Y(5T!BI3Z`qjo1CVu#zuu_s(cUz((wXU&?8tJOv&;Vwgs4ktx)3@@NdBGjK)M$YhAO`+}PgORhP17 ziTO*Qq^1P_=4>LluA?hOxjVX3s62Q%O&hyfCJm+LZ7r>vA@Z^%vlk@h z%$|)3QH|}Xj!vhmuDzk7EzwYy0wGJ>(Ac%MBWVjXH4J@Wp zoDLM<)Y`EzQPeWbuFocfbET&QqXoM)Ij_4uR=D_bsXGF zheItByokG{pd_i*wK}Xj)#G$EHYbvG8yZbP^>wYS9rX@Q>es!T?PT9i5Hs=290Gkwi(GJJXIaXW8;4HOrTY-RZ2N4Bjr%!)OW97~qpF$p+|& zUe;l}41%n8T0of;pZ?O!`O8mSvUJJfsz(Roa_UkYE&OS9PVa6(O-02t z!Nf|MfYR3`>swmj`KPzlbtd4Wv|zgNZKzAMwm_Orv;$Nq)oM7<#P#c18>GHd&}hZb z6;sfDJK_J(WfCTUt&$m+bK2^X>%|)zQ&V8UX8d8!7BtD6p=EjuK zCV#t}&X)G(K%sM%EM88fqTcn=KsTkl<6(A)R&g>rp^P zO+izuV|!0^bfEyYPHBMBKH=%jxV;lCk4=^pXo6fxxFtL)t-*B^~A z%92E}4Gj<*C)O+pG<7sLBPF6K8dT#3aS9to((bpYX5lh2X=!FSf_Jr}-G~k#P7{>a z(z#($ujmw@4ULekc zcarVaKyVguEJUMJS3`Fv{@5mNkp`A*K|7KV4v*Pjbi=*^O&F3xC)5N=W^GL$A`wx! zG)&GI7eupl;_(d$(}V&KVdsF>)7h5l#@}^Gp-6gI3mRR}XG$GWUPl-E1c|aJu(`dv zK5!vtEqs~LO$28bif$qyUN1IitJ@@8(e9Fo#;&f8E~7^1sB5!P+u|jQXDvi$BEgxF zOjt?xvUJWOG<%7p@J{**+QqW9t#$3|o$hvcV|!ymnd#lpMj56jNrd1L9IwIjAAtuf znpx{uS23N}+@&)Yp*~GkF>G?yBoeUfzG7qOHaWV z(9*GiI*0!VAuJ_rwhm!kI=#BJt>{`!FNv;18Zm>0$x_6?E%glvScu2aiV9c~*4aZt z7j>*}0l#431^(J#7yGdkKEZ978$B%NquYh5QYBcoiFXR@b+^tsZMoz#W|lBarm zA+UN-J_-}Z5rH5k+OQak?M6}(kp_8*iNs5n)UJfg;sk*K<}Im_PK+#*osIQuAoOr3 zOvO8%fgS^osYuw!~f-o@8 zT(~gsQzz(=5X@NFj`oHmT2he2fNW|?jzO~$~~%WxJ0!&t?}vy2=_frqH%C7C>(JeaKcR8KP1)fuTe(;oJQ^2!rLH;?`OzHEBXqQj zCZeOFy_T>{B6dh@P!DZ=UQ1Ob99lHH&K zVX&79Gt!~hb-1Gyxj~>G$-Wa99UuXK_qI0H!}H*C;!xrOyb&#uOeBw>&SuSAK6@U` zU5^-y1Xf~L{RZh-K;8k5f#Xb>gj#~gBxE6}r~}aO7J4dO4}Cx;n?{G-4vEoAS?w{s zq|+EXC8bhG&XY*sjL9*cvYj?slkvZFE2F~5mPvnbK1~7nuMw)t^*`ug9D;YI1C+Wl_!9x?WDOtJ*c2M2v zkuQ_lrAt;UugWw)4iwS3pgyQNcVb(M!v6eN?B&YLdFJerDwl-2*GF+ARPgU5V0KJ2u zm}W~zC^oGpP>jO}K%EDIRL!js1xh0dKCKEF0HUm)zW5 zzpksJy`wuhuDczbLBqHd+dle|Zj4{*QXB(HLSO;}TYDK@rG*nzEoe=sj&;6C#`HBa zXD_H)&V-T9Z3ezU^pNR*rjD*QWURChq*|X26KS7MSPC|YMofo6w~6`|#2WV0QXqdA z`4Cx{`shg~l!{&wEx(~1F)o$hya@B=WMVBN4`Ui{p-W5q56sN~GJo-0#$f!9(HD)A zsY1F#W4AP0eikmNs;!!h=xc(n@%yTiZ2c2-bvh2J$&ROf1C$objZq&em0+Q%4orV> z*D4{k48etYH?w89m*jHGs!m!ovnKJynG07`NlJ0zOir~_Ery`dc`s;T+7T6;~ z!Qaiy3jBrRk_1OmNF!L1%z?1#?Hz0`?4-*Zrfb?**VQib3~cC|Wugos$P_CBQ6`MA zL%{&FD<%0EWG|O%lFbHjWeQun$+kJ^5O{`lf=prsGfRlVj2k9Tk}XXwjjafA=|ljN zOETUT|1q6++AK5YnKW2(88nb}h!zf~7dab(StpLI92=t3d4uUNOpcB0A5B_%`?Tw0 zGQdPg26-e>$oD(fN&m?hD`|I-uEMSB8c=ucCflJnTcb=y$)qD^k-Act(vvdMmBM@v z!oN6!BoiVB!k$DZOo-;> zC8y71s9L{1iL}yAVTel6)7K*_HmRFTkTBncAq2LWpAAl`tEH}$smj{!=4SB` z2x4aw?X-m4Yo;190bb3dU}AUSe55538fM#g5%`FNHJQLcI?`q)2BlAyWYol5_$=*V zk|}s)gBkt8Se)KXhm)jnX3RT-x!i7n4r>K?Zu3Sq00|pQmdrBgrx_VbI1a3}Hn|D2 z>9h))icDj`qnae@G7vSvC_$>x-jM1LftYD<%d$f*9uI8#&to2k4eE#rcd0G3MuxU!vH-p$z>^Fy`RE1pd<6-G(etEDm-M zJaC;^RaMJt=A}<%t__`t=vNAbCnYyxiWm(MDG^f^2K=g}OHW!+Wkc`mC5um-zjTpY zShQrRjmPsB>&j&U0P58wljdl#&25;iZZaH~EKN&Mvx5GNpoT<7W>;kR=Agj@Qx2TI z>h3f_EuG#l$VimM;qlCQsh_}@^YQRRZcp+_T0QHXSj+AvO|fVmM3*@T_(c)}d^i#YXZ4(P z!*e=X9IcIWL?$sY^NYq2<}b7J3_*$qA5Sx0HX8|SLq~$+Cl)~sKxFBHC12x%4Ko!V zNIMsv0_~>YQlO+4OLL_KSs+_N8&XQhk4IE!`JLVE7$}33*$!G#XL?v^IzP@mnE(`& zz+oX-Aa=4zv7?bT)Bt0q=b)BWowQ>9(yBR`nMrEa#!Duo^mp@If=1ymq}N72$&Mm; zH>w58QO?8$>68N-Qw|wY1R^qrhppOZMhwRpo-s!5YHWkknUN7%U7!y;okI;t^APKx zFvJ>}GM=!mqpfj5!^Y%<(@vYv#E3khzGXtHt#kYrH_n~keNywPhAxATn>>Ef1oYJy zvVm%Rz4QNY>xAxP*90V(t=$cc6Oc_Orc4@#QFr&IahSZAAQ`46ar8;=^b_c@NkiD$ zvUWmqef`0N6_r7u{}+zTVS1E_2F7QeJ;AyzBzl1sg1xcu_;t?O&8bF)KOAC=3z^af z<0Pk()2{A%bU>WkGFKZKn{Xg?QTucnLyTEM%22~!#^GN(&Ln?C<1v@)a7(D92;K#s z>IrZ{mWT|(cwk$nP~o{zY8-oNa&O@envY~oK;vh zt8fr*m{k~`o8JL^c47I1$CU4xb|TU%bw4& z=d1XCID?IW<1vq86eV(l4=s3%{pIKP6J-VQ<)14hD zESdx9jXql~P4Fk!spG8{8;)ac#ICT|I0C3Yb#k-Cxbm&xZ|w7+#qT0MxA3({v@x$R zJ|`bliC+llHG6#+SDi#1zrs3R>cSkC#O4$pc|Ph`zTKZ&xF&jUp6CiyO&e-ne)qxP z?0l3!t!m2I`LM;hd4-+p3fHU)4m#vuRpA;G4X<=s?V6SMQ>Kh8@Et1)tR=EE99+QM z{91r;q@JaoBt_I0t~p1QH3{rruw|98tdnSuXcH7OKRt}%R@%pA8vj1QJuC`OKG?~s^U3RE%j>fLj@O1>{S|!h$7P+HEw91k1)p$V zjG!Xb`D~+)*lW{SSNPuf(b+9%R}fEaSATTMTJU!CvG zrypSTLbSYj${lASKD6TgyY2noNbB{)UTidnHkwzi2Y0gZ}w`m zx%n+1m=D4g*v|qX%3{4o$oi{}b2*Ob6PGgXT;jqLZJd~c=Ck~uFd_G@vGX2zJ#=(i5Om%6{s-g_L&#YXH7i_H?map>!hSnPMi7SR54sQYDw*GHm=z=Plt z(EZ%})6>UQ`4@upU-rIhxvH%A`tn}%D84?o@cL-<`d-yGJAY2$&Cykbcc5nX;@^Y# zw-5iGjzWN_yE1~S^Ki8t`m+TUI^70N0Q8Q%-ev7@32k^jZMYqAa7}b?o;+S%MSMm-KxS8>H`({>SR;L3&U2jbg-{zkc2uh3oL@!JC`;+gCjnlH-ihAdW{{och%p`#!Fmy^d`h zn{D#Wv2vCpZA%XA&rFNgXb{J9EnXkO7sHF7YpZPI= z)*;6^GXu#{qx|ML7l-im7QZHhpDyRV!`w@68|9=>Lvnn!{QAy2A^PnWA7u3w+<1}2 z=Y{agEFKT>xzgh6LipDO&v9;+edgzzIHbK!u>9F4aQnXe=GeWQ$j?0%|4{~#qx@)PoTYOOn zud?{+5Wc|T%_00Gi*F9$Uy^g*xiF-MQ!M?i5PiL+zavC{nx(%fM1Q))9}3}{EdFW; z-(vC4LiqV|?mI7p%DvRm9}@CsGloE%4+5uE>DMj&VIle(EdOaC`dci%DTLo)`HT=He>h$}Yw3$@?h<&)ix!_2!e6)eg(2L;P56HZf8Un7 zIaIH|TYO~*H+IT#mWA+`oaZ<-Aw1vW%^|!W&KZ9mlyV$rtF4%^tDnyMg8B}(e0GHR z9A)vVLwLEx?+)QpE&f0VKhEOYLU@&&qaO_EZK0(l2^mdJqw_%oJ%TD&J8GoJRH z&Jg~prQa9A-?n&JC=LFz#n*)Jk1T#~2>;aLAB1rH=~isMQxD7ZW?b(( z_lEF+md^(v{4k53kl#}eBQ3r&gpalO3n6@>#f$p%n;9q2=B7^k)hOdv&A=s@T~#=5PpHh9Www) z3-lF>uM6Q#kSYWr@$CxrjN;va~@8A^eXPcQ{5>8~!E`Hs7fU;s3CBc?c)9dr+3< zIR6&<9H&rrn z|42(8m3@YOg2g9>@F{ZcJM&62v^<(&>E8;;GsofsLwpuk+|(n(YpLMK-$MLXTKbJ4 z{t1hR^U@}Z$7P@4-zMiF=f`C;*OucPAEG}~&VA?RkUZN2&v7<~=r6MLAj5-4gDmcZ@WURFB+}n(=>t0q z1Wx{CRuA&b6Eq_&{mYg<&|4nz_@FF%Np=%J-y1&3@(Jb}gL1!M@p4;kfL8+-JK6%} znJG$GCG@TnjN<}%)>=H6XAAJtfcGZPnOX2{z(o(xA2)fviv6xE^w(JWU_2E(YrPRT z^?b5$$xMsfX7MLO_>TiVc6>D4UVqKvcUXL!#eZq}tO@DuS>V0ZH#dvDUbOsQv;3!9 z{%<2y>W$C)mcGmy>Ml$FnU!agJrDFB&r)tNaO(Lr%SWCUA!68t%D3O&Ek73pRJZpQ1?45{evO;M=gD4i2fx@AEaLLo&w5v3wXfO7AZT$}zKOuzwFbkgt zEPc?A2J$~)@p&OW&t>8BMi%^i;H+=i;fB%WmY<7xz~20)066I%wDj^`2<{nZ@ej%j zgW#Qy;TA6+X7E{N=Zv-ZR*TEKAGkIfcyHw{wDfCiA|vm7fPOV_`bp4k1O2pFe5@@m zz|XRHYY4x<;=%AepufuEflLAZZHuo9@wwCDlS24I7C$nC?*~qOI!Bue^8N@8e=hlt zn|=>0Xs54RJ{MX(0e*&UM-SR|6v%l%=w0WX5dN{{Gbbbu{>T~h={oyD^aa2vXHmJi zLEclrVF~a+HEy8Ec8cb!7GGMP)o;=cUQn?N*4MVz$w3(kI&@E zbFhqB=NfU~`f zFlI@Qr+=G;{`Z#t$WXmL5ZrYh3F+vnQ-o@g98a1`WYRRjE9F<{rwH%K=Bl|@ zXeLW(Q%q@wvrtZ%q8E7@Z#c=_Qw(ppZ>roeRqmcDG*c`1736q9rkSfE*EE9&@2SFJ zn$S-ZS*8i+X@Vakl*dS&jxjWbgDFus93z~MF~`E;7@;{v_#9*S2z^Dlu&XE+eih}y zu%cY+;FKdTq+Eg3UgnD;Zk9E;-fWazM{e~t1!1$ z*xL=yN^@VOxuMc9t2C@DC)&?P$6MGis5Ey@G(;24HGCAtqAE>^6D?O$@I<>aw@)-8 zPPCMknGvee>?Rr3lML%ghP83X3geL#lMGMeVHL*3DvXa+Ofp=IzgA2(TqYYXlTGQ9 zjey2wD<&IRj4M`5HX<1}tT299VH~<*is3TFa4{ZSF~!IN|D+10m}(lIte9eCG5%Nq zS0st?%L?PF6;q8YQw^7?hRamL#rS2#RKvx1Y{fLg#dvFlap{U_hKq6DifM+6apDT& z#TC;G7vs$p#+@sS-&Pp6t}y;vag340cyNVr;Y#ComB!&JjcZmK->R$-omCpQtu$U( zX}qw~`j)ZjF(N~yao$Sf*pyPw9@jP);Vyng)N}O`e9vgUAm*1wT-TDH-(fvW6A)9Xm z>w^_j%;!k>Fj(+O_`XWMOUkSTVAlb%Ys%o0a#?GTpZW2d*UTr-ndOP}hmz(xK8nN# zUHII~tU4;I58`7dlw`hw3NK(}>J@zVua=5TuRs!7!Dksr;Llm0j$DL+16}|clE75a7RN*I|uHsuR^S!2CaWo_mmy1I`48^9u`!+{Sy)3vR zi+S~2X~`^_iEmB0Ql5MPe9)>G*0epp<+n>e9<=C&k%DCeD~Op@ez@j?SqicD#YD_~ zJyuVoYRt+2Jkm>K@I13_1kd;tC-aem*Cy(@LSSYY1bk^KA3t;5!1Urq^fP=+FO9%1 zwxG&2`Uw^pRExJ7uEA1C>Ce~gx~Z}%2^=8w6>HChEX;?yYI!KR3#`ls)k3VlCl@%g zv?C>k5$y-Ey?s(-mLiRZ1cqZ~rKus%FXTU_~r+6=o5<%z__SK@LKym07tghy=y-;#ED@ zqPDAJaH(2I&t-dphA4NT2w85^7HL*+vr8tMHClt!aQ}yOX^|JCm)*fJyp%QJky&5K zEG_{oSkhas)sSw<|Mk*fJ(j!6EP!GLl)*d$rzc*=zmGpR+i*MHB>slNPqH}2p>N{f zzbyTBg}<%vYZd;M!f#Z#rvI76SuUpb(){-+`adZA8HTe&s&^wYWmj{{tk`< z`Tt>Y@_AR`|F$^!{7K>XlTWe*^nu=j`KtiuecT2r`uA`ilsjDEe^I#ke!_9c2UC`5 z`rtVZaZE|4ar2#op~sYE8egLL)7C+`>n%?C-d8yO6s2ro{IV?g)e8SW@%e_uDJOX~ z@BrHn6wXJcfjsvrK3bla6g}U13+Ug-LjSJ9wLBjvK3blbm5V#hD+T<``};_m{9m%75_$sYk7kA@Oimd(Ff0Ei62n-b&3xkkp=R9)8gc<<-b|c^DU=< z{x(Ig>lJ)Qz{`AvDxm*y7W(HEe?B7!=-*fLS|0P>xA9xPViwSw_r4F-f3bZ}jO_TT zT0lR@;^F!R@8^@Ak0Jy5S&EO=r+LrX$fNbSJPZHeJy`PR+g<_xHHu#AvssnPM}+}> zYZm&XqUT#<0sW>d^ya;3BR`+@1oSs3KDxf&SGcb4-HN}q*L{k9sN(;iqSy8PwW6nO z)>uC{kOl8YB5Wl42>$~42Pyn-3a_v@cYjy-30de*RJi6JyjRJ~>&t7?t$u!Cabh3hUm(wG3jajm=drWI#@j!|zkvQY zc8b`D{|o;K{1HX}TZQZX_br8MJHDrI zeiIp#`=P}}T?+q9;adJ2`yhn$!<3w|Xa~;2at^Ze#I>AfD?ZEt0(o{TTB;kBxHjThD<1e0KKOi03K%G==9Y{4$GE{yqx-hN2&iYXN^ghv!Cm-QFKo z^qT)46usvEH${I0cm@3bspvI-J}2kKdg;7qu*E4)fs+43h3j$~6(8NtZdLdQ@CxMN zb8K$pA5;9lqUcBBT0nng7W%I%`ahvodeqG!$- z$oa0qHUCeu@Y!Yu0Mx&>?+q4bxmwS6D0=Nb_b7U8-(M(tzDpX&xnJS$DLwExDmRv^ z?Ou%MW8A{>Ot3iR*Lt3>@DaEclv|_tXuGde^xE#HW})ZvOl~Y!+x=XHYk4kIxVFpH z3fFf3w#8XrE$8iuUfca1g=_x5$in9ZMLz{)1p4_%;SVa@XR?ls_2oD80ez{$UsU)Q zg|iOV!S>uL6@Dbn13t%FoV2CNPnIcq&1aRuk5YV^v+zkOdd=qyg&(c>T#$v&R~5bH zbFIS1C_Xo3;d7Uw*L?OWe5~U0Xcj)tDtgW5MTL)3eEyJyPw-tH?W^N}-xmNj;scaj z`YK%acY`fXSvckm?0dMP{|l}Kc)7yID}1WLCn$Wm!gaX`g_kS(28&Z3orj#J=m#k| zFHpGVf2HE1>-BX-uj>_jw@AI|IB>h7AFRr~SK+$cM^(96{$DEkA&SrE3fFw{iXaF! z%2R=Vf&TkiJglE%6<(tF&r*Ce|M?29RQ#7IK3e`$6#Ya+zgE%fa$6L=E_Z{X*Zj9B zT=Tgo3!keLz2#iob40cPRRIRlW8q`adcB zkq~__|Msg8&U$crUg0|5cuDa;OzG_nMX%-mqr#_xZ=nBA6d!Hh&lSCn4@I1O!A3jk zxHnMY6}T4gKTP4}3ZJ8JEoY6z!*=|lqStXRrEtyX9K}c5YlosgTQmDXws@HSM1|}2yC@5vvB_yUdw;3qSyQ{Rk-GJMHW8aRP>t9&lSCnC%;m-jwjD6T+8`;h3k0o7mJ7W zKd_XBI@n&rEKYjuZ=)5x_N(y<*YZqNINx0i>@{8S*Ls+x=!YqPp09Atf2qQcQT)G@ zh5spvo^$?zJPiuh{M!`%1;xKB3;#`u{s_f?i^4Vk3l)B>;(uut{#Ph^&1biw*Y^6B zqUXF*P~Yzk8NW z-&Hu@=?~<2KMViADSD0{1Nwg{T=Vz(gDEz~x8w0IpwF{-xP28Xdd=q$MX&8OT+xqG z@>D9EYk&piPE~w#{5ek1>vF3Ueu9#JiQ=Q}`$a|1cdCPO6AIUIHY+|_o_0mA<>^-V zOeN12#Yf9?zM?-$$@67Jugkq$(d%-rQTQxX?v09%F88~N{%BS1JqjPA@cR|6%iX8& z*{a;<6t3t0U$l7GuU=R5n*XN?r=JA*m_Go8VWZztZvkGcaN04z4^=qr9^l7Vobvn; z{{nwFLDB2H?nH&_{$i2BwLVuVe2(H@uW+5WY*aYoc`)yHj>2`GyhGvRKp)6|g~eH~ z_f@&qDtgW5W<}3$iUK}&DtcYty$YY8=pR(LeqQjX;?K1M1O87b`f`QuS9pcOUst%6 z=MM_k{onzGS1CPwV)3wk{0rpoXYnwfA&Q>;W?;u76t3kz zO5wv)eJ3maTAt~Oey);dwxZW|U!-u&XQ{%=RJnBu*YxYM;Lll{`kAcwT*$_cEsTF# z;ruo*(C0pdYd&u&{0oXchYv?Be?7h%U~$?-kMD+s=z};gHiYv&ZeLKijswRl{(N^L zkUyd5Kf?V1-mP#wUwy9PGehyYSmA$He6Ch}bo>3b!gafQPT^Yq-z!|}^Ie5&{rBNR zWo*>T6eVXri_^Zk+^Gs@9u@fi@d`gq@mZ?yzkyevw>1jqbE|;Q84B0WtuC-Q<>cC* z0iRt8*U$T|Q+(#Ba=)YK^*s466+Tn(e?#H36n-EJo_h!i!$vu0EBYdfQ=fAbK0x7o zCnu=a9L48Eg|AomT!nWjK6+eyb{2fQ!as#fLAjSIe4gTejm257`3iqY(QChYN6~A2 zdVI+M8~JE_u*In#?a!kXuH(s6#Yg+?af+UCIPj~*3ZD-=sP8hxhwp9$_$ozTt?-1R zk19PhDf$J9etj1DE=9jk(Qj1rTApha{Q_0)+lqdn!bkFD3vAT0ejYd3;?(mZMSrZq z7c0D0;frujpr1y?e~F^ssPGdMezxLMqwrk{*YbQ#;aZ-(iodS!Q;Pm1#sANWUd!{L zqSx}o_!0&->TRjwb4(VzPT^Y5+bm8!>*xNv6#X*A|Lcl=G42WU{B1?Avch%V;@a=cSzj$rfyF6*nUZIqqSx}YD13#g*XatcR`_L#zoYQ06#ls?_Ztdd zqVR87obpE$pW79#^PGPxT>H=5GBChKJ{oT-BYLnubd?D#^js4ru-7()YyY{(;?$?E z?@on(j!OZbYZP9i@ZA;<*Y{?H>-v6Q;o83UTRbe!&lIlZd0gQqIT<;hv3OXXmlUq$ zc|+k^p1X&EDK_%a^Xku8oN_M3zd%2KP&iY_0Dn*M(Rp%wIEb*3&ocZA==)oo<*tfk z@WU1Taz#H%(QE!EDEbwOzEwNeHMX&SWS3~qc zKKyP7XW88Tp>W;*&gV-x*rNES!x{$Sam9{8QW)*lUx*^>eNZEgl1H ziQ<2)qSx`^I|{E={J*F8=(zVMh3o$4fa0V1f1>b}ioeU3TCm0NPxJ3%ar%SiGeFVn zdBPbA|0iw<^fO2C(eq;~vfw8xT+b`EWx-Pl*ZKCD3fJ?5+Z4|ErNF*dDqQEccPm_v zvwj}JsXuO?D_r|S0bjnsMtz>5{9&radB66Pd5T`=`AZeP3ikwhUa9!#cvY`(&HpsT zXSL#!QuLb7m5TmkMgN^F^tUN`J0+t)R{D)%mhuTgyVX5sUordNDkP6GcBq(K~#J z4O^Jrw>b5wy_RnDE=!IK3~x@?y-DsD?)fsuR4X-gD$|=DgL@$q!fLF zqCYbW{e=qGaqKe1r%~~_M$zkXA6B^b+m{ueCdKFXieB@{JsL#VsDC|QQLJ#CzYSKn z?nfpnT<0^36yB)p(x~tQC_B*enF>En(SJ+fI&b-|!u9&Ug+e=XHev8vT z__ufh{ErIP`Rd1t&%3xM@T<=iuJz!J0TDLp`E~pY_?If2dI?Wp}{jK#zL^Mx$Nf#USrr)<2t#F;M zF0?r7Gewn~Q1sfbHY!}pf40JPeJ@tHw)-xH>w0}p;kw-Y3fKLMJD#;Q_5Bz2fqn`U zuH`vY;kv(@sc_9_iNbXrUZ-%KZ?98$vy!L7;?%S57p_#e?x(I(d{!$y-%<3M&(9UT z&bOb>LjRh=b)NRN;-mHUH-&4v$0k5HZ1lHv%72C^yhY&?6@Hq+7g(J7(d}rZ!gV`c zulVTpc&5VFfmh%U+Z3Po6@ICr*Lltr3fKO5jpC#8pSu*j_Rl93uKnsmg|Aiee6IMv zukcd7tci_!Zo$8xULzE)$3bHi-m3JB<%DD-A3cvZ!{XGx9@keZT#w&RReVmvJ%K#+ zieA5Oyiw7wSM+CPq2HqZ`&yiK(ejij`YuI3Qqk-BVu>%=$Umv*k5lxTf0d%w zezH*EDaB`{;-kxLQ}o@6zDv>TayKjb4T}CEh3o$ADuqu`^j}x}wLITf^cxlZ-HKkz zvro})QuI${p?_V`Z&vhgXQBV6qCZ2?f1ZWDq!L8fXvZ`0FYuE=77zQ$SVe!9qQ`=4 zvW4lZ6#dzXzB&v2Ns9g)MPH|Iorkn5T-z(D_-lLZQ1n|A|BJHFe?!r4RrEI~dTrky zD*AI3{e4;JA6E3+6#cIiuICkBRk*J2n~J}#@5hRMyW;JieAgvqUbMB^zB*bw<-Dy75xQS=)bP$FH-c^ zXQ97a(O<0Sf1HK>DMkNfMgQw8^lvNrOBDT|ve197=r2|Du}L_=7PjLci_`93!N0)n zL$lChwM5xSf0?4kx|Onp`By9Yor-=*7W#Tcze~}t%R+yaqQ6|xpPPmLN=5%wMSpD; z`r8%#6^j0@EcA~m`YRRvlUe9rQ}kCU`nR&sf1>EGR`mbQLf>yPh_KOKU&Ft^z5^{D zw$~U%e~qHYGMuu7>9NG9Y~+6}{ssK!XQ8iA_&bXJbcMI8JaebQI~4w~!u9j?w-v6R zj}K?i#76n`^K`67Dq9$zZ*kU3=fgD$*ZIuJ3jaE83G`5>`0Mz*Ug25~U5bw`ceBEE zxmy)pqsqNN@z>?-TRB;R`IEoguu&;@5}p;O{=(5yDql z`UgY!T8sam(#|~Irt1Iy$2@b*nQ}>{%u}Kam5?EdLK!oad5kn%LK=vqkSQ6Xk`T%e zl2EDKk|aeLLNv%ns^5B_{d(VCy}q5le(UkL_nh-Qul-u@{oZS@z4mbS-Y2{d_z~gJ z^WCC*QrTBNzayZJ1LC8>?H&SFTt5yxS-3yH(60Svy+3cek??2WW7lG_{yFe&!e@dH z7XA`=itr`iQ-!|rHpaH%{(k<#`wioK{mhKGI;wXB`CH#^ z#q^xFm*X_z3&MM^cRBH2iN6MJ`58(68%WKT`XW1KZpHL`UDNf% z$B>U*gKEX%e<-~7cm@-Hn7F;SVtVG|iT@D3bD!tHEuMwMXOaFm@kONP<+UaO_x{cN z9|;=IPb%qo`F;a#@jn{gdz@!TpAz1?PZl!{#q>OG%mr>Qd|tj7aXY{7J{5`E`FH1y ziH{B3<7r0R)&=LSz%8C}q`!yskCFdK(sTR|k)F@*JW1S+t9zWYh}-qgzP>LYZr4A% z{te>1Uau#ZL-(HpZnJ$&d2v| zB_Gab8`4jtIJ*$%{?qS^X!UYGHkS14Go9)^N^wTdhmY3xCB&DJp4YE8$=}YW`0{#} zIG-QcOS}!`IeM;pRIe>}Zx7#*-r9-#N6%@G^j8qiYYQY4d*OWgbIC0~+&-h{rAI#8 zKCgj~>5GzoJ>s2-w@XlOC(=J2^xhu&lb*M;LrKre_c7wUd>4>UQ}W+L{Aid5uXiu` zEG7O4>3R8nMV$A8z9k=yGkRWkluwQ`dOmivT)wAzt6-dEd0s}mCb(6@@%a9S>6=jg zTaiy?;?Z-VqjP4oTlxNh#mV`3lJwjTr;G}NWZNyhnJa>~1kJAQ|{#DXHMEW6A?~|mr^Q0c9JwMrs#h;1zV&XQw^89Zl zzBo+d{C(oA|ByKQe-3W>Rf+w+I5*z&UN zxbyf;;lXWu;yi1%@F5h_^L8N*@zvowU+!gz^Z2bk@vlgKGjVRucM#|Cc^~53?+qk= zi2NTS{xxxXZm<=buWXcunZzwWK40^QTYj9cByRnc=WQ)F?z6XM*iIuPgew+nGwkKCshaqcHa5a)h!3~|=aA2~-1S|-EuO!K4re$Jva0-Xfn?q-P&{uCEoVcYXNtdV7$b$4etfZ^sN>|6l_BB+~Qvb1rc{ zez=r;__)&>q<<>32k)P^61RTO+nYVV*NV*-ZwEgnzA=2~@gE}2`wM(OYTmy%1HCOr zZa=?}56^FgTtOI$#q)Of^Ln#_n-4FSe8kzmF!5Vyz2N&`bNu#PUn^GcJK@jky_q=Y z$M2hM@$mfKLG^Mxet&H9-$efRlAiZp22#EE&~ki)ILAMMILG-k@y%54ba0J-E^&_E zo)2ur;^%r-5$eEljx+{Sgz{r=t-KaZd5lm46Vo#*XF;+%)(#J7>Y4RKyBoxnA3 zJ&`X%rgN}S^vOME-UGm-pxy_iaz>zzTI^RtNjx!%`_@1T0u6KDMv;_s3EW8yoB z?+3TMaXUFm`mVHmFA?W{HA|jg5Q?=Q9tY+k&f}JX#B&6HZx2@y=kZ|`;=Etem^hCQ zn-S;n;UnNSzr1~Xn)E!bTa-ZmCh6Y~ULL>SuiN~&-~Kv*&yVE8n%+M8*H|cwTTl_pu7()6zq#s54 zr^)|G(%($_mq|aF^gD?2@q}-Q^Y-yF`P=@2&sVyDi|qagL`U`Ea{!O?s~P4$^bI-H1=2`5jC?A5#1yNYDMlc+z(ZKHmRNC(iRV zmv~Chdplf2oX@jwAkORKcH%bPbD!PB`TYA4;%8~TP7}A^oA~lN4{po7G4V^JKTkfT z@`VqfSbMPTp!?JTH=k#SU!OqVnDkRg-;VT0f|vXEB>gnf4ZdPWlxI z_&RW#-;XGsw@J_YYuiZA>-%of+c|EZuWw1u{mBX9yr26QasFLQhWsJ8P%Qs5$Ui%{ z#s72o^Lh&rKTW&@asItqS>g@IzcRSh`#kYl#CsC2PrMTG8_EA;il-^*InOPL43fo%w+sDg>$>M)k@arC5_uTT`SnVOXKapv3W`3tHBFIlcjOn z=dohvIIMWRejQrz2&ZvtLspXG|Nqh3*vm?p=p{{W>xPx`(MuX13|>jN^`Ta(MK5W3 z%e9qS(MuYC2)wRv>+7vtAHAgM|IQSFM#3jSf3xtGST4g^zW0r)+_7lC&Zz7+mFh3^OND|{7v`U_tJK3MpA@ZrMmKt4waUjzP-@Iq+F zDZ+Qbf4p!%Pc}*TE!I#&c{+MY%X3HYslpGy|2g4@z-J0S0zOChG4KV#XQSRl!cRlL zO!ztQmBN1oUnTq^_!{At!Pg6qCnT_Ug!}Vlw+hdS_;(0D4ZcgbU$3)QxIf=?pKyQ9 z=zih;e9!~J{W_RK!Z&4zz!Bj$A`i!e?}z?`@M@T^)50rcjKDeJFMxF9%YFFxD$z6y8}CNMkWH-ldxybE|TaqD9G7K%W5;Zwn@311IhSNI9= zM#8Va?+2O*Zv@^(cnWw2;p@S>3BL&5S9mofV6gDP;G={u08b%q`5cbCO%gs9?SEiyRUD8T?NOKLvhHcsi_) z7ljuB_x0M_b5&V?o!#6e&u7|&!PWue+?FENX?uC>D(^G^+bgV9fxCH^_y+e>BQR__qB+gid8A&^GG`{VpmYvHpBMBonLxpGFJ zoA7kSBQQYtBk&n7+^-jTO8C;G2)rPCCH&_J-wFN8!Yy}J-iTh(mdhFVtP}3n32hU8 z0Qt0iTPwC)EYJP1zz-S>#kse`A0nK_H(|ZDeM~E^_vfhDzMB>2nUOc!_hJ4i+J7P8 zS&)a)!rPi*C{={dzvg@-V}M>DBPdB@Ud_|?te!3c#M<(CwwoC`(#2r9_PK- zpUfw`1Lmuw@SfQ2R~BA2cQpU?gu9Q=pV#|Ru}I%u^qsOs{C?rSUp+}Vmdo?P{rLxT zg||h$3xyX$|L~gdhtRS4df@T@jdttTt2@69@qZvb^U?l47JeT6bE@#)v0T0qZpXZ= zd@KAC`pM(M^IZ|?&k6q=^(GAkqF;CZKYYGYxbJr~7VgI-TMM6x z{NF9SA=-0a;V)VMp*$;mF6MWp@Y3i9<_RBw^A?MQ`*q~62>0u&RtewX{j>0ysP`S= zWznv-39pU$`at*vtdIMI=SSYY5dJOnhlTrfwBHNg5B+K3brAnA!p}f|NqAFy&VcE> zois(inp60&XfehL3h#~e`by!4v0juH-WBV0ZQ)tao^KL2lSt>2w#u9trzasqwEyE5OMl(8qa?{jF-}5eR4h#Jh$*{ z=og9#e;Rr7-z&RMHf+~wi2f%mFJF&c@4sK}DEeh+S6zh{DG@c4Uc%2HeqRpmUl0B5 z5YdmsdisFySFpSu7G4GG>0`nxAU{tC?~QiozYq3!zCk;mA^KcczAp;D3G220KG=OW z!)K}J3t+xp72XBokT-?5$MW*yvhMHa^R|e77M9CXgdn+$|3%DQ8@OphaT}$+nkhl86$Dw_;5ndJZdynwC$WLG4xzK+6cM~4Z z5csSXeNnV$-#>P}{r1(0|8By$|32iP`1o z!aXl<3isy~Z52Kf`TbCME397!g_nWee}Ccm^yk6n#rouYCi?Bd!u`2HC4?8U2}3C( zd@^`-;jg0|HV|GPd2S*6LA0N~!dqi|JzDrJ$iqb8e%;=)!p|T-{<{p%!vwUeHKH$y ze&Ai*zWl6DLl?>Xnzw#pAqA?XN4cfxMjKU&#~P7_Yv-Y0`cq-{RJ$q1H!S|#r*dU z?&Hs`zbtxxK4LZ#hT{6^nBQdKuVQ{H3-|l0)D!*|=F5+xxPM8s=gy+{?aF<^ef&CB z_(#a6uYc}e81c^%{f}t3i-oU2Ke-*2bzs7d$Z{bzIbD}MElty{8cQ+1HxNk{B%rsLA0NcF zM4uh&^(f)T&~Ny4`|eX2?c`a}my2dAwm|rmSiXK8zWemVdc8*U<hQgE_?yn;XdJIQ192mPoW*25*F`>kIXk}!>#tvD z?z}Skw+7-rIZ9ish48Xiz8!_{!}`)&_|@pgh6!&2K34cKwDT##f5Gy7QFvvvhvmZk zJn}l>HLyRmUHC+_&rgJZiS6KF;m?5oD104!E(-r1dCP-%J^x#rk_T$&9yN~Cgh3I|0x(lz4eq*5UJ!lVOglETk^sI2mW6Op6`IWW8mt(v9uJHP3 zCm#yG3FE^rh1WtmxgfkX`pFDf4xXRASRa#wcSCzFA-ol~vlWGR#QJru@M*|TTj3+I z{&o<48U951$lTvcsAtu8R0&TnIXJ6 z^6;YYmr?IR;YsM1UKc(W>)j^d4Z-&aZ-w>oOW}V0__*-&`23sjVOYQX`gU(WRnR{3 zV*BrW7nWl~;b^w87T`9F%!9F{Ef>EI+QAL$uEg!XL+S+$sDL+QVnU-^BWIM0i&8GiQW%LcN!Sw?})(g5~M+wI1_ZK=>1A zx21${#rjf3_z-M&>I?V%`DVgDz<8*=@V4MRg#U1O2g~DqWAl!3?_YDigUE+OCipQr1xuntQsFL z_4#H14MqP2 z`oor_x8GlT@$-%DzZdI857K|@;_%u}{C&S}6zRVs{aDd|g#C^wq@PXkyde4pXm5*1 z@7IP|HLr@^`{#|MznT2Ei@qqlfJd+-^b^> zN#Bh0Jw@LG;{?B+)TBRqFyVC)`PlDLy-X9I-x23L()+c4HqBDeAHjBZ4e9OoVqP|h z-jAE?CcXU*)XQh0KachQ2dNRZ70MUCpevtH~D4xee ze-+l>sigO7R;`*@qQ4T$YYFM?{z6_}7ky2P1K%P2WfzCn_e7r``T3OeWyt?4(Wjz4 zpCJ9!q(3iu9~1vY`rM??g8tIm!=q^b1;9;uisCOJdcU5(BI!?)zNY9;p#3x={WTO% zbJ2G~e(ofFMbi8Ap&q}FtNWAQeh=$qg!u2rIB*>4dz1bt(Ko?&Gf8jvAMo;$=-E9B)-!FIv=`)f3L(%WRcLzydjr2!Fe+b*_bELQXs(JaJ=;vWOlo|U0CiQEu zZJIpbp8v)ehx>6^(|0HTt404A+FK3s_j`$(e|^zkiQ^K@NMDuw+lu~8jKjN-{tq)o z=_C3|*bf>`dSB)?$-|H_-oFBzl{)0rn82#)+9djkpyx#&*)%Nqu~mAKX6L{b9Tm7yY}4rvmByns=L~hUjx(eA|%pU7jkueH2D)mGGn3@7g8&I@Ehq zcr$FLeiU8+^P92szvs6C@>5E2DE68eDw!Z%~Q{ef(}il%hrgt1 zQGH!SzYYEK{lxd1K9a`<3db-r_K5Iu(2o;-HTdJ;9#3P$vyiwo1;4(0C2@*QKT6#6m!Q8$-1G~e&wq9J5Q;CC{MDn+<%ygA z9P~F4H~$LIcOh>2x@ez6h@1XK=qD04{b1-{B5wN5(7!|6^t+(nN!;`!q5q1w>65Wt zyFlFZ^P$gMHhc)h+e0_#ixD^ddg!YWH~;m}w;*o%PoVEc-1O(5A4A;qr=XuoJRU## zlNH2GpP@$h7s^)RruX}Fe?{E%#i2h(JRU#%bCff;f7(NB=#z=ZA92$^0R2Sbrk@J^RN|(e4E+k?ruXYXHxf7f66ilBZu%s2WT%Lmehc(}6E}S~ z=!=#QA42i<D7)7QngbUty@*Mxoz zant*Cfgck$eIw{k3-1V?u0jxnV)L6d{Q2)CixD@Uq0m<&ZuR#8#7(~m`mMy{d4T>a;->!``g6qN@k5`ZVi1Mm%l#+llZl%? zhV5^C;^v>VmVFtvGsI2b7y5q0OzlON!CqUnbxcQ%h{%+!?p9lS5;-+ttH~b6bDdMJo z3;G4bO}`BKw~3p6AN2c(oBjawKN2_nN$6vh!iP|NyKqIm=yNgRrcYlx;?;=(`a&eG2qrh?~9^^izqOejoHJh?~9@^jnFWK9=A9#bRF(H+?(k&w*zT?2GXC z5cKIPhYz7RA8l_!$s@c5^aa6veMu=5=_`rekE>rxe1DKOj^wfW!VzYy5pj$2b&RW9 z5I3KR@VQO+aPW4-&F3K6XHVh29t{`1qCjNyC~>Rz5d0q#Zr@p%1n&7+kNmtO{2cf? z;?@t3wuKhTR^o<=l#b)rVc`|Qe-&!~hQcQS895*j7ykInWtiJFg zHiMzG67D{og!_G{`wCCW9r+9d_q?6M{^ZJDG)oUaN0BdRv`CUI*g zL$M#dnYj5}37>7k{n+;|;^xx;c|Iom?fA+X&IJqi`&neE8U^Od%k>3>`}I7fgnJ&U z3itb5-7MVw+X{F8F2dcvzwp{(RmJW2_)?)BAmIsu4H+PU!0qH~mw&qc7SM zH~l{7yAn6O{~q8$;->!w`tig~zX$&FiJN{8^vj8x{zvGy5;uJ+^k0E{J6wVV@B68i zAM^3+g)WLd8QY5t*zYkPTfP^O|183P2G2#@)+4`Op#-?s>(BkFCwhM#Nh8r8$r8*$ zxl8o@A{^^M+~O=@GZ#v4;YGmviT_FXj}q?t*As;M{kvupxBR~quQe8Xg}7B&+`bHD zGq^98ZWt%*5dA8|^Ofj*et#ft^Ls7k%lA`#c~uAhN&G*9f5sZ|u;Sw=3-R^nW2_)? zv-leN3g909HJPIcs)~LUj?3L5dcWSaEpdy#GvaJ7+_!_Bh+Dhz>mGX%H=h~sxlj00 z-~)-9&$?{kUnrxAo6jET9~SQSX&Oh|d|u9DF8}NYd;b4~&ot7T|9SBF!W(3W+r(ZL zUI+XQ;rD^B72X|uyKw)V=KI2zL%$c?*Hb^Qc}n!}L4Q{GcJN=sry0h9nQBJ!=l+Fo zoHkDaehs+i)9;&FRrsfrbknosS`I=w9fj61Sn%3FLD&anlci{&nJ}-wOQ(;-()1{chr>UjTh7xc6hT(GPq@ zdh!_@}EKK7``!)}KF}nYi^EN3mTlMcjOP!slw?-M}jnH=kNL z!oN`J3BSK^#G4Q||FQ6CF5J&owkB@=OW@y;xcMxCPiNutz?}Y8h zIO3^6=hyl?McjPOqJ2J3+~V1VdS?sY20ov7YS7y=Jgh7uZvHREX*hli?(55D>=%3| z{05xgJtw>uc%eFxp|yw9@YfXeRwQom|AjcK2)_hg6Wrrzf_R#d-r^sJ@kR&H-v|AJ z#7)}F8ha>HiO1I?=vN4@0KQ-N49xGh!k2?zAa3hplKl%M^R>~d&(}8SO9?-P^|6KU z^N8m@;aTA`R(KYi&z>T@82EhRJTCeK-2080=!XxH-tyM1bTmJ|h<e^B z1yLy8Zqp+_1%%&%e!h%wzi&k?;iI5$NZjJjhxxrpcuw$U#H~L(jP}-+xXqW}KkFXi z=3gB?-Go;K?*;Dt$%w1MM4^l$&h7jq;P4?suk{<_ z%`BAS#0~8)8^^K6!Y_f35T37Gq@PHf{a++*{vVZ&^ozlLyYmt9yjJvwpx=^!e?>l) z|3=93H^Li$f1kkT58|hy5aa)|*N;B<@~VbB7XbJ8e?t6ah+8~A0T`!_z>Z5f{z6Ecj-i&6nS&FDtmmvlH=D5&jI;-?|BSJMpiEdOHZO0^VJCL-1b0ZvYct(@n zmZKlndV;vkZyWeb7Tyy4dExhi&lc|Y8C(SJ@oX#`DhcH^(px-L(XKWVw|Hj4f1B`U z!S@J%7yM)4Z-XBI_jvp~{dWoYCGqj&hkpq_4F4=Q*xdcIzvlPT&LR9K=##)bp1xQg z>j*DdF7jp?mZ$CjiW0>B@Z?lNoqS}t_;6~!C zKS12{XQ2OH_|xcT{uJ*0Pre3W;!rFsir%1^o)*7Uvn{d9C;yv4s=LUeSA=4+{4@ zpAhbOz98K5T;j&49$${WUv`af-!HpPxbK%W74G|G?S=b(*%0AB;5gf(;ORnG>BC>< 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 q`sw_5oTV)>Lg-Jkl!(eu&&6f$^3 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 literal 0 HcmV?d00001 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; +} -- 2.43.0