summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format11
-rwxr-xr-x.github/mock.sh26
-rwxr-xr-x.github/prepare_debian.sh4
-rw-r--r--.github/workflows/test-next.yml78
-rw-r--r--.github/workflows/test.yml1
-rw-r--r--CODING35
-rw-r--r--doc/developer-guidelines.sgml53
-rw-r--r--lib/extra_opts.c149
-rw-r--r--lib/extra_opts.h1
-rw-r--r--lib/maxfd.c32
-rw-r--r--lib/maxfd.h6
-rw-r--r--lib/parse_ini.c135
-rw-r--r--lib/parse_ini.h1
-rw-r--r--lib/tests/test_base64.c308
-rw-r--r--lib/tests/test_cmd.c261
-rw-r--r--lib/tests/test_disk.c180
-rwxr-xr-xlib/tests/test_generic_outputbin0 -> 143808 bytes
-rw-r--r--lib/tests/test_ini1.c116
-rw-r--r--lib/tests/test_ini3.c37
-rw-r--r--lib/tests/test_opts1.c105
-rw-r--r--lib/tests/test_opts2.c124
-rw-r--r--lib/tests/test_opts3.c37
-rw-r--r--lib/tests/test_tcp.c48
-rw-r--r--lib/tests/test_utils.c491
-rw-r--r--lib/utils_base.c451
-rw-r--r--lib/utils_base.h61
-rw-r--r--lib/utils_cmd.c280
-rw-r--r--lib/utils_cmd.h20
-rw-r--r--lib/utils_disk.c397
-rw-r--r--lib/utils_disk.h66
-rw-r--r--lib/utils_tcp.c78
-rw-r--r--lib/utils_tcp.h11
-rw-r--r--plugins-root/check_dhcp.c1181
-rw-r--r--plugins-root/check_icmp.c1528
-rwxr-xr-xplugins-scripts/check_ifstatus.pl45
-rw-r--r--plugins/check_apt.c4
-rw-r--r--plugins/check_by_ssh.c528
-rw-r--r--plugins/check_cluster.c255
-rw-r--r--plugins/check_curl.c4583
-rw-r--r--plugins/check_dbi.c827
-rw-r--r--plugins/check_dig.c650
-rw-r--r--plugins/check_disk.c2036
-rw-r--r--plugins/check_dns.c1101
-rw-r--r--plugins/check_dummy.c195
-rw-r--r--plugins/check_fping.c921
-rw-r--r--plugins/check_game.c567
-rw-r--r--plugins/check_hpjd.c419
-rw-r--r--plugins/check_http.c4
-rw-r--r--plugins/check_ide_smart.c496
-rw-r--r--plugins/check_ldap.c4
-rw-r--r--plugins/check_mrtg.c456
-rw-r--r--plugins/check_mrtgtraf.c457
-rw-r--r--plugins/check_mysql.c12
-rw-r--r--plugins/check_mysql_query.c396
-rw-r--r--plugins/check_nagios.c306
-rw-r--r--plugins/check_nt.c943
-rw-r--r--plugins/check_ntp.c4
-rw-r--r--plugins/check_ntp_peer.c636
-rw-r--r--plugins/check_ntp_time.c628
-rw-r--r--plugins/check_nwstat.c2137
-rw-r--r--plugins/check_overcr.c397
-rw-r--r--plugins/check_pgsql.c629
-rw-r--r--plugins/check_ping.c603
-rw-r--r--plugins/check_procs.c4
-rw-r--r--plugins/check_radius.c4
-rw-r--r--plugins/check_real.c484
-rw-r--r--plugins/check_smtp.c4
-rw-r--r--plugins/check_snmp.c1399
-rw-r--r--plugins/check_ssh.c4
-rw-r--r--plugins/check_tcp.c598
-rw-r--r--plugins/check_time.c431
-rw-r--r--plugins/check_ups.c114
-rw-r--r--plugins/check_users.c291
-rw-r--r--plugins/negate.c298
-rw-r--r--plugins/netutils.c236
-rw-r--r--plugins/picohttpparser/picohttpparser.c1101
-rw-r--r--plugins/popen.c283
-rw-r--r--plugins/runcmd.c254
-rw-r--r--plugins/sslutils.c228
-rw-r--r--plugins/urlize.c195
-rw-r--r--plugins/utils.c509
81 files changed, 15626 insertions, 17362 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000..877a53b9
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,11 @@
1UseTab: ForContinuationAndIndentation
2IndentWidth: 4
3TabWidth: 4
4AllowShortIfStatementsOnASingleLine: false
5BreakBeforeBraces: Attach
6AlignConsecutiveMacros: true
7ColumnLimit: 140
8IndentPPDirectives: AfterHash
9SortIncludes: Never
10AllowShortEnumsOnASingleLine: false
11BinPackArguments: true
diff --git a/.github/mock.sh b/.github/mock.sh
index 7fbe6903..87543ce8 100755
--- a/.github/mock.sh
+++ b/.github/mock.sh
@@ -2,6 +2,8 @@
2 2
3set -x 3set -x
4 4
5set -euo pipefail
6
5export DEBIAN_FRONTEND=noninteractive 7export DEBIAN_FRONTEND=noninteractive
6 8
7BASE_PATH="/src" 9BASE_PATH="/src"
@@ -18,7 +20,11 @@ SPEC_FILE="${SPEC_DIR}monitoring-plugins.spec"
18cd ${BASE_PATH} 20cd ${BASE_PATH}
19 21
20dnf -y --setopt="tsflags=nodocs" update && \ 22dnf -y --setopt="tsflags=nodocs" update && \
21 if [ ${distro_id} != "fedora" ]; then dnf -y --setopt="tsflags=nodocs" install epel-release; else platform_id="$(echo ${platform_id} | sed s/^f/fc/)"; fi && \ 23 if [ "${distro_id}" != "fedora" ]; then
24 dnf -y --setopt="tsflags=nodocs" install epel-release;
25 else
26 platform_id="$(echo "${platform_id}" | sed s/^f/fc/)";
27 fi && \
22 case ${distro_id} in 28 case ${distro_id} in
23 ol) 29 ol)
24 case ${platform_id} in 30 case ${platform_id} in
@@ -32,19 +38,27 @@ dnf -y --setopt="tsflags=nodocs" update && \
32 ;; 38 ;;
33 esac 39 esac
34 dnf -y --setopt="tsflags=nodocs" install mock rpm-build git-core && \ 40 dnf -y --setopt="tsflags=nodocs" install mock rpm-build git-core && \
35 usermod -a -G mock $(whoami) 41 usermod -a -G mock "$(whoami)"
42
36SRC_RPM="monitoring-plugins-*-1.${platform_id}.src.rpm" 43SRC_RPM="monitoring-plugins-*-1.${platform_id}.src.rpm"
44
37if command -v git > /dev/null 2>&1; then 45if command -v git > /dev/null 2>&1; then
38 git config --global --add safe.directory ${BASE_PATH} 46 git config --global --add safe.directory ${BASE_PATH}
39 SHA="$(git rev-parse HEAD)" 47 SHA="$(git rev-parse HEAD)"
40 sed "s/^%global commit.*/%global commit ${SHA}/" ${SPEC_FILE} > ${SPEC_DIR}monitoring-plugins-git.spec 48 sed "s/^%global commit.*/%global commit ${SHA}/" ${SPEC_FILE} > ${SPEC_DIR}monitoring-plugins-git.spec
41 sed -i "s/^%global fromgit.*/%global fromgit 1/" ${SPEC_DIR}monitoring-plugins-git.spec 49 sed -i "s/^%global fromgit.*/%global fromgit 1/" ${SPEC_DIR}monitoring-plugins-git.spec
42 SPEC_FILE="${SPEC_DIR}monitoring-plugins-git.spec" 50 SPEC_FILE="${SPEC_DIR}monitoring-plugins-git.spec"
43 SRC_RPM="monitoring-plugins-*git.$(echo ${SHA:0:7})*.${platform_id}.src.rpm" 51 SRC_RPM="monitoring-plugins-*git.${SHA:0:7}*.${platform_id}.src.rpm"
44fi 52fi
53
45mkdir -p "${SRCRPM_DIR}" "${RPM_DIR}" 54mkdir -p "${SRCRPM_DIR}" "${RPM_DIR}"
46#rpmbuild --undefine=_disable_source_fetch --define "_sourcedir ${SOURCE_DIR}" -ba ${SPEC_FILE} 55#rpmbuild --undefine=_disable_source_fetch --define "_sourcedir ${SOURCE_DIR}" -ba ${SPEC_FILE}
47dnf -y --setopt="tsflags=nodocs" install rpmdevtools && spectool -g -C ${SOURCE_DIR} ${SPEC_FILE} && \ 56dnf -y --setopt="tsflags=nodocs" install rpmdevtools && \
48mock --dnf --clean --spec ${SPEC_FILE} --sources=${SOURCE_DIR} --result=${SRCRPM_DIR} --build || { cat ${SRCRPM_DIR}/{root,build}.log; exit 1; } 57 spectool -g -C ${SOURCE_DIR} ${SPEC_FILE} && \
49mock --dnf --clean --sources=${SOURCE_DIR} --result=${RPM_DIR} --rebuild ${SRCRPM_DIR}/${SRC_RPM} || { cat ${RPM_DIR}/{root,build}.log; exit 1; } 58 { mock --dnf --clean --spec ${SPEC_FILE} --sources=${SOURCE_DIR} --result=${SRCRPM_DIR} --build || \
59 { cat ${SRCRPM_DIR}/{root,build}.log; exit 1; } }
60
61mock --dnf --clean --sources=${SOURCE_DIR} --result=${RPM_DIR} --rebuild "${SRCRPM_DIR}"/${SRC_RPM} || \
62 { cat ${RPM_DIR}/{root,build}.log; exit 1; }
63
50ls -la ${SOURCE_DIR} ${SRCRPM_DIR} ${RPM_DIR} 64ls -la ${SOURCE_DIR} ${SRCRPM_DIR} ${RPM_DIR}
diff --git a/.github/prepare_debian.sh b/.github/prepare_debian.sh
index 3f4674a2..3640e500 100755
--- a/.github/prepare_debian.sh
+++ b/.github/prepare_debian.sh
@@ -1,7 +1,7 @@
1#!/bin/bash 1#!/bin/bash
2 2
3set -x 3set -x
4set -e 4set -euo pipefail
5 5
6export DEBIAN_FRONTEND=noninteractive 6export DEBIAN_FRONTEND=noninteractive
7 7
@@ -127,5 +127,5 @@ sed "/NP_HOST_TLS_CERT/s/.*/'NP_HOST_TLS_CERT' => '$(hostname)',/" -i /src/.gith
127 127
128# create some test files to lower inodes 128# create some test files to lower inodes
129for i in $(seq 10); do 129for i in $(seq 10); do
130 touch /media/ramdisk2/test.$1 130 touch /media/ramdisk2/test.$i
131done 131done
diff --git a/.github/workflows/test-next.yml b/.github/workflows/test-next.yml
new file mode 100644
index 00000000..81240759
--- /dev/null
+++ b/.github/workflows/test-next.yml
@@ -0,0 +1,78 @@
1---
2name: Tests Debian:Testing and Fedora:Rawhide
3
4on:
5 workflow_dispatch: {}
6 push:
7 branches-ignore:
8 - '*'
9 schedule:
10 # Run every week on Monday at 9:00 AM (UTC)
11 - cron: '0 9 * * 1'
12
13jobs:
14 full-test:
15 name: Running unit and integrationt tests
16 runs-on: ubuntu-latest
17 strategy:
18 fail-fast: false
19 matrix:
20 distro:
21 - 'debian:testing'
22 include:
23 - distro: 'debian:testing'
24 prepare: .github/prepare_debian.sh
25 steps:
26 - name: Git clone repository
27 uses: actions/checkout@v4
28 - name: Run the tests on ${{ matrix.distro }}
29 run: |
30 docker volume create --driver local --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 tmp-vol
31 docker run \
32 -e NPTEST_ACCEPTDEFAULT=1 \
33 -e NPTEST_CACHE="/src/.github/NPTest.cache" \
34 -w /src -v ${PWD}:/src \
35 --tmpfs /media/ramdisk1 \
36 -v /var/run/utmp:/var/run/utmp \
37 --mount source=tmp-vol,destination=/src,target=/media/ramdisk2 \
38 ${{ matrix.distro }} \
39 /bin/sh -c '${{ matrix.prepare }} && \
40 tools/setup && \
41 ./configure --enable-libtap --with-ipv6=no && \
42 make && \
43 make test && \
44 make dist && \
45 tar zxf monitoring-plugins-*.tar.gz && \
46 cd monitoring-plugins-*/ && \
47 ./configure && \
48 make'
49 docker container prune -f
50 docker volume prune -f
51
52 build-test:
53 name: Running rpm build test on ${{ matrix.distro }}
54 runs-on: ubuntu-latest
55 strategy:
56 fail-fast: false
57 matrix:
58 include:
59 - {"distro": "fedora:rawhide", "build": ".github/mock.sh"}
60 steps:
61 - name: Git clone repository
62 uses: actions/checkout@v4
63 - name: Run the tests on ${{ matrix.distro }}
64 run: |
65 docker volume create --driver local --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 tmp-vol
66 docker run \
67 --privileged=true \
68 -e NPTEST_ACCEPTDEFAULT=1 \
69 -e NPTEST_CACHE="/src/.github/NPTest.cache" \
70 -w /src -v ${PWD}:/src \
71 --tmpfs /media/ramdisk1 \
72 -v /var/run/utmp:/var/run/utmp \
73 --mount source=tmp-vol,destination=/src,target=/media/ramdisk2 \
74 ${{ matrix.distro }} \
75 /bin/sh -c '${{ matrix.build }} && \
76 ls -la'
77 docker container prune -f
78 docker volume prune -f
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 33220d6d..77ca6585 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -54,7 +54,6 @@ jobs:
54 matrix: 54 matrix:
55 include: 55 include:
56 - {"distro": "fedora:latest", "build": ".github/mock.sh"} 56 - {"distro": "fedora:latest", "build": ".github/mock.sh"}
57 - {"distro": "fedora:rawhide", "build": ".github/mock.sh"}
58 - {"distro": "rockylinux:8", "build": ".github/mock.sh"} 57 - {"distro": "rockylinux:8", "build": ".github/mock.sh"}
59 - {"distro": "almalinux:9", "build": ".github/mock.sh"} 58 - {"distro": "almalinux:9", "build": ".github/mock.sh"}
60# - {"distro": "oraclelinux:9", "build": ".github/mock.sh"} 59# - {"distro": "oraclelinux:9", "build": ".github/mock.sh"}
diff --git a/CODING b/CODING
index 74438e7c..d0673e7e 100644
--- a/CODING
+++ b/CODING
@@ -7,33 +7,20 @@ readability in a wide range of environments.
7 7
81. C Language Programming 81. C Language Programming
9 9
10All code should comply with the requirements of the Free Software 10All code should comply with most of the requirements of the Free Software
11Foundation Coding standards (which are currently available at 11Foundation Coding standards (which are currently available at
12http://www.gnu.org/prep/standards_toc.html). We also follow most of 12https://www.gnu.org/prep/standards/standards.html ).
13the FSF guidelines. Developers may suggest deviations from the FSF 13We also follow most of the FSF guidelines, with the huge and explicit
14exception of the style guidelines.
15Developers may suggest deviations from the FSF
14style recommendations, which will be considered by open discussion on 16style recommendations, which will be considered by open discussion on
15the Monitoring Plugins devel mailing list. Any such deviations will 17the Monitoring Plugins devel mailing list or the Github Pull Request.
16apply to the entire code base to ensure consistency. 18Any such deviations should be
17 19applied to the entire code base to ensure consistency.
18Currently, the exceptions to FSF recommendations are roughly equivalent
19to GNU indent with invoked as 'indent -ts 2 -br'. Specifically, the
20exceptions are as follows:
21
22a) leading white space for a statement should be formatted as tabs,
23with one tab for each code indentation level.
24
25b) in statement continuation lines, format whitespace up to the column
26starting the statement as tabs, format the rest as spaces (this
27results in code that is legible regardless of tab-width setting).
28
29c) with the exception of the above, tabs should generally be avoided
30
31d) when tab width is 2 spaces, line-length should not exceed 80
32characters
33
34e) The opening brace of an if or while block is on the same line as
35the end of the conditional expression (the '-br' option).
36 20
21The style guideline is the following:
22Whatever clang-format does with the configuration file available (.clang-format)
23Apart from that, code should naturally be readable and easy to understand.
37 24
382. Perl Language Programming 252. Perl Language Programming
39 26
diff --git a/doc/developer-guidelines.sgml b/doc/developer-guidelines.sgml
index 37c963ed..0afa733b 100644
--- a/doc/developer-guidelines.sgml
+++ b/doc/developer-guidelines.sgml
@@ -14,15 +14,8 @@
14 <pubdate>2013</pubdate> 14 <pubdate>2013</pubdate>
15 <title>Monitoring Plugins Development Guidelines</title> 15 <title>Monitoring Plugins Development Guidelines</title>
16 16
17 <revhistory>
18 <revision>
19 <revnumber>1796</revnumber>
20 <date>2007-09-24 14:51:07 -0400 (Mon, 24 Sep 2007)</date>
21 </revision>
22 </revhistory>
23
24 <copyright> 17 <copyright>
25 <year>2000 - 2013</year> 18 <year>2000 - 2024</year>
26 <holder>Monitoring Plugins Development Team</holder> 19 <holder>Monitoring Plugins Development Team</holder>
27 </copyright> 20 </copyright>
28 21
@@ -34,7 +27,7 @@
34 the plugin developers and encourage the standardization of the 27 the plugin developers and encourage the standardization of the
35 different kind of plugins: C, shell, perl, python, etc.</para> 28 different kind of plugins: C, shell, perl, python, etc.</para>
36 29
37 <para>Monitoring Plugins Development Guidelines Copyright (C) 2000-2013 30 <para>Monitoring Plugins Development Guidelines Copyright (C) 2000-2024
38 (Monitoring Plugins Team)</para> 31 (Monitoring Plugins Team)</para>
39 32
40 <para>Permission is granted to make and distribute verbatim 33 <para>Permission is granted to make and distribute verbatim
@@ -383,13 +376,6 @@
383 <para>It is up to third party programs to convert the Monitoring Plugins 376 <para>It is up to third party programs to convert the Monitoring Plugins
384 performance data into graphs.</para> 377 performance data into graphs.</para>
385 </section> 378 </section>
386
387 <section><title>Translations</title>
388 <para>If possible, use translation tools for all output to respect the user's language
389 settings. See <xref linkend="translationsdevelopers"> for guidelines
390 for the core plugins.
391 </para>
392 </section>
393</section> 379</section>
394 380
395<section id="SysCmdAuxFiles"><title>System Commands and Auxiliary Files</title> 381<section id="SysCmdAuxFiles"><title>System Commands and Auxiliary Files</title>
@@ -727,19 +713,18 @@ setup the tests. Run "make test" to run all the tests.
727</section> 713</section>
728<section id="CodingGuidelines"><title>Coding guidelines</title> 714<section id="CodingGuidelines"><title>Coding guidelines</title>
729 <para>See <ulink url="http://www.gnu.org/prep/standards_toc.html">GNU 715 <para>See <ulink url="http://www.gnu.org/prep/standards_toc.html">GNU
730 Coding standards</ulink> for general guidelines.</para> 716 Coding standards</ulink> for general guidelines.
717 Some parts of the guidelines (namely and explicitly the coding style)
718 are not seen as best practice by us.</para>
731 <section><title>C coding</title> 719 <section><title>C coding</title>
732 720
733 <para>Variables should be declared at the beginning of code blocks and
734 not inline because of portability with older compilers.</para>
735
736 <para>You should use the type "bool" and its values 721 <para>You should use the type "bool" and its values
737 "true" and "false" instead of the "int" type for booleans. 722 "true" and "false" instead of the "int" type for booleans.
738 </para> 723 </para>
739 </section> 724 </section>
740 725
741 <section><title>Crediting sources</title> 726 <section><title>Crediting sources</title>
742 <para>If you have copied a routine from another source, make sure the licence 727 <para>If you have copied a routine from another source, make sure the license
743 from your source allows this. Add a comment referencing the ACKNOWLEDGEMENTS 728 from your source allows this. Add a comment referencing the ACKNOWLEDGEMENTS
744 file, where you can put more detail about the source.</para> 729 file, where you can put more detail about the source.</para>
745 <para>For contributed code, do not add any named credits in the source code 730 <para>For contributed code, do not add any named credits in the source code
@@ -756,32 +741,6 @@ setup the tests. Run "make test" to run all the tests.
756 <para>All commits will be written to a ChangeLog at release time. 741 <para>All commits will be written to a ChangeLog at release time.
757 </para> 742 </para>
758 </section> 743 </section>
759
760 <section id="translationsdevelopers"><title>Translations for developers</title>
761 <para>To make the job easier for translators, please follow these guidelines:</para>
762 <orderedlist>
763 <listitem><para>
764 Before creating new strings, check the po/monitoring-plugins.pot file to
765 see if a similar string
766 already exists
767 </para></listitem>
768 <listitem><para>
769 For help texts, break into individual options so that these can be reused
770 between plugins
771 </para></listitem>
772 <listitem><para>Try to avoid linefeeds unless you are working on a block of text</para></listitem>
773 <listitem><para>Short help is not translated</para></listitem>
774 <listitem><para>Long help has options in English language, but text translated</para></listitem>
775 <listitem><para>"Copyright" kept in English</para></listitem>
776 <listitem><para>Copyright holder names kept in original text</para></listitem>
777 <listitem><para>Debugging output does not need to be translated</para></listitem>
778 </orderedlist>
779 </section>
780
781 <section><title>Translations for translators</title>
782 <para>To create an up to date list of translatable strings, run: tools/gen_locale.sh</para>
783 </section>
784
785</section> 744</section>
786 745
787<section id="SubmittingChanges"><title>Submission of new plugins and patches</title> 746<section id="SubmittingChanges"><title>Submission of new plugins and patches</title>
diff --git a/lib/extra_opts.c b/lib/extra_opts.c
index 771621d8..88787336 100644
--- a/lib/extra_opts.c
+++ b/lib/extra_opts.c
@@ -1,24 +1,24 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins extra_opts library 3 * Monitoring Plugins extra_opts library
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2007 Monitoring Plugins Development Team 6 * Copyright (c) 2007 - 2024 Monitoring Plugins Development Team
7* 7 *
8* This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or 10 * the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version. 11 * (at your option) any later version.
12* 12 *
13* This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details. 16 * GNU General Public License for more details.
17* 17 *
18* You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19* along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20* 20 *
21*****************************************************************************/ 21 *****************************************************************************/
22 22
23#include "common.h" 23#include "common.h"
24#include "utils_base.h" 24#include "utils_base.h"
@@ -26,110 +26,115 @@
26#include "extra_opts.h" 26#include "extra_opts.h"
27 27
28/* FIXME: copied from utils.h; we should move a bunch of libs! */ 28/* FIXME: copied from utils.h; we should move a bunch of libs! */
29bool is_option2 (char *str) 29bool is_option2(char *str) {
30{
31 if (!str) 30 if (!str)
32 return false; 31 return false;
33 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2) 32 else if (strspn(str, "-") == 1 || strspn(str, "-") == 2)
34 return true; 33 return true;
35 else 34 else
36 return false; 35 return false;
37} 36}
38 37
39/* this is the externally visible function used by plugins */ 38/* this is the externally visible function used by plugins */
40char **np_extra_opts(int *argc, char **argv, const char *plugin_name){ 39char **np_extra_opts(int *argc, char **argv, const char *plugin_name) {
41 np_arg_list *extra_args=NULL, *ea1=NULL, *ea_tmp=NULL; 40 np_arg_list *extra_args = NULL, *ea1 = NULL, *ea_tmp = NULL;
42 char **argv_new=NULL; 41 char **argv_new = NULL;
43 char *argptr=NULL; 42 char *argptr = NULL;
44 int i, j, optfound, argc_new, ea_num=*argc; 43 int i, j, optfound, argc_new, ea_num = *argc;
45 44
46 if(*argc<2) { 45 if (*argc < 2) {
47 /* No arguments provided */ 46 /* No arguments provided */
48 return argv; 47 return argv;
49 } 48 }
50 49
51 for(i=1; i<*argc; i++){ 50 for (i = 1; i < *argc; i++) {
52 argptr=NULL; 51 argptr = NULL;
53 optfound=0; 52 optfound = 0;
54 53
55 /* Do we have an extra-opts parameter? */ 54 /* Do we have an extra-opts parameter? */
56 if(strncmp(argv[i], "--extra-opts=", 13)==0){ 55 if (strncmp(argv[i], "--extra-opts=", 13) == 0) {
57 /* It is a single argument with value */ 56 /* It is a single argument with value */
58 argptr=argv[i]+13; 57 argptr = argv[i] + 13;
59 /* Delete the extra opts argument */ 58 /* Delete the extra opts argument */
60 for(j=i;j<*argc;j++) argv[j]=argv[j+1]; 59 for (j = i; j < *argc; j++)
60 argv[j] = argv[j + 1];
61 i--; 61 i--;
62 *argc-=1; 62 *argc -= 1;
63 }else if(strcmp(argv[i], "--extra-opts")==0){ 63 } else if (strcmp(argv[i], "--extra-opts") == 0) {
64 if((i+1<*argc)&&!is_option2(argv[i+1])){ 64 if ((i + 1 < *argc) && !is_option2(argv[i + 1])) {
65 /* It is a argument with separate value */ 65 /* It is a argument with separate value */
66 argptr=argv[i+1]; 66 argptr = argv[i + 1];
67 /* Delete the extra-opts argument/value */ 67 /* Delete the extra-opts argument/value */
68 for(j=i;j<*argc-1;j++) argv[j]=argv[j+2]; 68 for (j = i; j < *argc - 1; j++)
69 i-=2; 69 argv[j] = argv[j + 2];
70 *argc-=2; 70 i -= 2;
71 *argc -= 2;
71 ea_num--; 72 ea_num--;
72 }else{ 73 } else {
73 /* It has no value */ 74 /* It has no value */
74 optfound=1; 75 optfound = 1;
75 /* Delete the extra opts argument */ 76 /* Delete the extra opts argument */
76 for(j=i;j<*argc;j++) argv[j]=argv[j+1]; 77 for (j = i; j < *argc; j++)
78 argv[j] = argv[j + 1];
77 i--; 79 i--;
78 *argc-=1; 80 *argc -= 1;
79 } 81 }
80 } 82 }
81 83
82 /* If we found extra-opts, expand them and store them for later*/ 84 /* If we found extra-opts, expand them and store them for later*/
83 if(argptr||optfound){ 85 if (argptr || optfound) {
84 /* Process ini section, returning a linked list of arguments */ 86 /* Process ini section, returning a linked list of arguments */
85 ea1=np_get_defaults(argptr, plugin_name); 87 ea1 = np_get_defaults(argptr, plugin_name);
86 if(ea1==NULL) { 88 if (ea1 == NULL) {
87 /* no extra args (empty section)? */ 89 /* no extra args (empty section)? */
88 ea_num--; 90 ea_num--;
89 continue; 91 continue;
90 } 92 }
91 93
92 /* append the list to extra_args */ 94 /* append the list to extra_args */
93 if(extra_args==NULL){ 95 if (extra_args == NULL) {
94 extra_args=ea1; 96 extra_args = ea1;
95 while((ea1 = ea1->next)) ea_num++; 97 while ((ea1 = ea1->next))
96 }else{ 98 ea_num++;
97 ea_tmp=extra_args; 99 } else {
98 while(ea_tmp->next) { 100 ea_tmp = extra_args;
99 ea_tmp=ea_tmp->next; 101 while (ea_tmp->next) {
102 ea_tmp = ea_tmp->next;
100 } 103 }
101 ea_tmp->next=ea1; 104 ea_tmp->next = ea1;
102 while((ea1 = ea1->next)) ea_num++; 105 while ((ea1 = ea1->next))
106 ea_num++;
103 } 107 }
104 ea1=ea_tmp=NULL; 108 ea1 = ea_tmp = NULL;
105 } 109 }
106 } /* lather, rince, repeat */ 110 } /* lather, rince, repeat */
107 111
108 if(ea_num==*argc && extra_args==NULL){ 112 if (ea_num == *argc && extra_args == NULL) {
109 /* No extra-opts */ 113 /* No extra-opts */
110 return argv; 114 return argv;
111 } 115 }
112 116
113 /* done processing arguments. now create a new argv array... */ 117 /* done processing arguments. now create a new argv array... */
114 argv_new=(char**)malloc((ea_num+1)*sizeof(char**)); 118 argv_new = (char **)malloc((ea_num + 1) * sizeof(char **));
115 if(argv_new==NULL) die(STATE_UNKNOWN, _("malloc() failed!\n")); 119 if (argv_new == NULL)
120 die(STATE_UNKNOWN, _("malloc() failed!\n"));
116 121
117 /* starting with program name */ 122 /* starting with program name */
118 argv_new[0]=argv[0]; 123 argv_new[0] = argv[0];
119 argc_new=1; 124 argc_new = 1;
120 /* then parsed ini opts (frying them up in the same run) */ 125 /* then parsed ini opts (frying them up in the same run) */
121 while(extra_args){ 126 while (extra_args) {
122 argv_new[argc_new++]=extra_args->arg; 127 argv_new[argc_new++] = extra_args->arg;
123 ea1=extra_args; 128 ea1 = extra_args;
124 extra_args=extra_args->next; 129 extra_args = extra_args->next;
125 free(ea1); 130 free(ea1);
126 } 131 }
127 /* finally the rest of the argv array */ 132 /* finally the rest of the argv array */
128 for (i=1; i<*argc; i++) argv_new[argc_new++]=argv[i]; 133 for (i = 1; i < *argc; i++)
129 *argc=argc_new; 134 argv_new[argc_new++] = argv[i];
135 *argc = argc_new;
130 /* and terminate. */ 136 /* and terminate. */
131 argv_new[argc_new]=NULL; 137 argv_new[argc_new] = NULL;
132 138
133 return argv_new; 139 return argv_new;
134} 140}
135
diff --git a/lib/extra_opts.h b/lib/extra_opts.h
index 8ff14a16..3f64360f 100644
--- a/lib/extra_opts.h
+++ b/lib/extra_opts.h
@@ -20,4 +20,3 @@
20char **np_extra_opts(int *argc, char **argv, const char *plugin_name); 20char **np_extra_opts(int *argc, char **argv, const char *plugin_name);
21 21
22#endif /* _EXTRA_OPTS_H_ */ 22#endif /* _EXTRA_OPTS_H_ */
23
diff --git a/lib/maxfd.c b/lib/maxfd.c
index 529b3568..ca5b6e54 100644
--- a/lib/maxfd.c
+++ b/lib/maxfd.c
@@ -1,7 +1,27 @@
1/*****************************************************************************
2 *
3 * License: GPL
4 * Copyright (c) 2024 Monitoring Plugins Development Team
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 *****************************************************************************/
20
1#include "./maxfd.h" 21#include "./maxfd.h"
2#include <errno.h> 22#include <errno.h>
3 23
4long mp_open_max (void) { 24long mp_open_max(void) {
5 long maxfd = 0L; 25 long maxfd = 0L;
6 /* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX. 26 /* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
7 * If that fails and the macro isn't defined, we fall back to an educated 27 * If that fails and the macro isn't defined, we fall back to an educated
@@ -10,17 +30,17 @@ long mp_open_max (void) {
10 30
11#ifdef _SC_OPEN_MAX 31#ifdef _SC_OPEN_MAX
12 errno = 0; 32 errno = 0;
13 if ((maxfd = sysconf (_SC_OPEN_MAX)) < 0) { 33 if ((maxfd = sysconf(_SC_OPEN_MAX)) < 0) {
14 if (errno == 0) 34 if (errno == 0)
15 maxfd = DEFAULT_MAXFD; /* it's indeterminate */ 35 maxfd = DEFAULT_MAXFD; /* it's indeterminate */
16 else 36 else
17 die (STATE_UNKNOWN, _("sysconf error for _SC_OPEN_MAX\n")); 37 die(STATE_UNKNOWN, _("sysconf error for _SC_OPEN_MAX\n"));
18 } 38 }
19#elif defined(OPEN_MAX) 39#elif defined(OPEN_MAX)
20 return OPEN_MAX 40 return OPEN_MAX
21#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */ 41#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
22 return DEFAULT_MAXFD; 42 return DEFAULT_MAXFD;
23#endif 43#endif
24 44
25 return(maxfd); 45 return (maxfd);
26} 46}
diff --git a/lib/maxfd.h b/lib/maxfd.h
index 45218d0f..8fcd62d3 100644
--- a/lib/maxfd.h
+++ b/lib/maxfd.h
@@ -1,9 +1,9 @@
1#ifndef _MAXFD_ 1#ifndef _MAXFD_
2#define _MAXFD_ 2#define _MAXFD_
3 3
4#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */ 4#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */
5#define MAXFD_LIMIT 8192 /* upper limit of open files */ 5#define MAXFD_LIMIT 8192 /* upper limit of open files */
6 6
7long mp_open_max (void); 7long mp_open_max(void);
8 8
9#endif // _MAXFD_ 9#endif // _MAXFD_
diff --git a/lib/parse_ini.c b/lib/parse_ini.c
index 09c0dc4f..1289aae2 100644
--- a/lib/parse_ini.c
+++ b/lib/parse_ini.c
@@ -1,25 +1,25 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins parse_ini library 3 * Monitoring Plugins parse_ini library
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2007 Monitoring Plugins Development Team 6 * Copyright (c) 2007 - 2024 Monitoring Plugins Development Team
7* 7 *
8* This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or 10 * the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version. 11 * (at your option) any later version.
12* 12 *
13* This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details. 16 * GNU General Public License for more details.
17* 17 *
18* You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19* along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20* 20 *
21* 21 *
22*****************************************************************************/ 22 *****************************************************************************/
23 23
24#include "common.h" 24#include "common.h"
25#include "idpriv.h" 25#include "idpriv.h"
@@ -40,31 +40,20 @@ typedef struct {
40 char *stanza; 40 char *stanza;
41} np_ini_info; 41} np_ini_info;
42 42
43static char *default_ini_file_names[] = { 43static char *default_ini_file_names[] = {"monitoring-plugins.ini", "plugins.ini", "nagios-plugins.ini", NULL};
44 "monitoring-plugins.ini",
45 "plugins.ini",
46 "nagios-plugins.ini",
47 NULL
48};
49 44
50static char *default_ini_path_names[] = { 45static char *default_ini_path_names[] = {
51 "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", 46 "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", "/usr/local/etc/monitoring-plugins.ini",
52 "/usr/local/etc/monitoring-plugins.ini", 47 "/etc/monitoring-plugins/monitoring-plugins.ini", "/etc/monitoring-plugins.ini",
53 "/etc/monitoring-plugins/monitoring-plugins.ini",
54 "/etc/monitoring-plugins.ini",
55 /* deprecated path names (for backward compatibility): */ 48 /* deprecated path names (for backward compatibility): */
56 "/etc/nagios/plugins.ini", 49 "/etc/nagios/plugins.ini", "/usr/local/nagios/etc/plugins.ini", "/usr/local/etc/nagios/plugins.ini", "/etc/opt/nagios/plugins.ini",
57 "/usr/local/nagios/etc/plugins.ini", 50 "/etc/nagios-plugins.ini", "/usr/local/etc/nagios-plugins.ini", "/etc/opt/nagios-plugins.ini", NULL};
58 "/usr/local/etc/nagios/plugins.ini",
59 "/etc/opt/nagios/plugins.ini",
60 "/etc/nagios-plugins.ini",
61 "/usr/local/etc/nagios-plugins.ini",
62 "/etc/opt/nagios-plugins.ini",
63 NULL
64};
65 51
66/* eat all characters from a FILE pointer until n is encountered */ 52/* eat all characters from a FILE pointer until n is encountered */
67#define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n)) 53#define GOBBLE_TO(f, c, n) \
54 do { \
55 (c) = fgetc((f)); \
56 } while ((c) != EOF && (c) != (n))
68 57
69/* internal function that returns the constructed defaults options */ 58/* internal function that returns the constructed defaults options */
70static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts); 59static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts);
@@ -81,9 +70,7 @@ static char *default_file_in_path(void);
81 * [stanza][@filename] 70 * [stanza][@filename]
82 * into its separate parts. 71 * into its separate parts.
83 */ 72 */
84static void 73static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) {
85parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
86{
87 size_t locator_len = 0, stanza_len = 0; 74 size_t locator_len = 0, stanza_len = 0;
88 75
89 /* if locator is NULL we'll use default values */ 76 /* if locator is NULL we'll use default values */
@@ -96,7 +83,7 @@ parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
96 i->stanza = malloc(sizeof(char) * (stanza_len + 1)); 83 i->stanza = malloc(sizeof(char) * (stanza_len + 1));
97 strncpy(i->stanza, locator, stanza_len); 84 strncpy(i->stanza, locator, stanza_len);
98 i->stanza[stanza_len] = '\0'; 85 i->stanza[stanza_len] = '\0';
99 } else {/* otherwise we use the default stanza */ 86 } else { /* otherwise we use the default stanza */
100 i->stanza = strdup(def_stanza); 87 i->stanza = strdup(def_stanza);
101 } 88 }
102 89
@@ -105,7 +92,7 @@ parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
105 92
106 /* check whether there's an @file part */ 93 /* check whether there's an @file part */
107 if (stanza_len == locator_len) { 94 if (stanza_len == locator_len) {
108 i->file = default_file(); 95 i->file = default_file();
109 i->file_string_on_heap = false; 96 i->file_string_on_heap = false;
110 } else { 97 } else {
111 i->file = strdup(&(locator[stanza_len + 1])); 98 i->file = strdup(&(locator[stanza_len + 1]));
@@ -113,35 +100,28 @@ parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
113 } 100 }
114 101
115 if (i->file == NULL || i->file[0] == '\0') 102 if (i->file == NULL || i->file[0] == '\0')
116 die(STATE_UNKNOWN, 103 die(STATE_UNKNOWN, _("Cannot find config file in any standard location.\n"));
117 _("Cannot find config file in any standard location.\n"));
118} 104}
119 105
120/* 106/*
121 * This is the externally visible function used by extra_opts. 107 * This is the externally visible function used by extra_opts.
122 */ 108 */
123np_arg_list * 109np_arg_list *np_get_defaults(const char *locator, const char *default_section) {
124np_get_defaults(const char *locator, const char *default_section)
125{
126 FILE *inifile = NULL; 110 FILE *inifile = NULL;
127 np_arg_list *defaults = NULL; 111 np_arg_list *defaults = NULL;
128 np_ini_info i; 112 np_ini_info i;
129 int is_suid_plugin = mp_suid(); 113 int is_suid_plugin = mp_suid();
130 114
131 if (is_suid_plugin && idpriv_temp_drop() == -1) 115 if (is_suid_plugin && idpriv_temp_drop() == -1)
132 die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), 116 die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), strerror(errno));
133 strerror(errno));
134 117
135 parse_locator(locator, default_section, &i); 118 parse_locator(locator, default_section, &i);
136 inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r"); 119 inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r");
137 120
138 if (inifile == NULL) 121 if (inifile == NULL)
139 die(STATE_UNKNOWN, _("Can't read config file: %s\n"), 122 die(STATE_UNKNOWN, _("Can't read config file: %s\n"), strerror(errno));
140 strerror(errno));
141 if (!read_defaults(inifile, i.stanza, &defaults)) 123 if (!read_defaults(inifile, i.stanza, &defaults))
142 die(STATE_UNKNOWN, 124 die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file);
143 _("Invalid section '%s' in config file '%s'\n"), i.stanza,
144 i.file);
145 125
146 if (i.file_string_on_heap) { 126 if (i.file_string_on_heap) {
147 free(i.file); 127 free(i.file);
@@ -151,8 +131,7 @@ np_get_defaults(const char *locator, const char *default_section)
151 fclose(inifile); 131 fclose(inifile);
152 free(i.stanza); 132 free(i.stanza);
153 if (is_suid_plugin && idpriv_temp_restore() == -1) 133 if (is_suid_plugin && idpriv_temp_restore() == -1)
154 die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), 134 die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), strerror(errno));
155 strerror(errno));
156 135
157 return defaults; 136 return defaults;
158} 137}
@@ -164,13 +143,15 @@ np_get_defaults(const char *locator, const char *default_section)
164 * be extra careful about user-supplied input (i.e. avoiding possible 143 * be extra careful about user-supplied input (i.e. avoiding possible
165 * format string vulnerabilities, etc). 144 * format string vulnerabilities, etc).
166 */ 145 */
167static int 146static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) {
168read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
169{
170 int c = 0; 147 int c = 0;
171 bool status = false; 148 bool status = false;
172 size_t i, stanza_len; 149 size_t i, stanza_len;
173 enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate = NOSTANZA; 150 enum {
151 NOSTANZA,
152 WRONGSTANZA,
153 RIGHTSTANZA
154 } stanzastate = NOSTANZA;
174 155
175 stanza_len = strlen(stanza); 156 stanza_len = strlen(stanza);
176 157
@@ -217,8 +198,7 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
217 * we're dealing with a config error 198 * we're dealing with a config error
218 */ 199 */
219 case NOSTANZA: 200 case NOSTANZA:
220 die(STATE_UNKNOWN, "%s\n", 201 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
221 _("Config file error"));
222 /* we're in a stanza, but for a different plugin */ 202 /* we're in a stanza, but for a different plugin */
223 case WRONGSTANZA: 203 case WRONGSTANZA:
224 GOBBLE_TO(f, c, '\n'); 204 GOBBLE_TO(f, c, '\n');
@@ -227,8 +207,7 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
227 case RIGHTSTANZA: 207 case RIGHTSTANZA:
228 ungetc(c, f); 208 ungetc(c, f);
229 if (add_option(f, opts)) { 209 if (add_option(f, opts)) {
230 die(STATE_UNKNOWN, "%s\n", 210 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
231 _("Config file error"));
232 } 211 }
233 status = true; 212 status = true;
234 break; 213 break;
@@ -246,9 +225,7 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
246 * --option[=value] 225 * --option[=value]
247 * appending it to the linked list optbuf. 226 * appending it to the linked list optbuf.
248 */ 227 */
249static int 228static int add_option(FILE *f, np_arg_list **optlst) {
250add_option(FILE *f, np_arg_list **optlst)
251{
252 np_arg_list *opttmp = *optlst, *optnew; 229 np_arg_list *opttmp = *optlst, *optnew;
253 char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL; 230 char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL;
254 char *eqptr = NULL, *valptr = NULL, *valend = NULL; 231 char *eqptr = NULL, *valptr = NULL, *valend = NULL;
@@ -295,8 +272,7 @@ add_option(FILE *f, np_arg_list **optlst)
295 if (optptr == eqptr) 272 if (optptr == eqptr)
296 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 273 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
297 /* continue from '=' to start of value or EOL */ 274 /* continue from '=' to start of value or EOL */
298 for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); 275 for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++)
299 valptr++)
300 continue; 276 continue;
301 /* continue to the end of value */ 277 /* continue to the end of value */
302 for (valend = valptr; valend < lineend; valend++) 278 for (valend = valptr; valend < lineend; valend++)
@@ -365,13 +341,10 @@ add_option(FILE *f, np_arg_list **optlst)
365 return 0; 341 return 0;
366} 342}
367 343
368static char * 344static char *default_file(void) {
369default_file(void) 345 char *ini_file;
370{
371 char *ini_file;
372 346
373 if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || 347 if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || (ini_file = default_file_in_path()) != NULL) {
374 (ini_file = default_file_in_path()) != NULL) {
375 return ini_file; 348 return ini_file;
376 } 349 }
377 350
@@ -383,9 +356,7 @@ default_file(void)
383 return NULL; 356 return NULL;
384} 357}
385 358
386static char * 359static char *default_file_in_path(void) {
387default_file_in_path(void)
388{
389 char *config_path, **file; 360 char *config_path, **file;
390 char *dir, *ini_file, *tokens; 361 char *dir, *ini_file, *tokens;
391 362
diff --git a/lib/parse_ini.h b/lib/parse_ini.h
index e37601b5..d17409e3 100644
--- a/lib/parse_ini.h
+++ b/lib/parse_ini.h
@@ -19,4 +19,3 @@ typedef struct np_arg_el {
19np_arg_list *np_get_defaults(const char *locator, const char *default_section); 19np_arg_list *np_get_defaults(const char *locator, const char *default_section);
20 20
21#endif /* _PARSE_INI_H_ */ 21#endif /* _PARSE_INI_H_ */
22
diff --git a/lib/tests/test_base64.c b/lib/tests/test_base64.c
index 05dd7943..94cb5aa9 100644
--- a/lib/tests/test_base64.c
+++ b/lib/tests/test_base64.c
@@ -1,29 +1,27 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16* 16 *
17*****************************************************************************/ 17 *****************************************************************************/
18 18
19#include "common.h" 19#include "common.h"
20#include "gl/base64.h" 20#include "gl/base64.h"
21#include "tap.h" 21#include "tap.h"
22 22
23int 23int main(int argc, char **argv) {
24main (int argc, char **argv) 24#if 0 /* The current base64 function doesn't work on 8bit data */
25{
26#if 0 /* The current base64 function doesn't work on 8bit data */
27 char random[1024] = { 25 char random[1024] = {
28 0x8b,0xb0,0xc4,0xe2,0xfc,0x22,0x9f,0x0d,0x85,0xe7,0x2c,0xaa,0x39,0xa1,0x46,0x88, 26 0x8b,0xb0,0xc4,0xe2,0xfc,0x22,0x9f,0x0d,0x85,0xe7,0x2c,0xaa,0x39,0xa1,0x46,0x88,
29 0x50,0xe6,0x34,0x37,0x0b,0x45,0x4b,0xb8,0xb2,0x86,0x7a,0x3e,0x7f,0x0c,0x40,0x18, 27 0x50,0xe6,0x34,0x37,0x0b,0x45,0x4b,0xb8,0xb2,0x86,0x7a,0x3e,0x7f,0x0c,0x40,0x18,
@@ -182,168 +180,124 @@ main (int argc, char **argv)
182#endif 180#endif
183 181
184 char random[1024] = { 182 char random[1024] = {
185 0x0b,0x30,0x44,0x62,0x7c,0x22,0x1f,0x0d,0x05,0x67,0x2c,0x2a,0x39,0x21,0x46,0x08, 183 0x0b, 0x30, 0x44, 0x62, 0x7c, 0x22, 0x1f, 0x0d, 0x05, 0x67, 0x2c, 0x2a, 0x39, 0x21, 0x46, 0x08, 0x50, 0x66, 0x34, 0x37, 0x0b, 0x45,
186 0x50,0x66,0x34,0x37,0x0b,0x45,0x4b,0x38,0x32,0x06,0x7a,0x3e,0x7f,0x0c,0x40,0x18, 184 0x4b, 0x38, 0x32, 0x06, 0x7a, 0x3e, 0x7f, 0x0c, 0x40, 0x18, 0x6b, 0x2d, 0x60, 0x4c, 0x60, 0x0c, 0x23, 0x43, 0x3b, 0x3e, 0x1b, 0x16,
187 0x6b,0x2d,0x60,0x4c,0x60,0x0c,0x23,0x43,0x3b,0x3e,0x1b,0x16,0x04,0x46,0x58,0x3f, 185 0x04, 0x46, 0x58, 0x3f, 0x40, 0x6a, 0x11, 0x05, 0x63, 0x71, 0x14, 0x35, 0x47, 0x79, 0x13, 0x6f, 0x6b, 0x27, 0x18, 0x5b, 0x48, 0x27,
188 0x40,0x6a,0x11,0x05,0x63,0x71,0x14,0x35,0x47,0x79,0x13,0x6f,0x6b,0x27,0x18,0x5b, 186 0x3e, 0x6f, 0x15, 0x33, 0x4f, 0x3e, 0x5e, 0x51, 0x73, 0x68, 0x25, 0x0f, 0x06, 0x5b, 0x7c, 0x72, 0x75, 0x3e, 0x3f, 0x1b, 0x5c, 0x6d,
189 0x48,0x27,0x3e,0x6f,0x15,0x33,0x4f,0x3e,0x5e,0x51,0x73,0x68,0x25,0x0f,0x06,0x5b, 187 0x6a, 0x39, 0x7c, 0x63, 0x63, 0x60, 0x6c, 0x7a, 0x33, 0x76, 0x52, 0x13, 0x25, 0x33, 0x7d, 0x65, 0x23, 0x27, 0x11, 0x06, 0x06, 0x47,
190 0x7c,0x72,0x75,0x3e,0x3f,0x1b,0x5c,0x6d,0x6a,0x39,0x7c,0x63,0x63,0x60,0x6c,0x7a, 188 0x71, 0x1e, 0x14, 0x74, 0x63, 0x70, 0x2d, 0x15, 0x27, 0x18, 0x51, 0x06, 0x05, 0x33, 0x11, 0x2c, 0x6b, 0x00, 0x2d, 0x77, 0x20, 0x48,
191 0x33,0x76,0x52,0x13,0x25,0x33,0x7d,0x65,0x23,0x27,0x11,0x06,0x06,0x47,0x71,0x1e, 189 0x0d, 0x73, 0x51, 0x45, 0x25, 0x7f, 0x7f, 0x35, 0x26, 0x2e, 0x26, 0x53, 0x24, 0x68, 0x1e, 0x0e, 0x58, 0x3a, 0x59, 0x50, 0x56, 0x37,
192 0x14,0x74,0x63,0x70,0x2d,0x15,0x27,0x18,0x51,0x06,0x05,0x33,0x11,0x2c,0x6b,0x00, 190 0x5f, 0x66, 0x01, 0x4c, 0x5a, 0x64, 0x32, 0x50, 0x7b, 0x6a, 0x20, 0x72, 0x2b, 0x1d, 0x7e, 0x43, 0x7b, 0x61, 0x42, 0x0b, 0x61, 0x73,
193 0x2d,0x77,0x20,0x48,0x0d,0x73,0x51,0x45,0x25,0x7f,0x7f,0x35,0x26,0x2e,0x26,0x53, 191 0x24, 0x79, 0x3a, 0x6b, 0x4a, 0x79, 0x6e, 0x09, 0x0f, 0x27, 0x2d, 0x0c, 0x5e, 0x32, 0x4b, 0x0d, 0x79, 0x46, 0x39, 0x21, 0x0a, 0x26,
194 0x24,0x68,0x1e,0x0e,0x58,0x3a,0x59,0x50,0x56,0x37,0x5f,0x66,0x01,0x4c,0x5a,0x64, 192 0x5f, 0x3a, 0x00, 0x26, 0x3f, 0x13, 0x2e, 0x7e, 0x50, 0x2b, 0x67, 0x46, 0x72, 0x3f, 0x3b, 0x01, 0x46, 0x1b, 0x0b, 0x35, 0x49, 0x39,
195 0x32,0x50,0x7b,0x6a,0x20,0x72,0x2b,0x1d,0x7e,0x43,0x7b,0x61,0x42,0x0b,0x61,0x73, 193 0x19, 0x70, 0x3d, 0x02, 0x41, 0x0e, 0x38, 0x05, 0x76, 0x65, 0x4f, 0x31, 0x6c, 0x5e, 0x17, 0x04, 0x15, 0x36, 0x26, 0x64, 0x34, 0x14,
196 0x24,0x79,0x3a,0x6b,0x4a,0x79,0x6e,0x09,0x0f,0x27,0x2d,0x0c,0x5e,0x32,0x4b,0x0d, 194 0x17, 0x7c, 0x0e, 0x0b, 0x5b, 0x55, 0x53, 0x6b, 0x00, 0x42, 0x41, 0x4f, 0x02, 0x5c, 0x13, 0x0a, 0x2c, 0x2c, 0x3e, 0x10, 0x14, 0x33,
197 0x79,0x46,0x39,0x21,0x0a,0x26,0x5f,0x3a,0x00,0x26,0x3f,0x13,0x2e,0x7e,0x50,0x2b, 195 0x45, 0x7c, 0x7a, 0x5a, 0x31, 0x61, 0x39, 0x08, 0x22, 0x6a, 0x1e, 0x0f, 0x6f, 0x1b, 0x6c, 0x13, 0x5e, 0x79, 0x20, 0x79, 0x50, 0x62,
198 0x67,0x46,0x72,0x3f,0x3b,0x01,0x46,0x1b,0x0b,0x35,0x49,0x39,0x19,0x70,0x3d,0x02, 196 0x06, 0x2c, 0x76, 0x17, 0x04, 0x2b, 0x2a, 0x75, 0x1f, 0x0c, 0x37, 0x4e, 0x0f, 0x7b, 0x2d, 0x34, 0x75, 0x60, 0x31, 0x74, 0x2e, 0x0a,
199 0x41,0x0e,0x38,0x05,0x76,0x65,0x4f,0x31,0x6c,0x5e,0x17,0x04,0x15,0x36,0x26,0x64, 197 0x4a, 0x11, 0x6c, 0x49, 0x25, 0x01, 0x3a, 0x3d, 0x22, 0x1e, 0x6d, 0x18, 0x51, 0x78, 0x2d, 0x62, 0x31, 0x4c, 0x50, 0x40, 0x17, 0x4b,
200 0x34,0x14,0x17,0x7c,0x0e,0x0b,0x5b,0x55,0x53,0x6b,0x00,0x42,0x41,0x4f,0x02,0x5c, 198 0x6f, 0x22, 0x00, 0x7f, 0x61, 0x2a, 0x34, 0x3e, 0x00, 0x5f, 0x2f, 0x5f, 0x2f, 0x14, 0x2a, 0x55, 0x27, 0x1f, 0x46, 0x1f, 0x12, 0x46,
201 0x13,0x0a,0x2c,0x2c,0x3e,0x10,0x14,0x33,0x45,0x7c,0x7a,0x5a,0x31,0x61,0x39,0x08, 199 0x5e, 0x1e, 0x0c, 0x7c, 0x38, 0x01, 0x61, 0x64, 0x76, 0x22, 0x6e, 0x08, 0x20, 0x38, 0x4f, 0x73, 0x72, 0x55, 0x12, 0x42, 0x19, 0x50,
202 0x22,0x6a,0x1e,0x0f,0x6f,0x1b,0x6c,0x13,0x5e,0x79,0x20,0x79,0x50,0x62,0x06,0x2c, 200 0x61, 0x43, 0x77, 0x7d, 0x41, 0x2e, 0x35, 0x4f, 0x3d, 0x31, 0x28, 0x58, 0x67, 0x1b, 0x03, 0x51, 0x20, 0x32, 0x1c, 0x08, 0x6e, 0x37,
203 0x76,0x17,0x04,0x2b,0x2a,0x75,0x1f,0x0c,0x37,0x4e,0x0f,0x7b,0x2d,0x34,0x75,0x60, 201 0x75, 0x37, 0x44, 0x4f, 0x68, 0x19, 0x07, 0x64, 0x14, 0x28, 0x25, 0x2b, 0x69, 0x35, 0x18, 0x27, 0x26, 0x14, 0x13, 0x70, 0x42, 0x19,
204 0x31,0x74,0x2e,0x0a,0x4a,0x11,0x6c,0x49,0x25,0x01,0x3a,0x3d,0x22,0x1e,0x6d,0x18, 202 0x12, 0x75, 0x3e, 0x02, 0x5d, 0x7c, 0x13, 0x1f, 0x16, 0x53, 0x3b, 0x74, 0x48, 0x3c, 0x5e, 0x39, 0x6c, 0x1c, 0x1c, 0x74, 0x39, 0x1f,
205 0x51,0x78,0x2d,0x62,0x31,0x4c,0x50,0x40,0x17,0x4b,0x6f,0x22,0x00,0x7f,0x61,0x2a, 203 0x00, 0x1b, 0x06, 0x0a, 0x68, 0x3b, 0x52, 0x4f, 0x1e, 0x6e, 0x3c, 0x35, 0x0c, 0x38, 0x0e, 0x0b, 0x3b, 0x1a, 0x76, 0x23, 0x29, 0x53,
206 0x34,0x3e,0x00,0x5f,0x2f,0x5f,0x2f,0x14,0x2a,0x55,0x27,0x1f,0x46,0x1f,0x12,0x46, 204 0x1e, 0x5f, 0x41, 0x0c, 0x4b, 0x0a, 0x65, 0x28, 0x78, 0x67, 0x48, 0x59, 0x26, 0x6d, 0x31, 0x76, 0x23, 0x70, 0x61, 0x64, 0x3b, 0x38,
207 0x5e,0x1e,0x0c,0x7c,0x38,0x01,0x61,0x64,0x76,0x22,0x6e,0x08,0x20,0x38,0x4f,0x73, 205 0x79, 0x66, 0x74, 0x53, 0x2c, 0x64, 0x64, 0x54, 0x03, 0x54, 0x65, 0x44, 0x4c, 0x18, 0x4f, 0x48, 0x20, 0x4f, 0x72, 0x10, 0x3f, 0x0c,
208 0x72,0x55,0x12,0x42,0x19,0x50,0x61,0x43,0x77,0x7d,0x41,0x2e,0x35,0x4f,0x3d,0x31, 206 0x52, 0x2d, 0x03, 0x14, 0x03, 0x51, 0x42, 0x10, 0x77, 0x6a, 0x34, 0x06, 0x32, 0x03, 0x72, 0x14, 0x7c, 0x08, 0x5d, 0x52, 0x1a, 0x62,
209 0x28,0x58,0x67,0x1b,0x03,0x51,0x20,0x32,0x1c,0x08,0x6e,0x37,0x75,0x37,0x44,0x4f, 207 0x7c, 0x3e, 0x30, 0x7e, 0x5f, 0x7f, 0x54, 0x0f, 0x44, 0x49, 0x5d, 0x5e, 0x10, 0x6a, 0x06, 0x2b, 0x06, 0x53, 0x10, 0x39, 0x37, 0x32,
210 0x68,0x19,0x07,0x64,0x14,0x28,0x25,0x2b,0x69,0x35,0x18,0x27,0x26,0x14,0x13,0x70, 208 0x4a, 0x4e, 0x3d, 0x2b, 0x65, 0x38, 0x39, 0x07, 0x72, 0x54, 0x64, 0x4d, 0x56, 0x6a, 0x03, 0x22, 0x70, 0x7b, 0x5f, 0x60, 0x0b, 0x2a,
211 0x42,0x19,0x12,0x75,0x3e,0x02,0x5d,0x7c,0x13,0x1f,0x16,0x53,0x3b,0x74,0x48,0x3c, 209 0x0b, 0x6b, 0x10, 0x64, 0x14, 0x05, 0x22, 0x00, 0x73, 0x40, 0x23, 0x5b, 0x51, 0x1f, 0x2b, 0x1a, 0x5d, 0x69, 0x7a, 0x46, 0x0c, 0x5f,
212 0x5e,0x39,0x6c,0x1c,0x1c,0x74,0x39,0x1f,0x00,0x1b,0x06,0x0a,0x68,0x3b,0x52,0x4f, 210 0x32, 0x4b, 0x4a, 0x28, 0x52, 0x79, 0x5b, 0x12, 0x42, 0x18, 0x00, 0x5d, 0x27, 0x31, 0x53, 0x3c, 0x4c, 0x36, 0x4e, 0x38, 0x3f, 0x72,
213 0x1e,0x6e,0x3c,0x35,0x0c,0x38,0x0e,0x0b,0x3b,0x1a,0x76,0x23,0x29,0x53,0x1e,0x5f, 211 0x03, 0x71, 0x02, 0x5b, 0x36, 0x59, 0x7f, 0x75, 0x6e, 0x08, 0x54, 0x0d, 0x34, 0x1c, 0x34, 0x57, 0x5d, 0x69, 0x48, 0x00, 0x3b, 0x05,
214 0x41,0x0c,0x4b,0x0a,0x65,0x28,0x78,0x67,0x48,0x59,0x26,0x6d,0x31,0x76,0x23,0x70, 212 0x07, 0x6e, 0x27, 0x65, 0x6e, 0x40, 0x3d, 0x3a, 0x4f, 0x72, 0x5d, 0x39, 0x16, 0x0f, 0x63, 0x12, 0x12, 0x15, 0x3a, 0x70, 0x0d, 0x57,
215 0x61,0x64,0x3b,0x38,0x79,0x66,0x74,0x53,0x2c,0x64,0x64,0x54,0x03,0x54,0x65,0x44, 213 0x18, 0x0d, 0x5e, 0x3d, 0x22, 0x68, 0x68, 0x7c, 0x6d, 0x4f, 0x0c, 0x7b, 0x09, 0x2d, 0x4a, 0x73, 0x20, 0x47, 0x07, 0x57, 0x75, 0x5d,
216 0x4c,0x18,0x4f,0x48,0x20,0x4f,0x72,0x10,0x3f,0x0c,0x52,0x2d,0x03,0x14,0x03,0x51, 214 0x53, 0x70, 0x34, 0x21, 0x40, 0x57, 0x51, 0x5e, 0x49, 0x44, 0x00, 0x54, 0x27, 0x04, 0x68, 0x7e, 0x59, 0x56, 0x58, 0x74, 0x14, 0x3c,
217 0x42,0x10,0x77,0x6a,0x34,0x06,0x32,0x03,0x72,0x14,0x7c,0x08,0x5d,0x52,0x1a,0x62, 215 0x16, 0x33, 0x41, 0x16, 0x4b, 0x2f, 0x49, 0x37, 0x0a, 0x54, 0x08, 0x08, 0x1f, 0x39, 0x67, 0x76, 0x28, 0x28, 0x07, 0x1d, 0x61, 0x47,
218 0x7c,0x3e,0x30,0x7e,0x5f,0x7f,0x54,0x0f,0x44,0x49,0x5d,0x5e,0x10,0x6a,0x06,0x2b, 216 0x51, 0x4d, 0x75, 0x26, 0x52, 0x47, 0x47, 0x0c, 0x57, 0x58, 0x74, 0x3e, 0x62, 0x6c, 0x58, 0x3a, 0x44, 0x1e, 0x16, 0x2e, 0x21, 0x1c,
219 0x06,0x53,0x10,0x39,0x37,0x32,0x4a,0x4e,0x3d,0x2b,0x65,0x38,0x39,0x07,0x72,0x54, 217 0x73, 0x45, 0x67, 0x74, 0x4f, 0x33, 0x66, 0x0e, 0x74, 0x66, 0x26, 0x1f, 0x2e, 0x38, 0x44, 0x40, 0x7e, 0x2a, 0x50, 0x52, 0x5e, 0x43,
220 0x64,0x4d,0x56,0x6a,0x03,0x22,0x70,0x7b,0x5f,0x60,0x0b,0x2a,0x0b,0x6b,0x10,0x64, 218 0x01, 0x7a, 0x38, 0x49, 0x3c, 0x55, 0x4d, 0x5a, 0x44, 0x08, 0x26, 0x59, 0x4d, 0x45, 0x0b, 0x48, 0x0a, 0x33, 0x5e, 0x4a, 0x4d, 0x75,
221 0x14,0x05,0x22,0x00,0x73,0x40,0x23,0x5b,0x51,0x1f,0x2b,0x1a,0x5d,0x69,0x7a,0x46, 219 0x16, 0x17, 0x63, 0x46, 0x01, 0x2a, 0x55, 0x7b, 0x0f, 0x02, 0x73, 0x6a, 0x4b, 0x7f, 0x75, 0x65, 0x3c, 0x4c, 0x33, 0x39, 0x6c, 0x74,
222 0x0c,0x5f,0x32,0x4b,0x4a,0x28,0x52,0x79,0x5b,0x12,0x42,0x18,0x00,0x5d,0x27,0x31, 220 0x05, 0x60, 0x0f, 0x7f, 0x2d, 0x41, 0x4d, 0x4d, 0x46, 0x71, 0x09, 0x6f, 0x4f, 0x60, 0x15, 0x0f, 0x46, 0x73, 0x63, 0x4c, 0x5e, 0x74,
223 0x53,0x3c,0x4c,0x36,0x4e,0x38,0x3f,0x72,0x03,0x71,0x02,0x5b,0x36,0x59,0x7f,0x75, 221 0x30, 0x0d, 0x28, 0x43, 0x08, 0x72, 0x32, 0x04, 0x2e, 0x31, 0x29, 0x27, 0x44, 0x6d, 0x13, 0x17, 0x48, 0x0f, 0x49, 0x52, 0x10, 0x13,
224 0x6e,0x08,0x54,0x0d,0x34,0x1c,0x34,0x57,0x5d,0x69,0x48,0x00,0x3b,0x05,0x07,0x6e, 222 0x7f, 0x17, 0x16, 0x62, 0x79, 0x35, 0x78, 0x3e, 0x01, 0x7c, 0x2e, 0x0f, 0x76, 0x3e, 0x5e, 0x53, 0x6c, 0x5b, 0x5f, 0x7c, 0x19, 0x41,
225 0x27,0x65,0x6e,0x40,0x3d,0x3a,0x4f,0x72,0x5d,0x39,0x16,0x0f,0x63,0x12,0x12,0x15, 223 0x02, 0x2f, 0x17, 0x64, 0x41, 0x75, 0x10, 0x04, 0x47, 0x7c, 0x3d, 0x4b, 0x52, 0x00, 0x10, 0x5d, 0x51, 0x4e, 0x7a, 0x27, 0x25, 0x55,
226 0x3a,0x70,0x0d,0x57,0x18,0x0d,0x5e,0x3d,0x22,0x68,0x68,0x7c,0x6d,0x4f,0x0c,0x7b, 224 0x40, 0x12, 0x35, 0x60, 0x05, 0x1b, 0x34, 0x2d, 0x04, 0x7a, 0x6a, 0x69, 0x02, 0x79, 0x03, 0x3a, 0x2f, 0x06, 0x0a, 0x79, 0x7b, 0x12,
227 0x09,0x2d,0x4a,0x73,0x20,0x47,0x07,0x57,0x75,0x5d,0x53,0x70,0x34,0x21,0x40,0x57, 225 0x5d, 0x7c, 0x52, 0x29, 0x47, 0x58, 0x12, 0x73, 0x3f, 0x27, 0x56, 0x05, 0x0c, 0x48, 0x32, 0x58, 0x6b, 0x57, 0x5c, 0x03, 0x64, 0x56,
228 0x51,0x5e,0x49,0x44,0x00,0x54,0x27,0x04,0x68,0x7e,0x59,0x56,0x58,0x74,0x14,0x3c, 226 0x11, 0x52, 0x7a, 0x30, 0x36, 0x29, 0x17, 0x3b, 0x68, 0x7a, 0x7c, 0x05, 0x6b, 0x6b, 0x13, 0x6a, 0x24, 0x5c, 0x68, 0x42, 0x18, 0x32,
229 0x16,0x33,0x41,0x16,0x4b,0x2f,0x49,0x37,0x0a,0x54,0x08,0x08,0x1f,0x39,0x67,0x76, 227 0x03, 0x73, 0x6e, 0x04, 0x21, 0x2e, 0x01, 0x04, 0x63, 0x7d, 0x44, 0x41, 0x12, 0x31, 0x0b, 0x15, 0x1f, 0x70, 0x00, 0x2e, 0x66, 0x14,
230 0x28,0x28,0x07,0x1d,0x61,0x47,0x51,0x4d,0x75,0x26,0x52,0x47,0x47,0x0c,0x57,0x58, 228 0x3c, 0x7f, 0x2b, 0x00, 0x1f, 0x0c, 0x28, 0x59, 0x0a, 0x16, 0x49, 0x5a, 0x5c, 0x64, 0x65, 0x4b, 0x11, 0x29, 0x15, 0x36, 0x5a, 0x65,
231 0x74,0x3e,0x62,0x6c,0x58,0x3a,0x44,0x1e,0x16,0x2e,0x21,0x1c,0x73,0x45,0x67,0x74, 229 0x19, 0x4f, 0x60, 0x23, 0x3a, 0x3a, 0x13, 0x25, 0x02, 0x78, 0x4c, 0x54};
232 0x4f,0x33,0x66,0x0e,0x74,0x66,0x26,0x1f,0x2e,0x38,0x44,0x40,0x7e,0x2a,0x50,0x52, 230 char b64_known[1369] = {
233 0x5e,0x43,0x01,0x7a,0x38,0x49,0x3c,0x55,0x4d,0x5a,0x44,0x08,0x26,0x59,0x4d,0x45, 231 0x43, 0x7a, 0x42, 0x45, 0x59, 0x6e, 0x77, 0x69, 0x48, 0x77, 0x30, 0x46, 0x5a, 0x79, 0x77, 0x71, 0x4f, 0x53, 0x46, 0x47, 0x43, 0x46,
234 0x0b,0x48,0x0a,0x33,0x5e,0x4a,0x4d,0x75,0x16,0x17,0x63,0x46,0x01,0x2a,0x55,0x7b, 232 0x42, 0x6d, 0x4e, 0x44, 0x63, 0x4c, 0x52, 0x55, 0x73, 0x34, 0x4d, 0x67, 0x5a, 0x36, 0x50, 0x6e, 0x38, 0x4d, 0x51, 0x42, 0x68, 0x72,
235 0x0f,0x02,0x73,0x6a,0x4b,0x7f,0x75,0x65,0x3c,0x4c,0x33,0x39,0x6c,0x74,0x05,0x60, 233 0x4c, 0x57, 0x42, 0x4d, 0x59, 0x41, 0x77, 0x6a, 0x51, 0x7a, 0x73, 0x2b, 0x47, 0x78, 0x59, 0x45, 0x52, 0x6c, 0x67, 0x2f, 0x51, 0x47,
236 0x0f,0x7f,0x2d,0x41,0x4d,0x4d,0x46,0x71,0x09,0x6f,0x4f,0x60,0x15,0x0f,0x46,0x73, 234 0x6f, 0x52, 0x42, 0x57, 0x4e, 0x78, 0x46, 0x44, 0x56, 0x48, 0x65, 0x52, 0x4e, 0x76, 0x61, 0x79, 0x63, 0x59, 0x57, 0x30, 0x67, 0x6e,
237 0x63,0x4c,0x5e,0x74,0x30,0x0d,0x28,0x43,0x08,0x72,0x32,0x04,0x2e,0x31,0x29,0x27, 235 0x50, 0x6d, 0x38, 0x56, 0x4d, 0x30, 0x38, 0x2b, 0x58, 0x6c, 0x46, 0x7a, 0x61, 0x43, 0x55, 0x50, 0x42, 0x6c, 0x74, 0x38, 0x63, 0x6e,
238 0x44,0x6d,0x13,0x17,0x48,0x0f,0x49,0x52,0x10,0x13,0x7f,0x17,0x16,0x62,0x79,0x35, 236 0x55, 0x2b, 0x50, 0x78, 0x74, 0x63, 0x62, 0x57, 0x6f, 0x35, 0x66, 0x47, 0x4e, 0x6a, 0x59, 0x47, 0x78, 0x36, 0x4d, 0x33, 0x5a, 0x53,
239 0x78,0x3e,0x01,0x7c,0x2e,0x0f,0x76,0x3e,0x5e,0x53,0x6c,0x5b,0x5f,0x7c,0x19,0x41, 237 0x45, 0x79, 0x55, 0x7a, 0x66, 0x57, 0x55, 0x6a, 0x4a, 0x78, 0x45, 0x47, 0x42, 0x6b, 0x64, 0x78, 0x48, 0x68, 0x52, 0x30, 0x59, 0x33,
240 0x02,0x2f,0x17,0x64,0x41,0x75,0x10,0x04,0x47,0x7c,0x3d,0x4b,0x52,0x00,0x10,0x5d, 238 0x41, 0x74, 0x46, 0x53, 0x63, 0x59, 0x55, 0x51, 0x59, 0x46, 0x4d, 0x78, 0x45, 0x73, 0x61, 0x77, 0x41, 0x74, 0x64, 0x79, 0x42, 0x49,
241 0x51,0x4e,0x7a,0x27,0x25,0x55,0x40,0x12,0x35,0x60,0x05,0x1b,0x34,0x2d,0x04,0x7a, 239 0x44, 0x58, 0x4e, 0x52, 0x52, 0x53, 0x56, 0x2f, 0x66, 0x7a, 0x55, 0x6d, 0x4c, 0x69, 0x5a, 0x54, 0x4a, 0x47, 0x67, 0x65, 0x44, 0x6c,
242 0x6a,0x69,0x02,0x79,0x03,0x3a,0x2f,0x06,0x0a,0x79,0x7b,0x12,0x5d,0x7c,0x52,0x29, 240 0x67, 0x36, 0x57, 0x56, 0x42, 0x57, 0x4e, 0x31, 0x39, 0x6d, 0x41, 0x55, 0x78, 0x61, 0x5a, 0x44, 0x4a, 0x51, 0x65, 0x32, 0x6f, 0x67,
243 0x47,0x58,0x12,0x73,0x3f,0x27,0x56,0x05,0x0c,0x48,0x32,0x58,0x6b,0x57,0x5c,0x03, 241 0x63, 0x69, 0x73, 0x64, 0x66, 0x6b, 0x4e, 0x37, 0x59, 0x55, 0x49, 0x4c, 0x59, 0x58, 0x4d, 0x6b, 0x65, 0x54, 0x70, 0x72, 0x53, 0x6e,
244 0x64,0x56,0x11,0x52,0x7a,0x30,0x36,0x29,0x17,0x3b,0x68,0x7a,0x7c,0x05,0x6b,0x6b, 242 0x6c, 0x75, 0x43, 0x51, 0x38, 0x6e, 0x4c, 0x51, 0x78, 0x65, 0x4d, 0x6b, 0x73, 0x4e, 0x65, 0x55, 0x59, 0x35, 0x49, 0x51, 0x6f, 0x6d,
245 0x13,0x6a,0x24,0x5c,0x68,0x42,0x18,0x32,0x03,0x73,0x6e,0x04,0x21,0x2e,0x01,0x04, 243 0x58, 0x7a, 0x6f, 0x41, 0x4a, 0x6a, 0x38, 0x54, 0x4c, 0x6e, 0x35, 0x51, 0x4b, 0x32, 0x64, 0x47, 0x63, 0x6a, 0x38, 0x37, 0x41, 0x55,
246 0x63,0x7d,0x44,0x41,0x12,0x31,0x0b,0x15,0x1f,0x70,0x00,0x2e,0x66,0x14,0x3c,0x7f, 244 0x59, 0x62, 0x43, 0x7a, 0x56, 0x4a, 0x4f, 0x52, 0x6c, 0x77, 0x50, 0x51, 0x4a, 0x42, 0x44, 0x6a, 0x67, 0x46, 0x64, 0x6d, 0x56, 0x50,
247 0x2b,0x00,0x1f,0x0c,0x28,0x59,0x0a,0x16,0x49,0x5a,0x5c,0x64,0x65,0x4b,0x11,0x29, 245 0x4d, 0x57, 0x78, 0x65, 0x46, 0x77, 0x51, 0x56, 0x4e, 0x69, 0x5a, 0x6b, 0x4e, 0x42, 0x51, 0x58, 0x66, 0x41, 0x34, 0x4c, 0x57, 0x31,
248 0x15,0x36,0x5a,0x65,0x19,0x4f,0x60,0x23,0x3a,0x3a,0x13,0x25,0x02,0x78,0x4c,0x54 246 0x56, 0x54, 0x61, 0x77, 0x42, 0x43, 0x51, 0x55, 0x38, 0x43, 0x58, 0x42, 0x4d, 0x4b, 0x4c, 0x43, 0x77, 0x2b, 0x45, 0x42, 0x51, 0x7a,
249 }; 247 0x52, 0x58, 0x78, 0x36, 0x57, 0x6a, 0x46, 0x68, 0x4f, 0x51, 0x67, 0x69, 0x61, 0x68, 0x34, 0x50, 0x62, 0x78, 0x74, 0x73, 0x45, 0x31,
250 char b64_known[1369] = { 248 0x35, 0x35, 0x49, 0x48, 0x6c, 0x51, 0x59, 0x67, 0x59, 0x73, 0x64, 0x68, 0x63, 0x45, 0x4b, 0x79, 0x70, 0x31, 0x48, 0x77, 0x77, 0x33,
251 0x43,0x7a,0x42,0x45,0x59,0x6e,0x77,0x69,0x48,0x77,0x30,0x46,0x5a,0x79,0x77,0x71, 249 0x54, 0x67, 0x39, 0x37, 0x4c, 0x54, 0x52, 0x31, 0x59, 0x44, 0x46, 0x30, 0x4c, 0x67, 0x70, 0x4b, 0x45, 0x57, 0x78, 0x4a, 0x4a, 0x51,
252 0x4f,0x53,0x46,0x47,0x43,0x46,0x42,0x6d,0x4e,0x44,0x63,0x4c,0x52,0x55,0x73,0x34, 250 0x45, 0x36, 0x50, 0x53, 0x49, 0x65, 0x62, 0x52, 0x68, 0x52, 0x65, 0x43, 0x31, 0x69, 0x4d, 0x55, 0x78, 0x51, 0x51, 0x42, 0x64, 0x4c,
253 0x4d,0x67,0x5a,0x36,0x50,0x6e,0x38,0x4d,0x51,0x42,0x68,0x72,0x4c,0x57,0x42,0x4d, 251 0x62, 0x79, 0x49, 0x41, 0x66, 0x32, 0x45, 0x71, 0x4e, 0x44, 0x34, 0x41, 0x58, 0x79, 0x39, 0x66, 0x4c, 0x78, 0x51, 0x71, 0x56, 0x53,
254 0x59,0x41,0x77,0x6a,0x51,0x7a,0x73,0x2b,0x47,0x78,0x59,0x45,0x52,0x6c,0x67,0x2f, 252 0x63, 0x66, 0x52, 0x68, 0x38, 0x53, 0x52, 0x6c, 0x34, 0x65, 0x44, 0x48, 0x77, 0x34, 0x41, 0x57, 0x46, 0x6b, 0x64, 0x69, 0x4a, 0x75,
255 0x51,0x47,0x6f,0x52,0x42,0x57,0x4e,0x78,0x46,0x44,0x56,0x48,0x65,0x52,0x4e,0x76, 253 0x43, 0x43, 0x41, 0x34, 0x54, 0x33, 0x4e, 0x79, 0x56, 0x52, 0x4a, 0x43, 0x47, 0x56, 0x42, 0x68, 0x51, 0x33, 0x64, 0x39, 0x51, 0x53,
256 0x61,0x79,0x63,0x59,0x57,0x30,0x67,0x6e,0x50,0x6d,0x38,0x56,0x4d,0x30,0x38,0x2b, 254 0x34, 0x31, 0x54, 0x7a, 0x30, 0x78, 0x4b, 0x46, 0x68, 0x6e, 0x47, 0x77, 0x4e, 0x52, 0x49, 0x44, 0x49, 0x63, 0x43, 0x47, 0x34, 0x33,
257 0x58,0x6c,0x46,0x7a,0x61,0x43,0x55,0x50,0x42,0x6c,0x74,0x38,0x63,0x6e,0x55,0x2b, 255 0x64, 0x54, 0x64, 0x45, 0x54, 0x32, 0x67, 0x5a, 0x42, 0x32, 0x51, 0x55, 0x4b, 0x43, 0x55, 0x72, 0x61, 0x54, 0x55, 0x59, 0x4a, 0x79,
258 0x50,0x78,0x74,0x63,0x62,0x57,0x6f,0x35,0x66,0x47,0x4e,0x6a,0x59,0x47,0x78,0x36, 256 0x59, 0x55, 0x45, 0x33, 0x42, 0x43, 0x47, 0x52, 0x4a, 0x31, 0x50, 0x67, 0x4a, 0x64, 0x66, 0x42, 0x4d, 0x66, 0x46, 0x6c, 0x4d, 0x37,
259 0x4d,0x33,0x5a,0x53,0x45,0x79,0x55,0x7a,0x66,0x57,0x55,0x6a,0x4a,0x78,0x45,0x47, 257 0x64, 0x45, 0x67, 0x38, 0x58, 0x6a, 0x6c, 0x73, 0x48, 0x42, 0x78, 0x30, 0x4f, 0x52, 0x38, 0x41, 0x47, 0x77, 0x59, 0x4b, 0x61, 0x44,
260 0x42,0x6b,0x64,0x78,0x48,0x68,0x52,0x30,0x59,0x33,0x41,0x74,0x46,0x53,0x63,0x59, 258 0x74, 0x53, 0x54, 0x78, 0x35, 0x75, 0x50, 0x44, 0x55, 0x4d, 0x4f, 0x41, 0x34, 0x4c, 0x4f, 0x78, 0x70, 0x32, 0x49, 0x79, 0x6c, 0x54,
261 0x55,0x51,0x59,0x46,0x4d,0x78,0x45,0x73,0x61,0x77,0x41,0x74,0x64,0x79,0x42,0x49, 259 0x48, 0x6c, 0x39, 0x42, 0x44, 0x45, 0x73, 0x4b, 0x5a, 0x53, 0x68, 0x34, 0x5a, 0x30, 0x68, 0x5a, 0x4a, 0x6d, 0x30, 0x78, 0x64, 0x69,
262 0x44,0x58,0x4e,0x52,0x52,0x53,0x56,0x2f,0x66,0x7a,0x55,0x6d,0x4c,0x69,0x5a,0x54, 260 0x4e, 0x77, 0x59, 0x57, 0x51, 0x37, 0x4f, 0x48, 0x6c, 0x6d, 0x64, 0x46, 0x4d, 0x73, 0x5a, 0x47, 0x52, 0x55, 0x41, 0x31, 0x52, 0x6c,
263 0x4a,0x47,0x67,0x65,0x44,0x6c,0x67,0x36,0x57,0x56,0x42,0x57,0x4e,0x31,0x39,0x6d, 261 0x52, 0x45, 0x77, 0x59, 0x54, 0x30, 0x67, 0x67, 0x54, 0x33, 0x49, 0x51, 0x50, 0x77, 0x78, 0x53, 0x4c, 0x51, 0x4d, 0x55, 0x41, 0x31,
264 0x41,0x55,0x78,0x61,0x5a,0x44,0x4a,0x51,0x65,0x32,0x6f,0x67,0x63,0x69,0x73,0x64, 262 0x46, 0x43, 0x45, 0x48, 0x64, 0x71, 0x4e, 0x41, 0x59, 0x79, 0x41, 0x33, 0x49, 0x55, 0x66, 0x41, 0x68, 0x64, 0x55, 0x68, 0x70, 0x69,
265 0x66,0x6b,0x4e,0x37,0x59,0x55,0x49,0x4c,0x59,0x58,0x4d,0x6b,0x65,0x54,0x70,0x72, 263 0x66, 0x44, 0x34, 0x77, 0x66, 0x6c, 0x39, 0x2f, 0x56, 0x41, 0x39, 0x45, 0x53, 0x56, 0x31, 0x65, 0x45, 0x47, 0x6f, 0x47, 0x4b, 0x77,
266 0x53,0x6e,0x6c,0x75,0x43,0x51,0x38,0x6e,0x4c,0x51,0x78,0x65,0x4d,0x6b,0x73,0x4e, 264 0x5a, 0x54, 0x45, 0x44, 0x6b, 0x33, 0x4d, 0x6b, 0x70, 0x4f, 0x50, 0x53, 0x74, 0x6c, 0x4f, 0x44, 0x6b, 0x48, 0x63, 0x6c, 0x52, 0x6b,
267 0x65,0x55,0x59,0x35,0x49,0x51,0x6f,0x6d,0x58,0x7a,0x6f,0x41,0x4a,0x6a,0x38,0x54, 265 0x54, 0x56, 0x5a, 0x71, 0x41, 0x79, 0x4a, 0x77, 0x65, 0x31, 0x39, 0x67, 0x43, 0x79, 0x6f, 0x4c, 0x61, 0x78, 0x42, 0x6b, 0x46, 0x41,
268 0x4c,0x6e,0x35,0x51,0x4b,0x32,0x64,0x47,0x63,0x6a,0x38,0x37,0x41,0x55,0x59,0x62, 266 0x55, 0x69, 0x41, 0x48, 0x4e, 0x41, 0x49, 0x31, 0x74, 0x52, 0x48, 0x79, 0x73, 0x61, 0x58, 0x57, 0x6c, 0x36, 0x52, 0x67, 0x78, 0x66,
269 0x43,0x7a,0x56,0x4a,0x4f,0x52,0x6c,0x77,0x50,0x51,0x4a,0x42,0x44,0x6a,0x67,0x46, 267 0x4d, 0x6b, 0x74, 0x4b, 0x4b, 0x46, 0x4a, 0x35, 0x57, 0x78, 0x4a, 0x43, 0x47, 0x41, 0x42, 0x64, 0x4a, 0x7a, 0x46, 0x54, 0x50, 0x45,
270 0x64,0x6d,0x56,0x50,0x4d,0x57,0x78,0x65,0x46,0x77,0x51,0x56,0x4e,0x69,0x5a,0x6b, 268 0x77, 0x32, 0x54, 0x6a, 0x67, 0x2f, 0x63, 0x67, 0x4e, 0x78, 0x41, 0x6c, 0x73, 0x32, 0x57, 0x58, 0x39, 0x31, 0x62, 0x67, 0x68, 0x55,
271 0x4e,0x42,0x51,0x58,0x66,0x41,0x34,0x4c,0x57,0x31,0x56,0x54,0x61,0x77,0x42,0x43, 269 0x44, 0x54, 0x51, 0x63, 0x4e, 0x46, 0x64, 0x64, 0x61, 0x55, 0x67, 0x41, 0x4f, 0x77, 0x55, 0x48, 0x62, 0x69, 0x64, 0x6c, 0x62, 0x6b,
272 0x51,0x55,0x38,0x43,0x58,0x42,0x4d,0x4b,0x4c,0x43,0x77,0x2b,0x45,0x42,0x51,0x7a, 270 0x41, 0x39, 0x4f, 0x6b, 0x39, 0x79, 0x58, 0x54, 0x6b, 0x57, 0x44, 0x32, 0x4d, 0x53, 0x45, 0x68, 0x55, 0x36, 0x63, 0x41, 0x31, 0x58,
273 0x52,0x58,0x78,0x36,0x57,0x6a,0x46,0x68,0x4f,0x51,0x67,0x69,0x61,0x68,0x34,0x50, 271 0x47, 0x41, 0x31, 0x65, 0x50, 0x53, 0x4a, 0x6f, 0x61, 0x48, 0x78, 0x74, 0x54, 0x77, 0x78, 0x37, 0x43, 0x53, 0x31, 0x4b, 0x63, 0x79,
274 0x62,0x78,0x74,0x73,0x45,0x31,0x35,0x35,0x49,0x48,0x6c,0x51,0x59,0x67,0x59,0x73, 272 0x42, 0x48, 0x42, 0x31, 0x64, 0x31, 0x58, 0x56, 0x4e, 0x77, 0x4e, 0x43, 0x46, 0x41, 0x56, 0x31, 0x46, 0x65, 0x53, 0x55, 0x51, 0x41,
275 0x64,0x68,0x63,0x45,0x4b,0x79,0x70,0x31,0x48,0x77,0x77,0x33,0x54,0x67,0x39,0x37, 273 0x56, 0x43, 0x63, 0x45, 0x61, 0x48, 0x35, 0x5a, 0x56, 0x6c, 0x68, 0x30, 0x46, 0x44, 0x77, 0x57, 0x4d, 0x30, 0x45, 0x57, 0x53, 0x79,
276 0x4c,0x54,0x52,0x31,0x59,0x44,0x46,0x30,0x4c,0x67,0x70,0x4b,0x45,0x57,0x78,0x4a, 274 0x39, 0x4a, 0x4e, 0x77, 0x70, 0x55, 0x43, 0x41, 0x67, 0x66, 0x4f, 0x57, 0x64, 0x32, 0x4b, 0x43, 0x67, 0x48, 0x48, 0x57, 0x46, 0x48,
277 0x4a,0x51,0x45,0x36,0x50,0x53,0x49,0x65,0x62,0x52,0x68,0x52,0x65,0x43,0x31,0x69, 275 0x55, 0x55, 0x31, 0x31, 0x4a, 0x6c, 0x4a, 0x48, 0x52, 0x77, 0x78, 0x58, 0x57, 0x48, 0x51, 0x2b, 0x59, 0x6d, 0x78, 0x59, 0x4f, 0x6b,
278 0x4d,0x55,0x78,0x51,0x51,0x42,0x64,0x4c,0x62,0x79,0x49,0x41,0x66,0x32,0x45,0x71, 276 0x51, 0x65, 0x46, 0x69, 0x34, 0x68, 0x48, 0x48, 0x4e, 0x46, 0x5a, 0x33, 0x52, 0x50, 0x4d, 0x32, 0x59, 0x4f, 0x64, 0x47, 0x59, 0x6d,
279 0x4e,0x44,0x34,0x41,0x58,0x79,0x39,0x66,0x4c,0x78,0x51,0x71,0x56,0x53,0x63,0x66, 277 0x48, 0x79, 0x34, 0x34, 0x52, 0x45, 0x42, 0x2b, 0x4b, 0x6c, 0x42, 0x53, 0x58, 0x6b, 0x4d, 0x42, 0x65, 0x6a, 0x68, 0x4a, 0x50, 0x46,
280 0x52,0x68,0x38,0x53,0x52,0x6c,0x34,0x65,0x44,0x48,0x77,0x34,0x41,0x57,0x46,0x6b, 278 0x56, 0x4e, 0x57, 0x6b, 0x51, 0x49, 0x4a, 0x6c, 0x6c, 0x4e, 0x52, 0x51, 0x74, 0x49, 0x43, 0x6a, 0x4e, 0x65, 0x53, 0x6b, 0x31, 0x31,
281 0x64,0x69,0x4a,0x75,0x43,0x43,0x41,0x34,0x54,0x33,0x4e,0x79,0x56,0x52,0x4a,0x43, 279 0x46, 0x68, 0x64, 0x6a, 0x52, 0x67, 0x45, 0x71, 0x56, 0x58, 0x73, 0x50, 0x41, 0x6e, 0x4e, 0x71, 0x53, 0x33, 0x39, 0x31, 0x5a, 0x54,
282 0x47,0x56,0x42,0x68,0x51,0x33,0x64,0x39,0x51,0x53,0x34,0x31,0x54,0x7a,0x30,0x78, 280 0x78, 0x4d, 0x4d, 0x7a, 0x6c, 0x73, 0x64, 0x41, 0x56, 0x67, 0x44, 0x33, 0x38, 0x74, 0x51, 0x55, 0x31, 0x4e, 0x52, 0x6e, 0x45, 0x4a,
283 0x4b,0x46,0x68,0x6e,0x47,0x77,0x4e,0x52,0x49,0x44,0x49,0x63,0x43,0x47,0x34,0x33, 281 0x62, 0x30, 0x39, 0x67, 0x46, 0x51, 0x39, 0x47, 0x63, 0x32, 0x4e, 0x4d, 0x58, 0x6e, 0x51, 0x77, 0x44, 0x53, 0x68, 0x44, 0x43, 0x48,
284 0x64,0x54,0x64,0x45,0x54,0x32,0x67,0x5a,0x42,0x32,0x51,0x55,0x4b,0x43,0x55,0x72, 282 0x49, 0x79, 0x42, 0x43, 0x34, 0x78, 0x4b, 0x53, 0x64, 0x45, 0x62, 0x52, 0x4d, 0x58, 0x53, 0x41, 0x39, 0x4a, 0x55, 0x68, 0x41, 0x54,
285 0x61,0x54,0x55,0x59,0x4a,0x79,0x59,0x55,0x45,0x33,0x42,0x43,0x47,0x52,0x4a,0x31, 283 0x66, 0x78, 0x63, 0x57, 0x59, 0x6e, 0x6b, 0x31, 0x65, 0x44, 0x34, 0x42, 0x66, 0x43, 0x34, 0x50, 0x64, 0x6a, 0x35, 0x65, 0x55, 0x32,
286 0x50,0x67,0x4a,0x64,0x66,0x42,0x4d,0x66,0x46,0x6c,0x4d,0x37,0x64,0x45,0x67,0x38, 284 0x78, 0x62, 0x58, 0x33, 0x77, 0x5a, 0x51, 0x51, 0x49, 0x76, 0x46, 0x32, 0x52, 0x42, 0x64, 0x52, 0x41, 0x45, 0x52, 0x33, 0x77, 0x39,
287 0x58,0x6a,0x6c,0x73,0x48,0x42,0x78,0x30,0x4f,0x52,0x38,0x41,0x47,0x77,0x59,0x4b, 285 0x53, 0x31, 0x49, 0x41, 0x45, 0x46, 0x31, 0x52, 0x54, 0x6e, 0x6f, 0x6e, 0x4a, 0x56, 0x56, 0x41, 0x45, 0x6a, 0x56, 0x67, 0x42, 0x52,
288 0x61,0x44,0x74,0x53,0x54,0x78,0x35,0x75,0x50,0x44,0x55,0x4d,0x4f,0x41,0x34,0x4c, 286 0x73, 0x30, 0x4c, 0x51, 0x52, 0x36, 0x61, 0x6d, 0x6b, 0x43, 0x65, 0x51, 0x4d, 0x36, 0x4c, 0x77, 0x59, 0x4b, 0x65, 0x58, 0x73, 0x53,
289 0x4f,0x78,0x70,0x32,0x49,0x79,0x6c,0x54,0x48,0x6c,0x39,0x42,0x44,0x45,0x73,0x4b, 287 0x58, 0x58, 0x78, 0x53, 0x4b, 0x55, 0x64, 0x59, 0x45, 0x6e, 0x4d, 0x2f, 0x4a, 0x31, 0x59, 0x46, 0x44, 0x45, 0x67, 0x79, 0x57, 0x47,
290 0x5a,0x53,0x68,0x34,0x5a,0x30,0x68,0x5a,0x4a,0x6d,0x30,0x78,0x64,0x69,0x4e,0x77, 288 0x74, 0x58, 0x58, 0x41, 0x4e, 0x6b, 0x56, 0x68, 0x46, 0x53, 0x65, 0x6a, 0x41, 0x32, 0x4b, 0x52, 0x63, 0x37, 0x61, 0x48, 0x70, 0x38,
291 0x59,0x57,0x51,0x37,0x4f,0x48,0x6c,0x6d,0x64,0x46,0x4d,0x73,0x5a,0x47,0x52,0x55, 289 0x42, 0x57, 0x74, 0x72, 0x45, 0x32, 0x6f, 0x6b, 0x58, 0x47, 0x68, 0x43, 0x47, 0x44, 0x49, 0x44, 0x63, 0x32, 0x34, 0x45, 0x49, 0x53,
292 0x41,0x31,0x52,0x6c,0x52,0x45,0x77,0x59,0x54,0x30,0x67,0x67,0x54,0x33,0x49,0x51, 290 0x34, 0x42, 0x42, 0x47, 0x4e, 0x39, 0x52, 0x45, 0x45, 0x53, 0x4d, 0x51, 0x73, 0x56, 0x48, 0x33, 0x41, 0x41, 0x4c, 0x6d, 0x59, 0x55,
293 0x50,0x77,0x78,0x53,0x4c,0x51,0x4d,0x55,0x41,0x31,0x46,0x43,0x45,0x48,0x64,0x71, 291 0x50, 0x48, 0x38, 0x72, 0x41, 0x42, 0x38, 0x4d, 0x4b, 0x46, 0x6b, 0x4b, 0x46, 0x6b, 0x6c, 0x61, 0x58, 0x47, 0x52, 0x6c, 0x53, 0x78,
294 0x4e,0x41,0x59,0x79,0x41,0x33,0x49,0x55,0x66,0x41,0x68,0x64,0x55,0x68,0x70,0x69, 292 0x45, 0x70, 0x46, 0x54, 0x5a, 0x61, 0x5a, 0x52, 0x6c, 0x50, 0x59, 0x43, 0x4d, 0x36, 0x4f, 0x68, 0x4d, 0x6c, 0x41, 0x6e, 0x68, 0x4d,
295 0x66,0x44,0x34,0x77,0x66,0x6c,0x39,0x2f,0x56,0x41,0x39,0x45,0x53,0x56,0x31,0x65, 293 0x56, 0x41, 0x3d, 0x3d, 0x00};
296 0x45,0x47,0x6f,0x47,0x4b,0x77,0x5a,0x54,0x45,0x44,0x6b,0x33,0x4d,0x6b,0x70,0x4f,
297 0x50,0x53,0x74,0x6c,0x4f,0x44,0x6b,0x48,0x63,0x6c,0x52,0x6b,0x54,0x56,0x5a,0x71,
298 0x41,0x79,0x4a,0x77,0x65,0x31,0x39,0x67,0x43,0x79,0x6f,0x4c,0x61,0x78,0x42,0x6b,
299 0x46,0x41,0x55,0x69,0x41,0x48,0x4e,0x41,0x49,0x31,0x74,0x52,0x48,0x79,0x73,0x61,
300 0x58,0x57,0x6c,0x36,0x52,0x67,0x78,0x66,0x4d,0x6b,0x74,0x4b,0x4b,0x46,0x4a,0x35,
301 0x57,0x78,0x4a,0x43,0x47,0x41,0x42,0x64,0x4a,0x7a,0x46,0x54,0x50,0x45,0x77,0x32,
302 0x54,0x6a,0x67,0x2f,0x63,0x67,0x4e,0x78,0x41,0x6c,0x73,0x32,0x57,0x58,0x39,0x31,
303 0x62,0x67,0x68,0x55,0x44,0x54,0x51,0x63,0x4e,0x46,0x64,0x64,0x61,0x55,0x67,0x41,
304 0x4f,0x77,0x55,0x48,0x62,0x69,0x64,0x6c,0x62,0x6b,0x41,0x39,0x4f,0x6b,0x39,0x79,
305 0x58,0x54,0x6b,0x57,0x44,0x32,0x4d,0x53,0x45,0x68,0x55,0x36,0x63,0x41,0x31,0x58,
306 0x47,0x41,0x31,0x65,0x50,0x53,0x4a,0x6f,0x61,0x48,0x78,0x74,0x54,0x77,0x78,0x37,
307 0x43,0x53,0x31,0x4b,0x63,0x79,0x42,0x48,0x42,0x31,0x64,0x31,0x58,0x56,0x4e,0x77,
308 0x4e,0x43,0x46,0x41,0x56,0x31,0x46,0x65,0x53,0x55,0x51,0x41,0x56,0x43,0x63,0x45,
309 0x61,0x48,0x35,0x5a,0x56,0x6c,0x68,0x30,0x46,0x44,0x77,0x57,0x4d,0x30,0x45,0x57,
310 0x53,0x79,0x39,0x4a,0x4e,0x77,0x70,0x55,0x43,0x41,0x67,0x66,0x4f,0x57,0x64,0x32,
311 0x4b,0x43,0x67,0x48,0x48,0x57,0x46,0x48,0x55,0x55,0x31,0x31,0x4a,0x6c,0x4a,0x48,
312 0x52,0x77,0x78,0x58,0x57,0x48,0x51,0x2b,0x59,0x6d,0x78,0x59,0x4f,0x6b,0x51,0x65,
313 0x46,0x69,0x34,0x68,0x48,0x48,0x4e,0x46,0x5a,0x33,0x52,0x50,0x4d,0x32,0x59,0x4f,
314 0x64,0x47,0x59,0x6d,0x48,0x79,0x34,0x34,0x52,0x45,0x42,0x2b,0x4b,0x6c,0x42,0x53,
315 0x58,0x6b,0x4d,0x42,0x65,0x6a,0x68,0x4a,0x50,0x46,0x56,0x4e,0x57,0x6b,0x51,0x49,
316 0x4a,0x6c,0x6c,0x4e,0x52,0x51,0x74,0x49,0x43,0x6a,0x4e,0x65,0x53,0x6b,0x31,0x31,
317 0x46,0x68,0x64,0x6a,0x52,0x67,0x45,0x71,0x56,0x58,0x73,0x50,0x41,0x6e,0x4e,0x71,
318 0x53,0x33,0x39,0x31,0x5a,0x54,0x78,0x4d,0x4d,0x7a,0x6c,0x73,0x64,0x41,0x56,0x67,
319 0x44,0x33,0x38,0x74,0x51,0x55,0x31,0x4e,0x52,0x6e,0x45,0x4a,0x62,0x30,0x39,0x67,
320 0x46,0x51,0x39,0x47,0x63,0x32,0x4e,0x4d,0x58,0x6e,0x51,0x77,0x44,0x53,0x68,0x44,
321 0x43,0x48,0x49,0x79,0x42,0x43,0x34,0x78,0x4b,0x53,0x64,0x45,0x62,0x52,0x4d,0x58,
322 0x53,0x41,0x39,0x4a,0x55,0x68,0x41,0x54,0x66,0x78,0x63,0x57,0x59,0x6e,0x6b,0x31,
323 0x65,0x44,0x34,0x42,0x66,0x43,0x34,0x50,0x64,0x6a,0x35,0x65,0x55,0x32,0x78,0x62,
324 0x58,0x33,0x77,0x5a,0x51,0x51,0x49,0x76,0x46,0x32,0x52,0x42,0x64,0x52,0x41,0x45,
325 0x52,0x33,0x77,0x39,0x53,0x31,0x49,0x41,0x45,0x46,0x31,0x52,0x54,0x6e,0x6f,0x6e,
326 0x4a,0x56,0x56,0x41,0x45,0x6a,0x56,0x67,0x42,0x52,0x73,0x30,0x4c,0x51,0x52,0x36,
327 0x61,0x6d,0x6b,0x43,0x65,0x51,0x4d,0x36,0x4c,0x77,0x59,0x4b,0x65,0x58,0x73,0x53,
328 0x58,0x58,0x78,0x53,0x4b,0x55,0x64,0x59,0x45,0x6e,0x4d,0x2f,0x4a,0x31,0x59,0x46,
329 0x44,0x45,0x67,0x79,0x57,0x47,0x74,0x58,0x58,0x41,0x4e,0x6b,0x56,0x68,0x46,0x53,
330 0x65,0x6a,0x41,0x32,0x4b,0x52,0x63,0x37,0x61,0x48,0x70,0x38,0x42,0x57,0x74,0x72,
331 0x45,0x32,0x6f,0x6b,0x58,0x47,0x68,0x43,0x47,0x44,0x49,0x44,0x63,0x32,0x34,0x45,
332 0x49,0x53,0x34,0x42,0x42,0x47,0x4e,0x39,0x52,0x45,0x45,0x53,0x4d,0x51,0x73,0x56,
333 0x48,0x33,0x41,0x41,0x4c,0x6d,0x59,0x55,0x50,0x48,0x38,0x72,0x41,0x42,0x38,0x4d,
334 0x4b,0x46,0x6b,0x4b,0x46,0x6b,0x6c,0x61,0x58,0x47,0x52,0x6c,0x53,0x78,0x45,0x70,
335 0x46,0x54,0x5a,0x61,0x5a,0x52,0x6c,0x50,0x59,0x43,0x4d,0x36,0x4f,0x68,0x4d,0x6c,
336 0x41,0x6e,0x68,0x4d,0x56,0x41,0x3d,0x3d,0x00
337 };
338 char *b64_test; 294 char *b64_test;
339 295
340 plan_tests(1); 296 plan_tests(1);
341 297
342 base64_encode_alloc (random, 1024, &b64_test); 298 base64_encode_alloc(random, 1024, &b64_test);
343 299
344 ok(strcmp(b64_known, b64_test) == 0, 300 ok(strcmp(b64_known, b64_test) == 0, "Test matching a base64 encoded 1024 bytes random string");
345 "Test matching a base64 encoded 1024 bytes random string");
346 301
347 return exit_status(); 302 return exit_status();
348} 303}
349
diff --git a/lib/tests/test_cmd.c b/lib/tests/test_cmd.c
index 02ae11f5..c8867dfb 100644
--- a/lib/tests/test_cmd.c
+++ b/lib/tests/test_cmd.c
@@ -1,20 +1,20 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16* 16 *
17*****************************************************************************/ 17 *****************************************************************************/
18 18
19#include "common.h" 19#include "common.h"
20#include "utils_cmd.h" 20#include "utils_cmd.h"
@@ -22,27 +22,23 @@
22#include "tap.h" 22#include "tap.h"
23 23
24#define COMMAND_LINE 1024 24#define COMMAND_LINE 1024
25#define UNSET 65530 25#define UNSET 65530
26 26
27char * 27char *get_command(char *const *line) {
28get_command (char *const *line)
29{
30 char *cmd; 28 char *cmd;
31 int i = 0; 29 int i = 0;
32 30
33 asprintf (&cmd, " %s", line[i++]); 31 asprintf(&cmd, " %s", line[i++]);
34 while (line[i] != NULL) { 32 while (line[i] != NULL) {
35 asprintf (&cmd, "%s %s", cmd, line[i]); 33 asprintf(&cmd, "%s %s", cmd, line[i]);
36 i++; 34 i++;
37 } 35 }
38 36
39 return cmd; 37 return cmd;
40} 38}
41 39
42int 40int main(int argc, char **argv) {
43main (int argc, char **argv) 41 char **command_line = malloc(sizeof(char *) * COMMAND_LINE);
44{
45 char **command_line = malloc (sizeof (char *) * COMMAND_LINE);
46 char *command = NULL; 42 char *command = NULL;
47 char *perl; 43 char *perl;
48 output chld_out, chld_err; 44 output chld_out, chld_err;
@@ -51,183 +47,154 @@ main (int argc, char **argv)
51 47
52 plan_tests(51); 48 plan_tests(51);
53 49
54 diag ("Running plain echo command, set one"); 50 diag("Running plain echo command, set one");
55 51
56 /* ensure everything is empty before we begin */ 52 /* ensure everything is empty before we begin */
57 memset (&chld_out, 0, sizeof (output)); 53 memset(&chld_out, 0, sizeof(output));
58 memset (&chld_err, 0, sizeof (output)); 54 memset(&chld_err, 0, sizeof(output));
59 ok (chld_out.lines == 0, "(initialised) Checking stdout is reset"); 55 ok(chld_out.lines == 0, "(initialised) Checking stdout is reset");
60 ok (chld_err.lines == 0, "(initialised) Checking stderr is reset"); 56 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset");
61 ok (result == UNSET, "(initialised) Checking exit code is reset"); 57 ok(result == UNSET, "(initialised) Checking exit code is reset");
62 58
63 command_line[0] = strdup ("/bin/echo"); 59 command_line[0] = strdup("/bin/echo");
64 command_line[1] = strdup ("this"); 60 command_line[1] = strdup("this");
65 command_line[2] = strdup ("is"); 61 command_line[2] = strdup("is");
66 command_line[3] = strdup ("test"); 62 command_line[3] = strdup("test");
67 command_line[4] = strdup ("one"); 63 command_line[4] = strdup("one");
68 64
69 command = get_command (command_line); 65 command = get_command(command_line);
70 66
71 result = cmd_run_array (command_line, &chld_out, &chld_err, 0); 67 result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
72 ok (chld_out.lines == 1, 68 ok(chld_out.lines == 1, "(array) Check for expected number of stdout lines");
73 "(array) Check for expected number of stdout lines"); 69 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines");
74 ok (chld_err.lines == 0, 70 ok(strcmp(chld_out.line[0], "this is test one") == 0, "(array) Check for expected stdout output");
75 "(array) Check for expected number of stderr lines"); 71 ok(result == 0, "(array) Checking exit code");
76 ok (strcmp (chld_out.line[0], "this is test one") == 0,
77 "(array) Check for expected stdout output");
78 ok (result == 0, "(array) Checking exit code");
79 72
80 /* ensure everything is empty again */ 73 /* ensure everything is empty again */
81 memset (&chld_out, 0, sizeof (output)); 74 memset(&chld_out, 0, sizeof(output));
82 memset (&chld_err, 0, sizeof (output)); 75 memset(&chld_err, 0, sizeof(output));
83 result = UNSET; 76 result = UNSET;
84 ok (chld_out.lines == 0, "(initialised) Checking stdout is reset"); 77 ok(chld_out.lines == 0, "(initialised) Checking stdout is reset");
85 ok (chld_err.lines == 0, "(initialised) Checking stderr is reset"); 78 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset");
86 ok (result == UNSET, "(initialised) Checking exit code is reset"); 79 ok(result == UNSET, "(initialised) Checking exit code is reset");
87 80
88 result = cmd_run (command, &chld_out, &chld_err, 0); 81 result = cmd_run(command, &chld_out, &chld_err, 0);
89 82
90 ok (chld_out.lines == 1, 83 ok(chld_out.lines == 1, "(string) Check for expected number of stdout lines");
91 "(string) Check for expected number of stdout lines"); 84 ok(chld_err.lines == 0, "(string) Check for expected number of stderr lines");
92 ok (chld_err.lines == 0, 85 ok(strcmp(chld_out.line[0], "this is test one") == 0, "(string) Check for expected stdout output");
93 "(string) Check for expected number of stderr lines"); 86 ok(result == 0, "(string) Checking exit code");
94 ok (strcmp (chld_out.line[0], "this is test one") == 0,
95 "(string) Check for expected stdout output");
96 ok (result == 0, "(string) Checking exit code");
97 87
98 diag ("Running plain echo command, set two"); 88 diag("Running plain echo command, set two");
99 89
100 /* ensure everything is empty again */ 90 /* ensure everything is empty again */
101 memset (&chld_out, 0, sizeof (output)); 91 memset(&chld_out, 0, sizeof(output));
102 memset (&chld_err, 0, sizeof (output)); 92 memset(&chld_err, 0, sizeof(output));
103 result = UNSET; 93 result = UNSET;
104 ok (chld_out.lines == 0, "(initialised) Checking stdout is reset"); 94 ok(chld_out.lines == 0, "(initialised) Checking stdout is reset");
105 ok (chld_err.lines == 0, "(initialised) Checking stderr is reset"); 95 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset");
106 ok (result == UNSET, "(initialised) Checking exit code is reset"); 96 ok(result == UNSET, "(initialised) Checking exit code is reset");
107 97
108 command_line[0] = strdup ("/bin/echo"); 98 command_line[0] = strdup("/bin/echo");
109 command_line[1] = strdup ("this is test two"); 99 command_line[1] = strdup("this is test two");
110 command_line[2] = NULL; 100 command_line[2] = NULL;
111 command_line[3] = NULL; 101 command_line[3] = NULL;
112 command_line[4] = NULL; 102 command_line[4] = NULL;
113 103
114 result = cmd_run_array (command_line, &chld_out, &chld_err, 0); 104 result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
115 ok (chld_out.lines == 1, 105 ok(chld_out.lines == 1, "(array) Check for expected number of stdout lines");
116 "(array) Check for expected number of stdout lines"); 106 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines");
117 ok (chld_err.lines == 0, 107 ok(strcmp(chld_out.line[0], "this is test two") == 0, "(array) Check for expected stdout output");
118 "(array) Check for expected number of stderr lines"); 108 ok(result == 0, "(array) Checking exit code");
119 ok (strcmp (chld_out.line[0], "this is test two") == 0,
120 "(array) Check for expected stdout output");
121 ok (result == 0, "(array) Checking exit code");
122 109
123 /* ensure everything is empty again */ 110 /* ensure everything is empty again */
124 memset (&chld_out, 0, sizeof (output)); 111 memset(&chld_out, 0, sizeof(output));
125 memset (&chld_err, 0, sizeof (output)); 112 memset(&chld_err, 0, sizeof(output));
126 result = UNSET; 113 result = UNSET;
127 ok (chld_out.lines == 0, "(initialised) Checking stdout is reset"); 114 ok(chld_out.lines == 0, "(initialised) Checking stdout is reset");
128 ok (chld_err.lines == 0, "(initialised) Checking stderr is reset"); 115 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset");
129 ok (result == UNSET, "(initialised) Checking exit code is reset"); 116 ok(result == UNSET, "(initialised) Checking exit code is reset");
130
131 result = cmd_run (command, &chld_out, &chld_err, 0);
132 117
133 ok (chld_out.lines == 1, 118 result = cmd_run(command, &chld_out, &chld_err, 0);
134 "(string) Check for expected number of stdout lines");
135 ok (chld_err.lines == 0,
136 "(string) Check for expected number of stderr lines");
137 ok (strcmp (chld_out.line[0], "this is test one") == 0,
138 "(string) Check for expected stdout output");
139 ok (result == 0, "(string) Checking exit code");
140 119
120 ok(chld_out.lines == 1, "(string) Check for expected number of stdout lines");
121 ok(chld_err.lines == 0, "(string) Check for expected number of stderr lines");
122 ok(strcmp(chld_out.line[0], "this is test one") == 0, "(string) Check for expected stdout output");
123 ok(result == 0, "(string) Checking exit code");
141 124
142 /* ensure everything is empty again */ 125 /* ensure everything is empty again */
143 memset (&chld_out, 0, sizeof (output)); 126 memset(&chld_out, 0, sizeof(output));
144 memset (&chld_err, 0, sizeof (output)); 127 memset(&chld_err, 0, sizeof(output));
145 result = UNSET; 128 result = UNSET;
146 ok (chld_out.lines == 0, "(initialised) Checking stdout is reset"); 129 ok(chld_out.lines == 0, "(initialised) Checking stdout is reset");
147 ok (chld_err.lines == 0, "(initialised) Checking stderr is reset"); 130 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset");
148 ok (result == UNSET, "(initialised) Checking exit code is reset"); 131 ok(result == UNSET, "(initialised) Checking exit code is reset");
149 132
150 /* Pass linefeeds via parameters through - those should be evaluated by echo to give multi line output */ 133 /* Pass linefeeds via parameters through - those should be evaluated by echo to give multi line output */
151 command_line[0] = strdup("/bin/echo"); 134 command_line[0] = strdup("/bin/echo");
152 command_line[1] = strdup("this is a test via echo\nline two\nit's line 3"); 135 command_line[1] = strdup("this is a test via echo\nline two\nit's line 3");
153 command_line[2] = strdup("and (note space between '3' and 'and') $$ will not get evaluated"); 136 command_line[2] = strdup("and (note space between '3' and 'and') $$ will not get evaluated");
154 137
155 result = cmd_run_array (command_line, &chld_out, &chld_err, 0); 138 result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
156 ok (chld_out.lines == 3, 139 ok(chld_out.lines == 3, "(array) Check for expected number of stdout lines");
157 "(array) Check for expected number of stdout lines"); 140 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines");
158 ok (chld_err.lines == 0, 141 ok(strcmp(chld_out.line[0], "this is a test via echo") == 0, "(array) Check line 1 for expected stdout output");
159 "(array) Check for expected number of stderr lines"); 142 ok(strcmp(chld_out.line[1], "line two") == 0, "(array) Check line 2 for expected stdout output");
160 ok (strcmp (chld_out.line[0], "this is a test via echo") == 0, 143 ok(strcmp(chld_out.line[2], "it's line 3 and (note space between '3' and 'and') $$ will not get evaluated") == 0,
161 "(array) Check line 1 for expected stdout output"); 144 "(array) Check line 3 for expected stdout output");
162 ok (strcmp (chld_out.line[1], "line two") == 0, 145 ok(result == 0, "(array) Checking exit code");
163 "(array) Check line 2 for expected stdout output");
164 ok (strcmp (chld_out.line[2], "it's line 3 and (note space between '3' and 'and') $$ will not get evaluated") == 0,
165 "(array) Check line 3 for expected stdout output");
166 ok (result == 0, "(array) Checking exit code");
167
168
169 146
170 /* ensure everything is empty again */ 147 /* ensure everything is empty again */
171 memset (&chld_out, 0, sizeof (output)); 148 memset(&chld_out, 0, sizeof(output));
172 memset (&chld_err, 0, sizeof (output)); 149 memset(&chld_err, 0, sizeof(output));
173 result = UNSET; 150 result = UNSET;
174 ok (chld_out.lines == 0, "(initialised) Checking stdout is reset"); 151 ok(chld_out.lines == 0, "(initialised) Checking stdout is reset");
175 ok (chld_err.lines == 0, "(initialised) Checking stderr is reset"); 152 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset");
176 ok (result == UNSET, "(initialised) Checking exit code is reset"); 153 ok(result == UNSET, "(initialised) Checking exit code is reset");
177 154
178 command = (char *)malloc(COMMAND_LINE); 155 command = (char *)malloc(COMMAND_LINE);
179 strcpy(command, "/bin/echo3456 non-existent command"); 156 strcpy(command, "/bin/echo3456 non-existent command");
180 result = cmd_run (command, &chld_out, &chld_err, 0); 157 result = cmd_run(command, &chld_out, &chld_err, 0);
181
182 ok (chld_out.lines == 0,
183 "Non existent command, so no output");
184 ok (chld_err.lines == 0,
185 "No stderr either");
186 ok (result == 3, "Get return code 3 (?) for non-existent command");
187 158
159 ok(chld_out.lines == 0, "Non existent command, so no output");
160 ok(chld_err.lines == 0, "No stderr either");
161 ok(result == 3, "Get return code 3 (?) for non-existent command");
188 162
189 /* ensure everything is empty again */ 163 /* ensure everything is empty again */
190 memset (&chld_out, 0, sizeof (output)); 164 memset(&chld_out, 0, sizeof(output));
191 memset (&chld_err, 0, sizeof (output)); 165 memset(&chld_err, 0, sizeof(output));
192 result = UNSET; 166 result = UNSET;
193 167
194 command = (char *)malloc(COMMAND_LINE); 168 command = (char *)malloc(COMMAND_LINE);
195 strcpy(command, "/bin/sh non-existent-file"); 169 strcpy(command, "/bin/sh non-existent-file");
196 result = cmd_run (command, &chld_out, &chld_err, 0); 170 result = cmd_run(command, &chld_out, &chld_err, 0);
197
198 ok (chld_out.lines == 0,
199 "/bin/sh returns no stdout when file is missing...");
200 ok (chld_err.lines == 1,
201 "...but does give an error line");
202 ok (strstr(chld_err.line[0],"non-existent-file") != NULL, "And missing filename is in error message");
203 ok (result != 0, "Get non-zero return code from /bin/sh");
204 171
172 ok(chld_out.lines == 0, "/bin/sh returns no stdout when file is missing...");
173 ok(chld_err.lines == 1, "...but does give an error line");
174 ok(strstr(chld_err.line[0], "non-existent-file") != NULL, "And missing filename is in error message");
175 ok(result != 0, "Get non-zero return code from /bin/sh");
205 176
206 /* ensure everything is empty again */ 177 /* ensure everything is empty again */
207 result = UNSET; 178 result = UNSET;
208 179
209 command = (char *)malloc(COMMAND_LINE); 180 command = (char *)malloc(COMMAND_LINE);
210 strcpy(command, "/bin/sh -c 'exit 7'"); 181 strcpy(command, "/bin/sh -c 'exit 7'");
211 result = cmd_run (command, NULL, NULL, 0); 182 result = cmd_run(command, NULL, NULL, 0);
212
213 ok (result == 7, "Get return code 7 from /bin/sh");
214 183
184 ok(result == 7, "Get return code 7 from /bin/sh");
215 185
216 /* ensure everything is empty again */ 186 /* ensure everything is empty again */
217 memset (&chld_out, 0, sizeof (output)); 187 memset(&chld_out, 0, sizeof(output));
218 memset (&chld_err, 0, sizeof (output)); 188 memset(&chld_err, 0, sizeof(output));
219 result = UNSET; 189 result = UNSET;
220 190
221 command = (char *)malloc(COMMAND_LINE); 191 command = (char *)malloc(COMMAND_LINE);
222 strcpy(command, "/bin/non-existent-command"); 192 strcpy(command, "/bin/non-existent-command");
223 result = cmd_run (command, &chld_out, &chld_err, 0); 193 result = cmd_run(command, &chld_out, &chld_err, 0);
224
225 ok (chld_out.lines == 0,
226 "/bin/non-existent-command returns no stdout...");
227 ok (chld_err.lines == 0,
228 "...and no stderr output either");
229 ok (result == 3, "Get return code 3 = UNKNOWN when command does not exist");
230 194
195 ok(chld_out.lines == 0, "/bin/non-existent-command returns no stdout...");
196 ok(chld_err.lines == 0, "...and no stderr output either");
197 ok(result == 3, "Get return code 3 = UNKNOWN when command does not exist");
231 198
232 return exit_status (); 199 return exit_status();
233} 200}
diff --git a/lib/tests/test_disk.c b/lib/tests/test_disk.c
index e283fe2e..c18db7a4 100644
--- a/lib/tests/test_disk.c
+++ b/lib/tests/test_disk.c
@@ -1,36 +1,31 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16* 16 *
17*****************************************************************************/ 17 *****************************************************************************/
18 18
19#include "common.h" 19#include "common.h"
20#include "utils_disk.h" 20#include "utils_disk.h"
21#include "tap.h" 21#include "tap.h"
22#include "regex.h" 22#include "regex.h"
23 23
24void np_test_mount_entry_regex (struct mount_entry *dummy_mount_list, 24void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc);
25 char *regstr, int cflags, int expect,
26 char *desc);
27 25
28 26int main(int argc, char **argv) {
29int 27 struct name_list *exclude_filesystem = NULL;
30main (int argc, char **argv) 28 struct name_list *exclude_fstype = NULL;
31{
32 struct name_list *exclude_filesystem=NULL;
33 struct name_list *exclude_fstype=NULL;
34 struct name_list *dummy_mountlist = NULL; 29 struct name_list *dummy_mountlist = NULL;
35 struct name_list *temp_name; 30 struct name_list *temp_name;
36 struct parameter_list *paths = NULL; 31 struct parameter_list *paths = NULL;
@@ -44,19 +39,19 @@ main (int argc, char **argv)
44 39
45 plan_tests(33); 40 plan_tests(33);
46 41
47 ok( np_find_name(exclude_filesystem, "/var/log") == false, "/var/log not in list"); 42 ok(np_find_name(exclude_filesystem, "/var/log") == false, "/var/log not in list");
48 np_add_name(&exclude_filesystem, "/var/log"); 43 np_add_name(&exclude_filesystem, "/var/log");
49 ok( np_find_name(exclude_filesystem, "/var/log") == true, "is in list now"); 44 ok(np_find_name(exclude_filesystem, "/var/log") == true, "is in list now");
50 ok( np_find_name(exclude_filesystem, "/home") == false, "/home not in list"); 45 ok(np_find_name(exclude_filesystem, "/home") == false, "/home not in list");
51 np_add_name(&exclude_filesystem, "/home"); 46 np_add_name(&exclude_filesystem, "/home");
52 ok( np_find_name(exclude_filesystem, "/home") == true, "is in list now"); 47 ok(np_find_name(exclude_filesystem, "/home") == true, "is in list now");
53 ok( np_find_name(exclude_filesystem, "/var/log") == true, "/var/log still in list"); 48 ok(np_find_name(exclude_filesystem, "/var/log") == true, "/var/log still in list");
54 49
55 ok( np_find_name(exclude_fstype, "iso9660") == false, "iso9660 not in list"); 50 ok(np_find_name(exclude_fstype, "iso9660") == false, "iso9660 not in list");
56 np_add_name(&exclude_fstype, "iso9660"); 51 np_add_name(&exclude_fstype, "iso9660");
57 ok( np_find_name(exclude_fstype, "iso9660") == true, "is in list now"); 52 ok(np_find_name(exclude_fstype, "iso9660") == true, "is in list now");
58 53
59 ok( np_find_name(exclude_filesystem, "iso9660") == false, "Make sure no clashing in variables"); 54 ok(np_find_name(exclude_filesystem, "iso9660") == false, "Make sure no clashing in variables");
60 55
61 /* 56 /*
62 for (temp_name = exclude_filesystem; temp_name; temp_name = temp_name->next) { 57 for (temp_name = exclude_filesystem; temp_name; temp_name = temp_name->next) {
@@ -64,55 +59,35 @@ main (int argc, char **argv)
64 } 59 }
65 */ 60 */
66 61
67 me = (struct mount_entry *) malloc(sizeof *me); 62 me = (struct mount_entry *)malloc(sizeof *me);
68 me->me_devname = strdup("/dev/c0t0d0s0"); 63 me->me_devname = strdup("/dev/c0t0d0s0");
69 me->me_mountdir = strdup("/"); 64 me->me_mountdir = strdup("/");
70 *mtail = me; 65 *mtail = me;
71 mtail = &me->me_next; 66 mtail = &me->me_next;
72 67
73 me = (struct mount_entry *) malloc(sizeof *me); 68 me = (struct mount_entry *)malloc(sizeof *me);
74 me->me_devname = strdup("/dev/c1t0d1s0"); 69 me->me_devname = strdup("/dev/c1t0d1s0");
75 me->me_mountdir = strdup("/var"); 70 me->me_mountdir = strdup("/var");
76 *mtail = me; 71 *mtail = me;
77 mtail = &me->me_next; 72 mtail = &me->me_next;
78 73
79 me = (struct mount_entry *) malloc(sizeof *me); 74 me = (struct mount_entry *)malloc(sizeof *me);
80 me->me_devname = strdup("/dev/c2t0d0s0"); 75 me->me_devname = strdup("/dev/c2t0d0s0");
81 me->me_mountdir = strdup("/home"); 76 me->me_mountdir = strdup("/home");
82 *mtail = me; 77 *mtail = me;
83 mtail = &me->me_next; 78 mtail = &me->me_next;
84 79
85 np_test_mount_entry_regex(dummy_mount_list, strdup("/"), 80 np_test_mount_entry_regex(dummy_mount_list, strdup("/"), cflags, 3, strdup("a"));
86 cflags, 3, strdup("a")); 81 np_test_mount_entry_regex(dummy_mount_list, strdup("/dev"), cflags, 3, strdup("regex on dev names:"));
87 np_test_mount_entry_regex(dummy_mount_list, strdup("/dev"), 82 np_test_mount_entry_regex(dummy_mount_list, strdup("/foo"), cflags, 0, strdup("regex on non existent dev/path:"));
88 cflags, 3,strdup("regex on dev names:")); 83 np_test_mount_entry_regex(dummy_mount_list, strdup("/Foo"), cflags | REG_ICASE, 0, strdup("regi on non existent dev/path:"));
89 np_test_mount_entry_regex(dummy_mount_list, strdup("/foo"), 84 np_test_mount_entry_regex(dummy_mount_list, strdup("/c.t0"), cflags, 3, strdup("partial devname regex match:"));
90 cflags, 0, 85 np_test_mount_entry_regex(dummy_mount_list, strdup("c0t0"), cflags, 1, strdup("partial devname regex match:"));
91 strdup("regex on non existent dev/path:")); 86 np_test_mount_entry_regex(dummy_mount_list, strdup("C0t0"), cflags | REG_ICASE, 1, strdup("partial devname regi match:"));
92 np_test_mount_entry_regex(dummy_mount_list, strdup("/Foo"), 87 np_test_mount_entry_regex(dummy_mount_list, strdup("home"), cflags, 1, strdup("partial pathname regex match:"));
93 cflags | REG_ICASE,0, 88 np_test_mount_entry_regex(dummy_mount_list, strdup("hOme"), cflags | REG_ICASE, 1, strdup("partial pathname regi match:"));
94 strdup("regi on non existent dev/path:")); 89 np_test_mount_entry_regex(dummy_mount_list, strdup("(/home)|(/var)"), cflags, 2, strdup("grouped regex pathname match:"));
95 np_test_mount_entry_regex(dummy_mount_list, strdup("/c.t0"), 90 np_test_mount_entry_regex(dummy_mount_list, strdup("(/homE)|(/Var)"), cflags | REG_ICASE, 2, strdup("grouped regi pathname match:"));
96 cflags, 3,
97 strdup("partial devname regex match:"));
98 np_test_mount_entry_regex(dummy_mount_list, strdup("c0t0"),
99 cflags, 1,
100 strdup("partial devname regex match:"));
101 np_test_mount_entry_regex(dummy_mount_list, strdup("C0t0"),
102 cflags | REG_ICASE, 1,
103 strdup("partial devname regi match:"));
104 np_test_mount_entry_regex(dummy_mount_list, strdup("home"),
105 cflags, 1,
106 strdup("partial pathname regex match:"));
107 np_test_mount_entry_regex(dummy_mount_list, strdup("hOme"),
108 cflags | REG_ICASE, 1,
109 strdup("partial pathname regi match:"));
110 np_test_mount_entry_regex(dummy_mount_list, strdup("(/home)|(/var)"),
111 cflags, 2,
112 strdup("grouped regex pathname match:"));
113 np_test_mount_entry_regex(dummy_mount_list, strdup("(/homE)|(/Var)"),
114 cflags | REG_ICASE, 2,
115 strdup("grouped regi pathname match:"));
116 91
117 np_add_parameter(&paths, "/home/groups"); 92 np_add_parameter(&paths, "/home/groups");
118 np_add_parameter(&paths, "/var"); 93 np_add_parameter(&paths, "/var");
@@ -124,20 +99,20 @@ main (int argc, char **argv)
124 for (p = paths; p; p = p->name_next) { 99 for (p = paths; p; p = p->name_next) {
125 struct mount_entry *temp_me; 100 struct mount_entry *temp_me;
126 temp_me = p->best_match; 101 temp_me = p->best_match;
127 if (! strcmp(p->name, "/home/groups")) { 102 if (!strcmp(p->name, "/home/groups")) {
128 ok( temp_me && !strcmp(temp_me->me_mountdir, "/home"), "/home/groups got right best match: /home"); 103 ok(temp_me && !strcmp(temp_me->me_mountdir, "/home"), "/home/groups got right best match: /home");
129 } else if (! strcmp(p->name, "/var")) { 104 } else if (!strcmp(p->name, "/var")) {
130 ok( temp_me && !strcmp(temp_me->me_mountdir, "/var"), "/var got right best match: /var"); 105 ok(temp_me && !strcmp(temp_me->me_mountdir, "/var"), "/var got right best match: /var");
131 } else if (! strcmp(p->name, "/tmp")) { 106 } else if (!strcmp(p->name, "/tmp")) {
132 ok( temp_me && !strcmp(temp_me->me_mountdir, "/"), "/tmp got right best match: /"); 107 ok(temp_me && !strcmp(temp_me->me_mountdir, "/"), "/tmp got right best match: /");
133 } else if (! strcmp(p->name, "/home/tonvoon")) { 108 } else if (!strcmp(p->name, "/home/tonvoon")) {
134 ok( temp_me && !strcmp(temp_me->me_mountdir, "/home"), "/home/tonvoon got right best match: /home"); 109 ok(temp_me && !strcmp(temp_me->me_mountdir, "/home"), "/home/tonvoon got right best match: /home");
135 } else if (! strcmp(p->name, "/dev/c2t0d0s0")) { 110 } else if (!strcmp(p->name, "/dev/c2t0d0s0")) {
136 ok( temp_me && !strcmp(temp_me->me_devname, "/dev/c2t0d0s0"), "/dev/c2t0d0s0 got right best match: /dev/c2t0d0s0"); 111 ok(temp_me && !strcmp(temp_me->me_devname, "/dev/c2t0d0s0"), "/dev/c2t0d0s0 got right best match: /dev/c2t0d0s0");
137 } 112 }
138 } 113 }
139 114
140 paths = NULL; /* Bad boy - should free, but this is a test suite */ 115 paths = NULL; /* Bad boy - should free, but this is a test suite */
141 np_add_parameter(&paths, "/home/groups"); 116 np_add_parameter(&paths, "/home/groups");
142 np_add_parameter(&paths, "/var"); 117 np_add_parameter(&paths, "/var");
143 np_add_parameter(&paths, "/tmp"); 118 np_add_parameter(&paths, "/tmp");
@@ -146,31 +121,31 @@ main (int argc, char **argv)
146 121
147 np_set_best_match(paths, dummy_mount_list, true); 122 np_set_best_match(paths, dummy_mount_list, true);
148 for (p = paths; p; p = p->name_next) { 123 for (p = paths; p; p = p->name_next) {
149 if (! strcmp(p->name, "/home/groups")) { 124 if (!strcmp(p->name, "/home/groups")) {
150 ok( ! p->best_match , "/home/groups correctly not found"); 125 ok(!p->best_match, "/home/groups correctly not found");
151 } else if (! strcmp(p->name, "/var")) { 126 } else if (!strcmp(p->name, "/var")) {
152 ok( p->best_match, "/var found"); 127 ok(p->best_match, "/var found");
153 } else if (! strcmp(p->name, "/tmp")) { 128 } else if (!strcmp(p->name, "/tmp")) {
154 ok(! p->best_match, "/tmp correctly not found"); 129 ok(!p->best_match, "/tmp correctly not found");
155 } else if (! strcmp(p->name, "/home/tonvoon")) { 130 } else if (!strcmp(p->name, "/home/tonvoon")) {
156 ok(! p->best_match, "/home/tonvoon not found"); 131 ok(!p->best_match, "/home/tonvoon not found");
157 } else if (! strcmp(p->name, "/home")) { 132 } else if (!strcmp(p->name, "/home")) {
158 ok( p->best_match, "/home found"); 133 ok(p->best_match, "/home found");
159 } 134 }
160 } 135 }
161 136
162 /* test deleting first element in paths */ 137 /* test deleting first element in paths */
163 paths = np_del_parameter(paths, NULL); 138 paths = np_del_parameter(paths, NULL);
164 for (p = paths; p; p = p->name_next) { 139 for (p = paths; p; p = p->name_next) {
165 if (! strcmp(p->name, "/home/groups")) 140 if (!strcmp(p->name, "/home/groups"))
166 found = 1; 141 found = 1;
167 } 142 }
168 ok(found == 0, "first element successfully deleted"); 143 ok(found == 0, "first element successfully deleted");
169 found = 0; 144 found = 0;
170 145
171 p=paths; 146 p = paths;
172 while (p) { 147 while (p) {
173 if (! strcmp(p->name, "/tmp")) 148 if (!strcmp(p->name, "/tmp"))
174 p = np_del_parameter(p, prev); 149 p = np_del_parameter(p, prev);
175 else { 150 else {
176 prev = p; 151 prev = p;
@@ -179,7 +154,7 @@ main (int argc, char **argv)
179 } 154 }
180 155
181 for (p = paths; p; p = p->name_next) { 156 for (p = paths; p; p = p->name_next) {
182 if (! strcmp(p->name, "/tmp")) 157 if (!strcmp(p->name, "/tmp"))
183 found = 1; 158 found = 1;
184 if (p->name_next) 159 if (p->name_next)
185 prev = p; 160 prev = p;
@@ -190,7 +165,7 @@ main (int argc, char **argv)
190 165
191 p = np_del_parameter(last, prev); 166 p = np_del_parameter(last, prev);
192 for (p = paths; p; p = p->name_next) { 167 for (p = paths; p; p = p->name_next) {
193 if (! strcmp(p->name, "/home")) 168 if (!strcmp(p->name, "/home"))
194 found = 1; 169 found = 1;
195 last = p; 170 last = p;
196 count++; 171 count++;
@@ -198,27 +173,20 @@ main (int argc, char **argv)
198 ok(found == 0, "last (/home) element successfully deleted"); 173 ok(found == 0, "last (/home) element successfully deleted");
199 ok(count == 2, "two elements remaining"); 174 ok(count == 2, "two elements remaining");
200 175
201
202 return exit_status(); 176 return exit_status();
203} 177}
204 178
205 179void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc) {
206void
207np_test_mount_entry_regex (struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc)
208{
209 int matches = 0; 180 int matches = 0;
210 regex_t re; 181 regex_t re;
211 struct mount_entry *me; 182 struct mount_entry *me;
212 if (regcomp(&re,regstr, cflags) == 0) { 183 if (regcomp(&re, regstr, cflags) == 0) {
213 for (me = dummy_mount_list; me; me= me->me_next) { 184 for (me = dummy_mount_list; me; me = me->me_next) {
214 if(np_regex_match_mount_entry(me,&re)) 185 if (np_regex_match_mount_entry(me, &re))
215 matches++; 186 matches++;
216 } 187 }
217 ok( matches == expect, 188 ok(matches == expect, "%s '%s' matched %i/3 entries. ok: %i/3", desc, regstr, expect, matches);
218 "%s '%s' matched %i/3 entries. ok: %i/3",
219 desc, regstr, expect, matches);
220 189
221 } else 190 } else
222 ok ( false, "regex '%s' not compilable", regstr); 191 ok(false, "regex '%s' not compilable", regstr);
223} 192}
224
diff --git a/lib/tests/test_generic_output b/lib/tests/test_generic_output
new file mode 100755
index 00000000..51e299a0
--- /dev/null
+++ b/lib/tests/test_generic_output
Binary files differ
diff --git a/lib/tests/test_ini1.c b/lib/tests/test_ini1.c
index 6843bac2..246c1250 100644
--- a/lib/tests/test_ini1.c
+++ b/lib/tests/test_ini1.c
@@ -1,20 +1,20 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16* 16 *
17*****************************************************************************/ 17 *****************************************************************************/
18 18
19#include "common.h" 19#include "common.h"
20#include "utils_base.h" 20#include "utils_base.h"
@@ -29,81 +29,93 @@ void my_free(char *string) {
29 } 29 }
30} 30}
31 31
32char* 32char *list2str(np_arg_list *optlst) {
33list2str(np_arg_list *optlst) 33 char *optstr = NULL;
34{
35 char *optstr=NULL;
36 np_arg_list *optltmp; 34 np_arg_list *optltmp;
37 35
38 /* Put everything as a space-separated string */ 36 /* Put everything as a space-separated string */
39 asprintf(&optstr, ""); 37 asprintf(&optstr, "");
40 while (optlst) { 38 while (optlst) {
41 asprintf(&optstr, "%s%s ", optstr, optlst->arg); 39 asprintf(&optstr, "%s%s ", optstr, optlst->arg);
42 optltmp=optlst; 40 optltmp = optlst;
43 optlst=optlst->next; 41 optlst = optlst->next;
44 free(optltmp); 42 free(optltmp);
45 } 43 }
46 /* Strip last whitespace */ 44 /* Strip last whitespace */
47 if (strlen(optstr)>1) optstr[strlen(optstr)-1]='\0'; 45 if (strlen(optstr) > 1)
46 optstr[strlen(optstr) - 1] = '\0';
48 47
49 return optstr; 48 return optstr;
50} 49}
51 50
52int 51int main(int argc, char **argv) {
53main (int argc, char **argv) 52 char *optstr = NULL;
54{
55 char *optstr=NULL;
56 53
57 plan_tests(12); 54 plan_tests(12);
58 55
59 optstr=list2str(np_get_defaults("section@./config-tiny.ini", "check_disk")); 56 optstr = list2str(np_get_defaults("section@./config-tiny.ini", "check_disk"));
60 ok( !strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), "config-tiny.ini's section as expected"); 57 ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), "config-tiny.ini's section as expected");
61 my_free(optstr); 58 my_free(optstr);
62 59
63 optstr=list2str(np_get_defaults("@./config-tiny.ini", "section")); 60 optstr = list2str(np_get_defaults("@./config-tiny.ini", "section"));
64 ok( !strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), "Used default section name, without specific"); 61 ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), "Used default section name, without specific");
65 my_free(optstr); 62 my_free(optstr);
66 63
67 optstr=list2str(np_get_defaults("Section Two@./config-tiny.ini", "check_disk")); 64 optstr = list2str(np_get_defaults("Section Two@./config-tiny.ini", "check_disk"));
68 ok( !strcmp(optstr, "--something else=blah --remove=whitespace"), "config-tiny.ini's Section Two as expected"); 65 ok(!strcmp(optstr, "--something else=blah --remove=whitespace"), "config-tiny.ini's Section Two as expected");
69 my_free(optstr); 66 my_free(optstr);
70 67
71 optstr=list2str(np_get_defaults("/path/to/file.txt@./config-tiny.ini", "check_disk")); 68 optstr = list2str(np_get_defaults("/path/to/file.txt@./config-tiny.ini", "check_disk"));
72 ok( !strcmp(optstr, "--this=that"), "config-tiny.ini's filename as section name"); 69 ok(!strcmp(optstr, "--this=that"), "config-tiny.ini's filename as section name");
73 my_free(optstr); 70 my_free(optstr);
74 71
75 optstr=list2str(np_get_defaults("section2@./config-tiny.ini", "check_disk")); 72 optstr = list2str(np_get_defaults("section2@./config-tiny.ini", "check_disk"));
76 ok( !strcmp(optstr, "--this=that"), "config-tiny.ini's section2 with whitespace before section name"); 73 ok(!strcmp(optstr, "--this=that"), "config-tiny.ini's section2 with whitespace before section name");
77 my_free(optstr); 74 my_free(optstr);
78 75
79 optstr=list2str(np_get_defaults("section3@./config-tiny.ini", "check_disk")); 76 optstr = list2str(np_get_defaults("section3@./config-tiny.ini", "check_disk"));
80 ok( !strcmp(optstr, "--this=that"), "config-tiny.ini's section3 with whitespace after section name"); 77 ok(!strcmp(optstr, "--this=that"), "config-tiny.ini's section3 with whitespace after section name");
81 my_free(optstr); 78 my_free(optstr);
82 79
83 optstr=list2str(np_get_defaults("check_mysql@./plugin.ini", "check_disk")); 80 optstr = list2str(np_get_defaults("check_mysql@./plugin.ini", "check_disk"));
84 ok( !strcmp(optstr, "--username=operator --password=secret"), "plugin.ini's check_mysql as expected"); 81 ok(!strcmp(optstr, "--username=operator --password=secret"), "plugin.ini's check_mysql as expected");
85 my_free(optstr); 82 my_free(optstr);
86 83
87 optstr=list2str(np_get_defaults("check_mysql2@./plugin.ini", "check_disk")); 84 optstr = list2str(np_get_defaults("check_mysql2@./plugin.ini", "check_disk"));
88 ok( !strcmp(optstr, "-u=admin -p=secret"), "plugin.ini's check_mysql2 as expected"); 85 ok(!strcmp(optstr, "-u=admin -p=secret"), "plugin.ini's check_mysql2 as expected");
89 my_free(optstr); 86 my_free(optstr);
90 87
91 optstr=list2str(np_get_defaults("check space_and_flags@./plugin.ini", "check_disk")); 88 optstr = list2str(np_get_defaults("check space_and_flags@./plugin.ini", "check_disk"));
92 ok( !strcmp(optstr, "--foo=bar -a -b --bar"), "plugin.ini space in stanza and flag arguments"); 89 ok(!strcmp(optstr, "--foo=bar -a -b --bar"), "plugin.ini space in stanza and flag arguments");
93 my_free(optstr); 90 my_free(optstr);
94 91
95 optstr=list2str(np_get_defaults("Section Two@./config-dos.ini", "check_disk")); 92 optstr = list2str(np_get_defaults("Section Two@./config-dos.ini", "check_disk"));
96 ok( !strcmp(optstr, "--something else=blah --remove=whitespace"), "config-dos.ini's Section Two as expected"); 93 ok(!strcmp(optstr, "--something else=blah --remove=whitespace"), "config-dos.ini's Section Two as expected");
97 my_free(optstr); 94 my_free(optstr);
98 95
99 optstr=list2str(np_get_defaults("section_twice@./plugin.ini", "check_disk")); 96 optstr = list2str(np_get_defaults("section_twice@./plugin.ini", "check_disk"));
100 ok( !strcmp(optstr, "--foo=bar --bar=foo"), "plugin.ini's section_twice defined twice in the file"); 97 ok(!strcmp(optstr, "--foo=bar --bar=foo"), "plugin.ini's section_twice defined twice in the file");
101 my_free(optstr); 98 my_free(optstr);
102 99
103 optstr=list2str(np_get_defaults("tcp_long_lines@plugins.ini", "check_tcp")); 100 optstr = list2str(np_get_defaults("tcp_long_lines@plugins.ini", "check_tcp"));
104 ok( !strcmp(optstr, "--escape --send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda --expect=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda --jail"), "Long options"); 101 ok(!strcmp(optstr, "--escape --send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar "
102 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
103 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
104 "yadda yadda Foo bar BAZ yadda yadda yadda Foo "
105 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
106 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
107 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda --expect=Foo bar BAZ yadda yadda "
108 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
109 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo "
110 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
111 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
112 "yadda yadda Foo bar BAZ yadda yadda yadda Foo "
113 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
114 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
115 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo "
116 "bar BAZ yadda yadda yadda --jail"),
117 "Long options");
105 my_free(optstr); 118 my_free(optstr);
106 119
107 return exit_status(); 120 return exit_status();
108} 121}
109
diff --git a/lib/tests/test_ini3.c b/lib/tests/test_ini3.c
index 8a2a0414..2186e4bb 100644
--- a/lib/tests/test_ini3.c
+++ b/lib/tests/test_ini3.c
@@ -1,26 +1,24 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16* 16 *
17*****************************************************************************/ 17 *****************************************************************************/
18 18
19#include "parse_ini.h" 19#include "parse_ini.h"
20 20
21int 21int main(int argc, char **argv) {
22main (int argc, char **argv)
23{
24 22
25 /* 23 /*
26 * This is for testing arguments expected to die. 24 * This is for testing arguments expected to die.
@@ -30,4 +28,3 @@ main (int argc, char **argv)
30 28
31 return 0; 29 return 0;
32} 30}
33
diff --git a/lib/tests/test_opts1.c b/lib/tests/test_opts1.c
index 077c5b63..984183d3 100644
--- a/lib/tests/test_opts1.c
+++ b/lib/tests/test_opts1.c
@@ -1,19 +1,19 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16*****************************************************************************/ 16 *****************************************************************************/
17 17
18#include "common.h" 18#include "common.h"
19#include "utils_base.h" 19#include "utils_base.h"
@@ -40,23 +40,24 @@ void my_free(int *argc, char **newargv, char **argv) {
40#else 40#else
41void my_free(int *argc, char **newargv, char **argv) { 41void my_free(int *argc, char **newargv, char **argv) {
42 /* Free stuff (and print while we're at it) */ 42 /* Free stuff (and print while we're at it) */
43 int i, freeflag=1; 43 int i, freeflag = 1;
44 printf (" Arg(%i): ", *argc+1); 44 printf(" Arg(%i): ", *argc + 1);
45 printf ("'%s' ", newargv[0]); 45 printf("'%s' ", newargv[0]);
46 for (i=1; i<*argc; i++) { 46 for (i = 1; i < *argc; i++) {
47 printf ("'%s' ", newargv[i]); 47 printf("'%s' ", newargv[i]);
48 /* Stop freeing when we get to the start of the original array */ 48 /* Stop freeing when we get to the start of the original array */
49 if (freeflag) { 49 if (freeflag) {
50 if (newargv[i] == argv[1]) 50 if (newargv[i] == argv[1])
51 freeflag=0; 51 freeflag = 0;
52 else 52 else
53 free(newargv[i]); 53 free(newargv[i]);
54 } 54 }
55 } 55 }
56 printf ("\n"); 56 printf("\n");
57 /* Free only if it's a different array */ 57 /* Free only if it's a different array */
58 if (newargv != argv) free(newargv); 58 if (newargv != argv)
59 *argc=0; 59 free(newargv);
60 *argc = 0;
60} 61}
61#endif 62#endif
62 63
@@ -67,9 +68,10 @@ int array_diff(int i1, char **a1, int i2, char **a2) {
67 printf(" Argument count doesn't match!\n"); 68 printf(" Argument count doesn't match!\n");
68 return 0; 69 return 0;
69 } 70 }
70 for (i=0; i<=i1; i++) { 71 for (i = 0; i <= i1; i++) {
71 if (a1[i]==NULL && a2[i]==NULL) continue; 72 if (a1[i] == NULL && a2[i] == NULL)
72 if (a1[i]==NULL || a2[i]==NULL) { 73 continue;
74 if (a1[i] == NULL || a2[i] == NULL) {
73 printf(" Argument # %i null in one array!\n", i); 75 printf(" Argument # %i null in one array!\n", i);
74 return 0; 76 return 0;
75 } 77 }
@@ -81,59 +83,58 @@ int array_diff(int i1, char **a1, int i2, char **a2) {
81 return 1; 83 return 1;
82} 84}
83 85
84int 86int main(int argc, char **argv) {
85main (int argc, char **argv) 87 char **argv_new = NULL;
86{
87 char **argv_new=NULL;
88 int i, argc_test; 88 int i, argc_test;
89 89
90 plan_tests(5); 90 plan_tests(5);
91 91
92 { 92 {
93 char *argv_test[] = {"prog_name", (char *) NULL}; 93 char *argv_test[] = {"prog_name", (char *)NULL};
94 argc_test=1; 94 argc_test = 1;
95 char *argv_known[] = {"prog_name", (char *) NULL}; 95 char *argv_known[] = {"prog_name", (char *)NULL};
96 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 96 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
97 ok(array_diff(argc_test, argv_new, 1, argv_known), "No opts, returns correct argv/argc"); 97 ok(array_diff(argc_test, argv_new, 1, argv_known), "No opts, returns correct argv/argc");
98 my_free(&argc_test, argv_new, argv_test); 98 my_free(&argc_test, argv_new, argv_test);
99 } 99 }
100 100
101 { 101 {
102 char *argv_test[] = {"prog_name", "arg1", "--arg2=val1", "--arg3", "val2", (char *) NULL}; 102 char *argv_test[] = {"prog_name", "arg1", "--arg2=val1", "--arg3", "val2", (char *)NULL};
103 argc_test=5; 103 argc_test = 5;
104 char *argv_known[] = {"prog_name", "arg1", "--arg2=val1", "--arg3", "val2", (char *) NULL}; 104 char *argv_known[] = {"prog_name", "arg1", "--arg2=val1", "--arg3", "val2", (char *)NULL};
105 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 105 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
106 ok(array_diff(argc_test, argv_new, 5, argv_known), "No extra opts, verbatim copy of argv"); 106 ok(array_diff(argc_test, argv_new, 5, argv_known), "No extra opts, verbatim copy of argv");
107 my_free(&argc_test, argv_new, argv_test); 107 my_free(&argc_test, argv_new, argv_test);
108 } 108 }
109 109
110 { 110 {
111 char *argv_test[] = {"prog_name", "--extra-opts=@./config-opts.ini", (char *) NULL}; 111 char *argv_test[] = {"prog_name", "--extra-opts=@./config-opts.ini", (char *)NULL};
112 argc_test=2; 112 argc_test = 2;
113 char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", (char *) NULL}; 113 char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", (char *)NULL};
114 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 114 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
115 ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts using default section"); 115 ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts using default section");
116 my_free(&argc_test, argv_new, argv_test); 116 my_free(&argc_test, argv_new, argv_test);
117 } 117 }
118 118
119 { 119 {
120 char *argv_test[] = {"prog_name", "--extra-opts=sect1@./config-opts.ini", "--extra-opts", "sect2@./config-opts.ini", (char *) NULL}; 120 char *argv_test[] = {"prog_name", "--extra-opts=sect1@./config-opts.ini", "--extra-opts", "sect2@./config-opts.ini", (char *)NULL};
121 argc_test=4; 121 argc_test = 4;
122 char *argv_known[] = {"prog_name", "--one=two", "--something else=oops", "--this=that", (char *) NULL}; 122 char *argv_known[] = {"prog_name", "--one=two", "--something else=oops", "--this=that", (char *)NULL};
123 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 123 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
124 ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts specified twice"); 124 ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts specified twice");
125 my_free(&argc_test, argv_new, argv_test); 125 my_free(&argc_test, argv_new, argv_test);
126 } 126 }
127 127
128 { 128 {
129 char *argv_test[] = {"prog_name", "--arg1=val1", "--extra-opts=@./config-opts.ini", "--extra-opts", "sect1@./config-opts.ini", "--arg2", (char *) NULL}; 129 char *argv_test[] = {"prog_name", "--arg1=val1", "--extra-opts=@./config-opts.ini", "--extra-opts", "sect1@./config-opts.ini",
130 argc_test=6; 130 "--arg2", (char *)NULL};
131 char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", "--one=two", "--arg1=val1", "--arg2", (char *) NULL}; 131 argc_test = 6;
132 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 132 char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", "--one=two",
133 "--arg1=val1", "--arg2", (char *)NULL};
134 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
133 ok(array_diff(argc_test, argv_new, 7, argv_known), "twice extra opts using two sections"); 135 ok(array_diff(argc_test, argv_new, 7, argv_known), "twice extra opts using two sections");
134 my_free(&argc_test, argv_new, argv_test); 136 my_free(&argc_test, argv_new, argv_test);
135 } 137 }
136 138
137 return exit_status(); 139 return exit_status();
138} 140}
139
diff --git a/lib/tests/test_opts2.c b/lib/tests/test_opts2.c
index 780220ee..23496617 100644
--- a/lib/tests/test_opts2.c
+++ b/lib/tests/test_opts2.c
@@ -1,19 +1,19 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16*****************************************************************************/ 16 *****************************************************************************/
17 17
18#include "common.h" 18#include "common.h"
19#include "utils_base.h" 19#include "utils_base.h"
@@ -23,23 +23,24 @@
23 23
24void my_free(int *argc, char **newargv, char **argv) { 24void my_free(int *argc, char **newargv, char **argv) {
25 /* Free stuff (and print while we're at it) */ 25 /* Free stuff (and print while we're at it) */
26 int i, freeflag=1; 26 int i, freeflag = 1;
27 printf (" Arg(%i): ", *argc+1); 27 printf(" Arg(%i): ", *argc + 1);
28 printf ("'%s' ", newargv[0]); 28 printf("'%s' ", newargv[0]);
29 for (i=1; i<*argc; i++) { 29 for (i = 1; i < *argc; i++) {
30 printf ("'%s' ", newargv[i]); 30 printf("'%s' ", newargv[i]);
31 /* Stop freeing when we get to the start of the original array */ 31 /* Stop freeing when we get to the start of the original array */
32 if (freeflag) { 32 if (freeflag) {
33 if (newargv[i] == argv[1]) 33 if (newargv[i] == argv[1])
34 freeflag=0; 34 freeflag = 0;
35 else 35 else
36 free(newargv[i]); 36 free(newargv[i]);
37 } 37 }
38 } 38 }
39 printf ("\n"); 39 printf("\n");
40 /* Free only if it's a different array */ 40 /* Free only if it's a different array */
41 if (newargv != argv) free(newargv); 41 if (newargv != argv)
42 *argc=0; 42 free(newargv);
43 *argc = 0;
43} 44}
44 45
45int array_diff(int i1, char **a1, int i2, char **a2) { 46int array_diff(int i1, char **a1, int i2, char **a2) {
@@ -49,9 +50,10 @@ int array_diff(int i1, char **a1, int i2, char **a2) {
49 printf(" Argument count doesn't match!\n"); 50 printf(" Argument count doesn't match!\n");
50 return 0; 51 return 0;
51 } 52 }
52 for (i=0; i<=i1; i++) { 53 for (i = 0; i <= i1; i++) {
53 if (a1[i]==NULL && a2[i]==NULL) continue; 54 if (a1[i] == NULL && a2[i] == NULL)
54 if (a1[i]==NULL || a2[i]==NULL) { 55 continue;
56 if (a1[i] == NULL || a2[i] == NULL) {
55 printf(" Argument # %i null in one array!\n", i); 57 printf(" Argument # %i null in one array!\n", i);
56 return 0; 58 return 0;
57 } 59 }
@@ -63,59 +65,77 @@ int array_diff(int i1, char **a1, int i2, char **a2) {
63 return 1; 65 return 1;
64} 66}
65 67
66int 68int main(int argc, char **argv) {
67main (int argc, char **argv) 69 char **argv_new = NULL;
68{
69 char **argv_new=NULL;
70 int i, argc_test; 70 int i, argc_test;
71 71
72 plan_tests(5); 72 plan_tests(5);
73 73
74 { 74 {
75 char *argv_test[] = {"prog_name", "arg1", "--extra-opts", "--arg3", "val2", (char *) NULL}; 75 char *argv_test[] = {"prog_name", "arg1", "--extra-opts", "--arg3", "val2", (char *)NULL};
76 argc_test=5; 76 argc_test = 5;
77 char *argv_known[] = {"prog_name", "--foo=bar", "arg1", "--arg3", "val2", (char *) NULL}; 77 char *argv_known[] = {"prog_name", "--foo=bar", "arg1", "--arg3", "val2", (char *)NULL};
78 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 78 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
79 ok(array_diff(argc_test, argv_new, 5, argv_known), "Default section 1"); 79 ok(array_diff(argc_test, argv_new, 5, argv_known), "Default section 1");
80 my_free(&argc_test, argv_new, argv_test); 80 my_free(&argc_test, argv_new, argv_test);
81 } 81 }
82 82
83 { 83 {
84 char *argv_test[] = {"prog_name", "--extra-opts", (char *) NULL}; 84 char *argv_test[] = {"prog_name", "--extra-opts", (char *)NULL};
85 argc_test=2; 85 argc_test = 2;
86 char *argv_known[] = {"prog_name", "--foo=bar", (char *) NULL}; 86 char *argv_known[] = {"prog_name", "--foo=bar", (char *)NULL};
87 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 87 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
88 ok(array_diff(argc_test, argv_new, 2, argv_known), "Default section 2"); 88 ok(array_diff(argc_test, argv_new, 2, argv_known), "Default section 2");
89 my_free(&argc_test, argv_new, argv_test); 89 my_free(&argc_test, argv_new, argv_test);
90 } 90 }
91 91
92 { 92 {
93 char *argv_test[] = {"prog_name", "arg1", "--extra-opts=section1", "--arg3", "val2", (char *) NULL}; 93 char *argv_test[] = {"prog_name", "arg1", "--extra-opts=section1", "--arg3", "val2", (char *)NULL};
94 argc_test=5; 94 argc_test = 5;
95 char *argv_known[] = {"prog_name", "--foobar=baz", "arg1", "--arg3", "val2", (char *) NULL}; 95 char *argv_known[] = {"prog_name", "--foobar=baz", "arg1", "--arg3", "val2", (char *)NULL};
96 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 96 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
97 ok(array_diff(argc_test, argv_new, 5, argv_known), "Default section 3"); 97 ok(array_diff(argc_test, argv_new, 5, argv_known), "Default section 3");
98 my_free(&argc_test, argv_new, argv_test); 98 my_free(&argc_test, argv_new, argv_test);
99 } 99 }
100 100
101 { 101 {
102 char *argv_test[] = {"prog_name", "arg1", "--extra-opts", "-arg3", "val2", (char *) NULL}; 102 char *argv_test[] = {"prog_name", "arg1", "--extra-opts", "-arg3", "val2", (char *)NULL};
103 argc_test=5; 103 argc_test = 5;
104 char *argv_known[] = {"prog_name", "--foo=bar", "arg1", "-arg3", "val2", (char *) NULL}; 104 char *argv_known[] = {"prog_name", "--foo=bar", "arg1", "-arg3", "val2", (char *)NULL};
105 argv_new=np_extra_opts(&argc_test, argv_test, "check_disk"); 105 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
106 ok(array_diff(argc_test, argv_new, 5, argv_known), "Default section 4"); 106 ok(array_diff(argc_test, argv_new, 5, argv_known), "Default section 4");
107 my_free(&argc_test, argv_new, argv_test); 107 my_free(&argc_test, argv_new, argv_test);
108 } 108 }
109 109
110 { 110 {
111 char *argv_test[] = {"check_tcp", "--extra-opts", "--extra-opts=tcp_long_lines", (char *) NULL}; 111 char *argv_test[] = {"check_tcp", "--extra-opts", "--extra-opts=tcp_long_lines", (char *)NULL};
112 argc_test=3; 112 argc_test = 3;
113 char *argv_known[] = {"check_tcp", "--timeout=10", "--escape", "--send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda", "--expect=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda", "--jail", (char *) NULL}; 113 char *argv_known[] = {
114 argv_new=np_extra_opts(&argc_test, argv_test, "check_tcp"); 114 "check_tcp",
115 "--timeout=10",
116 "--escape",
117 "--send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
118 "yadda Foo bar BAZ yadda "
119 "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
120 "yadda Foo bar BAZ "
121 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
122 "yadda yadda Foo bar "
123 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda",
124 "--expect=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
125 "yadda Foo bar BAZ yadda "
126 "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
127 "yadda Foo bar BAZ "
128 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
129 "yadda yadda Foo bar "
130 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
131 "yadda yadda yadda Foo "
132 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda",
133 "--jail",
134 (char *)NULL};
135 argv_new = np_extra_opts(&argc_test, argv_test, "check_tcp");
115 ok(array_diff(argc_test, argv_new, 6, argv_known), "Long lines test"); 136 ok(array_diff(argc_test, argv_new, 6, argv_known), "Long lines test");
116 my_free(&argc_test, argv_new, argv_test); 137 my_free(&argc_test, argv_new, argv_test);
117 } 138 }
118 139
119 return exit_status(); 140 return exit_status();
120} 141}
121
diff --git a/lib/tests/test_opts3.c b/lib/tests/test_opts3.c
index b64270da..cecea437 100644
--- a/lib/tests/test_opts3.c
+++ b/lib/tests/test_opts3.c
@@ -1,31 +1,28 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16*****************************************************************************/ 16 *****************************************************************************/
17 17
18#include "extra_opts.h" 18#include "extra_opts.h"
19 19
20int 20int main(int argc, char **argv) {
21main (int argc, char **argv)
22{
23 21
24 /* 22 /*
25 * This is for testing arguments expected to die. 23 * This is for testing arguments expected to die.
26 */ 24 */
27 argv=np_extra_opts(&argc, argv, argv[0]); 25 argv = np_extra_opts(&argc, argv, argv[0]);
28 26
29 return 0; 27 return 0;
30} 28}
31
diff --git a/lib/tests/test_tcp.c b/lib/tests/test_tcp.c
index 1954b0fb..1b3003e9 100644
--- a/lib/tests/test_tcp.c
+++ b/lib/tests/test_tcp.c
@@ -1,34 +1,32 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16* 16 *
17*****************************************************************************/ 17 *****************************************************************************/
18 18
19#include "common.h" 19#include "common.h"
20#include "utils_tcp.h" 20#include "utils_tcp.h"
21#include "tap.h" 21#include "tap.h"
22 22
23int 23int main(void) {
24main(void)
25{
26 char **server_expect; 24 char **server_expect;
27 int server_expect_count = 3; 25 int server_expect_count = 3;
28 26
29 plan_tests(9); 27 plan_tests(9);
30 28
31 server_expect = malloc(sizeof(char*) * server_expect_count); 29 server_expect = malloc(sizeof(char *) * server_expect_count);
32 30
33 server_expect[0] = strdup("AA"); 31 server_expect[0] = strdup("AA");
34 server_expect[1] = strdup("bb"); 32 server_expect[1] = strdup("bb");
@@ -42,17 +40,13 @@ main(void)
42 "Test matching any string at the beginning (substring match)"); 40 "Test matching any string at the beginning (substring match)");
43 ok(np_expect_match("XX bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_FAILURE, 41 ok(np_expect_match("XX bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_FAILURE,
44 "Test with strings not matching at the beginning"); 42 "Test with strings not matching at the beginning");
45 ok(np_expect_match("XX CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_FAILURE, 43 ok(np_expect_match("XX CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_FAILURE, "Test matching any string");
46 "Test matching any string"); 44 ok(np_expect_match("XX", server_expect, server_expect_count, 0) == NP_MATCH_RETRY, "Test not matching any string");
47 ok(np_expect_match("XX", server_expect, server_expect_count, 0) == NP_MATCH_RETRY,
48 "Test not matching any string");
49 ok(np_expect_match("XX AA bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_SUCCESS, 45 ok(np_expect_match("XX AA bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_SUCCESS,
50 "Test matching all strings"); 46 "Test matching all strings");
51 ok(np_expect_match("XX bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY, 47 ok(np_expect_match("XX bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY, "Test not matching all strings");
52 "Test not matching all strings");
53 ok(np_expect_match("XX XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY, 48 ok(np_expect_match("XX XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY,
54 "Test not matching any string (testing all)"); 49 "Test not matching any string (testing all)");
55 50
56
57 return exit_status(); 51 return exit_status();
58} 52}
diff --git a/lib/tests/test_utils.c b/lib/tests/test_utils.c
index 01afacdc..c3150f00 100644
--- a/lib/tests/test_utils.c
+++ b/lib/tests/test_utils.c
@@ -1,20 +1,20 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5* the Free Software Foundation, either version 3 of the License, or 5 * the Free Software Foundation, either version 3 of the License, or
6* (at your option) any later version. 6 * (at your option) any later version.
7* 7 *
8* This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details. 11 * GNU General Public License for more details.
12* 12 *
13* You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15* 15 *
16* 16 *
17*****************************************************************************/ 17 *****************************************************************************/
18 18
19#include "common.h" 19#include "common.h"
20#include "utils_base.h" 20#include "utils_base.h"
@@ -27,331 +27,323 @@
27 27
28#include "utils_base.c" 28#include "utils_base.c"
29 29
30int 30int main(int argc, char **argv) {
31main (int argc, char **argv)
32{
33 char state_path[1024]; 31 char state_path[1024];
34 range *range; 32 range *range;
35 double temp; 33 double temp;
36 thresholds *thresholds = NULL; 34 thresholds *thresholds = NULL;
37 int i, rc; 35 int i, rc;
38 char *temp_string; 36 char *temp_string;
39 state_key *temp_state_key = NULL; 37 state_key *temp_state_key = NULL;
40 state_data *temp_state_data; 38 state_data *temp_state_data;
41 time_t current_time; 39 time_t current_time;
42 40
43 plan_tests(185); 41 plan_tests(185);
44 42
45 ok( this_monitoring_plugin==NULL, "monitoring_plugin not initialised"); 43 ok(this_monitoring_plugin == NULL, "monitoring_plugin not initialised");
46 44
47 np_init( "check_test", argc, argv ); 45 np_init("check_test", argc, argv);
48 46
49 ok( this_monitoring_plugin!=NULL, "monitoring_plugin now initialised"); 47 ok(this_monitoring_plugin != NULL, "monitoring_plugin now initialised");
50 ok( !strcmp(this_monitoring_plugin->plugin_name, "check_test"), "plugin name initialised" ); 48 ok(!strcmp(this_monitoring_plugin->plugin_name, "check_test"), "plugin name initialised");
51 49
52 ok( this_monitoring_plugin->argc==argc, "Argc set" ); 50 ok(this_monitoring_plugin->argc == argc, "Argc set");
53 ok( this_monitoring_plugin->argv==argv, "Argv set" ); 51 ok(this_monitoring_plugin->argv == argv, "Argv set");
54 52
55 np_set_args(0,0); 53 np_set_args(0, 0);
56 54
57 ok( this_monitoring_plugin->argc==0, "argc changed" ); 55 ok(this_monitoring_plugin->argc == 0, "argc changed");
58 ok( this_monitoring_plugin->argv==0, "argv changed" ); 56 ok(this_monitoring_plugin->argv == 0, "argv changed");
59 57
60 np_set_args(argc, argv); 58 np_set_args(argc, argv);
61 59
62 range = parse_range_string("6"); 60 range = parse_range_string("6");
63 ok( range != NULL, "'6' is valid range"); 61 ok(range != NULL, "'6' is valid range");
64 ok( range->start == 0, "Start correct"); 62 ok(range->start == 0, "Start correct");
65 ok( range->start_infinity == false, "Not using negative infinity"); 63 ok(range->start_infinity == false, "Not using negative infinity");
66 ok( range->end == 6, "End correct"); 64 ok(range->end == 6, "End correct");
67 ok( range->end_infinity == false, "Not using infinity"); 65 ok(range->end_infinity == false, "Not using infinity");
68 free(range); 66 free(range);
69 67
70 range = parse_range_string("1:12%%"); 68 range = parse_range_string("1:12%%");
71 ok( range != NULL, "'1:12%%' is valid - percentages are ignored"); 69 ok(range != NULL, "'1:12%%' is valid - percentages are ignored");
72 ok( range->start == 1, "Start correct"); 70 ok(range->start == 1, "Start correct");
73 ok( range->start_infinity == false, "Not using negative infinity"); 71 ok(range->start_infinity == false, "Not using negative infinity");
74 ok( range->end == 12, "End correct"); 72 ok(range->end == 12, "End correct");
75 ok( range->end_infinity == false, "Not using infinity"); 73 ok(range->end_infinity == false, "Not using infinity");
76 free(range); 74 free(range);
77 75
78 range = parse_range_string("-7:23"); 76 range = parse_range_string("-7:23");
79 ok( range != NULL, "'-7:23' is valid range"); 77 ok(range != NULL, "'-7:23' is valid range");
80 ok( range->start == -7, "Start correct"); 78 ok(range->start == -7, "Start correct");
81 ok( range->start_infinity == false, "Not using negative infinity"); 79 ok(range->start_infinity == false, "Not using negative infinity");
82 ok( range->end == 23, "End correct"); 80 ok(range->end == 23, "End correct");
83 ok( range->end_infinity == false, "Not using infinity"); 81 ok(range->end_infinity == false, "Not using infinity");
84 free(range); 82 free(range);
85 83
86 range = parse_range_string(":5.75"); 84 range = parse_range_string(":5.75");
87 ok( range != NULL, "':5.75' is valid range"); 85 ok(range != NULL, "':5.75' is valid range");
88 ok( range->start == 0, "Start correct"); 86 ok(range->start == 0, "Start correct");
89 ok( range->start_infinity == false, "Not using negative infinity"); 87 ok(range->start_infinity == false, "Not using negative infinity");
90 ok( range->end == 5.75, "End correct"); 88 ok(range->end == 5.75, "End correct");
91 ok( range->end_infinity == false, "Not using infinity"); 89 ok(range->end_infinity == false, "Not using infinity");
92 free(range); 90 free(range);
93 91
94 range = parse_range_string("~:-95.99"); 92 range = parse_range_string("~:-95.99");
95 ok( range != NULL, "~:-95.99' is valid range"); 93 ok(range != NULL, "~:-95.99' is valid range");
96 ok( range->start_infinity == true, "Using negative infinity"); 94 ok(range->start_infinity == true, "Using negative infinity");
97 ok( range->end == -95.99, "End correct (with rounding errors)"); 95 ok(range->end == -95.99, "End correct (with rounding errors)");
98 ok( range->end_infinity == false, "Not using infinity"); 96 ok(range->end_infinity == false, "Not using infinity");
99 free(range); 97 free(range);
100 98
101 range = parse_range_string("12345678901234567890:"); 99 range = parse_range_string("12345678901234567890:");
102 temp = atof("12345678901234567890"); /* Can't just use this because number too large */ 100 temp = atof("12345678901234567890"); /* Can't just use this because number too large */
103 ok( range != NULL, "'12345678901234567890:' is valid range"); 101 ok(range != NULL, "'12345678901234567890:' is valid range");
104 ok( range->start == temp, "Start correct"); 102 ok(range->start == temp, "Start correct");
105 ok( range->start_infinity == false, "Not using negative infinity"); 103 ok(range->start_infinity == false, "Not using negative infinity");
106 ok( range->end_infinity == true, "Using infinity"); 104 ok(range->end_infinity == true, "Using infinity");
107 /* Cannot do a "-1" on temp, as it appears to be same value */ 105 /* Cannot do a "-1" on temp, as it appears to be same value */
108 ok( check_range(temp/1.1, range) == true, "12345678901234567890/1.1 - alert"); 106 ok(check_range(temp / 1.1, range) == true, "12345678901234567890/1.1 - alert");
109 ok( check_range(temp, range) == false, "12345678901234567890 - no alert"); 107 ok(check_range(temp, range) == false, "12345678901234567890 - no alert");
110 ok( check_range(temp*2, range) == false, "12345678901234567890*2 - no alert"); 108 ok(check_range(temp * 2, range) == false, "12345678901234567890*2 - no alert");
111 free(range); 109 free(range);
112 110
113 range = parse_range_string("~:0"); 111 range = parse_range_string("~:0");
114 ok( range != NULL, "'~:0' is valid range"); 112 ok(range != NULL, "'~:0' is valid range");
115 ok( range->start_infinity == true, "Using negative infinity"); 113 ok(range->start_infinity == true, "Using negative infinity");
116 ok( range->end == 0, "End correct"); 114 ok(range->end == 0, "End correct");
117 ok( range->end_infinity == false, "Not using infinity"); 115 ok(range->end_infinity == false, "Not using infinity");
118 ok( range->alert_on == OUTSIDE, "Will alert on outside of this range"); 116 ok(range->alert_on == OUTSIDE, "Will alert on outside of this range");
119 ok( check_range(0.5, range) == true, "0.5 - alert"); 117 ok(check_range(0.5, range) == true, "0.5 - alert");
120 ok( check_range(-10, range) == false, "-10 - no alert"); 118 ok(check_range(-10, range) == false, "-10 - no alert");
121 ok( check_range(0, range) == false, "0 - no alert"); 119 ok(check_range(0, range) == false, "0 - no alert");
122 free(range); 120 free(range);
123 121
124 range = parse_range_string("@0:657.8210567"); 122 range = parse_range_string("@0:657.8210567");
125 ok( range != 0, "@0:657.8210567' is a valid range"); 123 ok(range != 0, "@0:657.8210567' is a valid range");
126 ok( range->start == 0, "Start correct"); 124 ok(range->start == 0, "Start correct");
127 ok( range->start_infinity == false, "Not using negative infinity"); 125 ok(range->start_infinity == false, "Not using negative infinity");
128 ok( range->end == 657.8210567, "End correct"); 126 ok(range->end == 657.8210567, "End correct");
129 ok( range->end_infinity == false, "Not using infinity"); 127 ok(range->end_infinity == false, "Not using infinity");
130 ok( range->alert_on == INSIDE, "Will alert on inside of this range" ); 128 ok(range->alert_on == INSIDE, "Will alert on inside of this range");
131 ok( check_range(32.88, range) == true, "32.88 - alert"); 129 ok(check_range(32.88, range) == true, "32.88 - alert");
132 ok( check_range(-2, range) == false, "-2 - no alert"); 130 ok(check_range(-2, range) == false, "-2 - no alert");
133 ok( check_range(657.8210567, range) == true, "657.8210567 - alert"); 131 ok(check_range(657.8210567, range) == true, "657.8210567 - alert");
134 ok( check_range(0, range) == true, "0 - alert"); 132 ok(check_range(0, range) == true, "0 - alert");
135 free(range); 133 free(range);
136 134
137 range = parse_range_string("@1:1"); 135 range = parse_range_string("@1:1");
138 ok( range != NULL, "'@1:1' is a valid range"); 136 ok(range != NULL, "'@1:1' is a valid range");
139 ok( range->start == 1, "Start correct"); 137 ok(range->start == 1, "Start correct");
140 ok( range->start_infinity == false, "Not using negative infinity"); 138 ok(range->start_infinity == false, "Not using negative infinity");
141 ok( range->end == 1, "End correct"); 139 ok(range->end == 1, "End correct");
142 ok( range->end_infinity == false, "Not using infinity"); 140 ok(range->end_infinity == false, "Not using infinity");
143 ok( range->alert_on == INSIDE, "Will alert on inside of this range" ); 141 ok(range->alert_on == INSIDE, "Will alert on inside of this range");
144 ok( check_range(0.5, range) == false, "0.5 - no alert"); 142 ok(check_range(0.5, range) == false, "0.5 - no alert");
145 ok( check_range(1, range) == true, "1 - alert"); 143 ok(check_range(1, range) == true, "1 - alert");
146 ok( check_range(5.2, range) == false, "5.2 - no alert"); 144 ok(check_range(5.2, range) == false, "5.2 - no alert");
147 free(range); 145 free(range);
148 146
149 range = parse_range_string("1:1"); 147 range = parse_range_string("1:1");
150 ok( range != NULL, "'1:1' is a valid range"); 148 ok(range != NULL, "'1:1' is a valid range");
151 ok( range->start == 1, "Start correct"); 149 ok(range->start == 1, "Start correct");
152 ok( range->start_infinity == false, "Not using negative infinity"); 150 ok(range->start_infinity == false, "Not using negative infinity");
153 ok( range->end == 1, "End correct"); 151 ok(range->end == 1, "End correct");
154 ok( range->end_infinity == false, "Not using infinity"); 152 ok(range->end_infinity == false, "Not using infinity");
155 ok( check_range(0.5, range) == true, "0.5 - alert"); 153 ok(check_range(0.5, range) == true, "0.5 - alert");
156 ok( check_range(1, range) == false, "1 - no alert"); 154 ok(check_range(1, range) == false, "1 - no alert");
157 ok( check_range(5.2, range) == true, "5.2 - alert"); 155 ok(check_range(5.2, range) == true, "5.2 - alert");
158 free(range); 156 free(range);
159 157
160 range = parse_range_string("2:1"); 158 range = parse_range_string("2:1");
161 ok( range == NULL, "'2:1' rejected"); 159 ok(range == NULL, "'2:1' rejected");
162 160
163 rc = _set_thresholds(&thresholds, NULL, NULL); 161 rc = _set_thresholds(&thresholds, NULL, NULL);
164 ok( rc == 0, "Thresholds (NULL, NULL) set"); 162 ok(rc == 0, "Thresholds (NULL, NULL) set");
165 ok( thresholds->warning == NULL, "Warning not set"); 163 ok(thresholds->warning == NULL, "Warning not set");
166 ok( thresholds->critical == NULL, "Critical not set"); 164 ok(thresholds->critical == NULL, "Critical not set");
167 165
168 rc = _set_thresholds(&thresholds, NULL, "80"); 166 rc = _set_thresholds(&thresholds, NULL, "80");
169 ok( rc == 0, "Thresholds (NULL, '80') set"); 167 ok(rc == 0, "Thresholds (NULL, '80') set");
170 ok( thresholds->warning == NULL, "Warning not set"); 168 ok(thresholds->warning == NULL, "Warning not set");
171 ok( thresholds->critical->end == 80, "Critical set correctly"); 169 ok(thresholds->critical->end == 80, "Critical set correctly");
172 170
173 rc = _set_thresholds(&thresholds, "5:33", NULL); 171 rc = _set_thresholds(&thresholds, "5:33", NULL);
174 ok( rc == 0, "Thresholds ('5:33', NULL) set"); 172 ok(rc == 0, "Thresholds ('5:33', NULL) set");
175 ok( thresholds->warning->start == 5, "Warning start set"); 173 ok(thresholds->warning->start == 5, "Warning start set");
176 ok( thresholds->warning->end == 33, "Warning end set"); 174 ok(thresholds->warning->end == 33, "Warning end set");
177 ok( thresholds->critical == NULL, "Critical not set"); 175 ok(thresholds->critical == NULL, "Critical not set");
178 176
179 rc = _set_thresholds(&thresholds, "30", "60"); 177 rc = _set_thresholds(&thresholds, "30", "60");
180 ok( rc == 0, "Thresholds ('30', '60') set"); 178 ok(rc == 0, "Thresholds ('30', '60') set");
181 ok( thresholds->warning->end == 30, "Warning set correctly"); 179 ok(thresholds->warning->end == 30, "Warning set correctly");
182 ok( thresholds->critical->end == 60, "Critical set correctly"); 180 ok(thresholds->critical->end == 60, "Critical set correctly");
183 ok( get_status(15.3, thresholds) == STATE_OK, "15.3 - ok"); 181 ok(get_status(15.3, thresholds) == STATE_OK, "15.3 - ok");
184 ok( get_status(30.0001, thresholds) == STATE_WARNING, "30.0001 - warning"); 182 ok(get_status(30.0001, thresholds) == STATE_WARNING, "30.0001 - warning");
185 ok( get_status(69, thresholds) == STATE_CRITICAL, "69 - critical"); 183 ok(get_status(69, thresholds) == STATE_CRITICAL, "69 - critical");
186 184
187 rc = _set_thresholds(&thresholds, "-10:-2", "-30:20"); 185 rc = _set_thresholds(&thresholds, "-10:-2", "-30:20");
188 ok( rc == 0, "Thresholds ('-30:20', '-10:-2') set"); 186 ok(rc == 0, "Thresholds ('-30:20', '-10:-2') set");
189 ok( thresholds->warning->start == -10, "Warning start set correctly"); 187 ok(thresholds->warning->start == -10, "Warning start set correctly");
190 ok( thresholds->warning->end == -2, "Warning end set correctly"); 188 ok(thresholds->warning->end == -2, "Warning end set correctly");
191 ok( thresholds->critical->start == -30, "Critical start set correctly"); 189 ok(thresholds->critical->start == -30, "Critical start set correctly");
192 ok( thresholds->critical->end == 20, "Critical end set correctly"); 190 ok(thresholds->critical->end == 20, "Critical end set correctly");
193 ok( get_status(-31, thresholds) == STATE_CRITICAL, "-31 - critical"); 191 ok(get_status(-31, thresholds) == STATE_CRITICAL, "-31 - critical");
194 ok( get_status(-29, thresholds) == STATE_WARNING, "-29 - warning"); 192 ok(get_status(-29, thresholds) == STATE_WARNING, "-29 - warning");
195 ok( get_status(-11, thresholds) == STATE_WARNING, "-11 - warning"); 193 ok(get_status(-11, thresholds) == STATE_WARNING, "-11 - warning");
196 ok( get_status(-10, thresholds) == STATE_OK, "-10 - ok"); 194 ok(get_status(-10, thresholds) == STATE_OK, "-10 - ok");
197 ok( get_status(-2, thresholds) == STATE_OK, "-2 - ok"); 195 ok(get_status(-2, thresholds) == STATE_OK, "-2 - ok");
198 ok( get_status(-1, thresholds) == STATE_WARNING, "-1 - warning"); 196 ok(get_status(-1, thresholds) == STATE_WARNING, "-1 - warning");
199 ok( get_status(19, thresholds) == STATE_WARNING, "19 - warning"); 197 ok(get_status(19, thresholds) == STATE_WARNING, "19 - warning");
200 ok( get_status(21, thresholds) == STATE_CRITICAL, "21 - critical"); 198 ok(get_status(21, thresholds) == STATE_CRITICAL, "21 - critical");
201 199
202 char *test; 200 char *test;
203 test = np_escaped_string("bob\\n"); 201 test = np_escaped_string("bob\\n");
204 ok( strcmp(test, "bob\n") == 0, "bob\\n ok"); 202 ok(strcmp(test, "bob\n") == 0, "bob\\n ok");
205 free(test); 203 free(test);
206 204
207 test = np_escaped_string("rhuba\\rb"); 205 test = np_escaped_string("rhuba\\rb");
208 ok( strcmp(test, "rhuba\rb") == 0, "rhuba\\rb okay"); 206 ok(strcmp(test, "rhuba\rb") == 0, "rhuba\\rb okay");
209 free(test); 207 free(test);
210 208
211 test = np_escaped_string("ba\\nge\\r"); 209 test = np_escaped_string("ba\\nge\\r");
212 ok( strcmp(test, "ba\nge\r") == 0, "ba\\nge\\r okay"); 210 ok(strcmp(test, "ba\nge\r") == 0, "ba\\nge\\r okay");
213 free(test); 211 free(test);
214 212
215 test = np_escaped_string("\\rabbi\\t"); 213 test = np_escaped_string("\\rabbi\\t");
216 ok( strcmp(test, "\rabbi\t") == 0, "\\rabbi\\t okay"); 214 ok(strcmp(test, "\rabbi\t") == 0, "\\rabbi\\t okay");
217 free(test); 215 free(test);
218 216
219 test = np_escaped_string("and\\\\or"); 217 test = np_escaped_string("and\\\\or");
220 ok( strcmp(test, "and\\or") == 0, "and\\\\or okay"); 218 ok(strcmp(test, "and\\or") == 0, "and\\\\or okay");
221 free(test); 219 free(test);
222 220
223 test = np_escaped_string("bo\\gus"); 221 test = np_escaped_string("bo\\gus");
224 ok( strcmp(test, "bogus") == 0, "bo\\gus okay"); 222 ok(strcmp(test, "bogus") == 0, "bo\\gus okay");
225 free(test); 223 free(test);
226 224
227 test = np_escaped_string("everything"); 225 test = np_escaped_string("everything");
228 ok( strcmp(test, "everything") == 0, "everything okay"); 226 ok(strcmp(test, "everything") == 0, "everything okay");
229 227
230 /* np_extract_ntpvar tests (23) */ 228 /* np_extract_ntpvar tests (23) */
231 test=np_extract_ntpvar("foo=bar, bar=foo, foobar=barfoo\n", "foo"); 229 test = np_extract_ntpvar("foo=bar, bar=foo, foobar=barfoo\n", "foo");
232 ok(test && !strcmp(test, "bar"), "1st test as expected"); 230 ok(test && !strcmp(test, "bar"), "1st test as expected");
233 free(test); 231 free(test);
234 232
235 test=np_extract_ntpvar("foo=bar,bar=foo,foobar=barfoo\n", "bar"); 233 test = np_extract_ntpvar("foo=bar,bar=foo,foobar=barfoo\n", "bar");
236 ok(test && !strcmp(test, "foo"), "2nd test as expected"); 234 ok(test && !strcmp(test, "foo"), "2nd test as expected");
237 free(test); 235 free(test);
238 236
239 test=np_extract_ntpvar("foo=bar, bar=foo, foobar=barfoo\n", "foobar"); 237 test = np_extract_ntpvar("foo=bar, bar=foo, foobar=barfoo\n", "foobar");
240 ok(test && !strcmp(test, "barfoo"), "3rd test as expected"); 238 ok(test && !strcmp(test, "barfoo"), "3rd test as expected");
241 free(test); 239 free(test);
242 240
243 test=np_extract_ntpvar("foo=bar\n", "foo"); 241 test = np_extract_ntpvar("foo=bar\n", "foo");
244 ok(test && !strcmp(test, "bar"), "Single test as expected"); 242 ok(test && !strcmp(test, "bar"), "Single test as expected");
245 free(test); 243 free(test);
246 244
247 test=np_extract_ntpvar("foo=bar, bar=foo, foobar=barfooi\n", "abcd"); 245 test = np_extract_ntpvar("foo=bar, bar=foo, foobar=barfooi\n", "abcd");
248 ok(!test, "Key not found 1"); 246 ok(!test, "Key not found 1");
249 247
250 test=np_extract_ntpvar("foo=bar\n", "abcd"); 248 test = np_extract_ntpvar("foo=bar\n", "abcd");
251 ok(!test, "Key not found 2"); 249 ok(!test, "Key not found 2");
252 250
253 test=np_extract_ntpvar("foo=bar=foobar", "foo"); 251 test = np_extract_ntpvar("foo=bar=foobar", "foo");
254 ok(test && !strcmp(test, "bar=foobar"), "Strange string 1"); 252 ok(test && !strcmp(test, "bar=foobar"), "Strange string 1");
255 free(test); 253 free(test);
256 254
257 test=np_extract_ntpvar("foo", "foo"); 255 test = np_extract_ntpvar("foo", "foo");
258 ok(!test, "Malformed string 1"); 256 ok(!test, "Malformed string 1");
259 257
260 test=np_extract_ntpvar("foo,", "foo"); 258 test = np_extract_ntpvar("foo,", "foo");
261 ok(!test, "Malformed string 2"); 259 ok(!test, "Malformed string 2");
262 260
263 test=np_extract_ntpvar("foo=", "foo"); 261 test = np_extract_ntpvar("foo=", "foo");
264 ok(!test, "Malformed string 3"); 262 ok(!test, "Malformed string 3");
265 263
266 test=np_extract_ntpvar("foo=,bar=foo", "foo"); 264 test = np_extract_ntpvar("foo=,bar=foo", "foo");
267 ok(!test, "Malformed string 4"); 265 ok(!test, "Malformed string 4");
268 266
269 test=np_extract_ntpvar(",foo", "foo"); 267 test = np_extract_ntpvar(",foo", "foo");
270 ok(!test, "Malformed string 5"); 268 ok(!test, "Malformed string 5");
271 269
272 test=np_extract_ntpvar("=foo", "foo"); 270 test = np_extract_ntpvar("=foo", "foo");
273 ok(!test, "Malformed string 6"); 271 ok(!test, "Malformed string 6");
274 272
275 test=np_extract_ntpvar("=foo,", "foo"); 273 test = np_extract_ntpvar("=foo,", "foo");
276 ok(!test, "Malformed string 7"); 274 ok(!test, "Malformed string 7");
277 275
278 test=np_extract_ntpvar(",,,", "foo"); 276 test = np_extract_ntpvar(",,,", "foo");
279 ok(!test, "Malformed string 8"); 277 ok(!test, "Malformed string 8");
280 278
281 test=np_extract_ntpvar("===", "foo"); 279 test = np_extract_ntpvar("===", "foo");
282 ok(!test, "Malformed string 9"); 280 ok(!test, "Malformed string 9");
283 281
284 test=np_extract_ntpvar(",=,=,", "foo"); 282 test = np_extract_ntpvar(",=,=,", "foo");
285 ok(!test, "Malformed string 10"); 283 ok(!test, "Malformed string 10");
286 284
287 test=np_extract_ntpvar("=,=,=", "foo"); 285 test = np_extract_ntpvar("=,=,=", "foo");
288 ok(!test, "Malformed string 11"); 286 ok(!test, "Malformed string 11");
289 287
290 test=np_extract_ntpvar(" foo=bar ,\n bar=foo\n , foobar=barfoo \n ", "foo"); 288 test = np_extract_ntpvar(" foo=bar ,\n bar=foo\n , foobar=barfoo \n ", "foo");
291 ok(test && !strcmp(test, "bar"), "Random spaces and newlines 1"); 289 ok(test && !strcmp(test, "bar"), "Random spaces and newlines 1");
292 free(test); 290 free(test);
293 291
294 test=np_extract_ntpvar(" foo=bar ,\n bar=foo\n , foobar=barfoo \n ", "bar"); 292 test = np_extract_ntpvar(" foo=bar ,\n bar=foo\n , foobar=barfoo \n ", "bar");
295 ok(test && !strcmp(test, "foo"), "Random spaces and newlines 2"); 293 ok(test && !strcmp(test, "foo"), "Random spaces and newlines 2");
296 free(test); 294 free(test);
297 295
298 test=np_extract_ntpvar(" foo=bar ,\n bar=foo\n , foobar=barfoo \n ", "foobar"); 296 test = np_extract_ntpvar(" foo=bar ,\n bar=foo\n , foobar=barfoo \n ", "foobar");
299 ok(test && !strcmp(test, "barfoo"), "Random spaces and newlines 3"); 297 ok(test && !strcmp(test, "barfoo"), "Random spaces and newlines 3");
300 free(test); 298 free(test);
301 299
302 test=np_extract_ntpvar(" foo=bar ,\n bar\n \n= \n foo\n , foobar=barfoo \n ", "bar"); 300 test = np_extract_ntpvar(" foo=bar ,\n bar\n \n= \n foo\n , foobar=barfoo \n ", "bar");
303 ok(test && !strcmp(test, "foo"), "Random spaces and newlines 4"); 301 ok(test && !strcmp(test, "foo"), "Random spaces and newlines 4");
304 free(test); 302 free(test);
305 303
306 test=np_extract_ntpvar("", "foo"); 304 test = np_extract_ntpvar("", "foo");
307 ok(!test, "Empty string return NULL"); 305 ok(!test, "Empty string return NULL");
308 306
309
310 /* This is the result of running ./test_utils */ 307 /* This is the result of running ./test_utils */
311 temp_string = (char *) _np_state_generate_key(); 308 temp_string = (char *)_np_state_generate_key();
312 ok(!strcmp(temp_string, "e2d17f995fd4c020411b85e3e3d0ff7306d4147e"), "Got hash with exe and no parameters" ) || 309 ok(!strcmp(temp_string, "e2d17f995fd4c020411b85e3e3d0ff7306d4147e"), "Got hash with exe and no parameters") ||
313 diag( "You are probably running in wrong directory. Must run as ./test_utils" ); 310 diag("You are probably running in wrong directory. Must run as ./test_utils");
314
315 311
316 this_monitoring_plugin->argc=4; 312 this_monitoring_plugin->argc = 4;
317 this_monitoring_plugin->argv[0] = "./test_utils"; 313 this_monitoring_plugin->argv[0] = "./test_utils";
318 this_monitoring_plugin->argv[1] = "here"; 314 this_monitoring_plugin->argv[1] = "here";
319 this_monitoring_plugin->argv[2] = "--and"; 315 this_monitoring_plugin->argv[2] = "--and";
320 this_monitoring_plugin->argv[3] = "now"; 316 this_monitoring_plugin->argv[3] = "now";
321 temp_string = (char *) _np_state_generate_key(); 317 temp_string = (char *)_np_state_generate_key();
322 ok(!strcmp(temp_string, "bd72da9f78ff1419fad921ea5e43ce56508aef6c"), "Got based on expected argv" ); 318 ok(!strcmp(temp_string, "bd72da9f78ff1419fad921ea5e43ce56508aef6c"), "Got based on expected argv");
323 319
324 unsetenv("MP_STATE_PATH"); 320 unsetenv("MP_STATE_PATH");
325 temp_string = (char *) _np_state_calculate_location_prefix(); 321 temp_string = (char *)_np_state_calculate_location_prefix();
326 ok(!strcmp(temp_string, NP_STATE_DIR_PREFIX), "Got default directory" ); 322 ok(!strcmp(temp_string, NP_STATE_DIR_PREFIX), "Got default directory");
327 323
328 setenv("MP_STATE_PATH", "", 1); 324 setenv("MP_STATE_PATH", "", 1);
329 temp_string = (char *) _np_state_calculate_location_prefix(); 325 temp_string = (char *)_np_state_calculate_location_prefix();
330 ok(!strcmp(temp_string, NP_STATE_DIR_PREFIX), "Got default directory even with empty string" ); 326 ok(!strcmp(temp_string, NP_STATE_DIR_PREFIX), "Got default directory even with empty string");
331 327
332 setenv("MP_STATE_PATH", "/usr/local/nagios/var", 1); 328 setenv("MP_STATE_PATH", "/usr/local/nagios/var", 1);
333 temp_string = (char *) _np_state_calculate_location_prefix(); 329 temp_string = (char *)_np_state_calculate_location_prefix();
334 ok(!strcmp(temp_string, "/usr/local/nagios/var"), "Got default directory" ); 330 ok(!strcmp(temp_string, "/usr/local/nagios/var"), "Got default directory");
335
336 331
332 ok(temp_state_key == NULL, "temp_state_key initially empty");
337 333
338 ok(temp_state_key==NULL, "temp_state_key initially empty"); 334 this_monitoring_plugin->argc = 1;
339
340 this_monitoring_plugin->argc=1;
341 this_monitoring_plugin->argv[0] = "./test_utils"; 335 this_monitoring_plugin->argv[0] = "./test_utils";
342 np_enable_state(NULL, 51); 336 np_enable_state(NULL, 51);
343 temp_state_key = this_monitoring_plugin->state; 337 temp_state_key = this_monitoring_plugin->state;
344 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); 338 ok(!strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name");
345 ok( !strcmp(temp_state_key->name, "e2d17f995fd4c020411b85e3e3d0ff7306d4147e"), "Got generated filename" ); 339 ok(!strcmp(temp_state_key->name, "e2d17f995fd4c020411b85e3e3d0ff7306d4147e"), "Got generated filename");
346
347 340
348 np_enable_state("allowedchars_in_keyname", 77); 341 np_enable_state("allowedchars_in_keyname", 77);
349 temp_state_key = this_monitoring_plugin->state; 342 temp_state_key = this_monitoring_plugin->state;
350 sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/allowedchars_in_keyname", (unsigned long)geteuid()); 343 sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/allowedchars_in_keyname", (unsigned long)geteuid());
351 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); 344 ok(!strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name");
352 ok( !strcmp(temp_state_key->name, "allowedchars_in_keyname"), "Got key name with valid chars" ); 345 ok(!strcmp(temp_state_key->name, "allowedchars_in_keyname"), "Got key name with valid chars");
353 ok( !strcmp(temp_state_key->_filename, state_path), "Got internal filename" ); 346 ok(!strcmp(temp_state_key->_filename, state_path), "Got internal filename");
354
355 347
356 /* Don't do this test just yet. Will die */ 348 /* Don't do this test just yet. Will die */
357 /* 349 /*
@@ -363,73 +355,65 @@ main (int argc, char **argv)
363 np_enable_state("funnykeyname", 54); 355 np_enable_state("funnykeyname", 54);
364 temp_state_key = this_monitoring_plugin->state; 356 temp_state_key = this_monitoring_plugin->state;
365 sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/funnykeyname", (unsigned long)geteuid()); 357 sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/funnykeyname", (unsigned long)geteuid());
366 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); 358 ok(!strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name");
367 ok( !strcmp(temp_state_key->name, "funnykeyname"), "Got key name" ); 359 ok(!strcmp(temp_state_key->name, "funnykeyname"), "Got key name");
368 360
369 361 ok(!strcmp(temp_state_key->_filename, state_path), "Got internal filename");
370 362 ok(temp_state_key->data_version == 54, "Version set");
371 ok( !strcmp(temp_state_key->_filename, state_path), "Got internal filename" );
372 ok( temp_state_key->data_version==54, "Version set" );
373 363
374 temp_state_data = np_state_read(); 364 temp_state_data = np_state_read();
375 ok( temp_state_data==NULL, "Got no state data as file does not exist" ); 365 ok(temp_state_data == NULL, "Got no state data as file does not exist");
376
377 366
378/* 367 /*
379 temp_fp = fopen("var/statefile", "r"); 368 temp_fp = fopen("var/statefile", "r");
380 if (temp_fp==NULL) 369 if (temp_fp==NULL)
381 printf("Error opening. errno=%d\n", errno); 370 printf("Error opening. errno=%d\n", errno);
382 printf("temp_fp=%s\n", temp_fp); 371 printf("temp_fp=%s\n", temp_fp);
383 ok( _np_state_read_file(temp_fp) == true, "Can read state file" ); 372 ok( _np_state_read_file(temp_fp) == true, "Can read state file" );
384 fclose(temp_fp); 373 fclose(temp_fp);
385*/ 374 */
386 375
387 temp_state_key->_filename="var/statefile"; 376 temp_state_key->_filename = "var/statefile";
388 temp_state_data = np_state_read(); 377 temp_state_data = np_state_read();
389 ok( this_monitoring_plugin->state->state_data!=NULL, "Got state data now" ) || diag("Are you running in right directory? Will get coredump next if not"); 378 ok(this_monitoring_plugin->state->state_data != NULL, "Got state data now") ||
390 ok( this_monitoring_plugin->state->state_data->time==1234567890, "Got time" ); 379 diag("Are you running in right directory? Will get coredump next if not");
391 ok( !strcmp((char *)this_monitoring_plugin->state->state_data->data, "String to read"), "Data as expected" ); 380 ok(this_monitoring_plugin->state->state_data->time == 1234567890, "Got time");
381 ok(!strcmp((char *)this_monitoring_plugin->state->state_data->data, "String to read"), "Data as expected");
392 382
393 temp_state_key->data_version=53; 383 temp_state_key->data_version = 53;
394 temp_state_data = np_state_read(); 384 temp_state_data = np_state_read();
395 ok( temp_state_data==NULL, "Older data version gives NULL" ); 385 ok(temp_state_data == NULL, "Older data version gives NULL");
396 temp_state_key->data_version=54; 386 temp_state_key->data_version = 54;
397 387
398 temp_state_key->_filename="var/nonexistent"; 388 temp_state_key->_filename = "var/nonexistent";
399 temp_state_data = np_state_read(); 389 temp_state_data = np_state_read();
400 ok( temp_state_data==NULL, "Missing file gives NULL" ); 390 ok(temp_state_data == NULL, "Missing file gives NULL");
401 ok( this_monitoring_plugin->state->state_data==NULL, "No state information" ); 391 ok(this_monitoring_plugin->state->state_data == NULL, "No state information");
402 392
403 temp_state_key->_filename="var/oldformat"; 393 temp_state_key->_filename = "var/oldformat";
404 temp_state_data = np_state_read(); 394 temp_state_data = np_state_read();
405 ok( temp_state_data==NULL, "Old file format gives NULL" ); 395 ok(temp_state_data == NULL, "Old file format gives NULL");
406 396
407 temp_state_key->_filename="var/baddate"; 397 temp_state_key->_filename = "var/baddate";
408 temp_state_data = np_state_read(); 398 temp_state_data = np_state_read();
409 ok( temp_state_data==NULL, "Bad date gives NULL" ); 399 ok(temp_state_data == NULL, "Bad date gives NULL");
410 400
411 temp_state_key->_filename="var/missingdataline"; 401 temp_state_key->_filename = "var/missingdataline";
412 temp_state_data = np_state_read(); 402 temp_state_data = np_state_read();
413 ok( temp_state_data==NULL, "Missing data line gives NULL" ); 403 ok(temp_state_data == NULL, "Missing data line gives NULL");
414
415
416
417 404
418 unlink("var/generated"); 405 unlink("var/generated");
419 temp_state_key->_filename="var/generated"; 406 temp_state_key->_filename = "var/generated";
420 current_time=1234567890; 407 current_time = 1234567890;
421 np_state_write_string(current_time, "String to read"); 408 np_state_write_string(current_time, "String to read");
422 ok(system("cmp var/generated var/statefile")==0, "Generated file same as expected"); 409 ok(system("cmp var/generated var/statefile") == 0, "Generated file same as expected");
423
424
425
426 410
427 unlink("var/generated_directory/statefile"); 411 unlink("var/generated_directory/statefile");
428 unlink("var/generated_directory"); 412 unlink("var/generated_directory");
429 temp_state_key->_filename="var/generated_directory/statefile"; 413 temp_state_key->_filename = "var/generated_directory/statefile";
430 current_time=1234567890; 414 current_time = 1234567890;
431 np_state_write_string(current_time, "String to read"); 415 np_state_write_string(current_time, "String to read");
432 ok(system("cmp var/generated_directory/statefile var/statefile")==0, "Have created directory"); 416 ok(system("cmp var/generated_directory/statefile var/statefile") == 0, "Have created directory");
433 417
434 /* This test to check cannot write to dir - can't automate yet */ 418 /* This test to check cannot write to dir - can't automate yet */
435 /* 419 /*
@@ -438,15 +422,13 @@ main (int argc, char **argv)
438 np_state_write_string(current_time, "String to read"); 422 np_state_write_string(current_time, "String to read");
439 */ 423 */
440 424
441 425 temp_state_key->_filename = "var/generated";
442 temp_state_key->_filename="var/generated";
443 time(&current_time); 426 time(&current_time);
444 np_state_write_string(0, "String to read"); 427 np_state_write_string(0, "String to read");
445 temp_state_data = np_state_read(); 428 temp_state_data = np_state_read();
446 /* Check time is set to current_time */ 429 /* Check time is set to current_time */
447 ok(system("cmp var/generated var/statefile > /dev/null")!=0, "Generated file should be different this time"); 430 ok(system("cmp var/generated var/statefile > /dev/null") != 0, "Generated file should be different this time");
448 ok(this_monitoring_plugin->state->state_data->time-current_time<=1, "Has time generated from current time"); 431 ok(this_monitoring_plugin->state->state_data->time - current_time <= 1, "Has time generated from current time");
449
450 432
451 /* Don't know how to automatically test this. Need to be able to redefine die and catch the error */ 433 /* Don't know how to automatically test this. Need to be able to redefine die and catch the error */
452 /* 434 /*
@@ -454,23 +436,16 @@ main (int argc, char **argv)
454 np_state_write_string(0, "Bad file"); 436 np_state_write_string(0, "Bad file");
455 */ 437 */
456 438
457
458 np_cleanup(); 439 np_cleanup();
459 440
460 ok(this_monitoring_plugin==NULL, "Free'd this_monitoring_plugin"); 441 ok(this_monitoring_plugin == NULL, "Free'd this_monitoring_plugin");
461 442
462 ok(mp_suid() == false, "Test aren't suid"); 443 ok(mp_suid() == false, "Test aren't suid");
463 444
464 /* base states with random case */ 445 /* base states with random case */
465 char *states[] = { 446 char *states[] = {"Ok", "wArnINg", "cRiTIcaL", "UnKNoWN", NULL};
466 "Ok", 447
467 "wArnINg", 448 for (i = 0; states[i] != NULL; i++) {
468 "cRiTIcaL",
469 "UnKNoWN",
470 NULL
471 };
472
473 for (i=0; states[i]!=NULL; i++) {
474 /* out of the random case states, create the lower and upper versions + numeric string one */ 449 /* out of the random case states, create the lower and upper versions + numeric string one */
475 char *statelower = strdup(states[i]); 450 char *statelower = strdup(states[i]);
476 char *stateupper = strdup(states[i]); 451 char *stateupper = strdup(states[i]);
@@ -488,23 +463,23 @@ main (int argc, char **argv)
488 char testname[64] = "Translate state string: "; 463 char testname[64] = "Translate state string: ";
489 int tlen = strlen(testname); 464 int tlen = strlen(testname);
490 465
491 strcpy(testname+tlen, states[i]); 466 strcpy(testname + tlen, states[i]);
492 ok(i==mp_translate_state(states[i]), testname); 467 ok(i == mp_translate_state(states[i]), testname);
493 468
494 strcpy(testname+tlen, statelower); 469 strcpy(testname + tlen, statelower);
495 ok(i==mp_translate_state(statelower), testname); 470 ok(i == mp_translate_state(statelower), testname);
496 471
497 strcpy(testname+tlen, stateupper); 472 strcpy(testname + tlen, stateupper);
498 ok(i==mp_translate_state(stateupper), testname); 473 ok(i == mp_translate_state(stateupper), testname);
499 474
500 strcpy(testname+tlen, statenum); 475 strcpy(testname + tlen, statenum);
501 ok(i==mp_translate_state(statenum), testname); 476 ok(i == mp_translate_state(statenum), testname);
502 } 477 }
503 ok(ERROR==mp_translate_state("warningfewgw"), "Translate state string with garbage"); 478 ok(ERROR == mp_translate_state("warningfewgw"), "Translate state string with garbage");
504 ok(ERROR==mp_translate_state("00"), "Translate state string: bad numeric string 1"); 479 ok(ERROR == mp_translate_state("00"), "Translate state string: bad numeric string 1");
505 ok(ERROR==mp_translate_state("01"), "Translate state string: bad numeric string 2"); 480 ok(ERROR == mp_translate_state("01"), "Translate state string: bad numeric string 2");
506 ok(ERROR==mp_translate_state("10"), "Translate state string: bad numeric string 3"); 481 ok(ERROR == mp_translate_state("10"), "Translate state string: bad numeric string 3");
507 ok(ERROR==mp_translate_state(""), "Translate state string: empty string"); 482 ok(ERROR == mp_translate_state(""), "Translate state string: empty string");
508 483
509 return exit_status(); 484 return exit_status();
510} 485}
diff --git a/lib/utils_base.c b/lib/utils_base.c
index f8592f41..90a4aaa5 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -1,28 +1,28 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* utils_base.c 3 * utils_base.c
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2006 Monitoring Plugins Development Team 6 * Copyright (c) 2006 - 2024 Monitoring Plugins Development Team
7* 7 *
8* Library of useful functions for plugins 8 * Library of useful functions for plugins
9* 9 *
10* 10 *
11* This program is free software: you can redistribute it and/or modify 11 * This program is free software: you can redistribute it and/or modify
12* it under the terms of the GNU General Public License as published by 12 * it under the terms of the GNU General Public License as published by
13* the Free Software Foundation, either version 3 of the License, or 13 * the Free Software Foundation, either version 3 of the License, or
14* (at your option) any later version. 14 * (at your option) any later version.
15* 15 *
16* This program is distributed in the hope that it will be useful, 16 * This program is distributed in the hope that it will be useful,
17* but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19* GNU General Public License for more details. 19 * GNU General Public License for more details.
20* 20 *
21* You should have received a copy of the GNU General Public License 21 * You should have received a copy of the GNU General Public License
22* along with this program. If not, see <http://www.gnu.org/licenses/>. 22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23* 23 *
24* 24 *
25*****************************************************************************/ 25 *****************************************************************************/
26 26
27#include "../plugins/common.h" 27#include "../plugins/common.h"
28#include <stdarg.h> 28#include <stdarg.h>
@@ -33,43 +33,47 @@
33#include <unistd.h> 33#include <unistd.h>
34#include <sys/types.h> 34#include <sys/types.h>
35 35
36#define np_free(ptr) { if(ptr) { free(ptr); ptr = NULL; } } 36#define np_free(ptr) \
37 { \
38 if (ptr) { \
39 free(ptr); \
40 ptr = NULL; \
41 } \
42 }
37 43
38monitoring_plugin *this_monitoring_plugin=NULL; 44monitoring_plugin *this_monitoring_plugin = NULL;
39 45
40int timeout_state = STATE_CRITICAL; 46int timeout_state = STATE_CRITICAL;
41unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT; 47unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
42 48
43bool _np_state_read_file(FILE *); 49bool _np_state_read_file(FILE *);
44 50
45void np_init( char *plugin_name, int argc, char **argv ) { 51void np_init(char *plugin_name, int argc, char **argv) {
46 if (this_monitoring_plugin==NULL) { 52 if (this_monitoring_plugin == NULL) {
47 this_monitoring_plugin = calloc(1, sizeof(monitoring_plugin)); 53 this_monitoring_plugin = calloc(1, sizeof(monitoring_plugin));
48 if (this_monitoring_plugin==NULL) { 54 if (this_monitoring_plugin == NULL) {
49 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 55 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
50 strerror(errno));
51 } 56 }
52 this_monitoring_plugin->plugin_name = strdup(plugin_name); 57 this_monitoring_plugin->plugin_name = strdup(plugin_name);
53 if (this_monitoring_plugin->plugin_name==NULL) 58 if (this_monitoring_plugin->plugin_name == NULL)
54 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 59 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
55 this_monitoring_plugin->argc = argc; 60 this_monitoring_plugin->argc = argc;
56 this_monitoring_plugin->argv = argv; 61 this_monitoring_plugin->argv = argv;
57 } 62 }
58} 63}
59 64
60void np_set_args( int argc, char **argv ) { 65void np_set_args(int argc, char **argv) {
61 if (this_monitoring_plugin==NULL) 66 if (this_monitoring_plugin == NULL)
62 die(STATE_UNKNOWN, _("This requires np_init to be called")); 67 die(STATE_UNKNOWN, _("This requires np_init to be called"));
63 68
64 this_monitoring_plugin->argc = argc; 69 this_monitoring_plugin->argc = argc;
65 this_monitoring_plugin->argv = argv; 70 this_monitoring_plugin->argv = argv;
66} 71}
67 72
68
69void np_cleanup() { 73void np_cleanup() {
70 if (this_monitoring_plugin!=NULL) { 74 if (this_monitoring_plugin != NULL) {
71 if(this_monitoring_plugin->state!=NULL) { 75 if (this_monitoring_plugin->state != NULL) {
72 if(this_monitoring_plugin->state->state_data) { 76 if (this_monitoring_plugin->state->state_data) {
73 np_free(this_monitoring_plugin->state->state_data->data); 77 np_free(this_monitoring_plugin->state->state_data->data);
74 np_free(this_monitoring_plugin->state->state_data); 78 np_free(this_monitoring_plugin->state->state_data);
75 } 79 }
@@ -79,48 +83,43 @@ void np_cleanup() {
79 np_free(this_monitoring_plugin->plugin_name); 83 np_free(this_monitoring_plugin->plugin_name);
80 np_free(this_monitoring_plugin); 84 np_free(this_monitoring_plugin);
81 } 85 }
82 this_monitoring_plugin=NULL; 86 this_monitoring_plugin = NULL;
83} 87}
84 88
85/* Hidden function to get a pointer to this_monitoring_plugin for testing */ 89/* Hidden function to get a pointer to this_monitoring_plugin for testing */
86void _get_monitoring_plugin( monitoring_plugin **pointer ){ 90void _get_monitoring_plugin(monitoring_plugin **pointer) { *pointer = this_monitoring_plugin; }
87 *pointer = this_monitoring_plugin;
88}
89 91
90void 92void die(int result, const char *fmt, ...) {
91die (int result, const char *fmt, ...) 93 if (fmt != NULL) {
92{
93 if(fmt!=NULL) {
94 va_list ap; 94 va_list ap;
95 va_start (ap, fmt); 95 va_start(ap, fmt);
96 vprintf (fmt, ap); 96 vprintf(fmt, ap);
97 va_end (ap); 97 va_end(ap);
98 } 98 }
99 99
100 if(this_monitoring_plugin!=NULL) { 100 if (this_monitoring_plugin != NULL) {
101 np_cleanup(); 101 np_cleanup();
102 } 102 }
103 exit (result); 103 exit(result);
104} 104}
105 105
106void set_range_start (range *this, double value) { 106void set_range_start(range *this, double value) {
107 this->start = value; 107 this->start = value;
108 this->start_infinity = false; 108 this->start_infinity = false;
109} 109}
110 110
111void set_range_end (range *this, double value) { 111void set_range_end(range *this, double value) {
112 this->end = value; 112 this->end = value;
113 this->end_infinity = false; 113 this->end_infinity = false;
114} 114}
115 115
116range 116range *parse_range_string(char *str) {
117*parse_range_string (char *str) {
118 range *temp_range; 117 range *temp_range;
119 double start; 118 double start;
120 double end; 119 double end;
121 char *end_str; 120 char *end_str;
122 121
123 temp_range = (range *) calloc(1, sizeof(range)); 122 temp_range = (range *)calloc(1, sizeof(range));
124 123
125 /* Set defaults */ 124 /* Set defaults */
126 temp_range->start = 0; 125 temp_range->start = 0;
@@ -140,10 +139,10 @@ range
140 if (str[0] == '~') { 139 if (str[0] == '~') {
141 temp_range->start_infinity = true; 140 temp_range->start_infinity = true;
142 } else { 141 } else {
143 start = strtod(str, NULL); /* Will stop at the ':' */ 142 start = strtod(str, NULL); /* Will stop at the ':' */
144 set_range_start(temp_range, start); 143 set_range_start(temp_range, start);
145 } 144 }
146 end_str++; /* Move past the ':' */ 145 end_str++; /* Move past the ':' */
147 } else { 146 } else {
148 end_str = str; 147 end_str = str;
149 } 148 }
@@ -152,9 +151,7 @@ range
152 set_range_end(temp_range, end); 151 set_range_end(temp_range, end);
153 } 152 }
154 153
155 if (temp_range->start_infinity == true || 154 if (temp_range->start_infinity == true || temp_range->end_infinity == true || temp_range->start <= temp_range->end) {
156 temp_range->end_infinity == true ||
157 temp_range->start <= temp_range->end) {
158 return temp_range; 155 return temp_range;
159 } 156 }
160 free(temp_range); 157 free(temp_range);
@@ -162,14 +159,11 @@ range
162} 159}
163 160
164/* returns 0 if okay, otherwise 1 */ 161/* returns 0 if okay, otherwise 1 */
165int 162int _set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string) {
166_set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string)
167{
168 thresholds *temp_thresholds = NULL; 163 thresholds *temp_thresholds = NULL;
169 164
170 if ((temp_thresholds = calloc(1, sizeof(thresholds))) == NULL) 165 if ((temp_thresholds = calloc(1, sizeof(thresholds))) == NULL)
171 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 166 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
172 strerror(errno));
173 167
174 temp_thresholds->warning = NULL; 168 temp_thresholds->warning = NULL;
175 temp_thresholds->critical = NULL; 169 temp_thresholds->critical = NULL;
@@ -190,9 +184,7 @@ _set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_st
190 return 0; 184 return 0;
191} 185}
192 186
193void 187void set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string) {
194set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string)
195{
196 switch (_set_thresholds(my_thresholds, warn_string, critical_string)) { 188 switch (_set_thresholds(my_thresholds, warn_string, critical_string)) {
197 case 0: 189 case 0:
198 return; 190 return;
@@ -206,7 +198,7 @@ set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_str
206 198
207void print_thresholds(const char *threshold_name, thresholds *my_threshold) { 199void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
208 printf("%s - ", threshold_name); 200 printf("%s - ", threshold_name);
209 if (! my_threshold) { 201 if (!my_threshold) {
210 printf("Threshold not set"); 202 printf("Threshold not set");
211 } else { 203 } else {
212 if (my_threshold->warning) { 204 if (my_threshold->warning) {
@@ -224,8 +216,7 @@ void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
224} 216}
225 217
226/* Returns true if alert should be raised based on the range */ 218/* Returns true if alert should be raised based on the range */
227bool check_range(double value, range *my_range) 219bool check_range(double value, range *my_range) {
228{
229 bool no = false; 220 bool no = false;
230 bool yes = true; 221 bool yes = true;
231 222
@@ -258,9 +249,7 @@ bool check_range(double value, range *my_range)
258} 249}
259 250
260/* Returns status */ 251/* Returns status */
261int 252int get_status(double value, thresholds *my_thresholds) {
262get_status(double value, thresholds *my_thresholds)
263{
264 if (my_thresholds->critical != NULL) { 253 if (my_thresholds->critical != NULL) {
265 if (check_range(value, my_thresholds->critical) == true) { 254 if (check_range(value, my_thresholds->critical) == true) {
266 return STATE_CRITICAL; 255 return STATE_CRITICAL;
@@ -274,27 +263,27 @@ get_status(double value, thresholds *my_thresholds)
274 return STATE_OK; 263 return STATE_OK;
275} 264}
276 265
277char *np_escaped_string (const char *string) { 266char *np_escaped_string(const char *string) {
278 char *data; 267 char *data;
279 int i, j=0; 268 int i, j = 0;
280 data = strdup(string); 269 data = strdup(string);
281 for (i=0; data[i]; i++) { 270 for (i = 0; data[i]; i++) {
282 if (data[i] == '\\') { 271 if (data[i] == '\\') {
283 switch(data[++i]) { 272 switch (data[++i]) {
284 case 'n': 273 case 'n':
285 data[j++] = '\n'; 274 data[j++] = '\n';
286 break; 275 break;
287 case 'r': 276 case 'r':
288 data[j++] = '\r'; 277 data[j++] = '\r';
289 break; 278 break;
290 case 't': 279 case 't':
291 data[j++] = '\t'; 280 data[j++] = '\t';
292 break; 281 break;
293 case '\\': 282 case '\\':
294 data[j++] = '\\'; 283 data[j++] = '\\';
295 break; 284 break;
296 default: 285 default:
297 data[j++] = data[i]; 286 data[j++] = data[i];
298 } 287 }
299 } else { 288 } else {
300 data[j++] = data[i]; 289 data[j++] = data[i];
@@ -313,33 +302,38 @@ int np_check_if_root(void) { return (geteuid() == 0); }
313 * data strings. 302 * data strings.
314 */ 303 */
315char *np_extract_value(const char *varlist, const char *name, char sep) { 304char *np_extract_value(const char *varlist, const char *name, char sep) {
316 char *tmp=NULL, *value=NULL; 305 char *tmp = NULL, *value = NULL;
317 int i; 306 int i;
318 307
319 while (1) { 308 while (1) {
320 /* Strip any leading space */ 309 /* Strip any leading space */
321 for (; isspace(varlist[0]); varlist++); 310 for (; isspace(varlist[0]); varlist++)
311 ;
322 312
323 if (strncmp(name, varlist, strlen(name)) == 0) { 313 if (strncmp(name, varlist, strlen(name)) == 0) {
324 varlist += strlen(name); 314 varlist += strlen(name);
325 /* strip trailing spaces */ 315 /* strip trailing spaces */
326 for (; isspace(varlist[0]); varlist++); 316 for (; isspace(varlist[0]); varlist++)
317 ;
327 318
328 if (varlist[0] == '=') { 319 if (varlist[0] == '=') {
329 /* We matched the key, go past the = sign */ 320 /* We matched the key, go past the = sign */
330 varlist++; 321 varlist++;
331 /* strip leading spaces */ 322 /* strip leading spaces */
332 for (; isspace(varlist[0]); varlist++); 323 for (; isspace(varlist[0]); varlist++)
324 ;
333 325
334 if ((tmp = index(varlist, sep))) { 326 if ((tmp = index(varlist, sep))) {
335 /* Value is delimited by a comma */ 327 /* Value is delimited by a comma */
336 if (tmp-varlist == 0) continue; 328 if (tmp - varlist == 0)
337 value = (char *)calloc(1, tmp-varlist+1); 329 continue;
338 strncpy(value, varlist, tmp-varlist); 330 value = (char *)calloc(1, tmp - varlist + 1);
339 value[tmp-varlist] = '\0'; 331 strncpy(value, varlist, tmp - varlist);
332 value[tmp - varlist] = '\0';
340 } else { 333 } else {
341 /* Value is delimited by a \0 */ 334 /* Value is delimited by a \0 */
342 if (strlen(varlist) == 0) continue; 335 if (strlen(varlist) == 0)
336 continue;
343 value = (char *)calloc(1, strlen(varlist) + 1); 337 value = (char *)calloc(1, strlen(varlist) + 1);
344 strncpy(value, varlist, strlen(varlist)); 338 strncpy(value, varlist, strlen(varlist));
345 value[strlen(varlist)] = '\0'; 339 value[strlen(varlist)] = '\0';
@@ -357,14 +351,14 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
357 } 351 }
358 352
359 /* Clean-up trailing spaces/newlines */ 353 /* Clean-up trailing spaces/newlines */
360 if (value) for (i=strlen(value)-1; isspace(value[i]); i--) value[i] = '\0'; 354 if (value)
355 for (i = strlen(value) - 1; isspace(value[i]); i--)
356 value[i] = '\0';
361 357
362 return value; 358 return value;
363} 359}
364 360
365const char * 361const char *state_text(int result) {
366state_text (int result)
367{
368 switch (result) { 362 switch (result) {
369 case STATE_OK: 363 case STATE_OK:
370 return "OK"; 364 return "OK";
@@ -383,14 +377,14 @@ state_text (int result)
383 * Read a string representing a state (ok, warning... or numeric: 0, 1) and 377 * Read a string representing a state (ok, warning... or numeric: 0, 1) and
384 * return the corresponding STATE_ value or ERROR) 378 * return the corresponding STATE_ value or ERROR)
385 */ 379 */
386int mp_translate_state (char *state_text) { 380int mp_translate_state(char *state_text) {
387 if (!strcasecmp(state_text,"OK") || !strcmp(state_text,"0")) 381 if (!strcasecmp(state_text, "OK") || !strcmp(state_text, "0"))
388 return STATE_OK; 382 return STATE_OK;
389 if (!strcasecmp(state_text,"WARNING") || !strcmp(state_text,"1")) 383 if (!strcasecmp(state_text, "WARNING") || !strcmp(state_text, "1"))
390 return STATE_WARNING; 384 return STATE_WARNING;
391 if (!strcasecmp(state_text,"CRITICAL") || !strcmp(state_text,"2")) 385 if (!strcasecmp(state_text, "CRITICAL") || !strcmp(state_text, "2"))
392 return STATE_CRITICAL; 386 return STATE_CRITICAL;
393 if (!strcasecmp(state_text,"UNKNOWN") || !strcmp(state_text,"3")) 387 if (!strcasecmp(state_text, "UNKNOWN") || !strcmp(state_text, "3"))
394 return STATE_UNKNOWN; 388 return STATE_UNKNOWN;
395 return ERROR; 389 return ERROR;
396} 390}
@@ -404,7 +398,7 @@ char *_np_state_generate_key() {
404 int i; 398 int i;
405 char **argv = this_monitoring_plugin->argv; 399 char **argv = this_monitoring_plugin->argv;
406 char keyname[41]; 400 char keyname[41];
407 char *p=NULL; 401 char *p = NULL;
408 402
409 unsigned char result[256]; 403 unsigned char result[256];
410 404
@@ -418,7 +412,7 @@ char *_np_state_generate_key() {
418 412
419 EVP_DigestInit(ctx, EVP_sha256()); 413 EVP_DigestInit(ctx, EVP_sha256());
420 414
421 for(i=0; i<this_monitoring_plugin->argc; i++) { 415 for (i = 0; i < this_monitoring_plugin->argc; i++) {
422 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i])); 416 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i]));
423 } 417 }
424 418
@@ -427,28 +421,28 @@ char *_np_state_generate_key() {
427 421
428 struct sha256_ctx ctx; 422 struct sha256_ctx ctx;
429 423
430 for(i=0; i<this_monitoring_plugin->argc; i++) { 424 for (i = 0; i < this_monitoring_plugin->argc; i++) {
431 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx); 425 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx);
432 } 426 }
433 427
434 sha256_finish_ctx(&ctx, result); 428 sha256_finish_ctx(&ctx, result);
435#endif // FOUNDOPENSSL 429#endif // FOUNDOPENSSL
436 430
437 for (i=0; i<20; ++i) { 431 for (i = 0; i < 20; ++i) {
438 sprintf(&keyname[2*i], "%02x", result[i]); 432 sprintf(&keyname[2 * i], "%02x", result[i]);
439 } 433 }
440 434
441 keyname[40]='\0'; 435 keyname[40] = '\0';
442 436
443 p = strdup(keyname); 437 p = strdup(keyname);
444 if(p==NULL) { 438 if (p == NULL) {
445 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 439 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
446 } 440 }
447 return p; 441 return p;
448} 442}
449 443
450void _cleanup_state_data() { 444void _cleanup_state_data() {
451 if (this_monitoring_plugin->state->state_data!=NULL) { 445 if (this_monitoring_plugin->state->state_data != NULL) {
452 np_free(this_monitoring_plugin->state->state_data->data); 446 np_free(this_monitoring_plugin->state->state_data->data);
453 np_free(this_monitoring_plugin->state->state_data); 447 np_free(this_monitoring_plugin->state->state_data);
454 } 448 }
@@ -459,18 +453,18 @@ void _cleanup_state_data() {
459 * envvar NAGIOS_PLUGIN_STATE_DIRECTORY 453 * envvar NAGIOS_PLUGIN_STATE_DIRECTORY
460 * statically compiled shared state directory 454 * statically compiled shared state directory
461 */ 455 */
462char* _np_state_calculate_location_prefix(){ 456char *_np_state_calculate_location_prefix() {
463 char *env_dir; 457 char *env_dir;
464 458
465 /* Do not allow passing MP_STATE_PATH in setuid plugins 459 /* Do not allow passing MP_STATE_PATH in setuid plugins
466 * for security reasons */ 460 * for security reasons */
467 if (!mp_suid()) { 461 if (!mp_suid()) {
468 env_dir = getenv("MP_STATE_PATH"); 462 env_dir = getenv("MP_STATE_PATH");
469 if(env_dir && env_dir[0] != '\0') 463 if (env_dir && env_dir[0] != '\0')
470 return env_dir; 464 return env_dir;
471 /* This is the former ENV, for backward-compatibility */ 465 /* This is the former ENV, for backward-compatibility */
472 env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY"); 466 env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY");
473 if(env_dir && env_dir[0] != '\0') 467 if (env_dir && env_dir[0] != '\0')
474 return env_dir; 468 return env_dir;
475 } 469 }
476 470
@@ -486,46 +480,43 @@ void np_enable_state(char *keyname, int expected_data_version) {
486 state_key *this_state = NULL; 480 state_key *this_state = NULL;
487 char *temp_filename = NULL; 481 char *temp_filename = NULL;
488 char *temp_keyname = NULL; 482 char *temp_keyname = NULL;
489 char *p=NULL; 483 char *p = NULL;
490 int ret; 484 int ret;
491 485
492 if(this_monitoring_plugin==NULL) 486 if (this_monitoring_plugin == NULL)
493 die(STATE_UNKNOWN, _("This requires np_init to be called")); 487 die(STATE_UNKNOWN, _("This requires np_init to be called"));
494 488
495 this_state = (state_key *) calloc(1, sizeof(state_key)); 489 this_state = (state_key *)calloc(1, sizeof(state_key));
496 if(this_state==NULL) 490 if (this_state == NULL)
497 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 491 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
498 strerror(errno));
499 492
500 if(keyname==NULL) { 493 if (keyname == NULL) {
501 temp_keyname = _np_state_generate_key(); 494 temp_keyname = _np_state_generate_key();
502 } else { 495 } else {
503 temp_keyname = strdup(keyname); 496 temp_keyname = strdup(keyname);
504 if(temp_keyname==NULL) 497 if (temp_keyname == NULL)
505 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 498 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
506 } 499 }
507 /* Die if invalid characters used for keyname */ 500 /* Die if invalid characters used for keyname */
508 p = temp_keyname; 501 p = temp_keyname;
509 while(*p!='\0') { 502 while (*p != '\0') {
510 if(! (isalnum(*p) || *p == '_')) { 503 if (!(isalnum(*p) || *p == '_')) {
511 die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'")); 504 die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'"));
512 } 505 }
513 p++; 506 p++;
514 } 507 }
515 this_state->name=temp_keyname; 508 this_state->name = temp_keyname;
516 this_state->plugin_name=this_monitoring_plugin->plugin_name; 509 this_state->plugin_name = this_monitoring_plugin->plugin_name;
517 this_state->data_version=expected_data_version; 510 this_state->data_version = expected_data_version;
518 this_state->state_data=NULL; 511 this_state->state_data = NULL;
519 512
520 /* Calculate filename */ 513 /* Calculate filename */
521 ret = asprintf(&temp_filename, "%s/%lu/%s/%s", 514 ret = asprintf(&temp_filename, "%s/%lu/%s/%s", _np_state_calculate_location_prefix(), (unsigned long)geteuid(),
522 _np_state_calculate_location_prefix(), (unsigned long)geteuid(), 515 this_monitoring_plugin->plugin_name, this_state->name);
523 this_monitoring_plugin->plugin_name, this_state->name);
524 if (ret < 0) 516 if (ret < 0)
525 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 517 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
526 strerror(errno));
527 518
528 this_state->_filename=temp_filename; 519 this_state->_filename = temp_filename;
529 520
530 this_monitoring_plugin->state = this_state; 521 this_monitoring_plugin->state = this_state;
531} 522}
@@ -538,23 +529,22 @@ void np_enable_state(char *keyname, int expected_data_version) {
538 * if exceptional error. 529 * if exceptional error.
539 */ 530 */
540state_data *np_state_read() { 531state_data *np_state_read() {
541 state_data *this_state_data=NULL; 532 state_data *this_state_data = NULL;
542 FILE *statefile; 533 FILE *statefile;
543 bool rc = false; 534 bool rc = false;
544 535
545 if(this_monitoring_plugin==NULL) 536 if (this_monitoring_plugin == NULL)
546 die(STATE_UNKNOWN, _("This requires np_init to be called")); 537 die(STATE_UNKNOWN, _("This requires np_init to be called"));
547 538
548 /* Open file. If this fails, no previous state found */ 539 /* Open file. If this fails, no previous state found */
549 statefile = fopen( this_monitoring_plugin->state->_filename, "r" ); 540 statefile = fopen(this_monitoring_plugin->state->_filename, "r");
550 if(statefile!=NULL) { 541 if (statefile != NULL) {
551 542
552 this_state_data = (state_data *) calloc(1, sizeof(state_data)); 543 this_state_data = (state_data *)calloc(1, sizeof(state_data));
553 if(this_state_data==NULL) 544 if (this_state_data == NULL)
554 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 545 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
555 strerror(errno));
556 546
557 this_state_data->data=NULL; 547 this_state_data->data = NULL;
558 this_monitoring_plugin->state->state_data = this_state_data; 548 this_monitoring_plugin->state->state_data = this_state_data;
559 549
560 rc = _np_state_read_file(statefile); 550 rc = _np_state_read_file(statefile);
@@ -562,7 +552,7 @@ state_data *np_state_read() {
562 fclose(statefile); 552 fclose(statefile);
563 } 553 }
564 554
565 if(!rc) { 555 if (!rc) {
566 _cleanup_state_data(); 556 _cleanup_state_data();
567 } 557 }
568 558
@@ -577,60 +567,65 @@ bool _np_state_read_file(FILE *f) {
577 size_t pos; 567 size_t pos;
578 char *line; 568 char *line;
579 int i; 569 int i;
580 int failure=0; 570 int failure = 0;
581 time_t current_time, data_time; 571 time_t current_time, data_time;
582 enum { STATE_FILE_VERSION, STATE_DATA_VERSION, STATE_DATA_TIME, STATE_DATA_TEXT, STATE_DATA_END } expected=STATE_FILE_VERSION; 572 enum {
573 STATE_FILE_VERSION,
574 STATE_DATA_VERSION,
575 STATE_DATA_TIME,
576 STATE_DATA_TEXT,
577 STATE_DATA_END
578 } expected = STATE_FILE_VERSION;
583 579
584 time(&current_time); 580 time(&current_time);
585 581
586 /* Note: This introduces a limit of 1024 bytes in the string data */ 582 /* Note: This introduces a limit of 1024 bytes in the string data */
587 line = (char *) calloc(1, 1024); 583 line = (char *)calloc(1, 1024);
588 if(line==NULL) 584 if (line == NULL)
589 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 585 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
590 strerror(errno)); 586
591 587 while (!failure && (fgets(line, 1024, f)) != NULL) {
592 while(!failure && (fgets(line,1024,f))!=NULL){ 588 pos = strlen(line);
593 pos=strlen(line); 589 if (line[pos - 1] == '\n') {
594 if(line[pos-1]=='\n') { 590 line[pos - 1] = '\0';
595 line[pos-1]='\0';
596 } 591 }
597 592
598 if(line[0] == '#') continue; 593 if (line[0] == '#')
594 continue;
599 595
600 switch(expected) { 596 switch (expected) {
601 case STATE_FILE_VERSION: 597 case STATE_FILE_VERSION:
602 i=atoi(line); 598 i = atoi(line);
603 if(i!=NP_STATE_FORMAT_VERSION) 599 if (i != NP_STATE_FORMAT_VERSION)
604 failure++; 600 failure++;
605 else 601 else
606 expected=STATE_DATA_VERSION; 602 expected = STATE_DATA_VERSION;
607 break; 603 break;
608 case STATE_DATA_VERSION: 604 case STATE_DATA_VERSION:
609 i=atoi(line); 605 i = atoi(line);
610 if(i != this_monitoring_plugin->state->data_version) 606 if (i != this_monitoring_plugin->state->data_version)
611 failure++; 607 failure++;
612 else 608 else
613 expected=STATE_DATA_TIME; 609 expected = STATE_DATA_TIME;
614 break; 610 break;
615 case STATE_DATA_TIME: 611 case STATE_DATA_TIME:
616 /* If time > now, error */ 612 /* If time > now, error */
617 data_time=strtoul(line,NULL,10); 613 data_time = strtoul(line, NULL, 10);
618 if(data_time > current_time) 614 if (data_time > current_time)
619 failure++; 615 failure++;
620 else { 616 else {
621 this_monitoring_plugin->state->state_data->time = data_time; 617 this_monitoring_plugin->state->state_data->time = data_time;
622 expected=STATE_DATA_TEXT; 618 expected = STATE_DATA_TEXT;
623 } 619 }
624 break; 620 break;
625 case STATE_DATA_TEXT: 621 case STATE_DATA_TEXT:
626 this_monitoring_plugin->state->state_data->data = strdup(line); 622 this_monitoring_plugin->state->state_data->data = strdup(line);
627 if(this_monitoring_plugin->state->state_data->data==NULL) 623 if (this_monitoring_plugin->state->state_data->data == NULL)
628 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 624 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
629 expected=STATE_DATA_END; 625 expected = STATE_DATA_END;
630 status=true; 626 status = true;
631 break; 627 break;
632 case STATE_DATA_END: 628 case STATE_DATA_END:;
633 ;
634 } 629 }
635 } 630 }
636 631
@@ -647,77 +642,75 @@ bool _np_state_read_file(FILE *f) {
647 */ 642 */
648void np_state_write_string(time_t data_time, char *data_string) { 643void np_state_write_string(time_t data_time, char *data_string) {
649 FILE *fp; 644 FILE *fp;
650 char *temp_file=NULL; 645 char *temp_file = NULL;
651 int fd=0, result=0; 646 int fd = 0, result = 0;
652 time_t current_time; 647 time_t current_time;
653 char *directories=NULL; 648 char *directories = NULL;
654 char *p=NULL; 649 char *p = NULL;
655 650
656 if(data_time==0) 651 if (data_time == 0)
657 time(&current_time); 652 time(&current_time);
658 else 653 else
659 current_time=data_time; 654 current_time = data_time;
660 655
661 /* If file doesn't currently exist, create directories */ 656 /* If file doesn't currently exist, create directories */
662 if(access(this_monitoring_plugin->state->_filename,F_OK)!=0) { 657 if (access(this_monitoring_plugin->state->_filename, F_OK) != 0) {
663 result = asprintf(&directories, "%s", this_monitoring_plugin->state->_filename); 658 result = asprintf(&directories, "%s", this_monitoring_plugin->state->_filename);
664 if(result < 0) 659 if (result < 0)
665 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 660 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
666 strerror(errno)); 661
667 662 for (p = directories + 1; *p; p++) {
668 for(p=directories+1; *p; p++) { 663 if (*p == '/') {
669 if(*p=='/') { 664 *p = '\0';
670 *p='\0'; 665 if ((access(directories, F_OK) != 0) && (mkdir(directories, S_IRWXU) != 0)) {
671 if((access(directories,F_OK)!=0) && (mkdir(directories, S_IRWXU)!=0)) {
672 /* Can't free this! Otherwise error message is wrong! */ 666 /* Can't free this! Otherwise error message is wrong! */
673 /* np_free(directories); */ 667 /* np_free(directories); */
674 die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories); 668 die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories);
675 } 669 }
676 *p='/'; 670 *p = '/';
677 } 671 }
678 } 672 }
679 np_free(directories); 673 np_free(directories);
680 } 674 }
681 675
682 result = asprintf(&temp_file,"%s.XXXXXX",this_monitoring_plugin->state->_filename); 676 result = asprintf(&temp_file, "%s.XXXXXX", this_monitoring_plugin->state->_filename);
683 if(result < 0) 677 if (result < 0)
684 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 678 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
685 strerror(errno));
686 679
687 if((fd=mkstemp(temp_file))==-1) { 680 if ((fd = mkstemp(temp_file)) == -1) {
688 np_free(temp_file); 681 np_free(temp_file);
689 die(STATE_UNKNOWN, _("Cannot create temporary filename")); 682 die(STATE_UNKNOWN, _("Cannot create temporary filename"));
690 } 683 }
691 684
692 fp=(FILE *)fdopen(fd,"w"); 685 fp = (FILE *)fdopen(fd, "w");
693 if(fp==NULL) { 686 if (fp == NULL) {
694 close(fd); 687 close(fd);
695 unlink(temp_file); 688 unlink(temp_file);
696 np_free(temp_file); 689 np_free(temp_file);
697 die(STATE_UNKNOWN, _("Unable to open temporary state file")); 690 die(STATE_UNKNOWN, _("Unable to open temporary state file"));
698 } 691 }
699 692
700 fprintf(fp,"# NP State file\n"); 693 fprintf(fp, "# NP State file\n");
701 fprintf(fp,"%d\n",NP_STATE_FORMAT_VERSION); 694 fprintf(fp, "%d\n", NP_STATE_FORMAT_VERSION);
702 fprintf(fp,"%d\n",this_monitoring_plugin->state->data_version); 695 fprintf(fp, "%d\n", this_monitoring_plugin->state->data_version);
703 fprintf(fp,"%lu\n",current_time); 696 fprintf(fp, "%lu\n", current_time);
704 fprintf(fp,"%s\n",data_string); 697 fprintf(fp, "%s\n", data_string);
705 698
706 fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP); 699 fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP);
707 700
708 fflush(fp); 701 fflush(fp);
709 702
710 result=fclose(fp); 703 result = fclose(fp);
711 704
712 fsync(fd); 705 fsync(fd);
713 706
714 if(result!=0) { 707 if (result != 0) {
715 unlink(temp_file); 708 unlink(temp_file);
716 np_free(temp_file); 709 np_free(temp_file);
717 die(STATE_UNKNOWN, _("Error writing temp file")); 710 die(STATE_UNKNOWN, _("Error writing temp file"));
718 } 711 }
719 712
720 if(rename(temp_file, this_monitoring_plugin->state->_filename)!=0) { 713 if (rename(temp_file, this_monitoring_plugin->state->_filename) != 0) {
721 unlink(temp_file); 714 unlink(temp_file);
722 np_free(temp_file); 715 np_free(temp_file);
723 die(STATE_UNKNOWN, _("Cannot rename state temp file")); 716 die(STATE_UNKNOWN, _("Cannot rename state temp file"));
diff --git a/lib/utils_base.h b/lib/utils_base.h
index 9d4dffed..a209cb6d 100644
--- a/lib/utils_base.h
+++ b/lib/utils_base.h
@@ -3,7 +3,7 @@
3/* Header file for Monitoring Plugins utils_base.c */ 3/* Header file for Monitoring Plugins utils_base.c */
4 4
5#ifndef USE_OPENSSL 5#ifndef USE_OPENSSL
6# include "sha256.h" 6# include "sha256.h"
7#endif 7#endif
8 8
9/* This file holds header information for thresholds - use this in preference to 9/* This file holds header information for thresholds - use this in preference to
@@ -20,44 +20,43 @@
20#define INSIDE 1 20#define INSIDE 1
21 21
22typedef struct range_struct { 22typedef struct range_struct {
23 double start; 23 double start;
24 bool start_infinity; 24 bool start_infinity;
25 double end; 25 double end;
26 int end_infinity; 26 int end_infinity;
27 int alert_on; /* OUTSIDE (default) or INSIDE */ 27 int alert_on; /* OUTSIDE (default) or INSIDE */
28 char* text; /* original unparsed text input */ 28 char *text; /* original unparsed text input */
29 } range; 29} range;
30 30
31typedef struct thresholds_struct { 31typedef struct thresholds_struct {
32 range *warning; 32 range *warning;
33 range *critical; 33 range *critical;
34 } thresholds; 34} thresholds;
35 35
36#define NP_STATE_FORMAT_VERSION 1 36#define NP_STATE_FORMAT_VERSION 1
37 37
38typedef struct state_data_struct { 38typedef struct state_data_struct {
39 time_t time; 39 time_t time;
40 void *data; 40 void *data;
41 int length; /* Of binary data */ 41 int length; /* Of binary data */
42 } state_data; 42} state_data;
43
44 43
45typedef struct state_key_struct { 44typedef struct state_key_struct {
46 char *name; 45 char *name;
47 char *plugin_name; 46 char *plugin_name;
48 int data_version; 47 int data_version;
49 char *_filename; 48 char *_filename;
50 state_data *state_data; 49 state_data *state_data;
51 } state_key; 50} state_key;
52 51
53typedef struct np_struct { 52typedef struct np_struct {
54 char *plugin_name; 53 char *plugin_name;
55 state_key *state; 54 state_key *state;
56 int argc; 55 int argc;
57 char **argv; 56 char **argv;
58 } monitoring_plugin; 57} monitoring_plugin;
59 58
60range *parse_range_string (char *); 59range *parse_range_string(char *);
61int _set_thresholds(thresholds **, char *, char *); 60int _set_thresholds(thresholds **, char *, char *);
62void set_thresholds(thresholds **, char *, char *); 61void set_thresholds(thresholds **, char *, char *);
63void print_thresholds(const char *, thresholds *); 62void print_thresholds(const char *, thresholds *);
@@ -71,13 +70,13 @@ extern unsigned int timeout_interval;
71/* All possible characters in a threshold range */ 70/* All possible characters in a threshold range */
72#define NP_THRESHOLDS_CHARS "-0123456789.:@~" 71#define NP_THRESHOLDS_CHARS "-0123456789.:@~"
73 72
74char *np_escaped_string (const char *); 73char *np_escaped_string(const char *);
75 74
76void die (int, const char *, ...) __attribute__((noreturn,format(printf, 2, 3))); 75void die(int, const char *, ...) __attribute__((noreturn, format(printf, 2, 3)));
77 76
78/* Return codes for _set_thresholds */ 77/* Return codes for _set_thresholds */
79#define NP_RANGE_UNPARSEABLE 1 78#define NP_RANGE_UNPARSEABLE 1
80#define NP_WARN_WITHIN_CRIT 2 79#define NP_WARN_WITHIN_CRIT 2
81 80
82/* a simple check to see if we're running as root. 81/* a simple check to see if we're running as root.
83 * returns zero on failure, nonzero on success */ 82 * returns zero on failure, nonzero on success */
@@ -93,7 +92,7 @@ int np_check_if_root(void);
93 * This function can be used to parse NTP control packet data and performance 92 * This function can be used to parse NTP control packet data and performance
94 * data strings. 93 * data strings.
95 */ 94 */
96char *np_extract_value(const char*, const char*, char); 95char *np_extract_value(const char *, const char *, char);
97 96
98/* 97/*
99 * Same as np_extract_value with separator suitable for NTP control packet 98 * Same as np_extract_value with separator suitable for NTP control packet
@@ -105,7 +104,7 @@ char *np_extract_value(const char*, const char*, char);
105 * Read a string representing a state (ok, warning... or numeric: 0, 1) and 104 * Read a string representing a state (ok, warning... or numeric: 0, 1) and
106 * return the corresponding NP_STATE or ERROR) 105 * return the corresponding NP_STATE or ERROR)
107 */ 106 */
108int mp_translate_state (char *); 107int mp_translate_state(char *);
109 108
110void np_enable_state(char *, int); 109void np_enable_state(char *, int);
111state_data *np_state_read(); 110state_data *np_state_read();
@@ -114,6 +113,6 @@ void np_state_write_string(time_t, char *);
114void np_init(char *, int argc, char **argv); 113void np_init(char *, int argc, char **argv);
115void np_set_args(int argc, char **argv); 114void np_set_args(int argc, char **argv);
116void np_cleanup(); 115void np_cleanup();
117const char *state_text (int); 116const char *state_text(int);
118 117
119#endif /* _UTILS_BASE_ */ 118#endif /* _UTILS_BASE_ */
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c
index 7957ec14..416cf824 100644
--- a/lib/utils_cmd.c
+++ b/lib/utils_cmd.c
@@ -1,40 +1,40 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring run command utilities 3 * Monitoring run command utilities
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2006 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* 7 *
8* Description : 8 * Description :
9* 9 *
10* A simple interface to executing programs from other programs, using an 10 * A simple interface to executing programs from other programs, using an
11* optimized and safe popen()-like implementation. It is considered safe 11 * optimized and safe popen()-like implementation. It is considered safe
12* in that no shell needs to be spawned and the environment passed to the 12 * in that no shell needs to be spawned and the environment passed to the
13* execve()'d program is essentially empty. 13 * execve()'d program is essentially empty.
14* 14 *
15* The code in this file is a derivative of popen.c which in turn was taken 15 * The code in this file is a derivative of popen.c which in turn was taken
16* from "Advanced Programming for the Unix Environment" by W. Richard Stevens. 16 * from "Advanced Programming for the Unix Environment" by W. Richard Stevens.
17* 17 *
18* Care has been taken to make sure the functions are async-safe. The one 18 * Care has been taken to make sure the functions are async-safe. The one
19* function which isn't is cmd_init() which it doesn't make sense to 19 * function which isn't is cmd_init() which it doesn't make sense to
20* call twice anyway, so the api as a whole should be considered async-safe. 20 * call twice anyway, so the api as a whole should be considered async-safe.
21* 21 *
22* 22 *
23* This program is free software: you can redistribute it and/or modify 23 * This program is free software: you can redistribute it and/or modify
24* it under the terms of the GNU General Public License as published by 24 * it under the terms of the GNU General Public License as published by
25* the Free Software Foundation, either version 3 of the License, or 25 * the Free Software Foundation, either version 3 of the License, or
26* (at your option) any later version. 26 * (at your option) any later version.
27* 27 *
28* This program is distributed in the hope that it will be useful, 28 * This program is distributed in the hope that it will be useful,
29* but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31* GNU General Public License for more details. 31 * GNU General Public License for more details.
32* 32 *
33* You should have received a copy of the GNU General Public License 33 * You should have received a copy of the GNU General Public License
34* along with this program. If not, see <http://www.gnu.org/licenses/>. 34 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35* 35 *
36* 36 *
37*****************************************************************************/ 37 *****************************************************************************/
38 38
39#define NAGIOSPLUG_API_C 1 39#define NAGIOSPLUG_API_C 1
40 40
@@ -59,7 +59,7 @@ static pid_t *_cmd_pids = NULL;
59#include <fcntl.h> 59#include <fcntl.h>
60 60
61#ifdef HAVE_SYS_WAIT_H 61#ifdef HAVE_SYS_WAIT_H
62# include <sys/wait.h> 62# include <sys/wait.h>
63#endif 63#endif
64 64
65/* used in _cmd_open to pass the environment to commands */ 65/* used in _cmd_open to pass the environment to commands */
@@ -67,57 +67,48 @@ extern char **environ;
67 67
68/** macros **/ 68/** macros **/
69#ifndef WEXITSTATUS 69#ifndef WEXITSTATUS
70# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 70# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
71#endif 71#endif
72 72
73#ifndef WIFEXITED 73#ifndef WIFEXITED
74# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 74# define WIFEXITED(stat_val) (((stat_val)&255) == 0)
75#endif 75#endif
76 76
77/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */ 77/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
78#if defined(SIG_IGN) && !defined(SIG_ERR) 78#if defined(SIG_IGN) && !defined(SIG_ERR)
79# define SIG_ERR ((Sigfunc *)-1) 79# define SIG_ERR ((Sigfunc *)-1)
80#endif 80#endif
81 81
82/** prototypes **/ 82/** prototypes **/
83static int _cmd_open (char *const *, int *, int *) 83static int _cmd_open(char *const *, int *, int *) __attribute__((__nonnull__(1, 2, 3)));
84 __attribute__ ((__nonnull__ (1, 2, 3)));
85 84
86static int _cmd_fetch_output (int, output *, int) 85static int _cmd_fetch_output(int, output *, int) __attribute__((__nonnull__(2)));
87 __attribute__ ((__nonnull__ (2)));
88 86
89static int _cmd_close (int); 87static int _cmd_close(int);
90 88
91/* prototype imported from utils.h */ 89/* prototype imported from utils.h */
92extern void die (int, const char *, ...) 90extern void die(int, const char *, ...) __attribute__((__noreturn__, __format__(__printf__, 2, 3)));
93 __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3)));
94
95 91
96/* this function is NOT async-safe. It is exported so multithreaded 92/* this function is NOT async-safe. It is exported so multithreaded
97 * plugins (or other apps) can call it prior to running any commands 93 * plugins (or other apps) can call it prior to running any commands
98 * through this api and thus achieve async-safeness throughout the api */ 94 * through this api and thus achieve async-safeness throughout the api */
99void 95void cmd_init(void) {
100cmd_init (void)
101{
102 long maxfd = mp_open_max(); 96 long maxfd = mp_open_max();
103 97
104 /* if maxfd is unnaturally high, we force it to a lower value 98 /* if maxfd is unnaturally high, we force it to a lower value
105 * ( e.g. on SunOS, when ulimit is set to unlimited: 2147483647 this would cause 99 * ( e.g. on SunOS, when ulimit is set to unlimited: 2147483647 this would cause
106 * a segfault when following calloc is called ... ) */ 100 * a segfault when following calloc is called ... ) */
107 101
108 if ( maxfd > MAXFD_LIMIT ) { 102 if (maxfd > MAXFD_LIMIT) {
109 maxfd = MAXFD_LIMIT; 103 maxfd = MAXFD_LIMIT;
110 } 104 }
111 105
112 if (!_cmd_pids) 106 if (!_cmd_pids)
113 _cmd_pids = calloc (maxfd, sizeof (pid_t)); 107 _cmd_pids = calloc(maxfd, sizeof(pid_t));
114} 108}
115 109
116
117/* Start running a command, array style */ 110/* Start running a command, array style */
118static int 111static int _cmd_open(char *const *argv, int *pfd, int *pfderr) {
119_cmd_open (char *const *argv, int *pfd, int *pfderr)
120{
121 pid_t pid; 112 pid_t pid;
122#ifdef RLIMIT_CORE 113#ifdef RLIMIT_CORE
123 struct rlimit limit; 114 struct rlimit limit;
@@ -130,26 +121,26 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
130 121
131 setenv("LC_ALL", "C", 1); 122 setenv("LC_ALL", "C", 1);
132 123
133 if (pipe (pfd) < 0 || pipe (pfderr) < 0 || (pid = fork ()) < 0) 124 if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0)
134 return -1; /* errno set by the failing function */ 125 return -1; /* errno set by the failing function */
135 126
136 /* child runs exceve() and _exit. */ 127 /* child runs exceve() and _exit. */
137 if (pid == 0) { 128 if (pid == 0) {
138#ifdef RLIMIT_CORE 129#ifdef RLIMIT_CORE
139 /* the program we execve shouldn't leave core files */ 130 /* the program we execve shouldn't leave core files */
140 getrlimit (RLIMIT_CORE, &limit); 131 getrlimit(RLIMIT_CORE, &limit);
141 limit.rlim_cur = 0; 132 limit.rlim_cur = 0;
142 setrlimit (RLIMIT_CORE, &limit); 133 setrlimit(RLIMIT_CORE, &limit);
143#endif 134#endif
144 close (pfd[0]); 135 close(pfd[0]);
145 if (pfd[1] != STDOUT_FILENO) { 136 if (pfd[1] != STDOUT_FILENO) {
146 dup2 (pfd[1], STDOUT_FILENO); 137 dup2(pfd[1], STDOUT_FILENO);
147 close (pfd[1]); 138 close(pfd[1]);
148 } 139 }
149 close (pfderr[0]); 140 close(pfderr[0]);
150 if (pfderr[1] != STDERR_FILENO) { 141 if (pfderr[1] != STDERR_FILENO) {
151 dup2 (pfderr[1], STDERR_FILENO); 142 dup2(pfderr[1], STDERR_FILENO);
152 close (pfderr[1]); 143 close(pfderr[1]);
153 } 144 }
154 145
155 /* close all descriptors in _cmd_pids[] 146 /* close all descriptors in _cmd_pids[]
@@ -158,16 +149,16 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
158 long maxfd = mp_open_max(); 149 long maxfd = mp_open_max();
159 for (i = 0; i < maxfd; i++) 150 for (i = 0; i < maxfd; i++)
160 if (_cmd_pids[i] > 0) 151 if (_cmd_pids[i] > 0)
161 close (i); 152 close(i);
162 153
163 execve (argv[0], argv, environ); 154 execve(argv[0], argv, environ);
164 _exit (STATE_UNKNOWN); 155 _exit(STATE_UNKNOWN);
165 } 156 }
166 157
167 /* parent picks up execution here */ 158 /* parent picks up execution here */
168 /* close children descriptors in our address space */ 159 /* close children descriptors in our address space */
169 close (pfd[1]); 160 close(pfd[1]);
170 close (pfderr[1]); 161 close(pfderr[1]);
171 162
172 /* tag our file's entry in the pid-list and return it */ 163 /* tag our file's entry in the pid-list and return it */
173 _cmd_pids[pfd[0]] = pid; 164 _cmd_pids[pfd[0]] = pid;
@@ -175,9 +166,7 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
175 return pfd[0]; 166 return pfd[0];
176} 167}
177 168
178static int 169static int _cmd_close(int fd) {
179_cmd_close (int fd)
180{
181 int status; 170 int status;
182 pid_t pid; 171 pid_t pid;
183 172
@@ -187,40 +176,37 @@ _cmd_close (int fd)
187 return -1; 176 return -1;
188 177
189 _cmd_pids[fd] = 0; 178 _cmd_pids[fd] = 0;
190 if (close (fd) == -1) 179 if (close(fd) == -1)
191 return -1; 180 return -1;
192 181
193 /* EINTR is ok (sort of), everything else is bad */ 182 /* EINTR is ok (sort of), everything else is bad */
194 while (waitpid (pid, &status, 0) < 0) 183 while (waitpid(pid, &status, 0) < 0)
195 if (errno != EINTR) 184 if (errno != EINTR)
196 return -1; 185 return -1;
197 186
198 /* return child's termination status */ 187 /* return child's termination status */
199 return (WIFEXITED (status)) ? WEXITSTATUS (status) : -1; 188 return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1;
200} 189}
201 190
202 191static int _cmd_fetch_output(int fd, output *op, int flags) {
203static int
204_cmd_fetch_output (int fd, output * op, int flags)
205{
206 size_t len = 0, i = 0, lineno = 0; 192 size_t len = 0, i = 0, lineno = 0;
207 size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */ 193 size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */
208 char *buf = NULL; 194 char *buf = NULL;
209 int ret; 195 int ret;
210 char tmpbuf[4096]; 196 char tmpbuf[4096];
211 197
212 op->buf = NULL; 198 op->buf = NULL;
213 op->buflen = 0; 199 op->buflen = 0;
214 while ((ret = read (fd, tmpbuf, sizeof (tmpbuf))) > 0) { 200 while ((ret = read(fd, tmpbuf, sizeof(tmpbuf))) > 0) {
215 len = (size_t) ret; 201 len = (size_t)ret;
216 op->buf = realloc (op->buf, op->buflen + len + 1); 202 op->buf = realloc(op->buf, op->buflen + len + 1);
217 memcpy (op->buf + op->buflen, tmpbuf, len); 203 memcpy(op->buf + op->buflen, tmpbuf, len);
218 op->buflen += len; 204 op->buflen += len;
219 i++; 205 i++;
220 } 206 }
221 207
222 if (ret < 0) { 208 if (ret < 0) {
223 printf ("read() returned %d: %s\n", ret, strerror (errno)); 209 printf("read() returned %d: %s\n", ret, strerror(errno));
224 return ret; 210 return ret;
225 } 211 }
226 212
@@ -231,10 +217,9 @@ _cmd_fetch_output (int fd, output * op, int flags)
231 217
232 /* and some may want both */ 218 /* and some may want both */
233 if (flags & CMD_NO_ASSOC) { 219 if (flags & CMD_NO_ASSOC) {
234 buf = malloc (op->buflen); 220 buf = malloc(op->buflen);
235 memcpy (buf, op->buf, op->buflen); 221 memcpy(buf, op->buf, op->buflen);
236 } 222 } else
237 else
238 buf = op->buf; 223 buf = op->buf;
239 224
240 op->line = NULL; 225 op->line = NULL;
@@ -248,8 +233,8 @@ _cmd_fetch_output (int fd, output * op, int flags)
248 ary_size = op->buflen >> --rsf; 233 ary_size = op->buflen >> --rsf;
249 } while (!ary_size); 234 } while (!ary_size);
250 235
251 op->line = realloc (op->line, ary_size * sizeof (char *)); 236 op->line = realloc(op->line, ary_size * sizeof(char *));
252 op->lens = realloc (op->lens, ary_size * sizeof (size_t)); 237 op->lens = realloc(op->lens, ary_size * sizeof(size_t));
253 } 238 }
254 239
255 /* set the pointer to the string */ 240 /* set the pointer to the string */
@@ -261,7 +246,7 @@ _cmd_fetch_output (int fd, output * op, int flags)
261 buf[i] = '\0'; 246 buf[i] = '\0';
262 247
263 /* calculate the string length using pointer difference */ 248 /* calculate the string length using pointer difference */
264 op->lens[lineno] = (size_t) & buf[i] - (size_t) op->line[lineno]; 249 op->lens[lineno] = (size_t)&buf[i] - (size_t)op->line[lineno];
265 250
266 lineno++; 251 lineno++;
267 i++; 252 i++;
@@ -270,10 +255,7 @@ _cmd_fetch_output (int fd, output * op, int flags)
270 return lineno; 255 return lineno;
271} 256}
272 257
273 258int cmd_run(const char *cmdstring, output *out, output *err, int flags) {
274int
275cmd_run (const char *cmdstring, output * out, output * err, int flags)
276{
277 int i = 0, argc; 259 int i = 0, argc;
278 size_t cmdlen; 260 size_t cmdlen;
279 char **argv = NULL; 261 char **argv = NULL;
@@ -285,120 +267,114 @@ cmd_run (const char *cmdstring, output * out, output * err, int flags)
285 267
286 /* initialize the structs */ 268 /* initialize the structs */
287 if (out) 269 if (out)
288 memset (out, 0, sizeof (output)); 270 memset(out, 0, sizeof(output));
289 if (err) 271 if (err)
290 memset (err, 0, sizeof (output)); 272 memset(err, 0, sizeof(output));
291 273
292 /* make copy of command string so strtok() doesn't silently modify it */ 274 /* make copy of command string so strtok() doesn't silently modify it */
293 /* (the calling program may want to access it later) */ 275 /* (the calling program may want to access it later) */
294 cmdlen = strlen (cmdstring); 276 cmdlen = strlen(cmdstring);
295 if ((cmd = malloc (cmdlen + 1)) == NULL) 277 if ((cmd = malloc(cmdlen + 1)) == NULL)
296 return -1; 278 return -1;
297 memcpy (cmd, cmdstring, cmdlen); 279 memcpy(cmd, cmdstring, cmdlen);
298 cmd[cmdlen] = '\0'; 280 cmd[cmdlen] = '\0';
299 281
300 /* This is not a shell, so we don't handle "???" */ 282 /* This is not a shell, so we don't handle "???" */
301 if (strstr (cmdstring, "\"")) return -1; 283 if (strstr(cmdstring, "\""))
284 return -1;
302 285
303 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ 286 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
304 if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''")) 287 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''"))
305 return -1; 288 return -1;
306 289
307 /* each arg must be whitespace-separated, so args can be a maximum 290 /* each arg must be whitespace-separated, so args can be a maximum
308 * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */ 291 * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */
309 argc = (cmdlen >> 1) + 2; 292 argc = (cmdlen >> 1) + 2;
310 argv = calloc (sizeof (char *), argc); 293 argv = calloc(sizeof(char *), argc);
311 294
312 if (argv == NULL) { 295 if (argv == NULL) {
313 printf ("%s\n", _("Could not malloc argv array in popen()")); 296 printf("%s\n", _("Could not malloc argv array in popen()"));
314 return -1; 297 return -1;
315 } 298 }
316 299
317 /* get command arguments (stupidly, but fairly quickly) */ 300 /* get command arguments (stupidly, but fairly quickly) */
318 while (cmd) { 301 while (cmd) {
319 str = cmd; 302 str = cmd;
320 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 303 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
321 304
322 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */ 305 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */
323 str++; 306 str++;
324 if (!strstr (str, "'")) 307 if (!strstr(str, "'"))
325 return -1; /* balanced? */ 308 return -1; /* balanced? */
326 cmd = 1 + strstr (str, "'"); 309 cmd = 1 + strstr(str, "'");
327 str[strcspn (str, "'")] = 0; 310 str[strcspn(str, "'")] = 0;
328 } 311 } else {
329 else { 312 if (strpbrk(str, " \t\r\n")) {
330 if (strpbrk (str, " \t\r\n")) { 313 cmd = 1 + strpbrk(str, " \t\r\n");
331 cmd = 1 + strpbrk (str, " \t\r\n"); 314 str[strcspn(str, " \t\r\n")] = 0;
332 str[strcspn (str, " \t\r\n")] = 0; 315 } else {
333 }
334 else {
335 cmd = NULL; 316 cmd = NULL;
336 } 317 }
337 } 318 }
338 319
339 if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n")) 320 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n"))
340 cmd = NULL; 321 cmd = NULL;
341 322
342 argv[i++] = str; 323 argv[i++] = str;
343 } 324 }
344 325
345 return cmd_run_array (argv, out, err, flags); 326 return cmd_run_array(argv, out, err, flags);
346} 327}
347 328
348int 329int cmd_run_array(char *const *argv, output *out, output *err, int flags) {
349cmd_run_array (char *const *argv, output * out, output * err, int flags)
350{
351 int fd, pfd_out[2], pfd_err[2]; 330 int fd, pfd_out[2], pfd_err[2];
352 331
353 /* initialize the structs */ 332 /* initialize the structs */
354 if (out) 333 if (out)
355 memset (out, 0, sizeof (output)); 334 memset(out, 0, sizeof(output));
356 if (err) 335 if (err)
357 memset (err, 0, sizeof (output)); 336 memset(err, 0, sizeof(output));
358 337
359 if ((fd = _cmd_open (argv, pfd_out, pfd_err)) == -1) 338 if ((fd = _cmd_open(argv, pfd_out, pfd_err)) == -1)
360 die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), argv[0]); 339 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), argv[0]);
361 340
362 if (out) 341 if (out)
363 out->lines = _cmd_fetch_output (pfd_out[0], out, flags); 342 out->lines = _cmd_fetch_output(pfd_out[0], out, flags);
364 if (err) 343 if (err)
365 err->lines = _cmd_fetch_output (pfd_err[0], err, flags); 344 err->lines = _cmd_fetch_output(pfd_err[0], err, flags);
366 345
367 return _cmd_close (fd); 346 return _cmd_close(fd);
368} 347}
369 348
370int 349int cmd_file_read(char *filename, output *out, int flags) {
371cmd_file_read ( char *filename, output *out, int flags)
372{
373 int fd; 350 int fd;
374 if(out) 351 if (out)
375 memset (out, 0, sizeof(output)); 352 memset(out, 0, sizeof(output));
376 353
377 if ((fd = open(filename, O_RDONLY)) == -1) { 354 if ((fd = open(filename, O_RDONLY)) == -1) {
378 die( STATE_UNKNOWN, _("Error opening %s: %s"), filename, strerror(errno) ); 355 die(STATE_UNKNOWN, _("Error opening %s: %s"), filename, strerror(errno));
379 } 356 }
380 357
381 if(out) 358 if (out)
382 out->lines = _cmd_fetch_output (fd, out, flags); 359 out->lines = _cmd_fetch_output(fd, out, flags);
383 360
384 if (close(fd) == -1) 361 if (close(fd) == -1)
385 die( STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno) ); 362 die(STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno));
386 363
387 return 0; 364 return 0;
388} 365}
389 366
390void 367void timeout_alarm_handler(int signo) {
391timeout_alarm_handler (int signo)
392{
393 if (signo == SIGALRM) { 368 if (signo == SIGALRM) {
394 printf (_("%s - Plugin timed out after %d seconds\n"), 369 printf(_("%s - Plugin timed out after %d seconds\n"), state_text(timeout_state), timeout_interval);
395 state_text(timeout_state), timeout_interval);
396 370
397 long maxfd = mp_open_max(); 371 long maxfd = mp_open_max();
398 if(_cmd_pids) for(long int i = 0; i < maxfd; i++) { 372 if (_cmd_pids)
399 if(_cmd_pids[i] != 0) kill(_cmd_pids[i], SIGKILL); 373 for (long int i = 0; i < maxfd; i++) {
400 } 374 if (_cmd_pids[i] != 0)
375 kill(_cmd_pids[i], SIGKILL);
376 }
401 377
402 exit (timeout_state); 378 exit(timeout_state);
403 } 379 }
404} 380}
diff --git a/lib/utils_cmd.h b/lib/utils_cmd.h
index 061f5d4f..d00069c9 100644
--- a/lib/utils_cmd.h
+++ b/lib/utils_cmd.h
@@ -4,12 +4,10 @@
4/* 4/*
5 * Header file for Monitoring Plugins utils_cmd.c 5 * Header file for Monitoring Plugins utils_cmd.c
6 * 6 *
7 *
8 */ 7 */
9 8
10/** types **/ 9/** types **/
11struct output 10struct output {
12{
13 char *buf; /* output buffer */ 11 char *buf; /* output buffer */
14 size_t buflen; /* output buffer content length */ 12 size_t buflen; /* output buffer content length */
15 char **line; /* array of lines (points to buf) */ 13 char **line; /* array of lines (points to buf) */
@@ -20,20 +18,18 @@ struct output
20typedef struct output output; 18typedef struct output output;
21 19
22/** prototypes **/ 20/** prototypes **/
23int cmd_run (const char *, output *, output *, int); 21int cmd_run(const char *, output *, output *, int);
24int cmd_run_array (char *const *, output *, output *, int); 22int cmd_run_array(char *const *, output *, output *, int);
25int cmd_file_read (char *, output *, int); 23int cmd_file_read(char *, output *, int);
26 24
27/* only multi-threaded plugins need to bother with this */ 25/* only multi-threaded plugins need to bother with this */
28void cmd_init (void); 26void cmd_init(void);
29#define CMD_INIT cmd_init() 27#define CMD_INIT cmd_init()
30 28
31/* possible flags for cmd_run()'s fourth argument */ 29/* possible flags for cmd_run()'s fourth argument */
32#define CMD_NO_ARRAYS 0x01 /* don't populate arrays at all */ 30#define CMD_NO_ARRAYS 0x01 /* don't populate arrays at all */
33#define CMD_NO_ASSOC 0x02 /* output.line won't point to buf */ 31#define CMD_NO_ASSOC 0x02 /* output.line won't point to buf */
34
35
36void timeout_alarm_handler (int);
37 32
33void timeout_alarm_handler(int);
38 34
39#endif /* _UTILS_CMD_ */ 35#endif /* _UTILS_CMD_ */
diff --git a/lib/utils_disk.c b/lib/utils_disk.c
index 483be06d..2b761f5e 100644
--- a/lib/utils_disk.c
+++ b/lib/utils_disk.c
@@ -1,44 +1,42 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Library for check_disk 3 * Library for check_disk
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains utilities for check_disk. These are tested by libtap 10 * This file contains utilities for check_disk. These are tested by libtap
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29#include "common.h" 29#include "common.h"
30#include "utils_disk.h" 30#include "utils_disk.h"
31#include "gl/fsusage.h" 31#include "gl/fsusage.h"
32#include <string.h> 32#include <string.h>
33 33
34void 34void np_add_name(struct name_list **list, const char *name) {
35np_add_name (struct name_list **list, const char *name) 35 struct name_list *new_entry;
36{ 36 new_entry = (struct name_list *)malloc(sizeof *new_entry);
37 struct name_list *new_entry; 37 new_entry->name = (char *)name;
38 new_entry = (struct name_list *) malloc (sizeof *new_entry); 38 new_entry->next = *list;
39 new_entry->name = (char *) name; 39 *list = new_entry;
40 new_entry->next = *list;
41 *list = new_entry;
42} 40}
43 41
44/* @brief Initialises a new regex at the begin of list via regcomp(3) 42/* @brief Initialises a new regex at the begin of list via regcomp(3)
@@ -50,17 +48,14 @@ np_add_name (struct name_list **list, const char *name)
50 * @param regex the string containing the regex which should be inserted into the list 48 * @param regex the string containing the regex which should be inserted into the list
51 * @param clags the cflags parameter for regcomp(3) 49 * @param clags the cflags parameter for regcomp(3)
52 */ 50 */
53int 51int np_add_regex(struct regex_list **list, const char *regex, int cflags) {
54np_add_regex (struct regex_list **list, const char *regex, int cflags) 52 struct regex_list *new_entry = (struct regex_list *)malloc(sizeof *new_entry);
55{
56 struct regex_list *new_entry = (struct regex_list *) malloc (sizeof *new_entry);
57 53
58 if (new_entry == NULL) { 54 if (new_entry == NULL) {
59 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 55 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
60 strerror(errno));
61 } 56 }
62 57
63 int regcomp_result = regcomp(&new_entry->regex, regex, cflags); 58 int regcomp_result = regcomp(&new_entry->regex, regex, cflags);
64 59
65 if (!regcomp_result) { 60 if (!regcomp_result) {
66 // regcomp succeeded 61 // regcomp succeeded
@@ -74,197 +69,187 @@ np_add_regex (struct regex_list **list, const char *regex, int cflags)
74 69
75 return regcomp_result; 70 return regcomp_result;
76 } 71 }
77
78} 72}
79 73
80/* Initialises a new parameter at the end of list */ 74/* Initialises a new parameter at the end of list */
81struct parameter_list * 75struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name) {
82np_add_parameter(struct parameter_list **list, const char *name) 76 struct parameter_list *current = *list;
83{ 77 struct parameter_list *new_path;
84 struct parameter_list *current = *list; 78 new_path = (struct parameter_list *)malloc(sizeof *new_path);
85 struct parameter_list *new_path; 79 new_path->name = (char *)malloc(strlen(name) + 1);
86 new_path = (struct parameter_list *) malloc (sizeof *new_path); 80 new_path->best_match = NULL;
87 new_path->name = (char *) malloc(strlen(name) + 1); 81 new_path->name_next = NULL;
88 new_path->best_match = NULL; 82 new_path->name_prev = NULL;
89 new_path->name_next = NULL; 83 new_path->freespace_bytes = NULL;
90 new_path->name_prev = NULL; 84 new_path->freespace_units = NULL;
91 new_path->freespace_bytes = NULL; 85 new_path->freespace_percent = NULL;
92 new_path->freespace_units = NULL; 86 new_path->usedspace_bytes = NULL;
93 new_path->freespace_percent = NULL; 87 new_path->usedspace_units = NULL;
94 new_path->usedspace_bytes = NULL; 88 new_path->usedspace_percent = NULL;
95 new_path->usedspace_units = NULL; 89 new_path->usedinodes_percent = NULL;
96 new_path->usedspace_percent = NULL; 90 new_path->freeinodes_percent = NULL;
97 new_path->usedinodes_percent = NULL; 91 new_path->group = NULL;
98 new_path->freeinodes_percent = NULL; 92 new_path->dfree_pct = -1;
99 new_path->group = NULL; 93 new_path->dused_pct = -1;
100 new_path->dfree_pct = -1; 94 new_path->total = 0;
101 new_path->dused_pct = -1; 95 new_path->available = 0;
102 new_path->total = 0; 96 new_path->available_to_root = 0;
103 new_path->available = 0; 97 new_path->used = 0;
104 new_path->available_to_root = 0; 98 new_path->dused_units = 0;
105 new_path->used = 0; 99 new_path->dfree_units = 0;
106 new_path->dused_units = 0; 100 new_path->dtotal_units = 0;
107 new_path->dfree_units = 0; 101 new_path->inodes_total = 0;
108 new_path->dtotal_units = 0; 102 new_path->inodes_free = 0;
109 new_path->inodes_total = 0; 103 new_path->inodes_free_to_root = 0;
110 new_path->inodes_free = 0; 104 new_path->inodes_used = 0;
111 new_path->inodes_free_to_root = 0; 105 new_path->dused_inodes_percent = 0;
112 new_path->inodes_used = 0; 106 new_path->dfree_inodes_percent = 0;
113 new_path->dused_inodes_percent = 0; 107
114 new_path->dfree_inodes_percent = 0; 108 strcpy(new_path->name, name);
115 109
116 strcpy(new_path->name, name); 110 if (current == NULL) {
117 111 *list = new_path;
118 if (current == NULL) { 112 new_path->name_prev = NULL;
119 *list = new_path; 113 } else {
120 new_path->name_prev = NULL; 114 while (current->name_next) {
121 } else { 115 current = current->name_next;
122 while (current->name_next) { 116 }
123 current = current->name_next; 117 current->name_next = new_path;
124 } 118 new_path->name_prev = current;
125 current->name_next = new_path; 119 }
126 new_path->name_prev = current; 120 return new_path;
127 }
128 return new_path;
129} 121}
130 122
131/* Delete a given parameter from list and return pointer to next element*/ 123/* Delete a given parameter from list and return pointer to next element*/
132struct parameter_list * 124struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev) {
133np_del_parameter(struct parameter_list *item, struct parameter_list *prev) 125 if (item == NULL) {
134{ 126 return NULL;
135 if (item == NULL) { 127 }
136 return NULL; 128 struct parameter_list *next;
137 } 129
138 struct parameter_list *next; 130 if (item->name_next)
139 131 next = item->name_next;
140 if (item->name_next) 132 else
141 next = item->name_next; 133 next = NULL;
142 else 134
143 next = NULL; 135 if (next)
144 136 next->name_prev = prev;
145 if (next)
146 next->name_prev = prev;
147
148 if (prev)
149 prev->name_next = next;
150
151 if (item->name) {
152 free(item->name);
153 }
154 free(item);
155
156 return next;
157}
158 137
138 if (prev)
139 prev->name_next = next;
140
141 if (item->name) {
142 free(item->name);
143 }
144 free(item);
145
146 return next;
147}
159 148
160/* returns a pointer to the struct found in the list */ 149/* returns a pointer to the struct found in the list */
161struct parameter_list * 150struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name) {
162np_find_parameter(struct parameter_list *list, const char *name) 151 struct parameter_list *temp_list;
163{ 152 for (temp_list = list; temp_list; temp_list = temp_list->name_next) {
164 struct parameter_list *temp_list; 153 if (!strcmp(temp_list->name, name))
165 for (temp_list = list; temp_list; temp_list = temp_list->name_next) { 154 return temp_list;
166 if (! strcmp(temp_list->name, name)) 155 }
167 return temp_list; 156
168 } 157 return NULL;
169
170 return NULL;
171} 158}
172 159
173void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact) { 160void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact) {
174 struct parameter_list *d; 161 struct parameter_list *d;
175 for (d = desired; d; d= d->name_next) { 162 for (d = desired; d; d = d->name_next) {
176 if (! d->best_match) { 163 if (!d->best_match) {
177 struct mount_entry *me; 164 struct mount_entry *me;
178 size_t name_len = strlen(d->name); 165 size_t name_len = strlen(d->name);
179 size_t best_match_len = 0; 166 size_t best_match_len = 0;
180 struct mount_entry *best_match = NULL; 167 struct mount_entry *best_match = NULL;
181 struct fs_usage fsp; 168 struct fs_usage fsp;
182 169
183 /* set best match if path name exactly matches a mounted device name */ 170 /* set best match if path name exactly matches a mounted device name */
184 for (me = mount_list; me; me = me->me_next) { 171 for (me = mount_list; me; me = me->me_next) {
185 if (strcmp(me->me_devname, d->name)==0) { 172 if (strcmp(me->me_devname, d->name) == 0) {
186 if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) { 173 if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
187 best_match = me; 174 best_match = me;
188 } 175 }
189 } 176 }
190 } 177 }
191 178
192 /* set best match by directory name if no match was found by devname */ 179 /* set best match by directory name if no match was found by devname */
193 if (! best_match) { 180 if (!best_match) {
194 for (me = mount_list; me; me = me->me_next) { 181 for (me = mount_list; me; me = me->me_next) {
195 size_t len = strlen (me->me_mountdir); 182 size_t len = strlen(me->me_mountdir);
196 if ((!exact && (best_match_len <= len && len <= name_len && 183 if ((!exact &&
197 (len == 1 || strncmp (me->me_mountdir, d->name, len) == 0))) 184 (best_match_len <= len && len <= name_len && (len == 1 || strncmp(me->me_mountdir, d->name, len) == 0))) ||
198 || (exact && strcmp(me->me_mountdir, d->name)==0)) 185 (exact && strcmp(me->me_mountdir, d->name) == 0)) {
199 { 186 if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
200 if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) { 187 best_match = me;
201 best_match = me; 188 best_match_len = len;
202 best_match_len = len; 189 }
203 } 190 }
204 } 191 }
205 } 192 }
206 } 193
207 194 if (best_match) {
208 if (best_match) { 195 d->best_match = best_match;
209 d->best_match = best_match; 196 } else {
210 } else { 197 d->best_match = NULL; /* Not sure why this is needed as it should be null on initialisation */
211 d->best_match = NULL; /* Not sure why this is needed as it should be null on initialisation */ 198 }
212 } 199 }
213 } 200 }
214 }
215} 201}
216 202
217/* Returns true if name is in list */ 203/* Returns true if name is in list */
218bool np_find_name (struct name_list *list, const char *name) { 204bool np_find_name(struct name_list *list, const char *name) {
219 const struct name_list *n; 205 const struct name_list *n;
220 206
221 if (list == NULL || name == NULL) { 207 if (list == NULL || name == NULL) {
222 return false; 208 return false;
223 } 209 }
224 for (n = list; n; n = n->next) { 210 for (n = list; n; n = n->next) {
225 if (!strcmp(name, n->name)) { 211 if (!strcmp(name, n->name)) {
226 return true; 212 return true;
227 } 213 }
228 } 214 }
229 return false; 215 return false;
230} 216}
231 217
232/* Returns true if name is in list */ 218/* Returns true if name is in list */
233bool np_find_regmatch (struct regex_list *list, const char *name) { 219bool np_find_regmatch(struct regex_list *list, const char *name) {
234 int len; 220 int len;
235 regmatch_t m; 221 regmatch_t m;
236 222
237 if (name == NULL) { 223 if (name == NULL) {
238 return false; 224 return false;
239 } 225 }
240 226
241 len = strlen(name); 227 len = strlen(name);
242 228
243 for (; list; list = list->next) { 229 for (; list; list = list->next) {
244 /* Emulate a full match as if surrounded with ^( )$ 230 /* Emulate a full match as if surrounded with ^( )$
245 by checking whether the match spans the whole name */ 231 by checking whether the match spans the whole name */
246 if (!regexec(&list->regex, name, 1, &m, 0) && m.rm_so == 0 && m.rm_eo == len) { 232 if (!regexec(&list->regex, name, 1, &m, 0) && m.rm_so == 0 && m.rm_eo == len) {
247 return true; 233 return true;
248 } 234 }
249 } 235 }
250 236
251 return false; 237 return false;
252} 238}
253 239
254bool np_seen_name(struct name_list *list, const char *name) { 240bool np_seen_name(struct name_list *list, const char *name) {
255 const struct name_list *s; 241 const struct name_list *s;
256 for (s = list; s; s=s->next) { 242 for (s = list; s; s = s->next) {
257 if (!strcmp(s->name, name)) { 243 if (!strcmp(s->name, name)) {
258 return true; 244 return true;
259 } 245 }
260 } 246 }
261 return false; 247 return false;
262} 248}
263 249
264bool np_regex_match_mount_entry (struct mount_entry* me, regex_t* re) { 250bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re) {
265 if (regexec(re, me->me_devname, (size_t) 0, NULL, 0) == 0 || 251 if (regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0 || regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0) {
266 regexec(re, me->me_mountdir, (size_t) 0, NULL, 0) == 0 ) { 252 return true;
267 return true; 253 }
268 }
269 return false; 254 return false;
270} 255}
diff --git a/lib/utils_disk.h b/lib/utils_disk.h
index 5b2caf23..c5e81dc1 100644
--- a/lib/utils_disk.h
+++ b/lib/utils_disk.h
@@ -4,49 +4,45 @@
4#include "utils_base.h" 4#include "utils_base.h"
5#include "regex.h" 5#include "regex.h"
6 6
7struct name_list 7struct name_list {
8{ 8 char *name;
9 char *name; 9 struct name_list *next;
10 struct name_list *next;
11}; 10};
12 11
13struct regex_list 12struct regex_list {
14{ 13 regex_t regex;
15 regex_t regex; 14 struct regex_list *next;
16 struct regex_list *next;
17}; 15};
18 16
19struct parameter_list 17struct parameter_list {
20{ 18 char *name;
21 char *name; 19 thresholds *freespace_bytes;
22 thresholds *freespace_bytes; 20 thresholds *freespace_units;
23 thresholds *freespace_units; 21 thresholds *freespace_percent;
24 thresholds *freespace_percent; 22 thresholds *usedspace_bytes;
25 thresholds *usedspace_bytes; 23 thresholds *usedspace_units;
26 thresholds *usedspace_units; 24 thresholds *usedspace_percent;
27 thresholds *usedspace_percent; 25 thresholds *usedinodes_percent;
28 thresholds *usedinodes_percent; 26 thresholds *freeinodes_percent;
29 thresholds *freeinodes_percent; 27 char *group;
30 char *group; 28 struct mount_entry *best_match;
31 struct mount_entry *best_match; 29 struct parameter_list *name_next;
32 struct parameter_list *name_next; 30 struct parameter_list *name_prev;
33 struct parameter_list *name_prev; 31 uintmax_t total, available, available_to_root, used, inodes_free, inodes_free_to_root, inodes_used, inodes_total;
34 uintmax_t total, available, available_to_root, used, 32 double dfree_pct, dused_pct;
35 inodes_free, inodes_free_to_root, inodes_used, inodes_total; 33 uint64_t dused_units, dfree_units, dtotal_units;
36 double dfree_pct, dused_pct; 34 double dused_inodes_percent, dfree_inodes_percent;
37 uint64_t dused_units, dfree_units, dtotal_units;
38 double dused_inodes_percent, dfree_inodes_percent;
39}; 35};
40 36
41void np_add_name (struct name_list **list, const char *name); 37void np_add_name(struct name_list **list, const char *name);
42bool np_find_name (struct name_list *list, const char *name); 38bool np_find_name(struct name_list *list, const char *name);
43bool np_seen_name (struct name_list *list, const char *name); 39bool np_seen_name(struct name_list *list, const char *name);
44int np_add_regex (struct regex_list **list, const char *regex, int cflags); 40int np_add_regex(struct regex_list **list, const char *regex, int cflags);
45bool np_find_regmatch (struct regex_list *list, const char *name); 41bool np_find_regmatch(struct regex_list *list, const char *name);
46struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name); 42struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name);
47struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name); 43struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name);
48struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev); 44struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev);
49 45
50int search_parameter_list (struct parameter_list *list, const char *name); 46int search_parameter_list(struct parameter_list *list, const char *name);
51void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact); 47void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact);
52bool np_regex_match_mount_entry (struct mount_entry* me, regex_t* re); 48bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re);
diff --git a/lib/utils_tcp.c b/lib/utils_tcp.c
index 23ee4a95..daae1d54 100644
--- a/lib/utils_tcp.c
+++ b/lib/utils_tcp.c
@@ -1,51 +1,46 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Library for check_tcp 3 * Library for check_tcp
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2013 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains utilities for check_tcp. These are tested by libtap 10 * This file contains utilities for check_tcp. These are tested by libtap
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29#include "common.h" 29#include "common.h"
30#include "utils_tcp.h" 30#include "utils_tcp.h"
31 31
32#define VERBOSE(message) \ 32#define VERBOSE(message) \
33 do { \ 33 do { \
34 if (flags & NP_MATCH_VERBOSE) \ 34 if (flags & NP_MATCH_VERBOSE) \
35 puts(message); \ 35 puts(message); \
36 } while (0) 36 } while (0)
37 37
38enum np_match_result 38enum np_match_result np_expect_match(char *status, char **server_expect, int expect_count, int flags) {
39np_expect_match(char *status, char **server_expect, int expect_count, int flags)
40{
41 int i, match = 0, partial = 0; 39 int i, match = 0, partial = 0;
42 40
43 for (i = 0; i < expect_count; i++) { 41 for (i = 0; i < expect_count; i++) {
44 if (flags & NP_MATCH_VERBOSE) 42 if (flags & NP_MATCH_VERBOSE)
45 printf("looking for [%s] %s [%s]\n", server_expect[i], 43 printf("looking for [%s] %s [%s]\n", server_expect[i], (flags & NP_MATCH_EXACT) ? "in beginning of" : "anywhere in", status);
46 (flags & NP_MATCH_EXACT) ?
47 "in beginning of" : "anywhere in",
48 status);
49 44
50 if (flags & NP_MATCH_EXACT) { 45 if (flags & NP_MATCH_EXACT) {
51 if (strncmp(status, server_expect[i], strlen(server_expect[i])) == 0) { 46 if (strncmp(status, server_expect[i], strlen(server_expect[i])) == 0) {
@@ -58,15 +53,14 @@ np_expect_match(char *status, char **server_expect, int expect_count, int flags)
58 continue; 53 continue;
59 } 54 }
60 } else if (strstr(status, server_expect[i]) != NULL) { 55 } else if (strstr(status, server_expect[i]) != NULL) {
61 VERBOSE("found it"); 56 VERBOSE("found it");
62 match++; 57 match++;
63 continue; 58 continue;
64 } 59 }
65 VERBOSE("couldn't find it"); 60 VERBOSE("couldn't find it");
66 } 61 }
67 62
68 if ((flags & NP_MATCH_ALL && match == expect_count) || 63 if ((flags & NP_MATCH_ALL && match == expect_count) || (!(flags & NP_MATCH_ALL) && match >= 1))
69 (!(flags & NP_MATCH_ALL) && match >= 1))
70 return NP_MATCH_SUCCESS; 64 return NP_MATCH_SUCCESS;
71 else if (partial > 0 || !(flags & NP_MATCH_EXACT)) 65 else if (partial > 0 || !(flags & NP_MATCH_EXACT))
72 return NP_MATCH_RETRY; 66 return NP_MATCH_RETRY;
diff --git a/lib/utils_tcp.h b/lib/utils_tcp.h
index 0328a9cf..d5999e9b 100644
--- a/lib/utils_tcp.h
+++ b/lib/utils_tcp.h
@@ -1,8 +1,8 @@
1/* Header file for utils_tcp */ 1/* Header file for utils_tcp */
2 2
3#define NP_MATCH_ALL 0x1 3#define NP_MATCH_ALL 0x1
4#define NP_MATCH_EXACT 0x2 4#define NP_MATCH_EXACT 0x2
5#define NP_MATCH_VERBOSE 0x4 5#define NP_MATCH_VERBOSE 0x4
6 6
7/* 7/*
8 * The NP_MATCH_RETRY state indicates that matching might succeed if 8 * The NP_MATCH_RETRY state indicates that matching might succeed if
@@ -16,7 +16,4 @@ enum np_match_result {
16 NP_MATCH_RETRY 16 NP_MATCH_RETRY
17}; 17};
18 18
19enum np_match_result np_expect_match(char *status, 19enum np_match_result np_expect_match(char *status, char **server_expect, int server_expect_count, int flags);
20 char **server_expect,
21 int server_expect_count,
22 int flags);
diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c
index 4b8f5e27..6802232e 100644
--- a/plugins-root/check_dhcp.c
+++ b/plugins-root/check_dhcp.c
@@ -4,7 +4,7 @@
4 * 4 *
5 * License: GPL 5 * License: GPL
6 * Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org) 6 * Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)
7 * Copyright (c) 2001-2007 Monitoring Plugins Development Team 7 * Copyright (c) 2001-2023 Monitoring Plugins Development Team
8 * 8 *
9 * Description: 9 * Description:
10 * 10 *
@@ -34,7 +34,7 @@
34 *****************************************************************************/ 34 *****************************************************************************/
35 35
36const char *progname = "check_dhcp"; 36const char *progname = "check_dhcp";
37const char *copyright = "2001-2023"; 37const char *copyright = "2001-2024";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include "common.h" 40#include "common.h"
@@ -59,45 +59,45 @@ const char *email = "devel@monitoring-plugins.org";
59#include <arpa/inet.h> 59#include <arpa/inet.h>
60 60
61#if HAVE_SYS_SOCKIO_H 61#if HAVE_SYS_SOCKIO_H
62#include <sys/sockio.h> 62# include <sys/sockio.h>
63#endif // HAVE_SYS_SOCKIO_H 63#endif // HAVE_SYS_SOCKIO_H
64 64
65#if defined( __linux__ ) 65#if defined(__linux__)
66 66
67#include <linux/if_ether.h> 67# include <linux/if_ether.h>
68#include <features.h> 68# include <features.h>
69 69
70#elif defined (__bsd__) 70#elif defined(__bsd__)
71 71
72#include <netinet/if_ether.h> 72# include <netinet/if_ether.h>
73#include <sys/param.h> 73# include <sys/param.h>
74#include <sys/sysctl.h> 74# include <sys/sysctl.h>
75#include <net/if_dl.h> 75# include <net/if_dl.h>
76 76
77#elif defined(__sun__) || defined(__solaris__) || defined(__hpux__) 77#elif defined(__sun__) || defined(__solaris__) || defined(__hpux__)
78 78
79#define INSAP 22 79# define INSAP 22
80#define OUTSAP 24 80# define OUTSAP 24
81 81
82#include <signal.h> 82# include <signal.h>
83#include <ctype.h> 83# include <ctype.h>
84#include <sys/stropts.h> 84# include <sys/stropts.h>
85#include <sys/poll.h> 85# include <sys/poll.h>
86#include <sys/dlpi.h> 86# include <sys/dlpi.h>
87 87
88#define bcopy(source, destination, length) memcpy(destination, source, length) 88# define bcopy(source, destination, length) memcpy(destination, source, length)
89 89
90#define AREA_SZ 5000 /* buffer length in bytes */ 90# define AREA_SZ 5000 /* buffer length in bytes */
91static u_long ctl_area[AREA_SZ]; 91static u_long ctl_area[AREA_SZ];
92static u_long dat_area[AREA_SZ]; 92static u_long dat_area[AREA_SZ];
93static struct strbuf ctl = {AREA_SZ, 0, (char *)ctl_area}; 93static struct strbuf ctl = {AREA_SZ, 0, (char *)ctl_area};
94static struct strbuf dat = {AREA_SZ, 0, (char *)dat_area}; 94static struct strbuf dat = {AREA_SZ, 0, (char *)dat_area};
95 95
96#define GOT_CTRL 1 96# define GOT_CTRL 1
97#define GOT_DATA 2 97# define GOT_DATA 2
98#define GOT_BOTH 3 98# define GOT_BOTH 3
99#define GOT_INTR 4 99# define GOT_INTR 4
100#define GOT_ERR 128 100# define GOT_ERR 128
101 101
102static int get_msg(int); 102static int get_msg(int);
103static int check_ctrl(int); 103static int check_ctrl(int);
@@ -105,178 +105,168 @@ static int put_ctrl(int, int, int);
105static int put_both(int, int, int, int); 105static int put_both(int, int, int, int);
106static int dl_open(const char *, int, int *); 106static int dl_open(const char *, int, int *);
107static int dl_bind(int, int, u_char *); 107static int dl_bind(int, int, u_char *);
108long mac_addr_dlpi( const char *, int, u_char *); 108static long mac_addr_dlpi(const char *, int, u_char *);
109 109
110#endif // __sun__ || __solaris__ || __hpux 110#endif // __sun__ || __solaris__ || __hpux
111 111
112
113
114/**** Common definitions ****/ 112/**** Common definitions ****/
115 113
116#define OK 0 114#define OK 0
117#define ERROR -1 115#define ERROR -1
118
119 116
120/**** DHCP definitions ****/ 117/**** DHCP definitions ****/
121 118
122#define MAX_DHCP_CHADDR_LENGTH 16 119#define MAX_DHCP_CHADDR_LENGTH 16
123#define MAX_DHCP_SNAME_LENGTH 64 120#define MAX_DHCP_SNAME_LENGTH 64
124#define MAX_DHCP_FILE_LENGTH 128 121#define MAX_DHCP_FILE_LENGTH 128
125#define MAX_DHCP_OPTIONS_LENGTH 312 122#define MAX_DHCP_OPTIONS_LENGTH 312
126 123
127 124typedef struct dhcp_packet_struct {
128typedef struct dhcp_packet_struct{ 125 uint8_t op; /* packet type */
129 uint8_t op; /* packet type */ 126 uint8_t htype; /* type of hardware address for this machine (Ethernet, etc) */
130 uint8_t htype; /* type of hardware address for this machine (Ethernet, etc) */ 127 uint8_t hlen; /* length of hardware address (of this machine) */
131 uint8_t hlen; /* length of hardware address (of this machine) */ 128 uint8_t hops; /* hops */
132 uint8_t hops; /* hops */ 129 uint32_t xid; /* random transaction id number - chosen by this machine */
133 uint32_t xid; /* random transaction id number - chosen by this machine */ 130 uint16_t secs; /* seconds used in timing */
134 uint16_t secs; /* seconds used in timing */ 131 uint16_t flags; /* flags */
135 uint16_t flags; /* flags */ 132 struct in_addr ciaddr; /* IP address of this machine (if we already have one) */
136 struct in_addr ciaddr; /* IP address of this machine (if we already have one) */ 133 struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */
137 struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */ 134 struct in_addr siaddr; /* IP address of next server */
138 struct in_addr siaddr; /* IP address of next server */ 135 struct in_addr giaddr; /* IP address of DHCP relay */
139 struct in_addr giaddr; /* IP address of DHCP relay */ 136 unsigned char chaddr[MAX_DHCP_CHADDR_LENGTH]; /* hardware address of this machine */
140 unsigned char chaddr [MAX_DHCP_CHADDR_LENGTH]; /* hardware address of this machine */ 137 char sname[MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */
141 char sname [MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */ 138 char file[MAX_DHCP_FILE_LENGTH]; /* boot file name (used for diskless booting?) */
142 char file [MAX_DHCP_FILE_LENGTH]; /* boot file name (used for diskless booting?) */ 139 char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */
143 char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */ 140} dhcp_packet;
144}dhcp_packet; 141
145 142typedef struct dhcp_offer_struct {
146 143 struct in_addr server_address; /* address of DHCP server that sent this offer */
147typedef struct dhcp_offer_struct{ 144 struct in_addr offered_address; /* the IP address that was offered to us */
148 struct in_addr server_address; /* address of DHCP server that sent this offer */
149 struct in_addr offered_address; /* the IP address that was offered to us */
150 uint32_t lease_time; /* lease time in seconds */ 145 uint32_t lease_time; /* lease time in seconds */
151 uint32_t renewal_time; /* renewal time in seconds */ 146 uint32_t renewal_time; /* renewal time in seconds */
152 uint32_t rebinding_time; /* rebinding time in seconds */ 147 uint32_t rebinding_time; /* rebinding time in seconds */
153 bool desired; /* is this offer desired (necessary in exclusive mode) */ 148 bool desired; /* is this offer desired (necessary in exclusive mode) */
154 struct dhcp_offer_struct *next; 149 struct dhcp_offer_struct *next;
155}dhcp_offer; 150} dhcp_offer;
156
157 151
158typedef struct requested_server_struct{ 152typedef struct requested_server_struct {
159 struct in_addr server_address; 153 struct in_addr server_address;
160 bool answered; 154 bool answered;
161 struct requested_server_struct *next; 155 struct requested_server_struct *next;
162}requested_server; 156} requested_server;
163 157
164 158#define BOOTREQUEST 1
165#define BOOTREQUEST 1 159#define BOOTREPLY 2
166#define BOOTREPLY 2 160
167 161#define DHCPDISCOVER 1
168#define DHCPDISCOVER 1 162#define DHCPOFFER 2
169#define DHCPOFFER 2 163#define DHCPREQUEST 3
170#define DHCPREQUEST 3 164#define DHCPDECLINE 4
171#define DHCPDECLINE 4 165#define DHCPACK 5
172#define DHCPACK 5 166#define DHCPNACK 6
173#define DHCPNACK 6 167#define DHCPRELEASE 7
174#define DHCPRELEASE 7 168
175 169#define DHCP_OPTION_MESSAGE_TYPE 53
176#define DHCP_OPTION_MESSAGE_TYPE 53 170#define DHCP_OPTION_HOST_NAME 12
177#define DHCP_OPTION_HOST_NAME 12 171#define DHCP_OPTION_BROADCAST_ADDRESS 28
178#define DHCP_OPTION_BROADCAST_ADDRESS 28 172#define DHCP_OPTION_REQUESTED_ADDRESS 50
179#define DHCP_OPTION_REQUESTED_ADDRESS 50 173#define DHCP_OPTION_LEASE_TIME 51
180#define DHCP_OPTION_LEASE_TIME 51 174#define DHCP_OPTION_SERVER_IDENTIFIER 54
181#define DHCP_OPTION_SERVER_IDENTIFIER 54 175#define DHCP_OPTION_RENEWAL_TIME 58
182#define DHCP_OPTION_RENEWAL_TIME 58 176#define DHCP_OPTION_REBINDING_TIME 59
183#define DHCP_OPTION_REBINDING_TIME 59 177#define DHCP_OPTION_END 255
184#define DHCP_OPTION_END 255 178
185 179#define DHCP_INFINITE_TIME 0xFFFFFFFF
186#define DHCP_INFINITE_TIME 0xFFFFFFFF
187 180
188#define DHCP_BROADCAST_FLAG 32768 181#define DHCP_BROADCAST_FLAG 32768
189 182
190#define DHCP_SERVER_PORT 67 183#define DHCP_SERVER_PORT 67
191#define DHCP_CLIENT_PORT 68 184#define DHCP_CLIENT_PORT 68
192 185
193#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */ 186#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */
194#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */ 187#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */
195 188
196bool unicast = false; /* unicast mode: mimic a DHCP relay */ 189static bool unicast = false; /* unicast mode: mimic a DHCP relay */
197bool exclusive = false; /* exclusive mode aka "rogue DHCP server detection" */ 190static bool exclusive = false; /* exclusive mode aka "rogue DHCP server detection" */
198struct in_addr my_ip; /* our address (required for relay) */ 191static struct in_addr my_ip; /* our address (required for relay) */
199struct in_addr dhcp_ip; /* server to query (if in unicast mode) */ 192static struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
200unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]=""; 193static unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH] = "";
201unsigned char *user_specified_mac=NULL; 194static unsigned char *user_specified_mac = NULL;
202 195
203char network_interface_name[IFNAMSIZ]="eth0"; 196static char network_interface_name[IFNAMSIZ] = "eth0";
204 197
205uint32_t packet_xid=0; 198static uint32_t packet_xid = 0;
206 199
207uint32_t dhcp_lease_time=0; 200static uint32_t dhcp_lease_time = 0;
208uint32_t dhcp_renewal_time=0; 201static uint32_t dhcp_renewal_time = 0;
209uint32_t dhcp_rebinding_time=0; 202static uint32_t dhcp_rebinding_time = 0;
210 203
211int dhcpoffer_timeout=2; 204static int dhcpoffer_timeout = 2;
212 205
213dhcp_offer *dhcp_offer_list=NULL; 206static dhcp_offer *dhcp_offer_list = NULL;
214requested_server *requested_server_list=NULL; 207static requested_server *requested_server_list = NULL;
215 208
216int valid_responses=0; /* number of valid DHCPOFFERs we received */ 209static int valid_responses = 0; /* number of valid DHCPOFFERs we received */
217int requested_servers=0; 210static int requested_servers = 0;
218int requested_responses=0; 211static int requested_responses = 0;
219 212
220bool request_specific_address=false; 213static bool request_specific_address = false;
221bool received_requested_address=false; 214static bool received_requested_address = false;
222int verbose=0; 215static int verbose = 0;
223struct in_addr requested_address; 216static struct in_addr requested_address;
224 217
225 218static int process_arguments(int, char **);
226int process_arguments(int, char **); 219static int call_getopt(int, char **);
227int call_getopt(int, char **); 220static int validate_arguments(int);
228int validate_arguments(int);
229void print_usage(void); 221void print_usage(void);
230void print_help(void); 222static void print_help(void);
231
232void resolve_host(const char *in,struct in_addr *out);
233unsigned char *mac_aton(const char *);
234void print_hardware_address(const unsigned char *);
235int get_hardware_address(int,char *);
236int get_ip_address(int,char *);
237 223
238int send_dhcp_discover(int); 224static void resolve_host(const char *in, struct in_addr *out);
239int get_dhcp_offer(int); 225static unsigned char *mac_aton(const char *);
226static void print_hardware_address(const unsigned char *);
227static int get_hardware_address(int, char *);
228static int get_ip_address(int, char *);
240 229
241int get_results(void); 230static int send_dhcp_discover(int);
231static int get_dhcp_offer(int);
242 232
243int add_dhcp_offer(struct in_addr,dhcp_packet *); 233static int get_results(void);
244int free_dhcp_offer_list(void);
245int free_requested_server_list(void);
246 234
247int create_dhcp_socket(void); 235static int add_dhcp_offer(struct in_addr, dhcp_packet *);
248int close_dhcp_socket(int); 236static int free_dhcp_offer_list(void);
249int send_dhcp_packet(void *,int,int,struct sockaddr_in *); 237static int free_requested_server_list(void);
250int receive_dhcp_packet(void *,int,int,int,struct sockaddr_in *);
251 238
239static int create_dhcp_socket(void);
240static int close_dhcp_socket(int);
241static int send_dhcp_packet(void *, int, int, struct sockaddr_in *);
242static int receive_dhcp_packet(void *, int, int, int, struct sockaddr_in *);
252 243
253 244int main(int argc, char **argv) {
254int main(int argc, char **argv){
255 int dhcp_socket; 245 int dhcp_socket;
256 int result = STATE_UNKNOWN; 246 int result = STATE_UNKNOWN;
257 247
258 setlocale (LC_ALL, ""); 248 setlocale(LC_ALL, "");
259 bindtextdomain (PACKAGE, LOCALEDIR); 249 bindtextdomain(PACKAGE, LOCALEDIR);
260 textdomain (PACKAGE); 250 textdomain(PACKAGE);
261 251
262 /* Parse extra opts if any */ 252 /* Parse extra opts if any */
263 argv=np_extra_opts(&argc, argv, progname); 253 argv = np_extra_opts(&argc, argv, progname);
264 254
265 if(process_arguments(argc,argv)!=OK){ 255 if (process_arguments(argc, argv) != OK) {
266 usage4 (_("Could not parse arguments")); 256 usage4(_("Could not parse arguments"));
267 } 257 }
268 258
269 /* create socket for DHCP communications */ 259 /* create socket for DHCP communications */
270 dhcp_socket=create_dhcp_socket(); 260 dhcp_socket = create_dhcp_socket();
271 261
272 /* get hardware address of client machine */ 262 /* get hardware address of client machine */
273 if(user_specified_mac!=NULL) 263 if (user_specified_mac != NULL)
274 memcpy(client_hardware_address,user_specified_mac,6); 264 memcpy(client_hardware_address, user_specified_mac, 6);
275 else 265 else
276 get_hardware_address(dhcp_socket,network_interface_name); 266 get_hardware_address(dhcp_socket, network_interface_name);
277 267
278 if(unicast) /* get IP address of client machine */ 268 if (unicast) /* get IP address of client machine */
279 get_ip_address(dhcp_socket,network_interface_name); 269 get_ip_address(dhcp_socket, network_interface_name);
280 270
281 /* send DHCPDISCOVER packet */ 271 /* send DHCPDISCOVER packet */
282 send_dhcp_discover(dhcp_socket); 272 send_dhcp_discover(dhcp_socket);
@@ -288,7 +278,7 @@ int main(int argc, char **argv){
288 close_dhcp_socket(dhcp_socket); 278 close_dhcp_socket(dhcp_socket);
289 279
290 /* determine state/plugin output to return */ 280 /* determine state/plugin output to return */
291 result=get_results(); 281 result = get_results();
292 282
293 /* free allocated memory */ 283 /* free allocated memory */
294 free_dhcp_offer_list(); 284 free_dhcp_offer_list();
@@ -297,34 +287,32 @@ int main(int argc, char **argv){
297 return result; 287 return result;
298} 288}
299 289
300
301
302/* determines hardware address on client machine */ 290/* determines hardware address on client machine */
303int get_hardware_address(int sock,char *interface_name){ 291static int get_hardware_address(int sock, char *interface_name) {
304 292
305#if defined(__linux__) 293#if defined(__linux__)
306 struct ifreq ifr; 294 struct ifreq ifr;
307 295
308 strncpy((char *)&ifr.ifr_name,interface_name,sizeof(ifr.ifr_name)-1); 296 strncpy((char *)&ifr.ifr_name, interface_name, sizeof(ifr.ifr_name) - 1);
309 ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0'; 297 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
310 298
311 /* try and grab hardware address of requested interface */ 299 /* try and grab hardware address of requested interface */
312 if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){ 300 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
313 printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name); 301 printf(_("Error: Could not get hardware address of interface '%s'\n"), interface_name);
314 exit(STATE_UNKNOWN); 302 exit(STATE_UNKNOWN);
315 } 303 }
316 304
317 memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6); 305 memcpy(&client_hardware_address[0], &ifr.ifr_hwaddr.sa_data, 6);
318 306
319#elif defined(__bsd__) 307#elif defined(__bsd__)
320 /* King 2004 see ACKNOWLEDGEMENTS */ 308 /* King 2004 see ACKNOWLEDGEMENTS */
321 309
322 size_t len; 310 size_t len;
323 int mib[6]; 311 int mib[6];
324 char *buf; 312 char *buf;
325 unsigned char *ptr; 313 unsigned char *ptr;
326 struct if_msghdr *ifm; 314 struct if_msghdr *ifm;
327 struct sockaddr_dl *sdl; 315 struct sockaddr_dl *sdl;
328 316
329 mib[0] = CTL_NET; 317 mib[0] = CTL_NET;
330 mib[1] = AF_ROUTE; 318 mib[1] = AF_ROUTE;
@@ -332,22 +320,22 @@ int get_hardware_address(int sock,char *interface_name){
332 mib[3] = AF_LINK; 320 mib[3] = AF_LINK;
333 mib[4] = NET_RT_IFLIST; 321 mib[4] = NET_RT_IFLIST;
334 322
335 if((mib[5] = if_nametoindex(interface_name)) == 0){ 323 if ((mib[5] = if_nametoindex(interface_name)) == 0) {
336 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno)); 324 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno));
337 exit(STATE_UNKNOWN); 325 exit(STATE_UNKNOWN);
338 } 326 }
339 327
340 if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0){ 328 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
341 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno)); 329 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno));
342 exit(STATE_UNKNOWN); 330 exit(STATE_UNKNOWN);
343 } 331 }
344 332
345 if((buf = malloc(len)) == NULL){ 333 if ((buf = malloc(len)) == NULL) {
346 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno)); 334 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno));
347 exit(4); 335 exit(4);
348 } 336 }
349 337
350 if(sysctl(mib, 6, buf, &len, NULL, 0) < 0){ 338 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
351 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno)); 339 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno));
352 exit(STATE_UNKNOWN); 340 exit(STATE_UNKNOWN);
353 } 341 }
@@ -355,7 +343,7 @@ int get_hardware_address(int sock,char *interface_name){
355 ifm = (struct if_msghdr *)buf; 343 ifm = (struct if_msghdr *)buf;
356 sdl = (struct sockaddr_dl *)(ifm + 1); 344 sdl = (struct sockaddr_dl *)(ifm + 1);
357 ptr = (unsigned char *)LLADDR(sdl); 345 ptr = (unsigned char *)LLADDR(sdl);
358 memcpy(&client_hardware_address[0], ptr, 6) ; 346 memcpy(&client_hardware_address[0], ptr, 6);
359 /* King 2004 */ 347 /* King 2004 */
360 348
361#elif defined(__sun__) || defined(__solaris__) 349#elif defined(__sun__) || defined(__solaris__)
@@ -368,22 +356,21 @@ int get_hardware_address(int sock,char *interface_name){
368 356
369 /* get last number from interfacename, eg lnc0, e1000g0*/ 357 /* get last number from interfacename, eg lnc0, e1000g0*/
370 int i; 358 int i;
371 p = interface_name + strlen(interface_name) -1; 359 p = interface_name + strlen(interface_name) - 1;
372 for(i = strlen(interface_name) -1; i > 0; p--) { 360 for (i = strlen(interface_name) - 1; i > 0; p--) {
373 if(isalpha(*p)) 361 if (isalpha(*p))
374 break; 362 break;
375 } 363 }
376 p++; 364 p++;
377 if( p != interface_name ){ 365 if (p != interface_name) {
378 unit = atoi(p) ; 366 unit = atoi(p);
379 strncat(dev, interface_name, 6) ; 367 strncat(dev, interface_name, 6);
380 } 368 } else {
381 else{
382 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name); 369 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name);
383 exit(STATE_UNKNOWN); 370 exit(STATE_UNKNOWN);
384 } 371 }
385 stat = mac_addr_dlpi(dev, unit, client_hardware_address); 372 stat = mac_addr_dlpi(dev, unit, client_hardware_address);
386 if(stat != 0){ 373 if (stat != 0) {
387 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 374 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
388 exit(STATE_UNKNOWN); 375 exit(STATE_UNKNOWN);
389 } 376 }
@@ -391,11 +378,11 @@ int get_hardware_address(int sock,char *interface_name){
391#elif defined(__hpux__) 378#elif defined(__hpux__)
392 379
393 long stat; 380 long stat;
394 char dev[20] = "/dev/dlpi" ; 381 char dev[20] = "/dev/dlpi";
395 int unit = 0; 382 int unit = 0;
396 383
397 stat = mac_addr_dlpi(dev, unit, client_hardware_address); 384 stat = mac_addr_dlpi(dev, unit, client_hardware_address);
398 if(stat != 0){ 385 if (stat != 0) {
399 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 386 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
400 exit(STATE_UNKNOWN); 387 exit(STATE_UNKNOWN);
401 } 388 }
@@ -406,68 +393,65 @@ int get_hardware_address(int sock,char *interface_name){
406 exit(STATE_UNKNOWN); 393 exit(STATE_UNKNOWN);
407#endif 394#endif
408 395
409 if(verbose) 396 if (verbose)
410 print_hardware_address(client_hardware_address); 397 print_hardware_address(client_hardware_address);
411 398
412 return OK; 399 return OK;
413} 400}
414 401
415/* determines IP address of the client interface */ 402/* determines IP address of the client interface */
416int get_ip_address(int sock,char *interface_name){ 403static int get_ip_address(int sock, char *interface_name) {
417#if defined(SIOCGIFADDR) 404#if defined(SIOCGIFADDR)
418 struct ifreq ifr; 405 struct ifreq ifr;
419 406
420 strncpy((char *)&ifr.ifr_name,interface_name,sizeof(ifr.ifr_name)-1); 407 strncpy((char *)&ifr.ifr_name, interface_name, sizeof(ifr.ifr_name) - 1);
421 ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0'; 408 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
422 409
423 if(ioctl(sock,SIOCGIFADDR,&ifr)<0){ 410 if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
424 printf(_("Error: Cannot determine IP address of interface %s\n"), 411 printf(_("Error: Cannot determine IP address of interface %s\n"), interface_name);
425 interface_name);
426 exit(STATE_UNKNOWN); 412 exit(STATE_UNKNOWN);
427 } 413 }
428 414
429 my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 415 my_ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
430 416
431#else 417#else
432 printf(_("Error: Cannot get interface IP address on this platform.\n")); 418 printf(_("Error: Cannot get interface IP address on this platform.\n"));
433 exit(STATE_UNKNOWN); 419 exit(STATE_UNKNOWN);
434#endif 420#endif
435 421
436 if(verbose) 422 if (verbose)
437 printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip)); 423 printf(_("Pretending to be relay client %s\n"), inet_ntoa(my_ip));
438 424
439 return OK; 425 return OK;
440} 426}
441 427
442/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ 428/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */
443int send_dhcp_discover(int sock){ 429static int send_dhcp_discover(int sock) {
444 dhcp_packet discover_packet; 430 dhcp_packet discover_packet;
445 struct sockaddr_in sockaddr_broadcast; 431 struct sockaddr_in sockaddr_broadcast;
446 unsigned short opts; 432 unsigned short opts;
447 433
448
449 /* clear the packet data structure */ 434 /* clear the packet data structure */
450 bzero(&discover_packet,sizeof(discover_packet)); 435 bzero(&discover_packet, sizeof(discover_packet));
451
452 436
453 /* boot request flag (backward compatible with BOOTP servers) */ 437 /* boot request flag (backward compatible with BOOTP servers) */
454 discover_packet.op=BOOTREQUEST; 438 discover_packet.op = BOOTREQUEST;
455 439
456 /* hardware address type */ 440 /* hardware address type */
457 discover_packet.htype=ETHERNET_HARDWARE_ADDRESS; 441 discover_packet.htype = ETHERNET_HARDWARE_ADDRESS;
458 442
459 /* length of our hardware address */ 443 /* length of our hardware address */
460 discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH; 444 discover_packet.hlen = ETHERNET_HARDWARE_ADDRESS_LENGTH;
461 445
462 /* 446 /*
463 * transaction ID is supposed to be random. 447 * transaction ID is supposed to be random.
464 */ 448 */
465 srand(time(NULL)^getpid()); 449 srand(time(NULL) ^ getpid());
466 packet_xid=random(); 450 packet_xid = random();
467 discover_packet.xid=htonl(packet_xid); 451 discover_packet.xid = htonl(packet_xid);
468 452
469 /*discover_packet.secs=htons(65535);*/ 453 /*discover_packet.secs=htons(65535);*/
470 discover_packet.secs=0xFF; 454 discover_packet.secs = 0xFF;
471 455
472 /* 456 /*
473 * server needs to know if it should broadcast or unicast its response: 457 * server needs to know if it should broadcast or unicast its response:
@@ -476,71 +460,67 @@ int send_dhcp_discover(int sock){
476 discover_packet.flags = unicast ? 0 : htons(DHCP_BROADCAST_FLAG); 460 discover_packet.flags = unicast ? 0 : htons(DHCP_BROADCAST_FLAG);
477 461
478 /* our hardware address */ 462 /* our hardware address */
479 memcpy(discover_packet.chaddr,client_hardware_address,ETHERNET_HARDWARE_ADDRESS_LENGTH); 463 memcpy(discover_packet.chaddr, client_hardware_address, ETHERNET_HARDWARE_ADDRESS_LENGTH);
480 464
481 /* first four bytes of options field is magic cookie (as per RFC 2132) */ 465 /* first four bytes of options field is magic cookie (as per RFC 2132) */
482 discover_packet.options[0]='\x63'; 466 discover_packet.options[0] = '\x63';
483 discover_packet.options[1]='\x82'; 467 discover_packet.options[1] = '\x82';
484 discover_packet.options[2]='\x53'; 468 discover_packet.options[2] = '\x53';
485 discover_packet.options[3]='\x63'; 469 discover_packet.options[3] = '\x63';
486 470
487 opts = 4; 471 opts = 4;
488 /* DHCP message type is embedded in options field */ 472 /* DHCP message type is embedded in options field */
489 discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ 473 discover_packet.options[opts++] = DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */
490 discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */ 474 discover_packet.options[opts++] = '\x01'; /* DHCP message option length in bytes */
491 discover_packet.options[opts++]=DHCPDISCOVER; 475 discover_packet.options[opts++] = DHCPDISCOVER;
492 476
493 /* the IP address we're requesting */ 477 /* the IP address we're requesting */
494 if(request_specific_address){ 478 if (request_specific_address) {
495 discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS; 479 discover_packet.options[opts++] = DHCP_OPTION_REQUESTED_ADDRESS;
496 discover_packet.options[opts++]='\x04'; 480 discover_packet.options[opts++] = '\x04';
497 memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address)); 481 memcpy(&discover_packet.options[opts], &requested_address, sizeof(requested_address));
498 opts += sizeof(requested_address); 482 opts += sizeof(requested_address);
499 } 483 }
500 discover_packet.options[opts++]= (char)DHCP_OPTION_END; 484 discover_packet.options[opts++] = (char)DHCP_OPTION_END;
501 485
502 /* unicast fields */ 486 /* unicast fields */
503 if(unicast) 487 if (unicast)
504 discover_packet.giaddr.s_addr = my_ip.s_addr; 488 discover_packet.giaddr.s_addr = my_ip.s_addr;
505 489
506 /* see RFC 1542, 4.1.1 */ 490 /* see RFC 1542, 4.1.1 */
507 discover_packet.hops = unicast ? 1 : 0; 491 discover_packet.hops = unicast ? 1 : 0;
508 492
509 /* send the DHCPDISCOVER packet to broadcast address */ 493 /* send the DHCPDISCOVER packet to broadcast address */
510 sockaddr_broadcast.sin_family=AF_INET; 494 sockaddr_broadcast.sin_family = AF_INET;
511 sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT); 495 sockaddr_broadcast.sin_port = htons(DHCP_SERVER_PORT);
512 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST; 496 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST;
513 bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero)); 497 bzero(&sockaddr_broadcast.sin_zero, sizeof(sockaddr_broadcast.sin_zero));
514 498
515 499 if (verbose) {
516 if(verbose){ 500 printf(_("DHCPDISCOVER to %s port %d\n"), inet_ntoa(sockaddr_broadcast.sin_addr), ntohs(sockaddr_broadcast.sin_port));
517 printf(_("DHCPDISCOVER to %s port %d\n"),inet_ntoa(sockaddr_broadcast.sin_addr),ntohs(sockaddr_broadcast.sin_port)); 501 printf("DHCPDISCOVER XID: %u (0x%X)\n", ntohl(discover_packet.xid), ntohl(discover_packet.xid));
518 printf("DHCPDISCOVER XID: %u (0x%X)\n",ntohl(discover_packet.xid),ntohl(discover_packet.xid)); 502 printf("DHCDISCOVER ciaddr: %s\n", inet_ntoa(discover_packet.ciaddr));
519 printf("DHCDISCOVER ciaddr: %s\n",inet_ntoa(discover_packet.ciaddr)); 503 printf("DHCDISCOVER yiaddr: %s\n", inet_ntoa(discover_packet.yiaddr));
520 printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); 504 printf("DHCDISCOVER siaddr: %s\n", inet_ntoa(discover_packet.siaddr));
521 printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); 505 printf("DHCDISCOVER giaddr: %s\n", inet_ntoa(discover_packet.giaddr));
522 printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr));
523 } 506 }
524 507
525 /* send the DHCPDISCOVER packet out */ 508 /* send the DHCPDISCOVER packet out */
526 send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); 509 send_dhcp_packet(&discover_packet, sizeof(discover_packet), sock, &sockaddr_broadcast);
527 510
528 if(verbose) 511 if (verbose)
529 printf("\n\n"); 512 printf("\n\n");
530 513
531 return OK; 514 return OK;
532} 515}
533 516
534
535
536
537/* waits for a DHCPOFFER message from one or more DHCP servers */ 517/* waits for a DHCPOFFER message from one or more DHCP servers */
538int get_dhcp_offer(int sock){ 518static int get_dhcp_offer(int sock) {
539 dhcp_packet offer_packet; 519 dhcp_packet offer_packet;
540 struct sockaddr_in source; 520 struct sockaddr_in source;
541 struct sockaddr_in via; 521 struct sockaddr_in via;
542 int result=OK; 522 int result = OK;
543 int responses=0; 523 int responses = 0;
544 int x; 524 int x;
545 time_t start_time; 525 time_t start_time;
546 time_t current_time; 526 time_t current_time;
@@ -548,30 +528,29 @@ int get_dhcp_offer(int sock){
548 time(&start_time); 528 time(&start_time);
549 529
550 /* receive as many responses as we can */ 530 /* receive as many responses as we can */
551 for(responses=0,valid_responses=0;;){ 531 for (responses = 0, valid_responses = 0;;) {
552 532
553 time(&current_time); 533 time(&current_time);
554 if((current_time-start_time)>=dhcpoffer_timeout) 534 if ((current_time - start_time) >= dhcpoffer_timeout)
555 break; 535 break;
556 536
557 if(verbose) 537 if (verbose)
558 printf("\n\n"); 538 printf("\n\n");
559 539
560 bzero(&source,sizeof(source)); 540 bzero(&source, sizeof(source));
561 bzero(&via,sizeof(via)); 541 bzero(&via, sizeof(via));
562 bzero(&offer_packet,sizeof(offer_packet)); 542 bzero(&offer_packet, sizeof(offer_packet));
563 543
564 result=OK; 544 result = OK;
565 result=receive_dhcp_packet(&offer_packet,sizeof(offer_packet),sock,dhcpoffer_timeout,&source); 545 result = receive_dhcp_packet(&offer_packet, sizeof(offer_packet), sock, dhcpoffer_timeout, &source);
566 546
567 if(result!=OK){ 547 if (result != OK) {
568 if(verbose) 548 if (verbose)
569 printf(_("Result=ERROR\n")); 549 printf(_("Result=ERROR\n"));
570 550
571 continue; 551 continue;
572 } 552 } else {
573 else{ 553 if (verbose)
574 if(verbose)
575 printf(_("Result=OK\n")); 554 printf(_("Result=OK\n"));
576 555
577 responses++; 556 responses++;
@@ -579,85 +558,81 @@ int get_dhcp_offer(int sock){
579 558
580 /* The "source" is either a server or a relay. */ 559 /* The "source" is either a server or a relay. */
581 /* Save a copy of "source" into "via" even if it's via itself */ 560 /* Save a copy of "source" into "via" even if it's via itself */
582 memcpy(&via,&source,sizeof(source)) ; 561 memcpy(&via, &source, sizeof(source));
583 562
584 if(verbose){ 563 if (verbose) {
585 printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr)); 564 printf(_("DHCPOFFER from IP address %s"), inet_ntoa(source.sin_addr));
586 printf(_(" via %s\n"),inet_ntoa(via.sin_addr)); 565 printf(_(" via %s\n"), inet_ntoa(via.sin_addr));
587 printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid)); 566 printf("DHCPOFFER XID: %u (0x%X)\n", ntohl(offer_packet.xid), ntohl(offer_packet.xid));
588 } 567 }
589 568
590 /* check packet xid to see if its the same as the one we used in the discover packet */ 569 /* check packet xid to see if its the same as the one we used in the discover packet */
591 if(ntohl(offer_packet.xid)!=packet_xid){ 570 if (ntohl(offer_packet.xid) != packet_xid) {
592 if(verbose) 571 if (verbose)
593 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid); 572 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"), ntohl(offer_packet.xid), packet_xid);
594 573
595 continue; 574 continue;
596 } 575 }
597 576
598 /* check hardware address */ 577 /* check hardware address */
599 result=OK; 578 result = OK;
600 if(verbose) 579 if (verbose)
601 printf("DHCPOFFER chaddr: "); 580 printf("DHCPOFFER chaddr: ");
602 581
603 for(x=0;x<ETHERNET_HARDWARE_ADDRESS_LENGTH;x++){ 582 for (x = 0; x < ETHERNET_HARDWARE_ADDRESS_LENGTH; x++) {
604 if(verbose) 583 if (verbose)
605 printf("%02X",(unsigned char)offer_packet.chaddr[x]); 584 printf("%02X", (unsigned char)offer_packet.chaddr[x]);
606 585
607 if(offer_packet.chaddr[x]!=client_hardware_address[x]) 586 if (offer_packet.chaddr[x] != client_hardware_address[x])
608 result=ERROR; 587 result = ERROR;
609 } 588 }
610 if(verbose) 589 if (verbose)
611 printf("\n"); 590 printf("\n");
612 591
613 if(result==ERROR){ 592 if (result == ERROR) {
614 if(verbose) 593 if (verbose)
615 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n")); 594 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n"));
616 595
617 continue; 596 continue;
618 } 597 }
619 598
620 if(verbose){ 599 if (verbose) {
621 printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr)); 600 printf("DHCPOFFER ciaddr: %s\n", inet_ntoa(offer_packet.ciaddr));
622 printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr)); 601 printf("DHCPOFFER yiaddr: %s\n", inet_ntoa(offer_packet.yiaddr));
623 printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr)); 602 printf("DHCPOFFER siaddr: %s\n", inet_ntoa(offer_packet.siaddr));
624 printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr)); 603 printf("DHCPOFFER giaddr: %s\n", inet_ntoa(offer_packet.giaddr));
625 } 604 }
626 605
627 add_dhcp_offer(source.sin_addr,&offer_packet); 606 add_dhcp_offer(source.sin_addr, &offer_packet);
628 607
629 valid_responses++; 608 valid_responses++;
630 } 609 }
631 610
632 if(verbose){ 611 if (verbose) {
633 printf(_("Total responses seen on the wire: %d\n"),responses); 612 printf(_("Total responses seen on the wire: %d\n"), responses);
634 printf(_("Valid responses for this machine: %d\n"),valid_responses); 613 printf(_("Valid responses for this machine: %d\n"), valid_responses);
635 } 614 }
636 615
637 return OK; 616 return OK;
638} 617}
639 618
640
641
642/* sends a DHCP packet */ 619/* sends a DHCP packet */
643int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest){ 620static int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest) {
644 int result; 621 int result;
645 622
646 result=sendto(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)dest,sizeof(*dest)); 623 result = sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest));
647 624
648 if(verbose) 625 if (verbose)
649 printf(_("send_dhcp_packet result: %d\n"),result); 626 printf(_("send_dhcp_packet result: %d\n"), result);
650 627
651 if(result<0) 628 if (result < 0)
652 return ERROR; 629 return ERROR;
653 630
654 return OK; 631 return OK;
655} 632}
656 633
657
658
659/* receives a DHCP packet */ 634/* receives a DHCP packet */
660int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){ 635static int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address) {
661 struct timeval tv; 636 struct timeval tv;
662 fd_set readfds; 637 fd_set readfds;
663 fd_set oobfds; 638 fd_set oobfds;
@@ -666,44 +641,42 @@ int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, st
666 struct sockaddr_in source_address; 641 struct sockaddr_in source_address;
667 int nfound; 642 int nfound;
668 643
669
670 /* wait for data to arrive (up time timeout) */ 644 /* wait for data to arrive (up time timeout) */
671 tv.tv_sec=timeout; 645 tv.tv_sec = timeout;
672 tv.tv_usec=0; 646 tv.tv_usec = 0;
673 FD_ZERO(&readfds); 647 FD_ZERO(&readfds);
674 FD_ZERO(&oobfds); 648 FD_ZERO(&oobfds);
675 FD_SET(sock,&readfds); 649 FD_SET(sock, &readfds);
676 FD_SET(sock,&oobfds); 650 FD_SET(sock, &oobfds);
677 nfound = select(sock+1,&readfds,NULL,&oobfds,&tv); 651 nfound = select(sock + 1, &readfds, NULL, &oobfds, &tv);
678 652
679 /* make sure some data has arrived */ 653 /* make sure some data has arrived */
680 if(!FD_ISSET(sock,&readfds)){ 654 if (!FD_ISSET(sock, &readfds)) {
681 if(verbose) 655 if (verbose)
682 printf(_("No (more) data received (nfound: %d)\n"), nfound); 656 printf(_("No (more) data received (nfound: %d)\n"), nfound);
683 return ERROR; 657 return ERROR;
684 } 658 }
685 659
686 else{ 660 else {
687 bzero(&source_address,sizeof(source_address)); 661 bzero(&source_address, sizeof(source_address));
688 address_size=sizeof(source_address); 662 address_size = sizeof(source_address);
689 recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)&source_address,&address_size); 663 recv_result = recvfrom(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)&source_address, &address_size);
690 if(verbose) 664 if (verbose)
691 printf("recv_result: %d\n",recv_result); 665 printf("recv_result: %d\n", recv_result);
692 666
693 if(recv_result==-1){ 667 if (recv_result == -1) {
694 if(verbose){ 668 if (verbose) {
695 printf(_("recvfrom() failed, ")); 669 printf(_("recvfrom() failed, "));
696 printf("errno: (%d) -> %s\n",errno,strerror(errno)); 670 printf("errno: (%d) -> %s\n", errno, strerror(errno));
697 } 671 }
698 return ERROR; 672 return ERROR;
699 } 673 } else {
700 else{ 674 if (verbose) {
701 if(verbose){ 675 printf(_("receive_dhcp_packet() result: %d\n"), recv_result);
702 printf(_("receive_dhcp_packet() result: %d\n"),recv_result); 676 printf(_("receive_dhcp_packet() source: %s\n"), inet_ntoa(source_address.sin_addr));
703 printf(_("receive_dhcp_packet() source: %s\n"),inet_ntoa(source_address.sin_addr));
704 } 677 }
705 678
706 memcpy(address,&source_address,sizeof(source_address)); 679 memcpy(address, &source_address, sizeof(source_address));
707 return OK; 680 return OK;
708 } 681 }
709 } 682 }
@@ -711,172 +684,166 @@ int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, st
711 return OK; 684 return OK;
712} 685}
713 686
714
715/* creates a socket for DHCP communication */ 687/* creates a socket for DHCP communication */
716int create_dhcp_socket(void){ 688static int create_dhcp_socket(void) {
717 struct sockaddr_in myname; 689 struct sockaddr_in myname;
718 struct ifreq interface; 690 struct ifreq interface;
719 int sock; 691 int sock;
720 int flag=1; 692 int flag = 1;
721 693
722 /* Set up the address we're going to bind to. */ 694 /* Set up the address we're going to bind to. */
723 bzero(&myname,sizeof(myname)); 695 bzero(&myname, sizeof(myname));
724 myname.sin_family=AF_INET; 696 myname.sin_family = AF_INET;
725 /* listen to DHCP server port if we're in unicast mode */ 697 /* listen to DHCP server port if we're in unicast mode */
726 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT); 698 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT);
727 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY; 699 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY;
728 bzero(&myname.sin_zero,sizeof(myname.sin_zero)); 700 bzero(&myname.sin_zero, sizeof(myname.sin_zero));
729 701
730 /* create a socket for DHCP communications */ 702 /* create a socket for DHCP communications */
731 sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 703 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
732 if(sock<0){ 704 if (sock < 0) {
733 printf(_("Error: Could not create socket!\n")); 705 printf(_("Error: Could not create socket!\n"));
734 exit(STATE_UNKNOWN); 706 exit(STATE_UNKNOWN);
735 } 707 }
736 708
737 if(verbose) 709 if (verbose)
738 printf("DHCP socket: %d\n",sock); 710 printf("DHCP socket: %d\n", sock);
739 711
740 /* set the reuse address flag so we don't get errors when restarting */ 712 /* set the reuse address flag so we don't get errors when restarting */
741 flag=1; 713 flag = 1;
742 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ 714 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)) < 0) {
743 printf(_("Error: Could not set reuse address option on DHCP socket!\n")); 715 printf(_("Error: Could not set reuse address option on DHCP socket!\n"));
744 exit(STATE_UNKNOWN); 716 exit(STATE_UNKNOWN);
745 } 717 }
746 718
747 /* set the broadcast option - we need this to listen to DHCP broadcast messages */ 719 /* set the broadcast option - we need this to listen to DHCP broadcast messages */
748 if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){ 720 if (!unicast && setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&flag, sizeof flag) < 0) {
749 printf(_("Error: Could not set broadcast option on DHCP socket!\n")); 721 printf(_("Error: Could not set broadcast option on DHCP socket!\n"));
750 exit(STATE_UNKNOWN); 722 exit(STATE_UNKNOWN);
751 } 723 }
752 724
753 /* bind socket to interface */ 725 /* bind socket to interface */
754#if defined(__linux__) 726#if defined(__linux__)
755 strncpy(interface.ifr_ifrn.ifrn_name,network_interface_name,IFNAMSIZ-1); 727 strncpy(interface.ifr_ifrn.ifrn_name, network_interface_name, IFNAMSIZ - 1);
756 interface.ifr_ifrn.ifrn_name[IFNAMSIZ-1]='\0'; 728 interface.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = '\0';
757 if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){ 729 if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&interface, sizeof(interface)) < 0) {
758 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name); 730 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"), network_interface_name);
759 exit(STATE_UNKNOWN); 731 exit(STATE_UNKNOWN);
760 } 732 }
761 733
762#else 734#else
763 strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1); 735 strncpy(interface.ifr_name, network_interface_name, IFNAMSIZ - 1);
764 interface.ifr_name[IFNAMSIZ-1]='\0'; 736 interface.ifr_name[IFNAMSIZ - 1] = '\0';
765#endif 737#endif
766 738
767 /* bind the socket */ 739 /* bind the socket */
768 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){ 740 if (bind(sock, (struct sockaddr *)&myname, sizeof(myname)) < 0) {
769 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT); 741 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"), DHCP_CLIENT_PORT);
770 exit(STATE_UNKNOWN); 742 exit(STATE_UNKNOWN);
771 } 743 }
772 744
773 return sock; 745 return sock;
774} 746}
775 747
776
777/* closes DHCP socket */ 748/* closes DHCP socket */
778int close_dhcp_socket(int sock){ 749static int close_dhcp_socket(int sock) {
779 750
780 close(sock); 751 close(sock);
781 752
782 return OK; 753 return OK;
783} 754}
784 755
785
786/* adds a requested server address to list in memory */ 756/* adds a requested server address to list in memory */
787int add_requested_server(struct in_addr server_address){ 757static int add_requested_server(struct in_addr server_address) {
788 requested_server *new_server; 758 requested_server *new_server;
789 759
790 new_server=(requested_server *)malloc(sizeof(requested_server)); 760 new_server = (requested_server *)malloc(sizeof(requested_server));
791 if(new_server==NULL) 761 if (new_server == NULL)
792 return ERROR; 762 return ERROR;
793 763
794 new_server->server_address=server_address; 764 new_server->server_address = server_address;
795 new_server->answered=false; 765 new_server->answered = false;
796 766
797 new_server->next=requested_server_list; 767 new_server->next = requested_server_list;
798 requested_server_list=new_server; 768 requested_server_list = new_server;
799 769
800 requested_servers++; 770 requested_servers++;
801 771
802 if(verbose) 772 if (verbose)
803 printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address)); 773 printf(_("Requested server address: %s\n"), inet_ntoa(new_server->server_address));
804 774
805 return OK; 775 return OK;
806} 776}
807 777
808
809
810
811/* adds a DHCP OFFER to list in memory */ 778/* adds a DHCP OFFER to list in memory */
812int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){ 779static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) {
813 dhcp_offer *new_offer; 780 dhcp_offer *new_offer;
814 int x; 781 int x;
815 unsigned option_type; 782 unsigned option_type;
816 unsigned option_length; 783 unsigned option_length;
817 struct in_addr serv_ident = {0}; 784 struct in_addr serv_ident = {0};
818 785
819 if(offer_packet==NULL) 786 if (offer_packet == NULL)
820 return ERROR; 787 return ERROR;
821 788
822 /* process all DHCP options present in the packet */ 789 /* process all DHCP options present in the packet */
823 for(x=4;x<MAX_DHCP_OPTIONS_LENGTH-1;){ 790 for (x = 4; x < MAX_DHCP_OPTIONS_LENGTH - 1;) {
824 791
825 if((int)offer_packet->options[x]==-1) 792 if ((int)offer_packet->options[x] == -1)
826 break; 793 break;
827 794
828 /* get option type */ 795 /* get option type */
829 option_type=offer_packet->options[x++]; 796 option_type = offer_packet->options[x++];
830 797
831 /* get option length */ 798 /* get option length */
832 option_length=offer_packet->options[x++]; 799 option_length = offer_packet->options[x++];
833 800
834 if(verbose) 801 if (verbose)
835 printf("Option: %d (0x%02X)\n",option_type,option_length); 802 printf("Option: %d (0x%02X)\n", option_type, option_length);
836 803
837 /* get option data */ 804 /* get option data */
838 switch(option_type){ 805 switch (option_type) {
839 case DHCP_OPTION_LEASE_TIME: 806 case DHCP_OPTION_LEASE_TIME:
840 memcpy(&dhcp_lease_time, &offer_packet->options[x],sizeof(dhcp_lease_time)); 807 memcpy(&dhcp_lease_time, &offer_packet->options[x], sizeof(dhcp_lease_time));
841 dhcp_lease_time = ntohl(dhcp_lease_time); 808 dhcp_lease_time = ntohl(dhcp_lease_time);
842 break; 809 break;
843 case DHCP_OPTION_RENEWAL_TIME: 810 case DHCP_OPTION_RENEWAL_TIME:
844 memcpy(&dhcp_renewal_time, &offer_packet->options[x],sizeof(dhcp_renewal_time)); 811 memcpy(&dhcp_renewal_time, &offer_packet->options[x], sizeof(dhcp_renewal_time));
845 dhcp_renewal_time = ntohl(dhcp_renewal_time); 812 dhcp_renewal_time = ntohl(dhcp_renewal_time);
846 break; 813 break;
847 case DHCP_OPTION_REBINDING_TIME: 814 case DHCP_OPTION_REBINDING_TIME:
848 memcpy(&dhcp_rebinding_time, &offer_packet->options[x],sizeof(dhcp_rebinding_time)); 815 memcpy(&dhcp_rebinding_time, &offer_packet->options[x], sizeof(dhcp_rebinding_time));
849 dhcp_rebinding_time = ntohl(dhcp_rebinding_time); 816 dhcp_rebinding_time = ntohl(dhcp_rebinding_time);
850 break; 817 break;
851 case DHCP_OPTION_SERVER_IDENTIFIER: 818 case DHCP_OPTION_SERVER_IDENTIFIER:
852 memcpy(&serv_ident.s_addr, &offer_packet->options[x],sizeof(serv_ident.s_addr)); 819 memcpy(&serv_ident.s_addr, &offer_packet->options[x], sizeof(serv_ident.s_addr));
853 break; 820 break;
854 } 821 }
855 822
856 /* skip option data we're ignoring */ 823 /* skip option data we're ignoring */
857 if(option_type==0) /* "pad" option, see RFC 2132 (3.1) */ 824 if (option_type == 0) /* "pad" option, see RFC 2132 (3.1) */
858 x+=1; 825 x += 1;
859 else 826 else
860 x+=option_length; 827 x += option_length;
861 } 828 }
862 829
863 if(verbose){ 830 if (verbose) {
864 if(dhcp_lease_time==DHCP_INFINITE_TIME) 831 if (dhcp_lease_time == DHCP_INFINITE_TIME)
865 printf(_("Lease Time: Infinite\n")); 832 printf(_("Lease Time: Infinite\n"));
866 else 833 else
867 printf(_("Lease Time: %lu seconds\n"),(unsigned long)dhcp_lease_time); 834 printf(_("Lease Time: %lu seconds\n"), (unsigned long)dhcp_lease_time);
868 if(dhcp_renewal_time==DHCP_INFINITE_TIME) 835 if (dhcp_renewal_time == DHCP_INFINITE_TIME)
869 printf(_("Renewal Time: Infinite\n")); 836 printf(_("Renewal Time: Infinite\n"));
870 else 837 else
871 printf(_("Renewal Time: %lu seconds\n"),(unsigned long)dhcp_renewal_time); 838 printf(_("Renewal Time: %lu seconds\n"), (unsigned long)dhcp_renewal_time);
872 if(dhcp_rebinding_time==DHCP_INFINITE_TIME) 839 if (dhcp_rebinding_time == DHCP_INFINITE_TIME)
873 printf(_("Rebinding Time: Infinite\n")); 840 printf(_("Rebinding Time: Infinite\n"));
874 printf(_("Rebinding Time: %lu seconds\n"),(unsigned long)dhcp_rebinding_time); 841 printf(_("Rebinding Time: %lu seconds\n"), (unsigned long)dhcp_rebinding_time);
875 } 842 }
876 843
877 new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer)); 844 new_offer = (dhcp_offer *)malloc(sizeof(dhcp_offer));
878 845
879 if(new_offer==NULL) 846 if (new_offer == NULL)
880 return ERROR; 847 return ERROR;
881 848
882 /* 849 /*
@@ -891,298 +858,286 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
891 * DHCPOFFER from. If 'serv_ident' isn't available for some reason, we 858 * DHCPOFFER from. If 'serv_ident' isn't available for some reason, we
892 * use 'source'. 859 * use 'source'.
893 */ 860 */
894 new_offer->server_address=serv_ident.s_addr?serv_ident:source; 861 new_offer->server_address = serv_ident.s_addr ? serv_ident : source;
895 new_offer->offered_address=offer_packet->yiaddr; 862 new_offer->offered_address = offer_packet->yiaddr;
896 new_offer->lease_time=dhcp_lease_time; 863 new_offer->lease_time = dhcp_lease_time;
897 new_offer->renewal_time=dhcp_renewal_time; 864 new_offer->renewal_time = dhcp_renewal_time;
898 new_offer->rebinding_time=dhcp_rebinding_time; 865 new_offer->rebinding_time = dhcp_rebinding_time;
899 new_offer->desired=false; /* exclusive mode: we'll check that in get_results */ 866 new_offer->desired = false; /* exclusive mode: we'll check that in get_results */
900 867
901 868 if (verbose) {
902 if(verbose){ 869 printf(_("Added offer from server @ %s"), inet_ntoa(new_offer->server_address));
903 printf(_("Added offer from server @ %s"),inet_ntoa(new_offer->server_address)); 870 printf(_(" of IP address %s\n"), inet_ntoa(new_offer->offered_address));
904 printf(_(" of IP address %s\n"),inet_ntoa(new_offer->offered_address));
905 } 871 }
906 872
907 /* add new offer to head of list */ 873 /* add new offer to head of list */
908 new_offer->next=dhcp_offer_list; 874 new_offer->next = dhcp_offer_list;
909 dhcp_offer_list=new_offer; 875 dhcp_offer_list = new_offer;
910 876
911 return OK; 877 return OK;
912} 878}
913 879
914
915/* frees memory allocated to DHCP OFFER list */ 880/* frees memory allocated to DHCP OFFER list */
916int free_dhcp_offer_list(void){ 881static int free_dhcp_offer_list(void) {
917 dhcp_offer *this_offer; 882 dhcp_offer *this_offer;
918 dhcp_offer *next_offer; 883 dhcp_offer *next_offer;
919 884
920 for(this_offer=dhcp_offer_list;this_offer!=NULL;this_offer=next_offer){ 885 for (this_offer = dhcp_offer_list; this_offer != NULL; this_offer = next_offer) {
921 next_offer=this_offer->next; 886 next_offer = this_offer->next;
922 free(this_offer); 887 free(this_offer);
923 } 888 }
924 889
925 return OK; 890 return OK;
926} 891}
927 892
928
929/* frees memory allocated to requested server list */ 893/* frees memory allocated to requested server list */
930int free_requested_server_list(void){ 894static int free_requested_server_list(void) {
931 requested_server *this_server; 895 requested_server *this_server;
932 requested_server *next_server; 896 requested_server *next_server;
933 897
934 for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){ 898 for (this_server = requested_server_list; this_server != NULL; this_server = next_server) {
935 next_server=this_server->next; 899 next_server = this_server->next;
936 free(this_server); 900 free(this_server);
937 } 901 }
938 902
939 return OK; 903 return OK;
940} 904}
941 905
942
943/* gets state and plugin output to return */ 906/* gets state and plugin output to return */
944int get_results(void){ 907static int get_results(void) {
945 dhcp_offer *temp_offer, *undesired_offer=NULL; 908 dhcp_offer *temp_offer, *undesired_offer = NULL;
946 requested_server *temp_server; 909 requested_server *temp_server;
947 int result; 910 int result;
948 uint32_t max_lease_time=0; 911 uint32_t max_lease_time = 0;
949 912
950 received_requested_address=false; 913 received_requested_address = false;
951 914
952 /* checks responses from requested servers */ 915 /* checks responses from requested servers */
953 requested_responses=0; 916 requested_responses = 0;
954 if(requested_servers>0){ 917 if (requested_servers > 0) {
955 918
956 for(temp_server=requested_server_list;temp_server!=NULL;temp_server=temp_server->next){ 919 for (temp_server = requested_server_list; temp_server != NULL; temp_server = temp_server->next) {
957 920
958 for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next){ 921 for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
959 922
960 /* get max lease time we were offered */ 923 /* get max lease time we were offered */
961 if(temp_offer->lease_time>max_lease_time || temp_offer->lease_time==DHCP_INFINITE_TIME) 924 if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME)
962 max_lease_time=temp_offer->lease_time; 925 max_lease_time = temp_offer->lease_time;
963 926
964 /* see if we got the address we requested */ 927 /* see if we got the address we requested */
965 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 928 if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address)))
966 received_requested_address=true; 929 received_requested_address = true;
967 930
968 /* see if the servers we wanted a response from talked to us or not */ 931 /* see if the servers we wanted a response from talked to us or not */
969 if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){ 932 if (!memcmp(&temp_offer->server_address, &temp_server->server_address, sizeof(temp_server->server_address))) {
970 if(verbose){ 933 if (verbose) {
971 printf(_("DHCP Server Match: Offerer=%s"),inet_ntoa(temp_offer->server_address)); 934 printf(_("DHCP Server Match: Offerer=%s"), inet_ntoa(temp_offer->server_address));
972 printf(_(" Requested=%s"),inet_ntoa(temp_server->server_address)); 935 printf(_(" Requested=%s"), inet_ntoa(temp_server->server_address));
973 if(temp_server->answered) 936 if (temp_server->answered)
974 printf(_(" (duplicate)")); 937 printf(_(" (duplicate)"));
975 printf(_("\n")); 938 printf(_("\n"));
976 } 939 }
977 if(!temp_server->answered){ 940 if (!temp_server->answered) {
978 requested_responses++; 941 requested_responses++;
979 temp_server->answered=true; 942 temp_server->answered = true;
980 temp_offer->desired=true; 943 temp_offer->desired = true;
981 } 944 }
982 } 945 }
983 } 946 }
984 } 947 }
985 948
986 /* exclusive mode: check for undesired offers */ 949 /* exclusive mode: check for undesired offers */
987 for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next) { 950 for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
988 if (!temp_offer->desired) { 951 if (!temp_offer->desired) {
989 undesired_offer=temp_offer; /* Checks only for the first undesired offer */ 952 undesired_offer = temp_offer; /* Checks only for the first undesired offer */
990 break; /* no further checks needed */ 953 break; /* no further checks needed */
991 } 954 }
992 } 955 }
993 } 956 }
994 957
995 /* else check and see if we got our requested address from any server */ 958 /* else check and see if we got our requested address from any server */
996 else{ 959 else {
997 960
998 for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next){ 961 for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
999 962
1000 /* get max lease time we were offered */ 963 /* get max lease time we were offered */
1001 if(temp_offer->lease_time>max_lease_time || temp_offer->lease_time==DHCP_INFINITE_TIME) 964 if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME)
1002 max_lease_time=temp_offer->lease_time; 965 max_lease_time = temp_offer->lease_time;
1003 966
1004 /* see if we got the address we requested */ 967 /* see if we got the address we requested */
1005 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 968 if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address)))
1006 received_requested_address=true; 969 received_requested_address = true;
1007 } 970 }
1008 } 971 }
1009 972
1010 result=STATE_OK; 973 result = STATE_OK;
1011 if(valid_responses==0) 974 if (valid_responses == 0)
1012 result=STATE_CRITICAL; 975 result = STATE_CRITICAL;
1013 else if(requested_servers>0 && requested_responses==0) 976 else if (requested_servers > 0 && requested_responses == 0)
1014 result=STATE_CRITICAL; 977 result = STATE_CRITICAL;
1015 else if(requested_responses<requested_servers) 978 else if (requested_responses < requested_servers)
1016 result=STATE_WARNING; 979 result = STATE_WARNING;
1017 else if(request_specific_address && !received_requested_address) 980 else if (request_specific_address && !received_requested_address)
1018 result=STATE_WARNING; 981 result = STATE_WARNING;
1019 982
1020 if(exclusive && undesired_offer) 983 if (exclusive && undesired_offer)
1021 result=STATE_CRITICAL; 984 result = STATE_CRITICAL;
1022 985
1023 if(result==0) /* garrett honeycutt 2005 */ 986 if (result == 0) /* garrett honeycutt 2005 */
1024 printf("OK: "); 987 printf("OK: ");
1025 else if(result==1) 988 else if (result == 1)
1026 printf("WARNING: "); 989 printf("WARNING: ");
1027 else if(result==2) 990 else if (result == 2)
1028 printf("CRITICAL: "); 991 printf("CRITICAL: ");
1029 else if(result==3) 992 else if (result == 3)
1030 printf("UNKNOWN: "); 993 printf("UNKNOWN: ");
1031 994
1032 /* we didn't receive any DHCPOFFERs */ 995 /* we didn't receive any DHCPOFFERs */
1033 if(dhcp_offer_list==NULL){ 996 if (dhcp_offer_list == NULL) {
1034 printf(_("No DHCPOFFERs were received.\n")); 997 printf(_("No DHCPOFFERs were received.\n"));
1035 return result; 998 return result;
1036 } 999 }
1037 1000
1038 printf(_("Received %d DHCPOFFER(s)"),valid_responses); 1001 printf(_("Received %d DHCPOFFER(s)"), valid_responses);
1039
1040 1002
1041 if(exclusive && undesired_offer){ 1003 if (exclusive && undesired_offer) {
1042 printf(_(", Rogue DHCP Server detected! Server %s"),inet_ntoa(undesired_offer->server_address)); 1004 printf(_(", Rogue DHCP Server detected! Server %s"), inet_ntoa(undesired_offer->server_address));
1043 printf(_(" offered %s \n"),inet_ntoa(undesired_offer->offered_address)); 1005 printf(_(" offered %s \n"), inet_ntoa(undesired_offer->offered_address));
1044 return result; 1006 return result;
1045 } 1007 }
1046 1008
1047 if(requested_servers>0) 1009 if (requested_servers > 0)
1048 printf(_(", %s%d of %d requested servers responded"),((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers); 1010 printf(_(", %s%d of %d requested servers responded"), ((requested_responses < requested_servers) && requested_responses > 0) ? "only " : "", requested_responses,
1011 requested_servers);
1049 1012
1050 if(request_specific_address) 1013 if (request_specific_address)
1051 printf(_(", requested address (%s) was %soffered"),inet_ntoa(requested_address),(received_requested_address)?"":_("not ")); 1014 printf(_(", requested address (%s) was %soffered"), inet_ntoa(requested_address), (received_requested_address) ? "" : _("not "));
1052 1015
1053 printf(_(", max lease time = ")); 1016 printf(_(", max lease time = "));
1054 if(max_lease_time==DHCP_INFINITE_TIME) 1017 if (max_lease_time == DHCP_INFINITE_TIME)
1055 printf(_("Infinity")); 1018 printf(_("Infinity"));
1056 else 1019 else
1057 printf("%lu sec",(unsigned long)max_lease_time); 1020 printf("%lu sec", (unsigned long)max_lease_time);
1058 1021
1059 printf(".\n"); 1022 printf(".\n");
1060 1023
1061 return result; 1024 return result;
1062} 1025}
1063 1026
1064
1065/* process command-line arguments */ 1027/* process command-line arguments */
1066int process_arguments(int argc, char **argv){ 1028static int process_arguments(int argc, char **argv) {
1067 if(argc<1) 1029 if (argc < 1)
1068 return ERROR; 1030 return ERROR;
1069 1031
1070 call_getopt(argc,argv); 1032 call_getopt(argc, argv);
1071 return validate_arguments(argc); 1033 return validate_arguments(argc);
1072} 1034}
1073 1035
1074 1036static int call_getopt(int argc, char **argv) {
1075
1076int call_getopt(int argc, char **argv){
1077 extern int optind; 1037 extern int optind;
1078 int option_index = 0; 1038 int option_index = 0;
1079 static struct option long_options[] = 1039 static struct option long_options[] = {{"serverip", required_argument, 0, 's'},
1080 { 1040 {"requestedip", required_argument, 0, 'r'},
1081 {"serverip", required_argument,0,'s'}, 1041 {"timeout", required_argument, 0, 't'},
1082 {"requestedip", required_argument,0,'r'}, 1042 {"interface", required_argument, 0, 'i'},
1083 {"timeout", required_argument,0,'t'}, 1043 {"mac", required_argument, 0, 'm'},
1084 {"interface", required_argument,0,'i'}, 1044 {"unicast", no_argument, 0, 'u'},
1085 {"mac", required_argument,0,'m'}, 1045 {"exclusive", no_argument, 0, 'x'},
1086 {"unicast", no_argument, 0,'u'}, 1046 {"verbose", no_argument, 0, 'v'},
1087 {"exclusive", no_argument, 0,'x'}, 1047 {"version", no_argument, 0, 'V'},
1088 {"verbose", no_argument, 0,'v'}, 1048 {"help", no_argument, 0, 'h'},
1089 {"version", no_argument, 0,'V'}, 1049 {0, 0, 0, 0}};
1090 {"help", no_argument, 0,'h'}, 1050
1091 {0,0,0,0} 1051 int c = 0;
1092 }; 1052 while (true) {
1093 1053 c = getopt_long(argc, argv, "+hVvxt:s:r:t:i:m:u", long_options, &option_index);
1094 int c=0; 1054
1095 while(true){ 1055 if (c == -1 || c == EOF || c == 1)
1096 c=getopt_long(argc,argv,"+hVvxt:s:r:t:i:m:u",long_options,&option_index);
1097
1098 if(c==-1||c==EOF||c==1)
1099 break; 1056 break;
1100 1057
1101 switch(c){ 1058 switch (c) {
1102
1103 case 's': /* DHCP server address */
1104 resolve_host(optarg,&dhcp_ip);
1105 add_requested_server(dhcp_ip);
1106 break;
1107 1059
1108 case 'r': /* address we are requested from DHCP servers */ 1060 case 's': /* DHCP server address */
1109 resolve_host(optarg,&requested_address); 1061 resolve_host(optarg, &dhcp_ip);
1110 request_specific_address=true; 1062 add_requested_server(dhcp_ip);
1111 break; 1063 break;
1112 1064
1113 case 't': /* timeout */ 1065 case 'r': /* address we are requested from DHCP servers */
1066 resolve_host(optarg, &requested_address);
1067 request_specific_address = true;
1068 break;
1114 1069
1115 /* 1070 case 't': /* timeout */
1116 if(is_intnonneg(optarg)) 1071
1117 */ 1072 /*
1118 if(atoi(optarg)>0) 1073 if(is_intnonneg(optarg))
1119 dhcpoffer_timeout=atoi(optarg); 1074 */
1120 /* 1075 if (atoi(optarg) > 0)
1121 else 1076 dhcpoffer_timeout = atoi(optarg);
1122 usage("Time interval must be a nonnegative integer\n"); 1077 /*
1123 */ 1078 else
1124 break; 1079 usage("Time interval must be a nonnegative integer\n");
1080 */
1081 break;
1125 1082
1126 case 'm': /* MAC address */ 1083 case 'm': /* MAC address */
1127 1084
1128 if((user_specified_mac=mac_aton(optarg)) == NULL) 1085 if ((user_specified_mac = mac_aton(optarg)) == NULL)
1129 usage("Cannot parse MAC address.\n"); 1086 usage("Cannot parse MAC address.\n");
1130 if(verbose) 1087 if (verbose)
1131 print_hardware_address(user_specified_mac); 1088 print_hardware_address(user_specified_mac);
1132 1089
1133 break; 1090 break;
1134 1091
1135 case 'i': /* interface name */ 1092 case 'i': /* interface name */
1136 1093
1137 strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1); 1094 strncpy(network_interface_name, optarg, sizeof(network_interface_name) - 1);
1138 network_interface_name[sizeof(network_interface_name)-1]='\x0'; 1095 network_interface_name[sizeof(network_interface_name) - 1] = '\x0';
1139 1096
1140 break; 1097 break;
1141 1098
1142 case 'u': /* unicast testing */ 1099 case 'u': /* unicast testing */
1143 unicast=true; 1100 unicast = true;
1144 break; 1101 break;
1145 case 'x': /* exclusive testing aka "rogue DHCP server detection" */ 1102 case 'x': /* exclusive testing aka "rogue DHCP server detection" */
1146 exclusive=true; 1103 exclusive = true;
1147 break; 1104 break;
1148 1105
1149 case 'V': /* version */ 1106 case 'V': /* version */
1150 print_revision(progname, NP_VERSION); 1107 print_revision(progname, NP_VERSION);
1151 exit(STATE_UNKNOWN); 1108 exit(STATE_UNKNOWN);
1152 1109
1153 case 'h': /* help */ 1110 case 'h': /* help */
1154 print_help(); 1111 print_help();
1155 exit(STATE_UNKNOWN); 1112 exit(STATE_UNKNOWN);
1156 1113
1157 case 'v': /* verbose */ 1114 case 'v': /* verbose */
1158 verbose=1; 1115 verbose = 1;
1159 break; 1116 break;
1160 case '?': /* help */ 1117 case '?': /* help */
1161 usage5 (); 1118 usage5();
1162 break; 1119 break;
1163 1120
1164 default: 1121 default:
1165 break; 1122 break;
1166 } 1123 }
1167 } 1124 }
1168 return optind; 1125 return optind;
1169} 1126}
1170 1127
1128static int validate_arguments(int argc) {
1171 1129
1172int validate_arguments(int argc){ 1130 if (argc - optind > 0)
1173
1174 if(argc - optind > 0)
1175 usage(_("Got unexpected non-option argument")); 1131 usage(_("Got unexpected non-option argument"));
1176 1132
1177 return OK; 1133 return OK;
1178} 1134}
1179 1135
1180
1181#if defined(__sun__) || defined(__solaris__) || defined(__hpux__) 1136#if defined(__sun__) || defined(__solaris__) || defined(__hpux__)
1182/* Kompf 2000-2003 see ACKNOWLEDGEMENTS */ 1137/* Kompf 2000-2003 see ACKNOWLEDGEMENTS */
1183 1138
1184/* get a message from a stream; return type of message */ 1139/* get a message from a stream; return type of message */
1185static int get_msg(int fd){ 1140static int get_msg(int fd) {
1186 int flags = 0; 1141 int flags = 0;
1187 int res, ret; 1142 int res, ret;
1188 ctl_area[0] = 0; 1143 ctl_area[0] = 0;
@@ -1190,30 +1145,29 @@ static int get_msg(int fd){
1190 ret = 0; 1145 ret = 0;
1191 res = getmsg(fd, &ctl, &dat, &flags); 1146 res = getmsg(fd, &ctl, &dat, &flags);
1192 1147
1193 if(res < 0){ 1148 if (res < 0) {
1194 if(errno == EINTR){ 1149 if (errno == EINTR) {
1195 return(GOT_INTR); 1150 return (GOT_INTR);
1196 } 1151 } else {
1197 else{
1198 printf("%s\n", "get_msg FAILED."); 1152 printf("%s\n", "get_msg FAILED.");
1199 return(GOT_ERR); 1153 return (GOT_ERR);
1200 } 1154 }
1201 } 1155 }
1202 if(ctl.len > 0){ 1156 if (ctl.len > 0) {
1203 ret |= GOT_CTRL; 1157 ret |= GOT_CTRL;
1204 } 1158 }
1205 if(dat.len > 0){ 1159 if (dat.len > 0) {
1206 ret |= GOT_DATA; 1160 ret |= GOT_DATA;
1207 } 1161 }
1208 1162
1209 return(ret); 1163 return (ret);
1210} 1164}
1211 1165
1212/* verify that dl_primitive in ctl_area = prim */ 1166/* verify that dl_primitive in ctl_area = prim */
1213static int check_ctrl(int prim){ 1167static int check_ctrl(int prim) {
1214 dl_error_ack_t *err_ack = (dl_error_ack_t *)ctl_area; 1168 dl_error_ack_t *err_ack = (dl_error_ack_t *)ctl_area;
1215 1169
1216 if(err_ack->dl_primitive != prim){ 1170 if (err_ack->dl_primitive != prim) {
1217 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno)); 1171 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno));
1218 exit(STATE_UNKNOWN); 1172 exit(STATE_UNKNOWN);
1219 } 1173 }
@@ -1222,35 +1176,35 @@ static int check_ctrl(int prim){
1222} 1176}
1223 1177
1224/* put a control message on a stream */ 1178/* put a control message on a stream */
1225static int put_ctrl(int fd, int len, int pri){ 1179static int put_ctrl(int fd, int len, int pri) {
1226 1180
1227 ctl.len = len; 1181 ctl.len = len;
1228 if(putmsg(fd, &ctl, 0, pri) < 0){ 1182 if (putmsg(fd, &ctl, 0, pri) < 0) {
1229 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno)); 1183 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno));
1230 exit(STATE_UNKNOWN); 1184 exit(STATE_UNKNOWN);
1231 } 1185 }
1232 1186
1233 return 0; 1187 return 0;
1234} 1188}
1235 1189
1236/* put a control + data message on a stream */ 1190/* put a control + data message on a stream */
1237static int put_both(int fd, int clen, int dlen, int pri){ 1191static int put_both(int fd, int clen, int dlen, int pri) {
1238 1192
1239 ctl.len = clen; 1193 ctl.len = clen;
1240 dat.len = dlen; 1194 dat.len = dlen;
1241 if(putmsg(fd, &ctl, &dat, pri) < 0){ 1195 if (putmsg(fd, &ctl, &dat, pri) < 0) {
1242 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno)); 1196 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno));
1243 exit(STATE_UNKNOWN); 1197 exit(STATE_UNKNOWN);
1244 } 1198 }
1245 1199
1246 return 0; 1200 return 0;
1247} 1201}
1248 1202
1249/* open file descriptor and attach */ 1203/* open file descriptor and attach */
1250static int dl_open(const char *dev, int unit, int *fd){ 1204static int dl_open(const char *dev, int unit, int *fd) {
1251 dl_attach_req_t *attach_req = (dl_attach_req_t *)ctl_area; 1205 dl_attach_req_t *attach_req = (dl_attach_req_t *)ctl_area;
1252 1206
1253 if((*fd = open(dev, O_RDWR)) == -1){ 1207 if ((*fd = open(dev, O_RDWR)) == -1) {
1254 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno)); 1208 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno));
1255 exit(STATE_UNKNOWN); 1209 exit(STATE_UNKNOWN);
1256 } 1210 }
@@ -1262,7 +1216,7 @@ static int dl_open(const char *dev, int unit, int *fd){
1262} 1216}
1263 1217
1264/* send DL_BIND_REQ */ 1218/* send DL_BIND_REQ */
1265static int dl_bind(int fd, int sap, u_char *addr){ 1219static int dl_bind(int fd, int sap, u_char *addr) {
1266 dl_bind_req_t *bind_req = (dl_bind_req_t *)ctl_area; 1220 dl_bind_req_t *bind_req = (dl_bind_req_t *)ctl_area;
1267 dl_bind_ack_t *bind_ack = (dl_bind_ack_t *)ctl_area; 1221 dl_bind_ack_t *bind_ack = (dl_bind_ack_t *)ctl_area;
1268 1222
@@ -1274,12 +1228,11 @@ static int dl_bind(int fd, int sap, u_char *addr){
1274 bind_req->dl_xidtest_flg = 0; 1228 bind_req->dl_xidtest_flg = 0;
1275 put_ctrl(fd, sizeof(dl_bind_req_t), 0); 1229 put_ctrl(fd, sizeof(dl_bind_req_t), 0);
1276 get_msg(fd); 1230 get_msg(fd);
1277 if (GOT_ERR == check_ctrl(DL_BIND_ACK)){ 1231 if (GOT_ERR == check_ctrl(DL_BIND_ACK)) {
1278 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno)); 1232 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno));
1279 exit(STATE_UNKNOWN); 1233 exit(STATE_UNKNOWN);
1280 } 1234 }
1281 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr, 1235 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr, bind_ack->dl_addr_length);
1282 bind_ack->dl_addr_length);
1283 1236
1284 return 0; 1237 return 0;
1285} 1238}
@@ -1296,13 +1249,13 @@ static int dl_bind(int fd, int sap, u_char *addr){
1296 * 1249 *
1297 ***********************************************************************/ 1250 ***********************************************************************/
1298 1251
1299long mac_addr_dlpi( const char *dev, int unit, u_char *addr){ 1252static long mac_addr_dlpi(const char *dev, int unit, u_char *addr) {
1300 int fd; 1253 int fd;
1301 u_char mac_addr[25]; 1254 u_char mac_addr[25];
1302 1255
1303 if(GOT_ERR != dl_open(dev, unit, &fd)){ 1256 if (GOT_ERR != dl_open(dev, unit, &fd)) {
1304 if(GOT_ERR != dl_bind(fd, INSAP, mac_addr)){ 1257 if (GOT_ERR != dl_bind(fd, INSAP, mac_addr)) {
1305 bcopy( mac_addr, addr, 6); 1258 bcopy(mac_addr, addr, 6);
1306 return 0; 1259 return 0;
1307 } 1260 }
1308 } 1261 }
@@ -1314,99 +1267,93 @@ long mac_addr_dlpi( const char *dev, int unit, u_char *addr){
1314/* Kompf 2000-2003 */ 1267/* Kompf 2000-2003 */
1315#endif 1268#endif
1316 1269
1317
1318/* resolve host name or die (TODO: move this to netutils.c!) */ 1270/* resolve host name or die (TODO: move this to netutils.c!) */
1319void resolve_host(const char *in,struct in_addr *out){ 1271static void resolve_host(const char *in, struct in_addr *out) {
1320 struct addrinfo hints, *ai; 1272 struct addrinfo hints, *ai;
1321 1273
1322 memset(&hints,0,sizeof(hints)); 1274 memset(&hints, 0, sizeof(hints));
1323 hints.ai_family=PF_INET; 1275 hints.ai_family = PF_INET;
1324 if (getaddrinfo(in,NULL,&hints,&ai) != 0) 1276 if (getaddrinfo(in, NULL, &hints, &ai) != 0)
1325 usage_va(_("Invalid hostname/address - %s"),optarg); 1277 usage_va(_("Invalid hostname/address - %s"), optarg);
1326 1278
1327 memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out)); 1279 memcpy(out, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(*out));
1328 freeaddrinfo(ai); 1280 freeaddrinfo(ai);
1329} 1281}
1330 1282
1331
1332/* parse MAC address string, return 6 bytes (unterminated) or NULL */ 1283/* parse MAC address string, return 6 bytes (unterminated) or NULL */
1333unsigned char *mac_aton(const char *string){ 1284static unsigned char *mac_aton(const char *string) {
1334 static unsigned char result[6]; 1285 static unsigned char result[6];
1335 char tmp[3]; 1286 char tmp[3];
1336 unsigned i, j; 1287 unsigned i, j;
1337 1288
1338 for(i=0, j=0; string[i] != '\0' && j < sizeof(result); i++){ 1289 for (i = 0, j = 0; string[i] != '\0' && j < sizeof(result); i++) {
1339 /* ignore ':' and any other non-hex character */ 1290 /* ignore ':' and any other non-hex character */
1340 if(!isxdigit(string[i]) || !isxdigit(string[i+1])) 1291 if (!isxdigit(string[i]) || !isxdigit(string[i + 1]))
1341 continue; 1292 continue;
1342 tmp[0]=string[i]; 1293 tmp[0] = string[i];
1343 tmp[1]=string[i+1]; 1294 tmp[1] = string[i + 1];
1344 tmp[2]='\0'; 1295 tmp[2] = '\0';
1345 result[j]=strtol(tmp,(char **)NULL,16); 1296 result[j] = strtol(tmp, (char **)NULL, 16);
1346 i++; 1297 i++;
1347 j++; 1298 j++;
1348 } 1299 }
1349 1300
1350 return (j==6) ? result : NULL; 1301 return (j == 6) ? result : NULL;
1351} 1302}
1352 1303
1353 1304static void print_hardware_address(const unsigned char *address) {
1354void print_hardware_address(const unsigned char *address){
1355 int i; 1305 int i;
1356 1306
1357 printf(_("Hardware address: ")); 1307 printf(_("Hardware address: "));
1358 for (i=0; i<5; i++) 1308 for (i = 0; i < 5; i++)
1359 printf("%2.2x:", address[i]); 1309 printf("%2.2x:", address[i]);
1360 printf("%2.2x", address[i]); 1310 printf("%2.2x", address[i]);
1361 putchar('\n'); 1311 putchar('\n');
1362} 1312}
1363 1313
1364
1365/* print usage help */ 1314/* print usage help */
1366void print_help(void){ 1315static void print_help(void) {
1367 1316
1368 print_revision(progname, NP_VERSION); 1317 print_revision(progname, NP_VERSION);
1369 1318
1370 printf("Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)\n"); 1319 printf("Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)\n");
1371 printf (COPYRIGHT, copyright, email); 1320 printf(COPYRIGHT, copyright, email);
1372 1321
1373 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network.")); 1322 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network."));
1374 1323
1375 printf ("\n\n"); 1324 printf("\n\n");
1376 1325
1377 print_usage(); 1326 print_usage();
1378 1327
1379 printf (UT_HELP_VRSN); 1328 printf(UT_HELP_VRSN);
1380 printf (UT_EXTRA_OPTS); 1329 printf(UT_EXTRA_OPTS);
1381 1330
1382 printf (UT_VERBOSE); 1331 printf(UT_VERBOSE);
1383 1332
1384 printf (" %s\n", "-s, --serverip=IPADDRESS"); 1333 printf(" %s\n", "-s, --serverip=IPADDRESS");
1385 printf (" %s\n", _("IP address of DHCP server that we must hear from")); 1334 printf(" %s\n", _("IP address of DHCP server that we must hear from"));
1386 printf (" %s\n", "-r, --requestedip=IPADDRESS"); 1335 printf(" %s\n", "-r, --requestedip=IPADDRESS");
1387 printf (" %s\n", _("IP address that should be offered by at least one DHCP server")); 1336 printf(" %s\n", _("IP address that should be offered by at least one DHCP server"));
1388 printf (" %s\n", "-t, --timeout=INTEGER"); 1337 printf(" %s\n", "-t, --timeout=INTEGER");
1389 printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs")); 1338 printf(" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs"));
1390 printf (" %s\n", "-i, --interface=STRING"); 1339 printf(" %s\n", "-i, --interface=STRING");
1391 printf (" %s\n", _("Interface to to use for listening (i.e. eth0)")); 1340 printf(" %s\n", _("Interface to to use for listening (i.e. eth0)"));
1392 printf (" %s\n", "-m, --mac=STRING"); 1341 printf(" %s\n", "-m, --mac=STRING");
1393 printf (" %s\n", _("MAC address to use in the DHCP request")); 1342 printf(" %s\n", _("MAC address to use in the DHCP request"));
1394 printf (" %s\n", "-u, --unicast"); 1343 printf(" %s\n", "-u, --unicast");
1395 printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s")); 1344 printf(" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s"));
1396 printf (" %s\n", "-x, --exclusive"); 1345 printf(" %s\n", "-x, --exclusive");
1397 printf (" %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s")); 1346 printf(" %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s"));
1398 1347
1399 printf (UT_SUPPORT); 1348 printf(UT_SUPPORT);
1400 return; 1349 return;
1401} 1350}
1402 1351
1352void print_usage(void) {
1403 1353
1404void 1354 printf("%s\n", _("Usage:"));
1405print_usage(void){ 1355 printf(" %s [-v] [-u] [-x] [-s serverip] [-r requestedip] [-t timeout]\n", progname);
1406 1356 printf(" [-i interface] [-m mac]\n");
1407 printf ("%s\n", _("Usage:"));
1408 printf (" %s [-v] [-u] [-x] [-s serverip] [-r requestedip] [-t timeout]\n",progname);
1409 printf (" [-i interface] [-m mac]\n");
1410 1357
1411 return; 1358 return;
1412} 1359}
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index f788d428..960ab8f1 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -1,45 +1,45 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_icmp plugin 3 * Monitoring check_icmp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* Original Author : Andreas Ericsson <ae@op5.se> 7 * Original Author : Andreas Ericsson <ae@op5.se>
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_icmp plugin 11 * This file contains the check_icmp plugin
12* 12 *
13* Relevant RFC's: 792 (ICMP), 791 (IP) 13 * Relevant RFC's: 792 (ICMP), 791 (IP)
14* 14 *
15* This program was modeled somewhat after the check_icmp program, 15 * This program was modeled somewhat after the check_icmp program,
16* which was in turn a hack of fping (www.fping.org) but has been 16 * which was in turn a hack of fping (www.fping.org) but has been
17* completely rewritten since to generate higher precision rta values, 17 * completely rewritten since to generate higher precision rta values,
18* and support several different modes as well as setting ttl to control. 18 * and support several different modes as well as setting ttl to control.
19* redundant routes. The only remainders of fping is currently a few 19 * redundant routes. The only remainders of fping is currently a few
20* function names. 20 * function names.
21* 21 *
22* 22 *
23* This program is free software: you can redistribute it and/or modify 23 * This program is free software: you can redistribute it and/or modify
24* it under the terms of the GNU General Public License as published by 24 * it under the terms of the GNU General Public License as published by
25* the Free Software Foundation, either version 3 of the License, or 25 * the Free Software Foundation, either version 3 of the License, or
26* (at your option) any later version. 26 * (at your option) any later version.
27* 27 *
28* This program is distributed in the hope that it will be useful, 28 * This program is distributed in the hope that it will be useful,
29* but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31* GNU General Public License for more details. 31 * GNU General Public License for more details.
32* 32 *
33* You should have received a copy of the GNU General Public License 33 * You should have received a copy of the GNU General Public License
34* along with this program. If not, see <http://www.gnu.org/licenses/>. 34 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35* 35 *
36* 36 *
37*****************************************************************************/ 37 *****************************************************************************/
38 38
39/* progname may change */ 39/* progname may change */
40/* char *progname = "check_icmp"; */ 40/* char *progname = "check_icmp"; */
41char *progname; 41char *progname;
42const char *copyright = "2005-2008"; 42const char *copyright = "2005-2024";
43const char *email = "devel@monitoring-plugins.org"; 43const char *email = "devel@monitoring-plugins.org";
44 44
45/** Monitoring Plugins basic includes */ 45/** Monitoring Plugins basic includes */
@@ -48,7 +48,7 @@ const char *email = "devel@monitoring-plugins.org";
48#include "utils.h" 48#include "utils.h"
49 49
50#if HAVE_SYS_SOCKIO_H 50#if HAVE_SYS_SOCKIO_H
51#include <sys/sockio.h> 51# include <sys/sockio.h>
52#endif 52#endif
53 53
54#include <sys/time.h> 54#include <sys/time.h>
@@ -65,84 +65,83 @@ const char *email = "devel@monitoring-plugins.org";
65#include <netinet/icmp6.h> 65#include <netinet/icmp6.h>
66#include <arpa/inet.h> 66#include <arpa/inet.h>
67 67
68
69/** sometimes undefined system macros (quite a few, actually) **/ 68/** sometimes undefined system macros (quite a few, actually) **/
70#ifndef MAXTTL 69#ifndef MAXTTL
71# define MAXTTL 255 70# define MAXTTL 255
72#endif 71#endif
73#ifndef INADDR_NONE 72#ifndef INADDR_NONE
74# define INADDR_NONE (in_addr_t)(-1) 73# define INADDR_NONE (in_addr_t)(-1)
75#endif 74#endif
76 75
77#ifndef SOL_IP 76#ifndef SOL_IP
78#define SOL_IP 0 77# define SOL_IP 0
79#endif 78#endif
80 79
81/* we bundle these in one #ifndef, since they're all from BSD 80/* we bundle these in one #ifndef, since they're all from BSD
82 * Put individual #ifndef's around those that bother you */ 81 * Put individual #ifndef's around those that bother you */
83#ifndef ICMP_UNREACH_NET_UNKNOWN 82#ifndef ICMP_UNREACH_NET_UNKNOWN
84# define ICMP_UNREACH_NET_UNKNOWN 6 83# define ICMP_UNREACH_NET_UNKNOWN 6
85# define ICMP_UNREACH_HOST_UNKNOWN 7 84# define ICMP_UNREACH_HOST_UNKNOWN 7
86# define ICMP_UNREACH_ISOLATED 8 85# define ICMP_UNREACH_ISOLATED 8
87# define ICMP_UNREACH_NET_PROHIB 9 86# define ICMP_UNREACH_NET_PROHIB 9
88# define ICMP_UNREACH_HOST_PROHIB 10 87# define ICMP_UNREACH_HOST_PROHIB 10
89# define ICMP_UNREACH_TOSNET 11 88# define ICMP_UNREACH_TOSNET 11
90# define ICMP_UNREACH_TOSHOST 12 89# define ICMP_UNREACH_TOSHOST 12
91#endif 90#endif
92/* tru64 has the ones above, but not these */ 91/* tru64 has the ones above, but not these */
93#ifndef ICMP_UNREACH_FILTER_PROHIB 92#ifndef ICMP_UNREACH_FILTER_PROHIB
94# define ICMP_UNREACH_FILTER_PROHIB 13 93# define ICMP_UNREACH_FILTER_PROHIB 13
95# define ICMP_UNREACH_HOST_PRECEDENCE 14 94# define ICMP_UNREACH_HOST_PRECEDENCE 14
96# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 95# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
97#endif 96#endif
98 97
99typedef unsigned short range_t; /* type for get_range() -- unimplemented */ 98typedef unsigned short range_t; /* type for get_range() -- unimplemented */
100 99
101typedef struct rta_host { 100typedef struct rta_host {
102 unsigned short id; /* id in **table, and icmp pkts */ 101 unsigned short id; /* id in **table, and icmp pkts */
103 char *name; /* arg used for adding this host */ 102 char *name; /* arg used for adding this host */
104 char *msg; /* icmp error message, if any */ 103 char *msg; /* icmp error message, if any */
105 struct sockaddr_storage saddr_in; /* the address of this host */ 104 struct sockaddr_storage saddr_in; /* the address of this host */
106 struct sockaddr_storage error_addr; /* stores address of error replies */ 105 struct sockaddr_storage error_addr; /* stores address of error replies */
107 unsigned long long time_waited; /* total time waited, in usecs */ 106 unsigned long long time_waited; /* total time waited, in usecs */
108 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ 107 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */
109 unsigned char icmp_type, icmp_code; /* type and code from errors */ 108 unsigned char icmp_type, icmp_code; /* type and code from errors */
110 unsigned short flags; /* control/status flags */ 109 unsigned short flags; /* control/status flags */
111 double rta; /* measured RTA */ 110 double rta; /* measured RTA */
112 int rta_status; // check result for RTA checks 111 int rta_status; // check result for RTA checks
113 double rtmax; /* max rtt */ 112 double rtmax; /* max rtt */
114 double rtmin; /* min rtt */ 113 double rtmin; /* min rtt */
115 double jitter; /* measured jitter */ 114 double jitter; /* measured jitter */
116 int jitter_status; // check result for Jitter checks 115 int jitter_status; // check result for Jitter checks
117 double jitter_max; /* jitter rtt maximum */ 116 double jitter_max; /* jitter rtt maximum */
118 double jitter_min; /* jitter rtt minimum */ 117 double jitter_min; /* jitter rtt minimum */
119 double EffectiveLatency; 118 double EffectiveLatency;
120 double mos; /* Mean opnion score */ 119 double mos; /* Mean opnion score */
121 int mos_status; // check result for MOS checks 120 int mos_status; // check result for MOS checks
122 double score; /* score */ 121 double score; /* score */
123 int score_status; // check result for score checks 122 int score_status; // check result for score checks
124 u_int last_tdiff; 123 u_int last_tdiff;
125 u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */ 124 u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */
126 unsigned char pl; /* measured packet loss */ 125 unsigned char pl; /* measured packet loss */
127 int pl_status; // check result for packet loss checks 126 int pl_status; // check result for packet loss checks
128 struct rta_host *next; /* linked list */ 127 struct rta_host *next; /* linked list */
129 int order_status; // check result for packet order checks 128 int order_status; // check result for packet order checks
130} rta_host; 129} rta_host;
131 130
132#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ 131#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */
133 132
134/* threshold structure. all values are maximum allowed, exclusive */ 133/* threshold structure. all values are maximum allowed, exclusive */
135typedef struct threshold { 134typedef struct threshold {
136 unsigned char pl; /* max allowed packet loss in percent */ 135 unsigned char pl; /* max allowed packet loss in percent */
137 unsigned int rta; /* roundtrip time average, microseconds */ 136 unsigned int rta; /* roundtrip time average, microseconds */
138 double jitter; /* jitter time average, microseconds */ 137 double jitter; /* jitter time average, microseconds */
139 double mos; /* MOS */ 138 double mos; /* MOS */
140 double score; /* Score */ 139 double score; /* Score */
141} threshold; 140} threshold;
142 141
143/* the data structure */ 142/* the data structure */
144typedef struct icmp_ping_data { 143typedef struct icmp_ping_data {
145 struct timeval stime; /* timestamp (saved in protocol struct as well) */ 144 struct timeval stime; /* timestamp (saved in protocol struct as well) */
146 unsigned short ping_id; 145 unsigned short ping_id;
147} icmp_ping_data; 146} icmp_ping_data;
148 147
@@ -171,10 +170,10 @@ typedef union icmp_packet {
171 * MODE_ICMP: implement something similar to check_icmp (MODE_RTA without 170 * MODE_ICMP: implement something similar to check_icmp (MODE_RTA without
172 * tcp and udp args does this) 171 * tcp and udp args does this)
173 */ 172 */
174#define MODE_RTA 0 173#define MODE_RTA 0
175#define MODE_HOSTCHECK 1 174#define MODE_HOSTCHECK 1
176#define MODE_ALL 2 175#define MODE_ALL 2
177#define MODE_ICMP 3 176#define MODE_ICMP 3
178 177
179enum enum_threshold_mode { 178enum enum_threshold_mode {
180 const_rta_mode, 179 const_rta_mode,
@@ -189,30 +188,30 @@ typedef enum enum_threshold_mode threshold_mode;
189/* the different ping types we can do 188/* the different ping types we can do
190 * TODO: investigate ARP ping as well */ 189 * TODO: investigate ARP ping as well */
191#define HAVE_ICMP 1 190#define HAVE_ICMP 1
192#define HAVE_UDP 2 191#define HAVE_UDP 2
193#define HAVE_TCP 4 192#define HAVE_TCP 4
194#define HAVE_ARP 8 193#define HAVE_ARP 8
195 194
196#define MIN_PING_DATA_SIZE sizeof(struct icmp_ping_data) 195#define MIN_PING_DATA_SIZE sizeof(struct icmp_ping_data)
197#define MAX_IP_PKT_SIZE 65536 /* (theoretical) max IP packet size */ 196#define MAX_IP_PKT_SIZE 65536 /* (theoretical) max IP packet size */
198#define IP_HDR_SIZE 20 197#define IP_HDR_SIZE 20
199#define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN) 198#define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN)
200#define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44) 199#define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44)
201 200
202/* various target states */ 201/* various target states */
203#define TSTATE_INACTIVE 0x01 /* don't ping this host anymore */ 202#define TSTATE_INACTIVE 0x01 /* don't ping this host anymore */
204#define TSTATE_WAITING 0x02 /* unanswered packets on the wire */ 203#define TSTATE_WAITING 0x02 /* unanswered packets on the wire */
205#define TSTATE_ALIVE 0x04 /* target is alive (has answered something) */ 204#define TSTATE_ALIVE 0x04 /* target is alive (has answered something) */
206#define TSTATE_UNREACH 0x08 205#define TSTATE_UNREACH 0x08
207 206
208/** prototypes **/ 207/** prototypes **/
209void print_help (void); 208void print_help(void);
210void print_usage (void); 209void print_usage(void);
211static u_int get_timevar(const char *); 210static u_int get_timevar(const char *);
212static u_int get_timevaldiff(struct timeval *, struct timeval *); 211static u_int get_timevaldiff(struct timeval *, struct timeval *);
213static in_addr_t get_ip_address(const char *); 212static in_addr_t get_ip_address(const char *);
214static int wait_for_reply(int, u_int); 213static int wait_for_reply(int, u_int);
215static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); 214static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval *);
216static int send_icmp_ping(int, struct rta_host *); 215static int send_icmp_ping(int, struct rta_host *);
217static int get_threshold(char *str, threshold *th); 216static int get_threshold(char *str, threshold *th);
218static bool get_threshold2(char *str, size_t length, threshold *, threshold *, threshold_mode mode); 217static bool get_threshold2(char *str, size_t length, threshold *, threshold *, threshold_mode mode);
@@ -235,20 +234,8 @@ extern char **environ;
235/** global variables **/ 234/** global variables **/
236static struct rta_host **table, *cursor, *list; 235static struct rta_host **table, *cursor, *list;
237 236
238static threshold crit = { 237static threshold crit = {.pl = 80, .rta = 500000, .jitter = 0.0, .mos = 0.0, .score = 0.0};
239 .pl = 80, 238static threshold warn = {.pl = 40, .rta = 200000, .jitter = 0.0, .mos = 0.0, .score = 0.0};
240 .rta = 500000,
241 .jitter = 0.0,
242 .mos = 0.0,
243 .score = 0.0
244};
245static threshold warn = {
246 .pl = 40,
247 .rta = 200000,
248 .jitter = 0.0,
249 .mos = 0.0,
250 .score = 0.0
251};
252 239
253static int mode, protocols, sockets, debug = 0, timeout = 10; 240static int mode, protocols, sockets, debug = 0, timeout = 10;
254static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE; 241static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE;
@@ -266,19 +253,17 @@ static struct timeval prog_start;
266static unsigned long long max_completion_time = 0; 253static unsigned long long max_completion_time = 0;
267static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */ 254static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */
268static int min_hosts_alive = -1; 255static int min_hosts_alive = -1;
269float pkt_backoff_factor = 1.5; 256static float pkt_backoff_factor = 1.5;
270float target_backoff_factor = 1.5; 257static float target_backoff_factor = 1.5;
271bool rta_mode=false; 258static bool rta_mode = false;
272bool pl_mode=false; 259static bool pl_mode = false;
273bool jitter_mode=false; 260static bool jitter_mode = false;
274bool score_mode=false; 261static bool score_mode = false;
275bool mos_mode=false; 262static bool mos_mode = false;
276bool order_mode=false; 263static bool order_mode = false;
277 264
278/** code start **/ 265/** code start **/
279static void 266static void crash(const char *fmt, ...) {
280crash(const char *fmt, ...)
281{
282 va_list ap; 267 va_list ap;
283 268
284 printf("%s: ", progname); 269 printf("%s: ", progname);
@@ -287,55 +272,100 @@ crash(const char *fmt, ...)
287 vprintf(fmt, ap); 272 vprintf(fmt, ap);
288 va_end(ap); 273 va_end(ap);
289 274
290 if(errno) printf(": %s", strerror(errno)); 275 if (errno)
276 printf(": %s", strerror(errno));
291 puts(""); 277 puts("");
292 278
293 exit(3); 279 exit(3);
294} 280}
295 281
296 282static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code) {
297static const char *
298get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
299{
300 const char *msg = "unreachable"; 283 const char *msg = "unreachable";
301 284
302 if(debug > 1) printf("get_icmp_error_msg(%u, %u)\n", icmp_type, icmp_code); 285 if (debug > 1)
303 switch(icmp_type) { 286 printf("get_icmp_error_msg(%u, %u)\n", icmp_type, icmp_code);
287 switch (icmp_type) {
304 case ICMP_UNREACH: 288 case ICMP_UNREACH:
305 switch(icmp_code) { 289 switch (icmp_code) {
306 case ICMP_UNREACH_NET: msg = "Net unreachable"; break; 290 case ICMP_UNREACH_NET:
307 case ICMP_UNREACH_HOST: msg = "Host unreachable"; break; 291 msg = "Net unreachable";
308 case ICMP_UNREACH_PROTOCOL: msg = "Protocol unreachable (firewall?)"; break; 292 break;
309 case ICMP_UNREACH_PORT: msg = "Port unreachable (firewall?)"; break; 293 case ICMP_UNREACH_HOST:
310 case ICMP_UNREACH_NEEDFRAG: msg = "Fragmentation needed"; break; 294 msg = "Host unreachable";
311 case ICMP_UNREACH_SRCFAIL: msg = "Source route failed"; break; 295 break;
312 case ICMP_UNREACH_ISOLATED: msg = "Source host isolated"; break; 296 case ICMP_UNREACH_PROTOCOL:
313 case ICMP_UNREACH_NET_UNKNOWN: msg = "Unknown network"; break; 297 msg = "Protocol unreachable (firewall?)";
314 case ICMP_UNREACH_HOST_UNKNOWN: msg = "Unknown host"; break; 298 break;
315 case ICMP_UNREACH_NET_PROHIB: msg = "Network denied (firewall?)"; break; 299 case ICMP_UNREACH_PORT:
316 case ICMP_UNREACH_HOST_PROHIB: msg = "Host denied (firewall?)"; break; 300 msg = "Port unreachable (firewall?)";
317 case ICMP_UNREACH_TOSNET: msg = "Bad TOS for network (firewall?)"; break; 301 break;
318 case ICMP_UNREACH_TOSHOST: msg = "Bad TOS for host (firewall?)"; break; 302 case ICMP_UNREACH_NEEDFRAG:
319 case ICMP_UNREACH_FILTER_PROHIB: msg = "Prohibited by filter (firewall)"; break; 303 msg = "Fragmentation needed";
320 case ICMP_UNREACH_HOST_PRECEDENCE: msg = "Host precedence violation"; break; 304 break;
321 case ICMP_UNREACH_PRECEDENCE_CUTOFF: msg = "Precedence cutoff"; break; 305 case ICMP_UNREACH_SRCFAIL:
322 default: msg = "Invalid code"; break; 306 msg = "Source route failed";
307 break;
308 case ICMP_UNREACH_ISOLATED:
309 msg = "Source host isolated";
310 break;
311 case ICMP_UNREACH_NET_UNKNOWN:
312 msg = "Unknown network";
313 break;
314 case ICMP_UNREACH_HOST_UNKNOWN:
315 msg = "Unknown host";
316 break;
317 case ICMP_UNREACH_NET_PROHIB:
318 msg = "Network denied (firewall?)";
319 break;
320 case ICMP_UNREACH_HOST_PROHIB:
321 msg = "Host denied (firewall?)";
322 break;
323 case ICMP_UNREACH_TOSNET:
324 msg = "Bad TOS for network (firewall?)";
325 break;
326 case ICMP_UNREACH_TOSHOST:
327 msg = "Bad TOS for host (firewall?)";
328 break;
329 case ICMP_UNREACH_FILTER_PROHIB:
330 msg = "Prohibited by filter (firewall)";
331 break;
332 case ICMP_UNREACH_HOST_PRECEDENCE:
333 msg = "Host precedence violation";
334 break;
335 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
336 msg = "Precedence cutoff";
337 break;
338 default:
339 msg = "Invalid code";
340 break;
323 } 341 }
324 break; 342 break;
325 343
326 case ICMP_TIMXCEED: 344 case ICMP_TIMXCEED:
327 /* really 'out of reach', or non-existent host behind a router serving 345 /* really 'out of reach', or non-existent host behind a router serving
328 * two different subnets */ 346 * two different subnets */
329 switch(icmp_code) { 347 switch (icmp_code) {
330 case ICMP_TIMXCEED_INTRANS: msg = "Time to live exceeded in transit"; break; 348 case ICMP_TIMXCEED_INTRANS:
331 case ICMP_TIMXCEED_REASS: msg = "Fragment reassembly time exceeded"; break; 349 msg = "Time to live exceeded in transit";
332 default: msg = "Invalid code"; break; 350 break;
351 case ICMP_TIMXCEED_REASS:
352 msg = "Fragment reassembly time exceeded";
353 break;
354 default:
355 msg = "Invalid code";
356 break;
333 } 357 }
334 break; 358 break;
335 359
336 case ICMP_SOURCEQUENCH: msg = "Transmitting too fast"; break; 360 case ICMP_SOURCEQUENCH:
337 case ICMP_REDIRECT: msg = "Redirect (change route)"; break; 361 msg = "Transmitting too fast";
338 case ICMP_PARAMPROB: msg = "Bad IP header (required option absent)"; break; 362 break;
363 case ICMP_REDIRECT:
364 msg = "Redirect (change route)";
365 break;
366 case ICMP_PARAMPROB:
367 msg = "Bad IP header (required option absent)";
368 break;
339 369
340 /* the following aren't error messages, so ignore */ 370 /* the following aren't error messages, so ignore */
341 case ICMP_TSTAMP: 371 case ICMP_TSTAMP:
@@ -344,25 +374,26 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
344 case ICMP_IREQREPLY: 374 case ICMP_IREQREPLY:
345 case ICMP_MASKREQ: 375 case ICMP_MASKREQ:
346 case ICMP_MASKREPLY: 376 case ICMP_MASKREPLY:
347 default: msg = ""; break; 377 default:
378 msg = "";
379 break;
348 } 380 }
349 381
350 return msg; 382 return msg;
351} 383}
352 384
353static int 385static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr) {
354handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr)
355{
356 struct icmp p, sent_icmp; 386 struct icmp p, sent_icmp;
357 struct rta_host *host = NULL; 387 struct rta_host *host = NULL;
358 388
359 memcpy(&p, packet, sizeof(p)); 389 memcpy(&p, packet, sizeof(p));
360 if(p.icmp_type == ICMP_ECHO && ntohs(p.icmp_id) == pid) { 390 if (p.icmp_type == ICMP_ECHO && ntohs(p.icmp_id) == pid) {
361 /* echo request from us to us (pinging localhost) */ 391 /* echo request from us to us (pinging localhost) */
362 return 0; 392 return 0;
363 } 393 }
364 394
365 if(debug) printf("handle_random_icmp(%p, %p)\n", (void *)&p, (void *)addr); 395 if (debug)
396 printf("handle_random_icmp(%p, %p)\n", (void *)&p, (void *)addr);
366 397
367 /* only handle a few types, since others can't possibly be replies to 398 /* only handle a few types, since others can't possibly be replies to
368 * us in a sane network (if it is anyway, it will be counted as lost 399 * us in a sane network (if it is anyway, it will be counted as lost
@@ -374,44 +405,39 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr)
374 * TIMXCEED actually sends a proper icmp response we will have passed 405 * TIMXCEED actually sends a proper icmp response we will have passed
375 * too many hops to have a hope of reaching it later, in which case it 406 * too many hops to have a hope of reaching it later, in which case it
376 * indicates overconfidence in the network, poor routing or both. */ 407 * indicates overconfidence in the network, poor routing or both. */
377 if(p.icmp_type != ICMP_UNREACH && p.icmp_type != ICMP_TIMXCEED && 408 if (p.icmp_type != ICMP_UNREACH && p.icmp_type != ICMP_TIMXCEED && p.icmp_type != ICMP_SOURCEQUENCH && p.icmp_type != ICMP_PARAMPROB) {
378 p.icmp_type != ICMP_SOURCEQUENCH && p.icmp_type != ICMP_PARAMPROB)
379 {
380 return 0; 409 return 0;
381 } 410 }
382 411
383 /* might be for us. At least it holds the original package (according 412 /* might be for us. At least it holds the original package (according
384 * to RFC 792). If it isn't, just ignore it */ 413 * to RFC 792). If it isn't, just ignore it */
385 memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp)); 414 memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp));
386 if(sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != pid || 415 if (sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != pid || ntohs(sent_icmp.icmp_seq) >= targets * packets) {
387 ntohs(sent_icmp.icmp_seq) >= targets*packets) 416 if (debug)
388 { 417 printf("Packet is no response to a packet we sent\n");
389 if(debug) printf("Packet is no response to a packet we sent\n");
390 return 0; 418 return 0;
391 } 419 }
392 420
393 /* it is indeed a response for us */ 421 /* it is indeed a response for us */
394 host = table[ntohs(sent_icmp.icmp_seq)/packets]; 422 host = table[ntohs(sent_icmp.icmp_seq) / packets];
395 if(debug) { 423 if (debug) {
396 char address[INET6_ADDRSTRLEN]; 424 char address[INET6_ADDRSTRLEN];
397 parse_address(addr, address, sizeof(address)); 425 parse_address(addr, address, sizeof(address));
398 printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", 426 printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", get_icmp_error_msg(p.icmp_type, p.icmp_code), address, host->name);
399 get_icmp_error_msg(p.icmp_type, p.icmp_code),
400 address, host->name);
401 } 427 }
402 428
403 icmp_lost++; 429 icmp_lost++;
404 host->icmp_lost++; 430 host->icmp_lost++;
405 /* don't spend time on lost hosts any more */ 431 /* don't spend time on lost hosts any more */
406 if(host->flags & FLAG_LOST_CAUSE) return 0; 432 if (host->flags & FLAG_LOST_CAUSE)
433 return 0;
407 434
408 /* source quench means we're sending too fast, so increase the 435 /* source quench means we're sending too fast, so increase the
409 * interval and mark this packet lost */ 436 * interval and mark this packet lost */
410 if(p.icmp_type == ICMP_SOURCEQUENCH) { 437 if (p.icmp_type == ICMP_SOURCEQUENCH) {
411 pkt_interval *= pkt_backoff_factor; 438 pkt_interval *= pkt_backoff_factor;
412 target_interval *= target_backoff_factor; 439 target_interval *= target_backoff_factor;
413 } 440 } else {
414 else {
415 targets_down++; 441 targets_down++;
416 host->flags |= FLAG_LOST_CAUSE; 442 host->flags |= FLAG_LOST_CAUSE;
417 } 443 }
@@ -422,21 +448,18 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr)
422 return 0; 448 return 0;
423} 449}
424 450
425void parse_address(struct sockaddr_storage *addr, char *address, int size) 451void parse_address(struct sockaddr_storage *addr, char *address, int size) {
426{
427 switch (address_family) { 452 switch (address_family) {
428 case AF_INET: 453 case AF_INET:
429 inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size); 454 inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size);
430 break; 455 break;
431 case AF_INET6: 456 case AF_INET6:
432 inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size); 457 inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size);
433 break; 458 break;
434 } 459 }
435} 460}
436 461
437int 462int main(int argc, char **argv) {
438main(int argc, char **argv)
439{
440 int i; 463 int i;
441 char *ptr; 464 char *ptr;
442 long int arg; 465 long int arg;
@@ -450,10 +473,10 @@ main(int argc, char **argv)
450 int on = 1; 473 int on = 1;
451#endif 474#endif
452 char *source_ip = NULL; 475 char *source_ip = NULL;
453 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; 476 char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64";
454 setlocale (LC_ALL, ""); 477 setlocale(LC_ALL, "");
455 bindtextdomain (PACKAGE, LOCALEDIR); 478 bindtextdomain(PACKAGE, LOCALEDIR);
456 textdomain (PACKAGE); 479 textdomain(PACKAGE);
457 480
458 /* we only need to be setsuid when we get the sockets, so do 481 /* we only need to be setsuid when we get the sockets, so do
459 * that before pointer magic (esp. on network data) */ 482 * that before pointer magic (esp. on network data) */
@@ -465,8 +488,10 @@ main(int argc, char **argv)
465 /* get calling name the old-fashioned way for portability instead 488 /* get calling name the old-fashioned way for portability instead
466 * of relying on the glibc-ism __progname */ 489 * of relying on the glibc-ism __progname */
467 ptr = strrchr(argv[0], '/'); 490 ptr = strrchr(argv[0], '/');
468 if(ptr) progname = &ptr[1]; 491 if (ptr)
469 else progname = argv[0]; 492 progname = &ptr[1];
493 else
494 progname = argv[0];
470 495
471 /* now set defaults. Use progname to set them initially (allows for 496 /* now set defaults. Use progname to set them initially (allows for
472 * superfast check_host program when target host is up */ 497 * superfast check_host program when target host is up */
@@ -478,31 +503,29 @@ main(int argc, char **argv)
478 crit.rta = 500000; 503 crit.rta = 500000;
479 crit.pl = 80; 504 crit.pl = 80;
480 crit.jitter = 50; 505 crit.jitter = 50;
481 crit.mos= 3; 506 crit.mos = 3;
482 crit.score=70; 507 crit.score = 70;
483 /* Default warning thresholds */ 508 /* Default warning thresholds */
484 warn.rta = 200000; 509 warn.rta = 200000;
485 warn.pl = 40; 510 warn.pl = 40;
486 warn.jitter = 40; 511 warn.jitter = 40;
487 warn.mos= 3.5; 512 warn.mos = 3.5;
488 warn.score=80; 513 warn.score = 80;
489 514
490 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; 515 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP;
491 pkt_interval = 80000; /* 80 msec packet interval by default */ 516 pkt_interval = 80000; /* 80 msec packet interval by default */
492 packets = 5; 517 packets = 5;
493 518
494 if(!strcmp(progname, "check_icmp") || !strcmp(progname, "check_ping")) { 519 if (!strcmp(progname, "check_icmp") || !strcmp(progname, "check_ping")) {
495 mode = MODE_ICMP; 520 mode = MODE_ICMP;
496 protocols = HAVE_ICMP; 521 protocols = HAVE_ICMP;
497 } 522 } else if (!strcmp(progname, "check_host")) {
498 else if(!strcmp(progname, "check_host")) {
499 mode = MODE_HOSTCHECK; 523 mode = MODE_HOSTCHECK;
500 pkt_interval = 1000000; 524 pkt_interval = 1000000;
501 packets = 5; 525 packets = 5;
502 crit.rta = warn.rta = 1000000; 526 crit.rta = warn.rta = 1000000;
503 crit.pl = warn.pl = 100; 527 crit.pl = warn.pl = 100;
504 } 528 } else if (!strcmp(progname, "check_rta_multi")) {
505 else if(!strcmp(progname, "check_rta_multi")) {
506 mode = MODE_ALL; 529 mode = MODE_ALL;
507 target_interval = 0; 530 target_interval = 0;
508 pkt_interval = 50000; 531 pkt_interval = 50000;
@@ -510,17 +533,17 @@ main(int argc, char **argv)
510 } 533 }
511 534
512 /* support "--help" and "--version" */ 535 /* support "--help" and "--version" */
513 if(argc == 2) { 536 if (argc == 2) {
514 if(!strcmp(argv[1], "--help")) 537 if (!strcmp(argv[1], "--help"))
515 strcpy(argv[1], "-h"); 538 strcpy(argv[1], "-h");
516 if(!strcmp(argv[1], "--version")) 539 if (!strcmp(argv[1], "--version"))
517 strcpy(argv[1], "-V"); 540 strcpy(argv[1], "-V");
518 } 541 }
519 542
520 /* Parse protocol arguments first */ 543 /* Parse protocol arguments first */
521 for(i = 1; i < argc; i++) { 544 for (i = 1; i < argc; i++) {
522 while((arg = getopt(argc, argv, opts_str)) != EOF) { 545 while ((arg = getopt(argc, argv, opts_str)) != EOF) {
523 switch(arg) { 546 switch (arg) {
524 case '4': 547 case '4':
525 if (address_family != -1) 548 if (address_family != -1)
526 crash("Multiple protocol versions not supported"); 549 crash("Multiple protocol versions not supported");
@@ -532,7 +555,7 @@ main(int argc, char **argv)
532 crash("Multiple protocol versions not supported"); 555 crash("Multiple protocol versions not supported");
533 address_family = AF_INET6; 556 address_family = AF_INET6;
534#else 557#else
535 usage (_("IPv6 support not available\n")); 558 usage(_("IPv6 support not available\n"));
536#endif 559#endif
537 break; 560 break;
538 } 561 }
@@ -545,22 +568,20 @@ main(int argc, char **argv)
545 unsigned long size; 568 unsigned long size;
546 bool err; 569 bool err;
547 /* parse the arguments */ 570 /* parse the arguments */
548 for(i = 1; i < argc; i++) { 571 for (i = 1; i < argc; i++) {
549 while((arg = getopt(argc, argv, opts_str)) != EOF) { 572 while ((arg = getopt(argc, argv, opts_str)) != EOF) {
550 switch(arg) { 573 switch (arg) {
551 case 'v': 574 case 'v':
552 debug++; 575 debug++;
553 break; 576 break;
554 case 'b': 577 case 'b':
555 size = strtol(optarg,NULL,0); 578 size = strtol(optarg, NULL, 0);
556 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && 579 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && size < MAX_PING_DATA) {
557 size < MAX_PING_DATA) {
558 icmp_data_size = size; 580 icmp_data_size = size;
559 icmp_pkt_size = size + ICMP_MINLEN; 581 icmp_pkt_size = size + ICMP_MINLEN;
560 } else 582 } else
561 usage_va("ICMP data length must be between: %lu and %lu", 583 usage_va("ICMP data length must be between: %lu and %lu", sizeof(struct icmp) + sizeof(struct icmp_ping_data),
562 sizeof(struct icmp) + sizeof(struct icmp_ping_data), 584 MAX_PING_DATA - 1);
563 MAX_PING_DATA - 1);
564 break; 585 break;
565 case 'i': 586 case 'i':
566 pkt_interval = get_timevar(optarg); 587 pkt_interval = get_timevar(optarg);
@@ -580,7 +601,8 @@ main(int argc, char **argv)
580 break; 601 break;
581 case 't': 602 case 't':
582 timeout = strtoul(optarg, NULL, 0); 603 timeout = strtoul(optarg, NULL, 0);
583 if(!timeout) timeout = 10; 604 if (!timeout)
605 timeout = 10;
584 break; 606 break;
585 case 'H': 607 case 'H':
586 add_target(optarg); 608 add_target(optarg);
@@ -593,7 +615,7 @@ main(int argc, char **argv)
593 break; 615 break;
594 case 'd': /* implement later, for cluster checks */ 616 case 'd': /* implement later, for cluster checks */
595 warn_down = (unsigned char)strtoul(optarg, &ptr, 0); 617 warn_down = (unsigned char)strtoul(optarg, &ptr, 0);
596 if(ptr) { 618 if (ptr) {
597 crit_down = (unsigned char)strtoul(ptr + 1, NULL, 0); 619 crit_down = (unsigned char)strtoul(ptr + 1, NULL, 0);
598 } 620 }
599 break; 621 break;
@@ -601,54 +623,54 @@ main(int argc, char **argv)
601 source_ip = optarg; 623 source_ip = optarg;
602 break; 624 break;
603 case 'V': /* version */ 625 case 'V': /* version */
604 print_revision (progname, NP_VERSION); 626 print_revision(progname, NP_VERSION);
605 exit (STATE_UNKNOWN); 627 exit(STATE_UNKNOWN);
606 case 'h': /* help */ 628 case 'h': /* help */
607 print_help (); 629 print_help();
608 exit (STATE_UNKNOWN); 630 exit(STATE_UNKNOWN);
609 break; 631 break;
610 case 'R': /* RTA mode */ 632 case 'R': /* RTA mode */
611 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_rta_mode); 633 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_rta_mode);
612 if (!err) { 634 if (!err) {
613 crash("Failed to parse RTA threshold"); 635 crash("Failed to parse RTA threshold");
614 } 636 }
615 637
616 rta_mode=true; 638 rta_mode = true;
617 break; 639 break;
618 case 'P': /* packet loss mode */ 640 case 'P': /* packet loss mode */
619 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_packet_loss_mode); 641 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_packet_loss_mode);
620 if (!err) { 642 if (!err) {
621 crash("Failed to parse packet loss threshold"); 643 crash("Failed to parse packet loss threshold");
622 } 644 }
623 645
624 pl_mode=true; 646 pl_mode = true;
625 break; 647 break;
626 case 'J': /* jitter mode */ 648 case 'J': /* jitter mode */
627 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_jitter_mode); 649 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_jitter_mode);
628 if (!err) { 650 if (!err) {
629 crash("Failed to parse jitter threshold"); 651 crash("Failed to parse jitter threshold");
630 } 652 }
631 653
632 jitter_mode=true; 654 jitter_mode = true;
633 break; 655 break;
634 case 'M': /* MOS mode */ 656 case 'M': /* MOS mode */
635 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_mos_mode); 657 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_mos_mode);
636 if (!err) { 658 if (!err) {
637 crash("Failed to parse MOS threshold"); 659 crash("Failed to parse MOS threshold");
638 } 660 }
639 661
640 mos_mode=true; 662 mos_mode = true;
641 break; 663 break;
642 case 'S': /* score mode */ 664 case 'S': /* score mode */
643 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_score_mode); 665 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_score_mode);
644 if (!err) { 666 if (!err) {
645 crash("Failed to parse score threshold"); 667 crash("Failed to parse score threshold");
646 } 668 }
647 669
648 score_mode=true; 670 score_mode = true;
649 break; 671 break;
650 case 'O': /* out of order mode */ 672 case 'O': /* out of order mode */
651 order_mode=true; 673 order_mode = true;
652 break; 674 break;
653 } 675 }
654 } 676 }
@@ -663,37 +685,42 @@ main(int argc, char **argv)
663 /* printf("pid = %u\n", pid); */ 685 /* printf("pid = %u\n", pid); */
664 686
665 /* Parse extra opts if any */ 687 /* Parse extra opts if any */
666 argv=np_extra_opts(&argc, argv, progname); 688 argv = np_extra_opts(&argc, argv, progname);
667 689
668 argv = &argv[optind]; 690 argv = &argv[optind];
669 while(*argv) { 691 while (*argv) {
670 add_target(*argv); 692 add_target(*argv);
671 argv++; 693 argv++;
672 } 694 }
673 695
674 if(!targets) { 696 if (!targets) {
675 errno = 0; 697 errno = 0;
676 crash("No hosts to check"); 698 crash("No hosts to check");
677 } 699 }
678 700
679 // add_target might change address_family 701 // add_target might change address_family
680 switch ( address_family ){ 702 switch (address_family) {
681 case AF_INET: icmp_proto = IPPROTO_ICMP; 703 case AF_INET:
682 break; 704 icmp_proto = IPPROTO_ICMP;
683 case AF_INET6: icmp_proto = IPPROTO_ICMPV6; 705 break;
684 break; 706 case AF_INET6:
685 default: crash("Address family not supported"); 707 icmp_proto = IPPROTO_ICMPV6;
708 break;
709 default:
710 crash("Address family not supported");
686 } 711 }
687 if((icmp_sock = socket(address_family, SOCK_RAW, icmp_proto)) != -1) 712 if ((icmp_sock = socket(address_family, SOCK_RAW, icmp_proto)) != -1)
688 sockets |= HAVE_ICMP; 713 sockets |= HAVE_ICMP;
689 else icmp_sockerrno = errno; 714 else
715 icmp_sockerrno = errno;
690 716
691 if( source_ip ) 717 if (source_ip)
692 set_source_ip(source_ip); 718 set_source_ip(source_ip);
693 719
694#ifdef SO_TIMESTAMP 720#ifdef SO_TIMESTAMP
695 if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) 721 if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
696 if(debug) printf("Warning: no SO_TIMESTAMP support\n"); 722 if (debug)
723 printf("Warning: no SO_TIMESTAMP support\n");
697#endif // SO_TIMESTAMP 724#endif // SO_TIMESTAMP
698 725
699 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ 726 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */
@@ -702,8 +729,8 @@ main(int argc, char **argv)
702 return 1; 729 return 1;
703 } 730 }
704 731
705 if(!sockets) { 732 if (!sockets) {
706 if(icmp_sock == -1) { 733 if (icmp_sock == -1) {
707 errno = icmp_sockerrno; 734 errno = icmp_sockerrno;
708 crash("Failed to obtain ICMP socket"); 735 crash("Failed to obtain ICMP socket");
709 return -1; 736 return -1;
@@ -719,13 +746,16 @@ main(int argc, char **argv)
719 /* return -1; */ 746 /* return -1; */
720 /* } */ 747 /* } */
721 } 748 }
722 if(!ttl) ttl = 64; 749 if (!ttl)
750 ttl = 64;
723 751
724 if(icmp_sock) { 752 if (icmp_sock) {
725 result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)); 753 result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl));
726 if(debug) { 754 if (debug) {
727 if(result == -1) printf("setsockopt failed\n"); 755 if (result == -1)
728 else printf("ttl set to %u\n", ttl); 756 printf("setsockopt failed\n");
757 else
758 printf("ttl set to %u\n", ttl);
729 } 759 }
730 } 760 }
731 761
@@ -733,85 +763,83 @@ main(int argc, char **argv)
733 * (nothing will break if they do), but some anal plugin maintainer 763 * (nothing will break if they do), but some anal plugin maintainer
734 * will probably add some printf() thing here later, so it might be 764 * will probably add some printf() thing here later, so it might be
735 * best to at least show them where to do it. ;) */ 765 * best to at least show them where to do it. ;) */
736 if(warn.pl > crit.pl) warn.pl = crit.pl; 766 if (warn.pl > crit.pl)
737 if(warn.rta > crit.rta) warn.rta = crit.rta; 767 warn.pl = crit.pl;
738 if(warn_down > crit_down) crit_down = warn_down; 768 if (warn.rta > crit.rta)
739 if(warn.jitter > crit.jitter) crit.jitter = warn.jitter; 769 warn.rta = crit.rta;
740 if(warn.mos < crit.mos) warn.mos = crit.mos; 770 if (warn_down > crit_down)
741 if(warn.score < crit.score) warn.score = crit.score; 771 crit_down = warn_down;
772 if (warn.jitter > crit.jitter)
773 crit.jitter = warn.jitter;
774 if (warn.mos < crit.mos)
775 warn.mos = crit.mos;
776 if (warn.score < crit.score)
777 warn.score = crit.score;
742 778
743#ifdef HAVE_SIGACTION 779#ifdef HAVE_SIGACTION
744 sig_action.sa_sigaction = NULL; 780 sig_action.sa_sigaction = NULL;
745 sig_action.sa_handler = finish; 781 sig_action.sa_handler = finish;
746 sigfillset(&sig_action.sa_mask); 782 sigfillset(&sig_action.sa_mask);
747 sig_action.sa_flags = SA_NODEFER|SA_RESTART; 783 sig_action.sa_flags = SA_NODEFER | SA_RESTART;
748 sigaction(SIGINT, &sig_action, NULL); 784 sigaction(SIGINT, &sig_action, NULL);
749 sigaction(SIGHUP, &sig_action, NULL); 785 sigaction(SIGHUP, &sig_action, NULL);
750 sigaction(SIGTERM, &sig_action, NULL); 786 sigaction(SIGTERM, &sig_action, NULL);
751 sigaction(SIGALRM, &sig_action, NULL); 787 sigaction(SIGALRM, &sig_action, NULL);
752#else /* HAVE_SIGACTION */ 788#else /* HAVE_SIGACTION */
753 signal(SIGINT, finish); 789 signal(SIGINT, finish);
754 signal(SIGHUP, finish); 790 signal(SIGHUP, finish);
755 signal(SIGTERM, finish); 791 signal(SIGTERM, finish);
756 signal(SIGALRM, finish); 792 signal(SIGALRM, finish);
757#endif /* HAVE_SIGACTION */ 793#endif /* HAVE_SIGACTION */
758 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); 794 if (debug)
795 printf("Setting alarm timeout to %u seconds\n", timeout);
759 alarm(timeout); 796 alarm(timeout);
760 797
761 /* make sure we don't wait any longer than necessary */ 798 /* make sure we don't wait any longer than necessary */
762 gettimeofday(&prog_start, &tz); 799 gettimeofday(&prog_start, &tz);
763 max_completion_time = 800 max_completion_time = ((targets * packets * pkt_interval) + (targets * target_interval)) + (targets * packets * crit.rta) + crit.rta;
764 ((targets * packets * pkt_interval) + (targets * target_interval)) +
765 (targets * packets * crit.rta) + crit.rta;
766 801
767 if(debug) { 802 if (debug) {
768 printf("packets: %u, targets: %u\n" 803 printf("packets: %u, targets: %u\n"
769 "target_interval: %0.3f, pkt_interval %0.3f\n" 804 "target_interval: %0.3f, pkt_interval %0.3f\n"
770 "crit.rta: %0.3f\n" 805 "crit.rta: %0.3f\n"
771 "max_completion_time: %0.3f\n", 806 "max_completion_time: %0.3f\n",
772 packets, targets, 807 packets, targets, (float)target_interval / 1000, (float)pkt_interval / 1000, (float)crit.rta / 1000,
773 (float)target_interval / 1000, (float)pkt_interval / 1000,
774 (float)crit.rta / 1000,
775 (float)max_completion_time / 1000); 808 (float)max_completion_time / 1000);
776 } 809 }
777 810
778 if(debug) { 811 if (debug) {
779 if(max_completion_time > (u_int)timeout * 1000000) { 812 if (max_completion_time > (u_int)timeout * 1000000) {
780 printf("max_completion_time: %llu timeout: %u\n", 813 printf("max_completion_time: %llu timeout: %u\n", max_completion_time, timeout);
781 max_completion_time, timeout); 814 printf("Timeout must be at least %llu\n", max_completion_time / 1000000 + 1);
782 printf("Timeout must be at least %llu\n",
783 max_completion_time / 1000000 + 1);
784 } 815 }
785 } 816 }
786 817
787 if(debug) { 818 if (debug) {
788 printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", 819 printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", crit.rta, crit.pl, warn.rta, warn.pl);
789 crit.rta, crit.pl, warn.rta, warn.pl); 820 printf("pkt_interval: %u target_interval: %u retry_interval: %u\n", pkt_interval, target_interval, retry_interval);
790 printf("pkt_interval: %u target_interval: %u retry_interval: %u\n", 821 printf("icmp_pkt_size: %u timeout: %u\n", icmp_pkt_size, timeout);
791 pkt_interval, target_interval, retry_interval);
792 printf("icmp_pkt_size: %u timeout: %u\n",
793 icmp_pkt_size, timeout);
794 } 822 }
795 823
796 if(packets > 20) { 824 if (packets > 20) {
797 errno = 0; 825 errno = 0;
798 crash("packets is > 20 (%d)", packets); 826 crash("packets is > 20 (%d)", packets);
799 } 827 }
800 828
801 if(min_hosts_alive < -1) { 829 if (min_hosts_alive < -1) {
802 errno = 0; 830 errno = 0;
803 crash("minimum alive hosts is negative (%i)", min_hosts_alive); 831 crash("minimum alive hosts is negative (%i)", min_hosts_alive);
804 } 832 }
805 833
806 host = list; 834 host = list;
807 table = malloc(sizeof(struct rta_host *) * targets); 835 table = malloc(sizeof(struct rta_host *) * targets);
808 if(!table) { 836 if (!table) {
809 crash("main(): malloc failed for host table"); 837 crash("main(): malloc failed for host table");
810 } 838 }
811 839
812 i = 0; 840 i = 0;
813 while(host) { 841 while (host) {
814 host->id = i*packets; 842 host->id = i * packets;
815 table[i] = host; 843 table[i] = host;
816 host = host->next; 844 host = host->next;
817 i++; 845 i++;
@@ -822,25 +850,24 @@ main(int argc, char **argv)
822 errno = 0; 850 errno = 0;
823 finish(0); 851 finish(0);
824 852
825 return(0); 853 return (0);
826} 854}
827 855
828static void 856static void run_checks(void) {
829run_checks()
830{
831 u_int i, t; 857 u_int i, t;
832 u_int final_wait, time_passed; 858 u_int final_wait, time_passed;
833 859
834 /* this loop might actually violate the pkt_interval or target_interval 860 /* this loop might actually violate the pkt_interval or target_interval
835 * settings, but only if there aren't any packets on the wire which 861 * settings, but only if there aren't any packets on the wire which
836 * indicates that the target can handle an increased packet rate */ 862 * indicates that the target can handle an increased packet rate */
837 for(i = 0; i < packets; i++) { 863 for (i = 0; i < packets; i++) {
838 for(t = 0; t < targets; t++) { 864 for (t = 0; t < targets; t++) {
839 /* don't send useless packets */ 865 /* don't send useless packets */
840 if(!targets_alive) finish(0); 866 if (!targets_alive)
841 if(table[t]->flags & FLAG_LOST_CAUSE) { 867 finish(0);
842 if(debug) printf("%s is a lost cause. not sending any more\n", 868 if (table[t]->flags & FLAG_LOST_CAUSE) {
843 table[t]->name); 869 if (debug)
870 printf("%s is a lost cause. not sending any more\n", table[t]->name);
844 continue; 871 continue;
845 } 872 }
846 873
@@ -851,28 +878,27 @@ run_checks()
851 wait_for_reply(icmp_sock, pkt_interval * targets); 878 wait_for_reply(icmp_sock, pkt_interval * targets);
852 } 879 }
853 880
854 if(icmp_pkts_en_route && targets_alive) { 881 if (icmp_pkts_en_route && targets_alive) {
855 time_passed = get_timevaldiff(NULL, NULL); 882 time_passed = get_timevaldiff(NULL, NULL);
856 final_wait = max_completion_time - time_passed; 883 final_wait = max_completion_time - time_passed;
857 884
858 if(debug) { 885 if (debug) {
859 printf("time_passed: %u final_wait: %u max_completion_time: %llu\n", 886 printf("time_passed: %u final_wait: %u max_completion_time: %llu\n", time_passed, final_wait, max_completion_time);
860 time_passed, final_wait, max_completion_time);
861 } 887 }
862 if(time_passed > max_completion_time) { 888 if (time_passed > max_completion_time) {
863 if(debug) printf("Time passed. Finishing up\n"); 889 if (debug)
890 printf("Time passed. Finishing up\n");
864 finish(0); 891 finish(0);
865 } 892 }
866 893
867 /* catch the packets that might come in within the timeframe, but 894 /* catch the packets that might come in within the timeframe, but
868 * haven't yet */ 895 * haven't yet */
869 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", 896 if (debug)
870 final_wait, (float)final_wait / 1000); 897 printf("Waiting for %u micro-seconds (%0.3f msecs)\n", final_wait, (float)final_wait / 1000);
871 wait_for_reply(icmp_sock, final_wait); 898 wait_for_reply(icmp_sock, final_wait);
872 } 899 }
873} 900}
874 901
875
876/* response structure: 902/* response structure:
877 * IPv4: 903 * IPv4:
878 * ip header : 20 bytes 904 * ip header : 20 bytes
@@ -883,9 +909,7 @@ run_checks()
883 * both: 909 * both:
884 * icmp echo reply : the rest 910 * icmp echo reply : the rest
885 */ 911 */
886static int 912static int wait_for_reply(int sock, u_int t) {
887wait_for_reply(int sock, u_int t)
888{
889 int n, hlen; 913 int n, hlen;
890 static unsigned char buf[65536]; 914 static unsigned char buf[65536];
891 struct sockaddr_storage resp_addr; 915 struct sockaddr_storage resp_addr;
@@ -898,15 +922,14 @@ wait_for_reply(int sock, u_int t)
898 double jitter_tmp; 922 double jitter_tmp;
899 923
900 if (!(packet.buf = malloc(icmp_pkt_size))) { 924 if (!(packet.buf = malloc(icmp_pkt_size))) {
901 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", 925 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size);
902 icmp_pkt_size); 926 return -1; /* might be reached if we're in debug mode */
903 return -1; /* might be reached if we're in debug mode */
904 } 927 }
905 928
906 memset(packet.buf, 0, icmp_pkt_size); 929 memset(packet.buf, 0, icmp_pkt_size);
907 930
908 /* if we can't listen or don't have anything to listen to, just return */ 931 /* if we can't listen or don't have anything to listen to, just return */
909 if(!t || !icmp_pkts_en_route) { 932 if (!t || !icmp_pkts_en_route) {
910 free(packet.buf); 933 free(packet.buf);
911 return 0; 934 return 0;
912 } 935 }
@@ -915,29 +938,25 @@ wait_for_reply(int sock, u_int t)
915 938
916 i = t; 939 i = t;
917 per_pkt_wait = t / icmp_pkts_en_route; 940 per_pkt_wait = t / icmp_pkts_en_route;
918 while(icmp_pkts_en_route && get_timevaldiff(&wait_start, NULL) < i) { 941 while (icmp_pkts_en_route && get_timevaldiff(&wait_start, NULL) < i) {
919 t = per_pkt_wait; 942 t = per_pkt_wait;
920 943
921 /* wrap up if all targets are declared dead */ 944 /* wrap up if all targets are declared dead */
922 if(!targets_alive || 945 if (!targets_alive || get_timevaldiff(&prog_start, NULL) >= max_completion_time || (mode == MODE_HOSTCHECK && targets_down)) {
923 get_timevaldiff(&prog_start, NULL) >= max_completion_time ||
924 (mode == MODE_HOSTCHECK && targets_down))
925 {
926 finish(0); 946 finish(0);
927 } 947 }
928 948
929 /* reap responses until we hit a timeout */ 949 /* reap responses until we hit a timeout */
930 n = recvfrom_wto(sock, buf, sizeof(buf), 950 n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, &t, &now);
931 (struct sockaddr *)&resp_addr, &t, &now); 951 if (!n) {
932 if(!n) { 952 if (debug > 1) {
933 if(debug > 1) { 953 printf("recvfrom_wto() timed out during a %u usecs wait\n", per_pkt_wait);
934 printf("recvfrom_wto() timed out during a %u usecs wait\n",
935 per_pkt_wait);
936 } 954 }
937 continue; /* timeout for this one, so keep trying */ 955 continue; /* timeout for this one, so keep trying */
938 } 956 }
939 if(n < 0) { 957 if (n < 0) {
940 if(debug) printf("recvfrom_wto() returned errors\n"); 958 if (debug)
959 printf("recvfrom_wto() returned errors\n");
941 free(packet.buf); 960 free(packet.buf);
942 return n; 961 return n;
943 } 962 }
@@ -946,31 +965,27 @@ wait_for_reply(int sock, u_int t)
946 if (address_family != AF_INET6) { 965 if (address_family != AF_INET6) {
947 ip = (union ip_hdr *)buf; 966 ip = (union ip_hdr *)buf;
948 967
949 if(debug > 1) { 968 if (debug > 1) {
950 char address[INET6_ADDRSTRLEN]; 969 char address[INET6_ADDRSTRLEN];
951 parse_address(&resp_addr, address, sizeof(address)); 970 parse_address(&resp_addr, address, sizeof(address));
952 printf("received %u bytes from %s\n", 971 printf("received %u bytes from %s\n", address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen) : ntohs(ip->ip.ip_len), address);
953 address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen)
954 : ntohs(ip->ip.ip_len),
955 address);
956 } 972 }
957 } 973 }
958 974
959/* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */ 975 /* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */
960/* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */ 976 /* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */
961 /* alpha headers are decidedly broken. Using an ansi compiler, 977 /* alpha headers are decidedly broken. Using an ansi compiler,
962 * they provide ip_vhl instead of ip_hl and ip_v, so we mask 978 * they provide ip_vhl instead of ip_hl and ip_v, so we mask
963 * off the bottom 4 bits */ 979 * off the bottom 4 bits */
964/* hlen = (ip->ip_vhl & 0x0f) << 2; */ 980 /* hlen = (ip->ip_vhl & 0x0f) << 2; */
965/* #else */ 981 /* #else */
966 hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2; 982 hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2;
967/* #endif */ 983 /* #endif */
968 984
969 if(n < (hlen + ICMP_MINLEN)) { 985 if (n < (hlen + ICMP_MINLEN)) {
970 char address[INET6_ADDRSTRLEN]; 986 char address[INET6_ADDRSTRLEN];
971 parse_address(&resp_addr, address, sizeof(address)); 987 parse_address(&resp_addr, address, sizeof(address));
972 crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", 988 crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", n, hlen + icmp_pkt_size, address);
973 n, hlen + icmp_pkt_size, address);
974 } 989 }
975 /* else if(debug) { */ 990 /* else if(debug) { */
976 /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */ 991 /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */
@@ -981,16 +996,15 @@ wait_for_reply(int sock, u_int t)
981 /* check the response */ 996 /* check the response */
982 997
983 memcpy(packet.buf, buf + hlen, icmp_pkt_size); 998 memcpy(packet.buf, buf + hlen, icmp_pkt_size);
984/* address_family == AF_INET6 ? sizeof(struct icmp6_hdr) 999 /* address_family == AF_INET6 ? sizeof(struct icmp6_hdr)
985 : sizeof(struct icmp));*/ 1000 : sizeof(struct icmp));*/
986 1001
987 if( (address_family == PF_INET && 1002 if ((address_family == PF_INET && (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY ||
988 (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY 1003 ntohs(packet.icp->icmp_seq) >= targets * packets)) ||
989 || ntohs(packet.icp->icmp_seq) >= targets * packets)) 1004 (address_family == PF_INET6 && (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY ||
990 || (address_family == PF_INET6 && 1005 ntohs(packet.icp6->icmp6_seq) >= targets * packets))) {
991 (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY 1006 if (debug > 2)
992 || ntohs(packet.icp6->icmp6_seq) >= targets * packets))) { 1007 printf("not a proper ICMP_ECHOREPLY\n");
993 if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n");
994 handle_random_icmp(buf + hlen, &resp_addr); 1008 handle_random_icmp(buf + hlen, &resp_addr);
995 continue; 1009 continue;
996 } 1010 }
@@ -999,22 +1013,20 @@ wait_for_reply(int sock, u_int t)
999 if (address_family == PF_INET) { 1013 if (address_family == PF_INET) {
1000 memcpy(&data, packet.icp->icmp_data, sizeof(data)); 1014 memcpy(&data, packet.icp->icmp_data, sizeof(data));
1001 if (debug > 2) 1015 if (debug > 2)
1002 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", 1016 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id),
1003 (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id), 1017 ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum);
1004 ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum); 1018 host = table[ntohs(packet.icp->icmp_seq) / packets];
1005 host = table[ntohs(packet.icp->icmp_seq)/packets];
1006 } else { 1019 } else {
1007 memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data)); 1020 memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data));
1008 if (debug > 2) 1021 if (debug > 2)
1009 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", 1022 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", (unsigned long)sizeof(data), ntohs(packet.icp6->icmp6_id),
1010 (unsigned long)sizeof(data), ntohs(packet.icp6->icmp6_id), 1023 ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum);
1011 ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum); 1024 host = table[ntohs(packet.icp6->icmp6_seq) / packets];
1012 host = table[ntohs(packet.icp6->icmp6_seq)/packets];
1013 } 1025 }
1014 1026
1015 tdiff = get_timevaldiff(&data.stime, &now); 1027 tdiff = get_timevaldiff(&data.stime, &now);
1016 1028
1017 if (host->last_tdiff>0) { 1029 if (host->last_tdiff > 0) {
1018 /* Calculate jitter */ 1030 /* Calculate jitter */
1019 if (host->last_tdiff > tdiff) { 1031 if (host->last_tdiff > tdiff) {
1020 jitter_tmp = host->last_tdiff - tdiff; 1032 jitter_tmp = host->last_tdiff - tdiff;
@@ -1022,29 +1034,29 @@ wait_for_reply(int sock, u_int t)
1022 jitter_tmp = tdiff - host->last_tdiff; 1034 jitter_tmp = tdiff - host->last_tdiff;
1023 } 1035 }
1024 1036
1025 if (host->jitter==0) { 1037 if (host->jitter == 0) {
1026 host->jitter=jitter_tmp; 1038 host->jitter = jitter_tmp;
1027 host->jitter_max=jitter_tmp; 1039 host->jitter_max = jitter_tmp;
1028 host->jitter_min=jitter_tmp; 1040 host->jitter_min = jitter_tmp;
1029 } else { 1041 } else {
1030 host->jitter+=jitter_tmp; 1042 host->jitter += jitter_tmp;
1031 1043
1032 if (jitter_tmp < host->jitter_min) { 1044 if (jitter_tmp < host->jitter_min) {
1033 host->jitter_min=jitter_tmp; 1045 host->jitter_min = jitter_tmp;
1034 } 1046 }
1035 1047
1036 if (jitter_tmp > host->jitter_max) { 1048 if (jitter_tmp > host->jitter_max) {
1037 host->jitter_max=jitter_tmp; 1049 host->jitter_max = jitter_tmp;
1038 } 1050 }
1039 } 1051 }
1040 1052
1041 /* Check if packets in order */ 1053 /* Check if packets in order */
1042 if (host->last_icmp_seq >= packet.icp->icmp_seq) 1054 if (host->last_icmp_seq >= packet.icp->icmp_seq)
1043 host->order_status=STATE_CRITICAL; 1055 host->order_status = STATE_CRITICAL;
1044 } 1056 }
1045 host->last_tdiff=tdiff; 1057 host->last_tdiff = tdiff;
1046 1058
1047 host->last_icmp_seq=packet.icp->icmp_seq; 1059 host->last_icmp_seq = packet.icp->icmp_seq;
1048 1060
1049 host->time_waited += tdiff; 1061 host->time_waited += tdiff;
1050 host->icmp_recv++; 1062 host->icmp_recv++;
@@ -1054,39 +1066,29 @@ wait_for_reply(int sock, u_int t)
1054 if (tdiff < (unsigned int)host->rtmin) 1066 if (tdiff < (unsigned int)host->rtmin)
1055 host->rtmin = tdiff; 1067 host->rtmin = tdiff;
1056 1068
1057 if(debug) { 1069 if (debug) {
1058 char address[INET6_ADDRSTRLEN]; 1070 char address[INET6_ADDRSTRLEN];
1059 parse_address(&resp_addr, address, sizeof(address)); 1071 parse_address(&resp_addr, address, sizeof(address));
1060 1072
1061 switch(address_family) { 1073 switch (address_family) {
1062 case AF_INET: { 1074 case AF_INET: {
1063 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", 1075 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, address,
1064 (float)tdiff / 1000, 1076 ttl, ip->ip.ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000);
1065 address, 1077 break;
1066 ttl, 1078 };
1067 ip->ip.ip_ttl, 1079 case AF_INET6: {
1068 (float)host->rtmax / 1000, 1080 printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, address, ttl,
1069 (float)host->rtmin / 1000); 1081 (float)host->rtmax / 1000, (float)host->rtmin / 1000);
1070 break; 1082 };
1071 }; 1083 }
1072 case AF_INET6: {
1073 printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n",
1074 (float)tdiff / 1000,
1075 address,
1076 ttl,
1077 (float)host->rtmax / 1000,
1078 (float)host->rtmin / 1000);
1079 };
1080 }
1081 } 1084 }
1082 1085
1083 /* if we're in hostcheck mode, exit with limited printouts */ 1086 /* if we're in hostcheck mode, exit with limited printouts */
1084 if(mode == MODE_HOSTCHECK) { 1087 if (mode == MODE_HOSTCHECK) {
1085 printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|" 1088 printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|"
1086 "pkt=%u;;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n", 1089 "pkt=%u;;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n",
1087 host->name, icmp_recv, (float)tdiff / 1000, 1090 host->name, icmp_recv, (float)tdiff / 1000, icmp_recv, packets, (float)tdiff / 1000, (float)warn.rta / 1000,
1088 icmp_recv, packets, (float)tdiff / 1000, 1091 (float)crit.rta / 1000);
1089 (float)warn.rta / 1000, (float)crit.rta / 1000);
1090 exit(STATE_OK); 1092 exit(STATE_OK);
1091 } 1093 }
1092 } 1094 }
@@ -1096,9 +1098,7 @@ wait_for_reply(int sock, u_int t)
1096} 1098}
1097 1099
1098/* the ping functions */ 1100/* the ping functions */
1099static int 1101static int send_icmp_ping(int sock, struct rta_host *host) {
1100send_icmp_ping(int sock, struct rta_host *host)
1101{
1102 long int len; 1102 long int len;
1103 size_t addrlen; 1103 size_t addrlen;
1104 struct icmp_ping_data data; 1104 struct icmp_ping_data data;
@@ -1107,22 +1107,21 @@ send_icmp_ping(int sock, struct rta_host *host)
1107 struct timeval tv; 1107 struct timeval tv;
1108 void *buf = NULL; 1108 void *buf = NULL;
1109 1109
1110 if(sock == -1) { 1110 if (sock == -1) {
1111 errno = 0; 1111 errno = 0;
1112 crash("Attempt to send on bogus socket"); 1112 crash("Attempt to send on bogus socket");
1113 return -1; 1113 return -1;
1114 } 1114 }
1115 1115
1116 if(!buf) { 1116 if (!buf) {
1117 if (!(buf = malloc(icmp_pkt_size))) { 1117 if (!(buf = malloc(icmp_pkt_size))) {
1118 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", 1118 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size);
1119 icmp_pkt_size); 1119 return -1; /* might be reached if we're in debug mode */
1120 return -1; /* might be reached if we're in debug mode */
1121 } 1120 }
1122 } 1121 }
1123 memset(buf, 0, icmp_pkt_size); 1122 memset(buf, 0, icmp_pkt_size);
1124 1123
1125 if((gettimeofday(&tv, &tz)) == -1) { 1124 if ((gettimeofday(&tv, &tz)) == -1) {
1126 free(buf); 1125 free(buf);
1127 return -1; 1126 return -1;
1128 } 1127 }
@@ -1131,7 +1130,7 @@ send_icmp_ping(int sock, struct rta_host *host)
1131 memcpy(&data.stime, &tv, sizeof(tv)); 1130 memcpy(&data.stime, &tv, sizeof(tv));
1132 1131
1133 if (address_family == AF_INET) { 1132 if (address_family == AF_INET) {
1134 struct icmp *icp = (struct icmp*)buf; 1133 struct icmp *icp = (struct icmp *)buf;
1135 addrlen = sizeof(struct sockaddr_in); 1134 addrlen = sizeof(struct sockaddr_in);
1136 1135
1137 memcpy(&icp->icmp_data, &data, sizeof(data)); 1136 memcpy(&icp->icmp_data, &data, sizeof(data));
@@ -1141,14 +1140,13 @@ send_icmp_ping(int sock, struct rta_host *host)
1141 icp->icmp_cksum = 0; 1140 icp->icmp_cksum = 0;
1142 icp->icmp_id = htons(pid); 1141 icp->icmp_id = htons(pid);
1143 icp->icmp_seq = htons(host->id++); 1142 icp->icmp_seq = htons(host->id++);
1144 icp->icmp_cksum = icmp_checksum((uint16_t*)buf, (size_t)icmp_pkt_size); 1143 icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size);
1145 1144
1146 if (debug > 2) 1145 if (debug > 2)
1147 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 1146 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", (unsigned long)sizeof(data),
1148 (unsigned long)sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, host->name); 1147 ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, host->name);
1149 } 1148 } else {
1150 else { 1149 struct icmp6_hdr *icp6 = (struct icmp6_hdr *)buf;
1151 struct icmp6_hdr *icp6 = (struct icmp6_hdr*)buf;
1152 addrlen = sizeof(struct sockaddr_in6); 1150 addrlen = sizeof(struct sockaddr_in6);
1153 1151
1154 memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data)); 1152 memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data));
@@ -1161,9 +1159,8 @@ send_icmp_ping(int sock, struct rta_host *host)
1161 // let checksum be calculated automatically 1159 // let checksum be calculated automatically
1162 1160
1163 if (debug > 2) { 1161 if (debug > 2) {
1164 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 1162 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", (unsigned long)sizeof(data),
1165 (unsigned long)sizeof(data), ntohs(icp6->icmp6_id), 1163 ntohs(icp6->icmp6_id), ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name);
1166 ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name);
1167 } 1164 }
1168 } 1165 }
1169 1166
@@ -1188,8 +1185,8 @@ send_icmp_ping(int sock, struct rta_host *host)
1188 1185
1189 free(buf); 1186 free(buf);
1190 1187
1191 if(len < 0 || (unsigned int)len != icmp_pkt_size) { 1188 if (len < 0 || (unsigned int)len != icmp_pkt_size) {
1192 if(debug) { 1189 if (debug) {
1193 char address[INET6_ADDRSTRLEN]; 1190 char address[INET6_ADDRSTRLEN];
1194 parse_address((struct sockaddr_storage *)&host->saddr_in, address, sizeof(address)); 1191 parse_address((struct sockaddr_storage *)&host->saddr_in, address, sizeof(address));
1195 printf("Failed to send ping to %s: %s\n", address, strerror(errno)); 1192 printf("Failed to send ping to %s: %s\n", address, strerror(errno));
@@ -1204,10 +1201,7 @@ send_icmp_ping(int sock, struct rta_host *host)
1204 return 0; 1201 return 0;
1205} 1202}
1206 1203
1207static int 1204static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, u_int *timo, struct timeval *tv) {
1208recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1209 u_int *timo, struct timeval* tv)
1210{
1211 u_int slen; 1205 u_int slen;
1212 int n, ret; 1206 int n, ret;
1213 struct timeval to, then, now; 1207 struct timeval to, then, now;
@@ -1218,11 +1212,12 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1218 struct msghdr hdr; 1212 struct msghdr hdr;
1219 struct iovec iov; 1213 struct iovec iov;
1220#ifdef SO_TIMESTAMP 1214#ifdef SO_TIMESTAMP
1221 struct cmsghdr* chdr; 1215 struct cmsghdr *chdr;
1222#endif 1216#endif
1223 1217
1224 if(!*timo) { 1218 if (!*timo) {
1225 if(debug) printf("*timo is not\n"); 1219 if (debug)
1220 printf("*timo is not\n");
1226 return 0; 1221 return 0;
1227 } 1222 }
1228 1223
@@ -1235,11 +1230,13 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1235 errno = 0; 1230 errno = 0;
1236 gettimeofday(&then, &tz); 1231 gettimeofday(&then, &tz);
1237 n = select(sock + 1, &rd, &wr, NULL, &to); 1232 n = select(sock + 1, &rd, &wr, NULL, &to);
1238 if(n < 0) crash("select() in recvfrom_wto"); 1233 if (n < 0)
1234 crash("select() in recvfrom_wto");
1239 gettimeofday(&now, &tz); 1235 gettimeofday(&now, &tz);
1240 *timo = get_timevaldiff(&then, &now); 1236 *timo = get_timevaldiff(&then, &now);
1241 1237
1242 if(!n) return 0; /* timeout */ 1238 if (!n)
1239 return 0; /* timeout */
1243 1240
1244 slen = sizeof(struct sockaddr_storage); 1241 slen = sizeof(struct sockaddr_storage);
1245 1242
@@ -1259,12 +1256,10 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1259 1256
1260 ret = recvmsg(sock, &hdr, 0); 1257 ret = recvmsg(sock, &hdr, 0);
1261#ifdef SO_TIMESTAMP 1258#ifdef SO_TIMESTAMP
1262 for(chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { 1259 for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) {
1263 if(chdr->cmsg_level == SOL_SOCKET 1260 if (chdr->cmsg_level == SOL_SOCKET && chdr->cmsg_type == SO_TIMESTAMP && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) {
1264 && chdr->cmsg_type == SO_TIMESTAMP
1265 && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) {
1266 memcpy(tv, CMSG_DATA(chdr), sizeof(*tv)); 1261 memcpy(tv, CMSG_DATA(chdr), sizeof(*tv));
1267 break ; 1262 break;
1268 } 1263 }
1269 } 1264 }
1270 1265
@@ -1274,54 +1269,55 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1274 return (ret); 1269 return (ret);
1275} 1270}
1276 1271
1277static void 1272static void finish(int sig) {
1278finish(int sig)
1279{
1280 u_int i = 0; 1273 u_int i = 0;
1281 unsigned char pl; 1274 unsigned char pl;
1282 double rta; 1275 double rta;
1283 struct rta_host *host; 1276 struct rta_host *host;
1284 const char *status_string[] = 1277 const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
1285 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
1286 int hosts_ok = 0; 1278 int hosts_ok = 0;
1287 int hosts_warn = 0; 1279 int hosts_warn = 0;
1288 int this_status; 1280 int this_status;
1289 double R; 1281 double R;
1290 1282
1291 alarm(0); 1283 alarm(0);
1292 if(debug > 1) printf("finish(%d) called\n", sig); 1284 if (debug > 1)
1293 1285 printf("finish(%d) called\n", sig);
1294 if(icmp_sock != -1) close(icmp_sock); 1286
1295 if(udp_sock != -1) close(udp_sock); 1287 if (icmp_sock != -1)
1296 if(tcp_sock != -1) close(tcp_sock); 1288 close(icmp_sock);
1297 1289 if (udp_sock != -1)
1298 if(debug) { 1290 close(udp_sock);
1299 printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", 1291 if (tcp_sock != -1)
1300 icmp_sent, icmp_recv, icmp_lost); 1292 close(tcp_sock);
1293
1294 if (debug) {
1295 printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", icmp_sent, icmp_recv, icmp_lost);
1301 printf("targets: %u targets_alive: %u\n", targets, targets_alive); 1296 printf("targets: %u targets_alive: %u\n", targets, targets_alive);
1302 } 1297 }
1303 1298
1304 /* iterate thrice to calculate values, give output, and print perfparse */ 1299 /* iterate thrice to calculate values, give output, and print perfparse */
1305 status=STATE_OK; 1300 status = STATE_OK;
1306 host = list; 1301 host = list;
1307 1302
1308 while(host) { 1303 while (host) {
1309 this_status = STATE_OK; 1304 this_status = STATE_OK;
1310 1305
1311 if(!host->icmp_recv) { 1306 if (!host->icmp_recv) {
1312 /* rta 0 is ofcourse not entirely correct, but will still show up 1307 /* rta 0 is ofcourse not entirely correct, but will still show up
1313 * conspicuously as missing entries in perfparse and cacti */ 1308 * conspicuously as missing entries in perfparse and cacti */
1314 pl = 100; 1309 pl = 100;
1315 rta = 0; 1310 rta = 0;
1316 status = STATE_CRITICAL; 1311 status = STATE_CRITICAL;
1317 /* up the down counter if not already counted */ 1312 /* up the down counter if not already counted */
1318 if(!(host->flags & FLAG_LOST_CAUSE) && targets_alive) targets_down++; 1313 if (!(host->flags & FLAG_LOST_CAUSE) && targets_alive)
1314 targets_down++;
1319 } else { 1315 } else {
1320 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; 1316 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent;
1321 rta = (double)host->time_waited / host->icmp_recv; 1317 rta = (double)host->time_waited / host->icmp_recv;
1322 } 1318 }
1323 1319
1324 if (host->icmp_recv>1) { 1320 if (host->icmp_recv > 1) {
1325 /* 1321 /*
1326 * This algorithm is probably pretty much blindly copied from 1322 * This algorithm is probably pretty much blindly copied from
1327 * locations like this one: https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos 1323 * locations like this one: https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos
@@ -1336,19 +1332,19 @@ finish(int sig)
1336 * More links: 1332 * More links:
1337 * - https://confluence.slac.stanford.edu/display/IEPM/MOS 1333 * - https://confluence.slac.stanford.edu/display/IEPM/MOS
1338 */ 1334 */
1339 host->jitter=(host->jitter / (host->icmp_recv - 1)/1000); 1335 host->jitter = (host->jitter / (host->icmp_recv - 1) / 1000);
1340 1336
1341 /* 1337 /*
1342 * Take the average round trip latency (in milliseconds), add 1338 * Take the average round trip latency (in milliseconds), add
1343 * round trip jitter, but double the impact to latency 1339 * round trip jitter, but double the impact to latency
1344 * then add 10 for protocol latencies (in milliseconds). 1340 * then add 10 for protocol latencies (in milliseconds).
1345 */ 1341 */
1346 host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10; 1342 host->EffectiveLatency = (rta / 1000) + host->jitter * 2 + 10;
1347 1343
1348 if (host->EffectiveLatency < 160) { 1344 if (host->EffectiveLatency < 160) {
1349 R = 93.2 - (host->EffectiveLatency / 40); 1345 R = 93.2 - (host->EffectiveLatency / 40);
1350 } else { 1346 } else {
1351 R = 93.2 - ((host->EffectiveLatency - 120) / 10); 1347 R = 93.2 - ((host->EffectiveLatency - 120) / 10);
1352 } 1348 }
1353 1349
1354 // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a 1350 // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a
@@ -1360,12 +1356,12 @@ finish(int sig)
1360 } 1356 }
1361 1357
1362 host->score = R; 1358 host->score = R;
1363 host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R)); 1359 host->mos = 1 + ((0.035) * R) + ((.000007) * R * (R - 60) * (100 - R));
1364 } else { 1360 } else {
1365 host->jitter=0; 1361 host->jitter = 0;
1366 host->jitter_min=0; 1362 host->jitter_min = 0;
1367 host->jitter_max=0; 1363 host->jitter_max = 0;
1368 host->mos=0; 1364 host->mos = 0;
1369 } 1365 }
1370 1366
1371 host->pl = pl; 1367 host->pl = pl;
@@ -1379,62 +1375,62 @@ finish(int sig)
1379 1375
1380 /* Check which mode is on and do the warn / Crit stuff */ 1376 /* Check which mode is on and do the warn / Crit stuff */
1381 if (rta_mode) { 1377 if (rta_mode) {
1382 if(rta >= crit.rta) { 1378 if (rta >= crit.rta) {
1383 this_status = STATE_CRITICAL; 1379 this_status = STATE_CRITICAL;
1384 status = STATE_CRITICAL; 1380 status = STATE_CRITICAL;
1385 host->rta_status=STATE_CRITICAL; 1381 host->rta_status = STATE_CRITICAL;
1386 } else if(status!=STATE_CRITICAL && (rta >= warn.rta)) { 1382 } else if (status != STATE_CRITICAL && (rta >= warn.rta)) {
1387 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1383 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1388 status = STATE_WARNING; 1384 status = STATE_WARNING;
1389 host->rta_status=STATE_WARNING; 1385 host->rta_status = STATE_WARNING;
1390 } 1386 }
1391 } 1387 }
1392 1388
1393 if (pl_mode) { 1389 if (pl_mode) {
1394 if(pl >= crit.pl) { 1390 if (pl >= crit.pl) {
1395 this_status = STATE_CRITICAL; 1391 this_status = STATE_CRITICAL;
1396 status = STATE_CRITICAL; 1392 status = STATE_CRITICAL;
1397 host->pl_status=STATE_CRITICAL; 1393 host->pl_status = STATE_CRITICAL;
1398 } else if(status!=STATE_CRITICAL && (pl >= warn.pl)) { 1394 } else if (status != STATE_CRITICAL && (pl >= warn.pl)) {
1399 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1395 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1400 status = STATE_WARNING; 1396 status = STATE_WARNING;
1401 host->pl_status=STATE_WARNING; 1397 host->pl_status = STATE_WARNING;
1402 } 1398 }
1403 } 1399 }
1404 1400
1405 if (jitter_mode) { 1401 if (jitter_mode) {
1406 if(host->jitter >= crit.jitter) { 1402 if (host->jitter >= crit.jitter) {
1407 this_status = STATE_CRITICAL; 1403 this_status = STATE_CRITICAL;
1408 status = STATE_CRITICAL; 1404 status = STATE_CRITICAL;
1409 host->jitter_status=STATE_CRITICAL; 1405 host->jitter_status = STATE_CRITICAL;
1410 } else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) { 1406 } else if (status != STATE_CRITICAL && (host->jitter >= warn.jitter)) {
1411 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1407 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1412 status = STATE_WARNING; 1408 status = STATE_WARNING;
1413 host->jitter_status=STATE_WARNING; 1409 host->jitter_status = STATE_WARNING;
1414 } 1410 }
1415 } 1411 }
1416 1412
1417 if (mos_mode) { 1413 if (mos_mode) {
1418 if(host->mos <= crit.mos) { 1414 if (host->mos <= crit.mos) {
1419 this_status = STATE_CRITICAL; 1415 this_status = STATE_CRITICAL;
1420 status = STATE_CRITICAL; 1416 status = STATE_CRITICAL;
1421 host->mos_status=STATE_CRITICAL; 1417 host->mos_status = STATE_CRITICAL;
1422 } else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) { 1418 } else if (status != STATE_CRITICAL && (host->mos <= warn.mos)) {
1423 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1419 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1424 status = STATE_WARNING; 1420 status = STATE_WARNING;
1425 host->mos_status=STATE_WARNING; 1421 host->mos_status = STATE_WARNING;
1426 } 1422 }
1427 } 1423 }
1428 1424
1429 if (score_mode) { 1425 if (score_mode) {
1430 if(host->score <= crit.score) { 1426 if (host->score <= crit.score) {
1431 this_status = STATE_CRITICAL; 1427 this_status = STATE_CRITICAL;
1432 status = STATE_CRITICAL; 1428 status = STATE_CRITICAL;
1433 host->score_status=STATE_CRITICAL; 1429 host->score_status = STATE_CRITICAL;
1434 } else if(status!=STATE_CRITICAL && (host->score <= warn.score)) { 1430 } else if (status != STATE_CRITICAL && (host->score <= warn.score)) {
1435 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1431 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1436 status = STATE_WARNING; 1432 status = STATE_WARNING;
1437 host->score_status=STATE_WARNING; 1433 host->score_status = STATE_WARNING;
1438 } 1434 }
1439 } 1435 }
1440 1436
@@ -1447,91 +1443,92 @@ finish(int sig)
1447 host = host->next; 1443 host = host->next;
1448 } 1444 }
1449 1445
1450
1451 /* this is inevitable */ 1446 /* this is inevitable */
1452 if(!targets_alive) status = STATE_CRITICAL; 1447 if (!targets_alive)
1453 if(min_hosts_alive > -1) { 1448 status = STATE_CRITICAL;
1454 if(hosts_ok >= min_hosts_alive) status = STATE_OK; 1449 if (min_hosts_alive > -1) {
1455 else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING; 1450 if (hosts_ok >= min_hosts_alive)
1451 status = STATE_OK;
1452 else if ((hosts_ok + hosts_warn) >= min_hosts_alive)
1453 status = STATE_WARNING;
1456 } 1454 }
1457 printf("%s - ", status_string[status]); 1455 printf("%s - ", status_string[status]);
1458 1456
1459 host = list; 1457 host = list;
1460 while(host) { 1458 while (host) {
1461 1459
1462 if(debug) puts(""); 1460 if (debug)
1463 if(i) { 1461 puts("");
1464 if(i < targets) printf(" :: "); 1462 if (i) {
1465 else printf("\n"); 1463 if (i < targets)
1464 printf(" :: ");
1465 else
1466 printf("\n");
1466 } 1467 }
1467 i++; 1468 i++;
1468 if(!host->icmp_recv) { 1469 if (!host->icmp_recv) {
1469 status = STATE_CRITICAL; 1470 status = STATE_CRITICAL;
1470 host->rtmin=0; 1471 host->rtmin = 0;
1471 host->jitter_min=0; 1472 host->jitter_min = 0;
1472 if(host->flags & FLAG_LOST_CAUSE) { 1473 if (host->flags & FLAG_LOST_CAUSE) {
1473 char address[INET6_ADDRSTRLEN]; 1474 char address[INET6_ADDRSTRLEN];
1474 parse_address(&host->error_addr, address, sizeof(address)); 1475 parse_address(&host->error_addr, address, sizeof(address));
1475 printf("%s: %s @ %s. rta nan, lost %d%%", 1476 printf("%s: %s @ %s. rta nan, lost %d%%", host->name, get_icmp_error_msg(host->icmp_type, host->icmp_code), address, 100);
1476 host->name,
1477 get_icmp_error_msg(host->icmp_type, host->icmp_code),
1478 address,
1479 100);
1480 } else { /* not marked as lost cause, so we have no flags for it */ 1477 } else { /* not marked as lost cause, so we have no flags for it */
1481 printf("%s: rta nan, lost 100%%", host->name); 1478 printf("%s: rta nan, lost 100%%", host->name);
1482 } 1479 }
1483 } else { /* !icmp_recv */ 1480 } else { /* !icmp_recv */
1484 printf("%s", host->name); 1481 printf("%s", host->name);
1485 /* rta text output */ 1482 /* rta text output */
1486 if (rta_mode) { 1483 if (rta_mode) {
1487 if (status == STATE_OK) 1484 if (status == STATE_OK)
1488 printf(" rta %0.3fms", host->rta / 1000); 1485 printf(" rta %0.3fms", host->rta / 1000);
1489 else if (status==STATE_WARNING && host->rta_status==status) 1486 else if (status == STATE_WARNING && host->rta_status == status)
1490 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta/1000); 1487 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta / 1000);
1491 else if (status==STATE_CRITICAL && host->rta_status==status) 1488 else if (status == STATE_CRITICAL && host->rta_status == status)
1492 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta/1000); 1489 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta / 1000);
1493 } 1490 }
1494 /* pl text output */ 1491 /* pl text output */
1495 if (pl_mode) { 1492 if (pl_mode) {
1496 if (status == STATE_OK) 1493 if (status == STATE_OK)
1497 printf(" lost %u%%", host->pl); 1494 printf(" lost %u%%", host->pl);
1498 else if (status==STATE_WARNING && host->pl_status==status) 1495 else if (status == STATE_WARNING && host->pl_status == status)
1499 printf(" lost %u%% > %u%%", host->pl, warn.pl); 1496 printf(" lost %u%% > %u%%", host->pl, warn.pl);
1500 else if (status==STATE_CRITICAL && host->pl_status==status) 1497 else if (status == STATE_CRITICAL && host->pl_status == status)
1501 printf(" lost %u%% > %u%%", host->pl, crit.pl); 1498 printf(" lost %u%% > %u%%", host->pl, crit.pl);
1502 } 1499 }
1503 /* jitter text output */ 1500 /* jitter text output */
1504 if (jitter_mode) { 1501 if (jitter_mode) {
1505 if (status == STATE_OK) 1502 if (status == STATE_OK)
1506 printf(" jitter %0.3fms", (float)host->jitter); 1503 printf(" jitter %0.3fms", (float)host->jitter);
1507 else if (status==STATE_WARNING && host->jitter_status==status) 1504 else if (status == STATE_WARNING && host->jitter_status == status)
1508 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter); 1505 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter);
1509 else if (status==STATE_CRITICAL && host->jitter_status==status) 1506 else if (status == STATE_CRITICAL && host->jitter_status == status)
1510 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter); 1507 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter);
1511 } 1508 }
1512 /* mos text output */ 1509 /* mos text output */
1513 if (mos_mode) { 1510 if (mos_mode) {
1514 if (status == STATE_OK) 1511 if (status == STATE_OK)
1515 printf(" MOS %0.1f", (float)host->mos); 1512 printf(" MOS %0.1f", (float)host->mos);
1516 else if (status==STATE_WARNING && host->mos_status==status) 1513 else if (status == STATE_WARNING && host->mos_status == status)
1517 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos); 1514 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos);
1518 else if (status==STATE_CRITICAL && host->mos_status==status) 1515 else if (status == STATE_CRITICAL && host->mos_status == status)
1519 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos); 1516 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos);
1520 } 1517 }
1521 /* score text output */ 1518 /* score text output */
1522 if (score_mode) { 1519 if (score_mode) {
1523 if (status == STATE_OK) 1520 if (status == STATE_OK)
1524 printf(" Score %u", (int)host->score); 1521 printf(" Score %u", (int)host->score);
1525 else if (status==STATE_WARNING && host->score_status==status ) 1522 else if (status == STATE_WARNING && host->score_status == status)
1526 printf(" Score %u < %u", (int)host->score, (int)warn.score); 1523 printf(" Score %u < %u", (int)host->score, (int)warn.score);
1527 else if (status==STATE_CRITICAL && host->score_status==status ) 1524 else if (status == STATE_CRITICAL && host->score_status == status)
1528 printf(" Score %u < %u", (int)host->score, (int)crit.score); 1525 printf(" Score %u < %u", (int)host->score, (int)crit.score);
1529 } 1526 }
1530 /* order statis text output */ 1527 /* order statis text output */
1531 if (order_mode) { 1528 if (order_mode) {
1532 if (status == STATE_OK) 1529 if (status == STATE_OK)
1533 printf(" Packets in order"); 1530 printf(" Packets in order");
1534 else if (status==STATE_CRITICAL && host->order_status==status) 1531 else if (status == STATE_CRITICAL && host->order_status == status)
1535 printf(" Packets out of order"); 1532 printf(" Packets out of order");
1536 } 1533 }
1537 } 1534 }
@@ -1540,25 +1537,23 @@ finish(int sig)
1540 1537
1541 /* iterate once more for pretty perfparse output */ 1538 /* iterate once more for pretty perfparse output */
1542 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) { 1539 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) {
1543 printf("|"); 1540 printf("|");
1544 } 1541 }
1545 i = 0; 1542 i = 0;
1546 host = list; 1543 host = list;
1547 while(host) { 1544 while (host) {
1548 if(debug) puts(""); 1545 if (debug)
1546 puts("");
1549 1547
1550 if (rta_mode) { 1548 if (rta_mode) {
1551 if (host->pl<100) { 1549 if (host->pl < 100) {
1552 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", 1550 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", (targets > 1) ? host->name : "",
1553 (targets > 1) ? host->name : "", 1551 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, (targets > 1) ? host->name : "",
1554 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, 1552 (float)host->rtmax / 1000, (targets > 1) ? host->name : "",
1555 (targets > 1) ? host->name : "", (float)host->rtmax / 1000, 1553 (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0);
1556 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0);
1557 } else { 1554 } else {
1558 printf("%srta=U;;;; %srtmax=U;;;; %srtmin=U;;;; ", 1555 printf("%srta=U;;;; %srtmax=U;;;; %srtmin=U;;;; ", (targets > 1) ? host->name : "", (targets > 1) ? host->name : "",
1559 (targets > 1) ? host->name : "", 1556 (targets > 1) ? host->name : "");
1560 (targets > 1) ? host->name : "",
1561 (targets > 1) ? host->name : "");
1562 } 1557 }
1563 } 1558 }
1564 1559
@@ -1567,43 +1562,28 @@ finish(int sig)
1567 } 1562 }
1568 1563
1569 if (jitter_mode) { 1564 if (jitter_mode) {
1570 if (host->pl<100) { 1565 if (host->pl < 100) {
1571 printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ", 1566 printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ",
1572 (targets > 1) ? host->name : "", 1567 (targets > 1) ? host->name : "", (float)host->jitter, (float)warn.jitter, (float)crit.jitter,
1573 (float)host->jitter, 1568 (targets > 1) ? host->name : "", (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",
1574 (float)warn.jitter, 1569 (float)host->jitter_min / 1000);
1575 (float)crit.jitter,
1576 (targets > 1) ? host->name : "",
1577 (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",
1578 (float)host->jitter_min / 1000
1579 );
1580 } else { 1570 } else {
1581 printf("%sjitter_avg=U;;;; %sjitter_max=U;;;; %sjitter_min=U;;;; ", 1571 printf("%sjitter_avg=U;;;; %sjitter_max=U;;;; %sjitter_min=U;;;; ", (targets > 1) ? host->name : "",
1582 (targets > 1) ? host->name : "", 1572 (targets > 1) ? host->name : "", (targets > 1) ? host->name : "");
1583 (targets > 1) ? host->name : "",
1584 (targets > 1) ? host->name : "");
1585 } 1573 }
1586 } 1574 }
1587 1575
1588 if (mos_mode) { 1576 if (mos_mode) {
1589 if (host->pl<100) { 1577 if (host->pl < 100) {
1590 printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", 1578 printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (targets > 1) ? host->name : "", (float)host->mos, (float)warn.mos, (float)crit.mos);
1591 (targets > 1) ? host->name : "",
1592 (float)host->mos,
1593 (float)warn.mos,
1594 (float)crit.mos);
1595 } else { 1579 } else {
1596 printf("%smos=U;;;; ", (targets > 1) ? host->name : ""); 1580 printf("%smos=U;;;; ", (targets > 1) ? host->name : "");
1597 } 1581 }
1598 } 1582 }
1599 1583
1600 if (score_mode) { 1584 if (score_mode) {
1601 if (host->pl<100) { 1585 if (host->pl < 100) {
1602 printf("%sscore=%u;%u;%u;0;100 ", 1586 printf("%sscore=%u;%u;%u;0;100 ", (targets > 1) ? host->name : "", (int)host->score, (int)warn.score, (int)crit.score);
1603 (targets > 1) ? host->name : "",
1604 (int)host->score,
1605 (int)warn.score,
1606 (int)crit.score);
1607 } else { 1587 } else {
1608 printf("%sscore=U;;;; ", (targets > 1) ? host->name : ""); 1588 printf("%sscore=U;;;; ", (targets > 1) ? host->name : "");
1609 } 1589 }
@@ -1612,35 +1592,35 @@ finish(int sig)
1612 host = host->next; 1592 host = host->next;
1613 } 1593 }
1614 1594
1615 if(min_hosts_alive > -1) { 1595 if (min_hosts_alive > -1) {
1616 if(hosts_ok >= min_hosts_alive) status = STATE_OK; 1596 if (hosts_ok >= min_hosts_alive)
1617 else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING; 1597 status = STATE_OK;
1598 else if ((hosts_ok + hosts_warn) >= min_hosts_alive)
1599 status = STATE_WARNING;
1618 } 1600 }
1619 1601
1620 /* finish with an empty line */ 1602 /* finish with an empty line */
1621 puts(""); 1603 puts("");
1622 if(debug) printf("targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", 1604 if (debug)
1623 targets, targets_alive, hosts_ok, hosts_warn, min_hosts_alive); 1605 printf("targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", targets, targets_alive, hosts_ok,
1606 hosts_warn, min_hosts_alive);
1624 1607
1625 exit(status); 1608 exit(status);
1626} 1609}
1627 1610
1628static u_int 1611static u_int get_timevaldiff(struct timeval *early, struct timeval *later) {
1629get_timevaldiff(struct timeval *early, struct timeval *later)
1630{
1631 u_int ret; 1612 u_int ret;
1632 struct timeval now; 1613 struct timeval now;
1633 1614
1634 if(!later) { 1615 if (!later) {
1635 gettimeofday(&now, &tz); 1616 gettimeofday(&now, &tz);
1636 later = &now; 1617 later = &now;
1637 } 1618 }
1638 if(!early) early = &prog_start; 1619 if (!early)
1620 early = &prog_start;
1639 1621
1640 /* if early > later we return 0 so as to indicate a timeout */ 1622 /* if early > later we return 0 so as to indicate a timeout */
1641 if(early->tv_sec > later->tv_sec || 1623 if (early->tv_sec > later->tv_sec || (early->tv_sec == later->tv_sec && early->tv_usec > later->tv_usec)) {
1642 (early->tv_sec == later->tv_sec && early->tv_usec > later->tv_usec))
1643 {
1644 return 0; 1624 return 0;
1645 } 1625 }
1646 ret = (later->tv_sec - early->tv_sec) * 1000000; 1626 ret = (later->tv_sec - early->tv_sec) * 1000000;
@@ -1649,9 +1629,7 @@ get_timevaldiff(struct timeval *early, struct timeval *later)
1649 return ret; 1629 return ret;
1650} 1630}
1651 1631
1652static int 1632static int add_target_ip(char *arg, struct sockaddr_storage *in) {
1653add_target_ip(char *arg, struct sockaddr_storage *in)
1654{
1655 struct rta_host *host; 1633 struct rta_host *host;
1656 struct sockaddr_in *sin, *host_sin; 1634 struct sockaddr_in *sin, *host_sin;
1657 struct sockaddr_in6 *sin6, *host_sin6; 1635 struct sockaddr_in6 *sin6, *host_sin6;
@@ -1661,51 +1639,46 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1661 else 1639 else
1662 sin6 = (struct sockaddr_in6 *)in; 1640 sin6 = (struct sockaddr_in6 *)in;
1663 1641
1664
1665
1666 /* disregard obviously stupid addresses 1642 /* disregard obviously stupid addresses
1667 * (I didn't find an ipv6 equivalent to INADDR_NONE) */ 1643 * (I didn't find an ipv6 equivalent to INADDR_NONE) */
1668 if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE 1644 if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) ||
1669 || sin->sin_addr.s_addr == INADDR_ANY))) 1645 (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
1670 || (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
1671 return -1; 1646 return -1;
1672 } 1647 }
1673 1648
1674 /* no point in adding two identical IP's, so don't. ;) */ 1649 /* no point in adding two identical IP's, so don't. ;) */
1675 host = list; 1650 host = list;
1676 while(host) { 1651 while (host) {
1677 host_sin = (struct sockaddr_in *)&host->saddr_in; 1652 host_sin = (struct sockaddr_in *)&host->saddr_in;
1678 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; 1653 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
1679 1654
1680 if( (address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) 1655 if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) ||
1681 || (address_family == AF_INET6 && host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { 1656 (address_family == AF_INET6 && host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) {
1682 if(debug) printf("Identical IP already exists. Not adding %s\n", arg); 1657 if (debug)
1658 printf("Identical IP already exists. Not adding %s\n", arg);
1683 return -1; 1659 return -1;
1684 } 1660 }
1685 host = host->next; 1661 host = host->next;
1686 } 1662 }
1687 1663
1688 /* add the fresh ip */ 1664 /* add the fresh ip */
1689 host = (struct rta_host*)malloc(sizeof(struct rta_host)); 1665 host = (struct rta_host *)malloc(sizeof(struct rta_host));
1690 if(!host) { 1666 if (!host) {
1691 char straddr[INET6_ADDRSTRLEN]; 1667 char straddr[INET6_ADDRSTRLEN];
1692 parse_address((struct sockaddr_storage*)&in, straddr, sizeof(straddr)); 1668 parse_address((struct sockaddr_storage *)&in, straddr, sizeof(straddr));
1693 crash("add_target_ip(%s, %s): malloc(%lu) failed", 1669 crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(struct rta_host));
1694 arg, straddr, sizeof(struct rta_host));
1695 } 1670 }
1696 memset(host, 0, sizeof(struct rta_host)); 1671 memset(host, 0, sizeof(struct rta_host));
1697 1672
1698 /* set the values. use calling name for output */ 1673 /* set the values. use calling name for output */
1699 host->name = strdup(arg); 1674 host->name = strdup(arg);
1700 1675
1701
1702 /* fill out the sockaddr_storage struct */ 1676 /* fill out the sockaddr_storage struct */
1703 if(address_family == AF_INET) { 1677 if (address_family == AF_INET) {
1704 host_sin = (struct sockaddr_in *)&host->saddr_in; 1678 host_sin = (struct sockaddr_in *)&host->saddr_in;
1705 host_sin->sin_family = AF_INET; 1679 host_sin->sin_family = AF_INET;
1706 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr; 1680 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr;
1707 } 1681 } else {
1708 else {
1709 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; 1682 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
1710 host_sin6->sin6_family = AF_INET6; 1683 host_sin6->sin6_family = AF_INET6;
1711 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); 1684 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr);
@@ -1714,22 +1687,23 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1714 /* fill out the sockaddr_in struct */ 1687 /* fill out the sockaddr_in struct */
1715 host->rtmin = INFINITY; 1688 host->rtmin = INFINITY;
1716 host->rtmax = 0; 1689 host->rtmax = 0;
1717 host->jitter=0; 1690 host->jitter = 0;
1718 host->jitter_max=0; 1691 host->jitter_max = 0;
1719 host->jitter_min=INFINITY; 1692 host->jitter_min = INFINITY;
1720 host->last_tdiff=0; 1693 host->last_tdiff = 0;
1721 host->order_status=STATE_OK; 1694 host->order_status = STATE_OK;
1722 host->last_icmp_seq=0; 1695 host->last_icmp_seq = 0;
1723 host->rta_status=0; 1696 host->rta_status = 0;
1724 host->pl_status=0; 1697 host->pl_status = 0;
1725 host->jitter_status=0; 1698 host->jitter_status = 0;
1726 host->mos_status=0; 1699 host->mos_status = 0;
1727 host->score_status=0; 1700 host->score_status = 0;
1728 host->pl_status=0; 1701 host->pl_status = 0;
1729 1702
1730 1703 if (!list)
1731 if(!list) list = cursor = host; 1704 list = cursor = host;
1732 else cursor->next = host; 1705 else
1706 cursor->next = host;
1733 1707
1734 cursor = host; 1708 cursor = host;
1735 targets++; 1709 targets++;
@@ -1738,9 +1712,7 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1738} 1712}
1739 1713
1740/* wrapper for add_target_ip */ 1714/* wrapper for add_target_ip */
1741static int 1715static int add_target(char *arg) {
1742add_target(char *arg)
1743{
1744 int error, result = -1; 1716 int error, result = -1;
1745 struct sockaddr_storage ip; 1717 struct sockaddr_storage ip;
1746 struct addrinfo hints, *res, *p; 1718 struct addrinfo hints, *res, *p;
@@ -1754,14 +1726,14 @@ add_target(char *arg)
1754 sin = (struct sockaddr_in *)&ip; 1726 sin = (struct sockaddr_in *)&ip;
1755 result = inet_pton(address_family, arg, &sin->sin_addr); 1727 result = inet_pton(address_family, arg, &sin->sin_addr);
1756#ifdef USE_IPV6 1728#ifdef USE_IPV6
1757 if( result != 1 ){ 1729 if (result != 1) {
1758 address_family = AF_INET6; 1730 address_family = AF_INET6;
1759 sin6 = (struct sockaddr_in6 *)&ip; 1731 sin6 = (struct sockaddr_in6 *)&ip;
1760 result = inet_pton(address_family, arg, &sin6->sin6_addr); 1732 result = inet_pton(address_family, arg, &sin6->sin6_addr);
1761 } 1733 }
1762#endif 1734#endif
1763 /* If we don't find any valid addresses, we still don't know the address_family */ 1735 /* If we don't find any valid addresses, we still don't know the address_family */
1764 if ( result != 1) { 1736 if (result != 1) {
1765 address_family = -1; 1737 address_family = -1;
1766 } 1738 }
1767 break; 1739 break;
@@ -1773,15 +1745,15 @@ add_target(char *arg)
1773 sin6 = (struct sockaddr_in6 *)&ip; 1745 sin6 = (struct sockaddr_in6 *)&ip;
1774 result = inet_pton(address_family, arg, &sin6->sin6_addr); 1746 result = inet_pton(address_family, arg, &sin6->sin6_addr);
1775 break; 1747 break;
1776 default: crash("Address family not supported"); 1748 default:
1749 crash("Address family not supported");
1777 } 1750 }
1778 1751
1779 /* don't resolve if we don't have to */ 1752 /* don't resolve if we don't have to */
1780 if(result == 1) { 1753 if (result == 1) {
1781 /* don't add all ip's if we were given a specific one */ 1754 /* don't add all ip's if we were given a specific one */
1782 return add_target_ip(arg, &ip); 1755 return add_target_ip(arg, &ip);
1783 } 1756 } else {
1784 else {
1785 errno = 0; 1757 errno = 0;
1786 memset(&hints, 0, sizeof(hints)); 1758 memset(&hints, 0, sizeof(hints));
1787 if (address_family == -1) { 1759 if (address_family == -1) {
@@ -1790,7 +1762,7 @@ add_target(char *arg)
1790 hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6; 1762 hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6;
1791 } 1763 }
1792 hints.ai_socktype = SOCK_RAW; 1764 hints.ai_socktype = SOCK_RAW;
1793 if((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) { 1765 if ((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) {
1794 errno = 0; 1766 errno = 0;
1795 crash("Failed to resolve %s: %s", arg, gai_strerror(error)); 1767 crash("Failed to resolve %s: %s", arg, gai_strerror(error));
1796 return -1; 1768 return -1;
@@ -1799,13 +1771,14 @@ add_target(char *arg)
1799 } 1771 }
1800 1772
1801 /* possibly add all the IP's as targets */ 1773 /* possibly add all the IP's as targets */
1802 for(p = res; p != NULL; p = p->ai_next) { 1774 for (p = res; p != NULL; p = p->ai_next) {
1803 memcpy(&ip, p->ai_addr, p->ai_addrlen); 1775 memcpy(&ip, p->ai_addr, p->ai_addrlen);
1804 add_target_ip(arg, &ip); 1776 add_target_ip(arg, &ip);
1805 1777
1806 /* this is silly, but it works */ 1778 /* this is silly, but it works */
1807 if(mode == MODE_HOSTCHECK || mode == MODE_ALL) { 1779 if (mode == MODE_HOSTCHECK || mode == MODE_ALL) {
1808 if(debug > 2) printf("mode: %d\n", mode); 1780 if (debug > 2)
1781 printf("mode: %d\n", mode);
1809 continue; 1782 continue;
1810 } 1783 }
1811 break; 1784 break;
@@ -1815,24 +1788,20 @@ add_target(char *arg)
1815 return 0; 1788 return 0;
1816} 1789}
1817 1790
1818static void 1791static void set_source_ip(char *arg) {
1819set_source_ip(char *arg)
1820{
1821 struct sockaddr_in src; 1792 struct sockaddr_in src;
1822 1793
1823 memset(&src, 0, sizeof(src)); 1794 memset(&src, 0, sizeof(src));
1824 src.sin_family = address_family; 1795 src.sin_family = address_family;
1825 if((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) 1796 if ((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE)
1826 src.sin_addr.s_addr = get_ip_address(arg); 1797 src.sin_addr.s_addr = get_ip_address(arg);
1827 if(bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1) 1798 if (bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1)
1828 crash("Cannot bind to IP address %s", arg); 1799 crash("Cannot bind to IP address %s", arg);
1829} 1800}
1830 1801
1831/* TODO: Move this to netutils.c and also change check_dhcp to use that. */ 1802/* TODO: Move this to netutils.c and also change check_dhcp to use that. */
1832static in_addr_t 1803static in_addr_t get_ip_address(const char *ifname) {
1833get_ip_address(const char *ifname) 1804 // TODO: Rewrite this so the function return an error and we exit somewhere else
1834{
1835 // TODO: Rewrite this so the function return an error and we exit somewhere else
1836 struct sockaddr_in ip; 1805 struct sockaddr_in ip;
1837 ip.sin_addr.s_addr = 0; // Fake initialization to make compiler happy 1806 ip.sin_addr.s_addr = 0; // Fake initialization to make compiler happy
1838#if defined(SIOCGIFADDR) 1807#if defined(SIOCGIFADDR)
@@ -1842,12 +1811,12 @@ get_ip_address(const char *ifname)
1842 1811
1843 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; 1812 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
1844 1813
1845 if(ioctl(icmp_sock, SIOCGIFADDR, &ifr) == -1) 1814 if (ioctl(icmp_sock, SIOCGIFADDR, &ifr) == -1)
1846 crash("Cannot determine IP address of interface %s", ifname); 1815 crash("Cannot determine IP address of interface %s", ifname);
1847 1816
1848 memcpy(&ip, &ifr.ifr_addr, sizeof(ip)); 1817 memcpy(&ip, &ifr.ifr_addr, sizeof(ip));
1849#else 1818#else
1850 (void) ifname; 1819 (void)ifname;
1851 errno = 0; 1820 errno = 0;
1852 crash("Cannot get interface IP address on this platform."); 1821 crash("Cannot get interface IP address on this platform.");
1853#endif 1822#endif
@@ -1860,63 +1829,73 @@ get_ip_address(const char *ifname)
1860 * s = seconds 1829 * s = seconds
1861 * return value is in microseconds 1830 * return value is in microseconds
1862 */ 1831 */
1863static u_int 1832static u_int get_timevar(const char *str) {
1864get_timevar(const char *str)
1865{
1866 char p, u, *ptr; 1833 char p, u, *ptr;
1867 size_t len; 1834 size_t len;
1868 u_int i, d; /* integer and decimal, respectively */ 1835 u_int i, d; /* integer and decimal, respectively */
1869 u_int factor = 1000; /* default to milliseconds */ 1836 u_int factor = 1000; /* default to milliseconds */
1870 1837
1871 if(!str) return 0; 1838 if (!str)
1839 return 0;
1872 len = strlen(str); 1840 len = strlen(str);
1873 if(!len) return 0; 1841 if (!len)
1842 return 0;
1874 1843
1875 /* unit might be given as ms|m (millisec), 1844 /* unit might be given as ms|m (millisec),
1876 * us|u (microsec) or just plain s, for seconds */ 1845 * us|u (microsec) or just plain s, for seconds */
1877 p = '\0'; 1846 p = '\0';
1878 u = str[len - 1]; 1847 u = str[len - 1];
1879 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; 1848 if (len >= 2 && !isdigit((int)str[len - 2]))
1880 if(p && u == 's') u = p; 1849 p = str[len - 2];
1881 else if(!p) p = u; 1850 if (p && u == 's')
1882 if(debug > 2) printf("evaluating %s, u: %c, p: %c\n", str, u, p); 1851 u = p;
1883 1852 else if (!p)
1884 if(u == 'u') factor = 1; /* microseconds */ 1853 p = u;
1885 else if(u == 'm') factor = 1000; /* milliseconds */ 1854 if (debug > 2)
1886 else if(u == 's') factor = 1000000; /* seconds */ 1855 printf("evaluating %s, u: %c, p: %c\n", str, u, p);
1887 if(debug > 2) printf("factor is %u\n", factor); 1856
1857 if (u == 'u')
1858 factor = 1; /* microseconds */
1859 else if (u == 'm')
1860 factor = 1000; /* milliseconds */
1861 else if (u == 's')
1862 factor = 1000000; /* seconds */
1863 if (debug > 2)
1864 printf("factor is %u\n", factor);
1888 1865
1889 i = strtoul(str, &ptr, 0); 1866 i = strtoul(str, &ptr, 0);
1890 if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) 1867 if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1)
1891 return i * factor; 1868 return i * factor;
1892 1869
1893 /* time specified in usecs can't have decimal points, so ignore them */ 1870 /* time specified in usecs can't have decimal points, so ignore them */
1894 if(factor == 1) return i; 1871 if (factor == 1)
1872 return i;
1895 1873
1896 d = strtoul(ptr + 1, NULL, 0); 1874 d = strtoul(ptr + 1, NULL, 0);
1897 1875
1898 /* d is decimal, so get rid of excess digits */ 1876 /* d is decimal, so get rid of excess digits */
1899 while(d >= factor) d /= 10; 1877 while (d >= factor)
1878 d /= 10;
1900 1879
1901 /* the last parenthesis avoids floating point exceptions. */ 1880 /* the last parenthesis avoids floating point exceptions. */
1902 return ((i * factor) + (d * (factor / 10))); 1881 return ((i * factor) + (d * (factor / 10)));
1903} 1882}
1904 1883
1905/* not too good at checking errors, but it'll do (main() should barfe on -1) */ 1884/* not too good at checking errors, but it'll do (main() should barfe on -1) */
1906static int 1885static int get_threshold(char *str, threshold *th) {
1907get_threshold(char *str, threshold *th)
1908{
1909 char *p = NULL, i = 0; 1886 char *p = NULL, i = 0;
1910 1887
1911 if(!str || !strlen(str) || !th) return -1; 1888 if (!str || !strlen(str) || !th)
1889 return -1;
1912 1890
1913 /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */ 1891 /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */
1914 p = &str[strlen(str) - 1]; 1892 p = &str[strlen(str) - 1];
1915 while(p != &str[1]) { 1893 while (p != &str[1]) {
1916 if(*p == '%') *p = '\0'; 1894 if (*p == '%')
1917 else if(*p == ',' && i) { 1895 *p = '\0';
1918 *p = '\0'; /* reset it so get_timevar(str) works nicely later */ 1896 else if (*p == ',' && i) {
1919 th->pl = (unsigned char)strtoul(p+1, NULL, 0); 1897 *p = '\0'; /* reset it so get_timevar(str) works nicely later */
1898 th->pl = (unsigned char)strtoul(p + 1, NULL, 0);
1920 break; 1899 break;
1921 } 1900 }
1922 i = 1; 1901 i = 1;
@@ -1924,10 +1903,13 @@ get_threshold(char *str, threshold *th)
1924 } 1903 }
1925 th->rta = get_timevar(str); 1904 th->rta = get_timevar(str);
1926 1905
1927 if(!th->rta) return -1; 1906 if (!th->rta)
1907 return -1;
1928 1908
1929 if(th->rta > MAXTTL * 1000000) th->rta = MAXTTL * 1000000; 1909 if (th->rta > MAXTTL * 1000000)
1930 if(th->pl > 100) th->pl = 100; 1910 th->rta = MAXTTL * 1000000;
1911 if (th->pl > 100)
1912 th->pl = 100;
1931 1913
1932 return 0; 1914 return 0;
1933} 1915}
@@ -1943,8 +1925,8 @@ get_threshold(char *str, threshold *th)
1943 * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score (exclusively) 1925 * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score (exclusively)
1944 */ 1926 */
1945static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, threshold_mode mode) { 1927static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, threshold_mode mode) {
1946 if (!str || !length || !warn || !crit) return false; 1928 if (!str || !length || !warn || !crit)
1947 1929 return false;
1948 1930
1949 // p points to the last char in str 1931 // p points to the last char in str
1950 char *p = &str[length - 1]; 1932 char *p = &str[length - 1];
@@ -1952,18 +1934,17 @@ static bool get_threshold2(char *str, size_t length, threshold *warn, threshold
1952 // first_iteration is bof-stop on stupid libc's 1934 // first_iteration is bof-stop on stupid libc's
1953 bool first_iteration = true; 1935 bool first_iteration = true;
1954 1936
1955 while(p != &str[0]) { 1937 while (p != &str[0]) {
1956 if( (*p == 'm') || (*p == '%') ) { 1938 if ((*p == 'm') || (*p == '%')) {
1957 *p = '\0'; 1939 *p = '\0';
1958 } else if(*p == ',' && !first_iteration) { 1940 } else if (*p == ',' && !first_iteration) {
1959 *p = '\0'; /* reset it so get_timevar(str) works nicely later */ 1941 *p = '\0'; /* reset it so get_timevar(str) works nicely later */
1960 1942
1961 char *start_of_value = p + 1; 1943 char *start_of_value = p + 1;
1962 1944
1963 if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)){ 1945 if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)) {
1964 return false; 1946 return false;
1965 } 1947 }
1966
1967 } 1948 }
1968 first_iteration = false; 1949 first_iteration = false;
1969 p--; 1950 p--;
@@ -1976,22 +1957,22 @@ static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, thre
1976 char *resultChecker = {0}; 1957 char *resultChecker = {0};
1977 1958
1978 switch (mode) { 1959 switch (mode) {
1979 case const_rta_mode: 1960 case const_rta_mode:
1980 thr->rta = strtod(s, &resultChecker) * 1000; 1961 thr->rta = strtod(s, &resultChecker) * 1000;
1981 break; 1962 break;
1982 case const_packet_loss_mode: 1963 case const_packet_loss_mode:
1983 thr->pl = (unsigned char)strtoul(s, &resultChecker, 0); 1964 thr->pl = (unsigned char)strtoul(s, &resultChecker, 0);
1984 break; 1965 break;
1985 case const_jitter_mode: 1966 case const_jitter_mode:
1986 thr->jitter = strtod(s, &resultChecker); 1967 thr->jitter = strtod(s, &resultChecker);
1987 1968
1988 break; 1969 break;
1989 case const_mos_mode: 1970 case const_mos_mode:
1990 thr->mos = strtod(s, &resultChecker); 1971 thr->mos = strtod(s, &resultChecker);
1991 break; 1972 break;
1992 case const_score_mode: 1973 case const_score_mode:
1993 thr->score = strtod(s, &resultChecker); 1974 thr->score = strtod(s, &resultChecker);
1994 break; 1975 break;
1995 } 1976 }
1996 1977
1997 if (resultChecker == s) { 1978 if (resultChecker == s) {
@@ -2007,123 +1988,116 @@ static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, thre
2007 return true; 1988 return true;
2008} 1989}
2009 1990
2010unsigned short 1991unsigned short icmp_checksum(uint16_t *p, size_t n) {
2011icmp_checksum(uint16_t *p, size_t n)
2012{
2013 unsigned short cksum; 1992 unsigned short cksum;
2014 long sum = 0; 1993 long sum = 0;
2015 1994
2016 /* sizeof(uint16_t) == 2 */ 1995 /* sizeof(uint16_t) == 2 */
2017 while(n >= 2) { 1996 while (n >= 2) {
2018 sum += *(p++); 1997 sum += *(p++);
2019 n -= 2; 1998 n -= 2;
2020 } 1999 }
2021 2000
2022 /* mop up the occasional odd byte */ 2001 /* mop up the occasional odd byte */
2023 if(n == 1) sum += *((uint8_t *)p -1); 2002 if (n == 1)
2003 sum += *((uint8_t *)p - 1);
2024 2004
2025 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 2005 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
2026 sum += (sum >> 16); /* add carry */ 2006 sum += (sum >> 16); /* add carry */
2027 cksum = ~sum; /* ones-complement, trunc to 16 bits */ 2007 cksum = ~sum; /* ones-complement, trunc to 16 bits */
2028 2008
2029 return cksum; 2009 return cksum;
2030} 2010}
2031 2011
2032void 2012void print_help(void) {
2033print_help(void)
2034{
2035 /*print_revision (progname);*/ /* FIXME: Why? */ 2013 /*print_revision (progname);*/ /* FIXME: Why? */
2036 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n"); 2014 printf("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n");
2037 2015
2038 printf (COPYRIGHT, copyright, email); 2016 printf(COPYRIGHT, copyright, email);
2039 2017
2040 printf ("\n\n"); 2018 printf("\n\n");
2041 2019
2042 print_usage (); 2020 print_usage();
2043 2021
2044 printf (UT_HELP_VRSN); 2022 printf(UT_HELP_VRSN);
2045 printf (UT_EXTRA_OPTS); 2023 printf(UT_EXTRA_OPTS);
2046 2024
2047 printf (" %s\n", "-H"); 2025 printf(" %s\n", "-H");
2048 printf (" %s\n", _("specify a target")); 2026 printf(" %s\n", _("specify a target"));
2049 printf (" %s\n", "[-4|-6]"); 2027 printf(" %s\n", "[-4|-6]");
2050 printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets")); 2028 printf(" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets"));
2051 printf (" %s\n", "-w"); 2029 printf(" %s\n", "-w");
2052 printf (" %s", _("warning threshold (currently ")); 2030 printf(" %s", _("warning threshold (currently "));
2053 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); 2031 printf("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl);
2054 printf (" %s\n", "-c"); 2032 printf(" %s\n", "-c");
2055 printf (" %s", _("critical threshold (currently ")); 2033 printf(" %s", _("critical threshold (currently "));
2056 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); 2034 printf("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl);
2057 2035
2058 printf (" %s\n", "-R"); 2036 printf(" %s\n", "-R");
2059 printf (" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms")); 2037 printf(" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"));
2060 printf (" %s\n", "-P"); 2038 printf(" %s\n", "-P");
2061 printf (" %s\n", _("packet loss mode, ex. 40%,50% , unit in %")); 2039 printf(" %s\n", _("packet loss mode, ex. 40%,50% , unit in %"));
2062 printf (" %s\n", "-J"); 2040 printf(" %s\n", "-J");
2063 printf (" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms ")); 2041 printf(" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "));
2064 printf (" %s\n", "-M"); 2042 printf(" %s\n", "-M");
2065 printf (" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0")); 2043 printf(" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"));
2066 printf (" %s\n", "-S"); 2044 printf(" %s\n", "-S");
2067 printf (" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 ")); 2045 printf(" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 "));
2068 printf (" %s\n", "-O"); 2046 printf(" %s\n", "-O");
2069 printf (" %s\n", _("detect out of order ICMP packts ")); 2047 printf(" %s\n", _("detect out of order ICMP packts "));
2070 printf (" %s\n", "-H"); 2048 printf(" %s\n", "-H");
2071 printf (" %s\n", _("specify a target")); 2049 printf(" %s\n", _("specify a target"));
2072 printf (" %s\n", "-s"); 2050 printf(" %s\n", "-s");
2073 printf (" %s\n", _("specify a source IP address or device name")); 2051 printf(" %s\n", _("specify a source IP address or device name"));
2074 printf (" %s\n", "-n"); 2052 printf(" %s\n", "-n");
2075 printf (" %s", _("number of packets to send (currently ")); 2053 printf(" %s", _("number of packets to send (currently "));
2076 printf ("%u)\n",packets); 2054 printf("%u)\n", packets);
2077 printf (" %s\n", "-p"); 2055 printf(" %s\n", "-p");
2078 printf (" %s", _("number of packets to send (currently ")); 2056 printf(" %s", _("number of packets to send (currently "));
2079 printf ("%u)\n",packets); 2057 printf("%u)\n", packets);
2080 printf (" %s\n", "-i"); 2058 printf(" %s\n", "-i");
2081 printf (" %s", _("max packet interval (currently ")); 2059 printf(" %s", _("max packet interval (currently "));
2082 printf ("%0.3fms)\n",(float)pkt_interval / 1000); 2060 printf("%0.3fms)\n", (float)pkt_interval / 1000);
2083 printf (" %s\n", "-I"); 2061 printf(" %s\n", "-I");
2084 printf (" %s", _("max target interval (currently ")); 2062 printf(" %s", _("max target interval (currently "));
2085 printf ("%0.3fms)\n", (float)target_interval / 1000); 2063 printf("%0.3fms)\n", (float)target_interval / 1000);
2086 printf (" %s\n", "-m"); 2064 printf(" %s\n", "-m");
2087 printf (" %s",_("number of alive hosts required for success")); 2065 printf(" %s", _("number of alive hosts required for success"));
2088 printf ("\n"); 2066 printf("\n");
2089 printf (" %s\n", "-l"); 2067 printf(" %s\n", "-l");
2090 printf (" %s", _("TTL on outgoing packets (currently ")); 2068 printf(" %s", _("TTL on outgoing packets (currently "));
2091 printf ("%u)\n", ttl); 2069 printf("%u)\n", ttl);
2092 printf (" %s\n", "-t"); 2070 printf(" %s\n", "-t");
2093 printf (" %s",_("timeout value (seconds, currently ")); 2071 printf(" %s", _("timeout value (seconds, currently "));
2094 printf ("%u)\n", timeout); 2072 printf("%u)\n", timeout);
2095 printf (" %s\n", "-b"); 2073 printf(" %s\n", "-b");
2096 printf (" %s\n", _("Number of icmp data bytes to send")); 2074 printf(" %s\n", _("Number of icmp data bytes to send"));
2097 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); 2075 printf(" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"), icmp_data_size, ICMP_MINLEN);
2098 printf (" %s\n", "-v"); 2076 printf(" %s\n", "-v");
2099 printf (" %s\n", _("verbose")); 2077 printf(" %s\n", _("verbose"));
2100 printf ("\n"); 2078 printf("\n");
2101 printf ("%s\n", _("Notes:")); 2079 printf("%s\n", _("Notes:"));
2102 printf (" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P")); 2080 printf(" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P"));
2103 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); 2081 printf(" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
2104 printf ("\n"); 2082 printf("\n");
2105 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); 2083 printf(" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));
2106 printf (" %s\n", _("packet loss. The default values should work well for most users.")); 2084 printf(" %s\n", _("packet loss. The default values should work well for most users."));
2107 printf (" %s\n", _("You can specify different RTA factors using the standardized abbreviations")); 2085 printf(" %s\n", _("You can specify different RTA factors using the standardized abbreviations"));
2108 printf (" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds.")); 2086 printf(" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds."));
2109 /* -d not yet implemented */ 2087 /* -d not yet implemented */
2110 /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops")); 2088 /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops"));
2111 printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent.")); 2089 printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent."));
2112 printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/ 2090 printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/
2113 printf ("\n"); 2091 printf("\n");
2114 printf (" %s\n", _("The -v switch can be specified several times for increased verbosity.")); 2092 printf(" %s\n", _("The -v switch can be specified several times for increased verbosity."));
2115 /* printf ("%s\n", _("Long options are currently unsupported.")); 2093 /* printf ("%s\n", _("Long options are currently unsupported."));
2116 printf ("%s\n", _("Options marked with * require an argument")); 2094 printf ("%s\n", _("Options marked with * require an argument"));
2117 */ 2095 */
2118 2096
2119 printf (UT_SUPPORT); 2097 printf(UT_SUPPORT);
2120} 2098}
2121 2099
2122 2100void print_usage(void) {
2123 2101 printf("%s\n", _("Usage:"));
2124void
2125print_usage (void)
2126{
2127 printf ("%s\n", _("Usage:"));
2128 printf(" %s [options] [-H] host1 host2 hostN\n", progname); 2102 printf(" %s [options] [-H] host1 host2 hostN\n", progname);
2129} 2103}
diff --git a/plugins-scripts/check_ifstatus.pl b/plugins-scripts/check_ifstatus.pl
index 38b87fcc..f0b7c491 100755
--- a/plugins-scripts/check_ifstatus.pl
+++ b/plugins-scripts/check_ifstatus.pl
@@ -97,11 +97,12 @@ my $opt_V ;
97my $opt_u; 97my $opt_u;
98my $opt_n; 98my $opt_n;
99my $opt_x ; 99my $opt_x ;
100my $opt_d;
100my %excluded ; 101my %excluded ;
101my %unused_names ; 102my %unused_names ;
102my @unused_ports ; 103my @unused_ports ;
103my %session_opts; 104my %session_opts;
104 105my @exclude_descriptions;
105 106
106 107
107 108
@@ -134,6 +135,7 @@ if (!defined($session)) {
134} 135}
135 136
136 137
138push(@snmpoids,$snmpLocIfDescr);
137push(@snmpoids,$snmpIfOperStatus); 139push(@snmpoids,$snmpIfOperStatus);
138push(@snmpoids,$snmpIfAdminStatus); 140push(@snmpoids,$snmpIfAdminStatus);
139push(@snmpoids,$snmpIfDescr); 141push(@snmpoids,$snmpIfDescr);
@@ -180,18 +182,28 @@ foreach $key (keys %ifStatus) {
180 if ($ifStatus{$key}{$snmpIfAdminStatus} == 1 ) { 182 if ($ifStatus{$key}{$snmpIfAdminStatus} == 1 ) {
181 #check only if interface is not excluded 183 #check only if interface is not excluded
182 if (!defined $unused_names{$ifStatus{$key}{$snmpIfDescr}} ) { 184 if (!defined $unused_names{$ifStatus{$key}{$snmpIfDescr}} ) {
183 # check only if interface type is not listed in %excluded 185 #check only if interface is not excluded (by description)
184 if (!defined $excluded{$ifStatus{$key}{$snmpIfType}} ) { 186 #counter for matching descriptions
185 if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ; } 187 my $match_descr = 0;
186 if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) { 188 foreach my $description (@exclude_descriptions) {
187 $ifdown++ ; 189 if ($ifStatus{$key}{$snmpLocIfDescr} =~ /^$description/) { $match_descr = 1; }
188 if (defined $ifXTable) { 190 }
189 $ifmessage .= sprintf("%s: down -> %s<BR>\n", $ifStatus{$key}{$snmpIfName}, $ifStatus{$key}{$snmpIfAlias}); 191 if ($match_descr == 0) {
190 }else{ 192 # check only if interface type is not listed in %excluded
191 $ifmessage .= sprintf("%s: down <BR>\n",$ifStatus{$key}{$snmpIfDescr}); 193 if (!defined $excluded{$ifStatus{$key}{$snmpIfType}} ) {
192 } 194 if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ; }
195 if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) {
196 $ifdown++ ;
197 if (defined $ifXTable) {
198 $ifmessage .= sprintf("%s: down -> %s<BR>\n", $ifStatus{$key}{$snmpIfName}, $ifStatus{$key}{$snmpIfAlias});
199 }else{
200 $ifmessage .= sprintf("%s: down <BR>\n",$ifStatus{$key}{$snmpIfDescr});
201 }
202 }
203 if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;}
204 } else {
205 $ifexclude++;
193 } 206 }
194 if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;}
195 } else { 207 } else {
196 $ifexclude++; 208 $ifexclude++;
197 } 209 }
@@ -264,6 +276,9 @@ sub print_help() {
264 printf " the descriptive name. Do not use if you don't know what this is. \n"; 276 printf " the descriptive name. Do not use if you don't know what this is. \n";
265 printf " -x (--exclude) A comma separated list of ifType values that should be excluded \n"; 277 printf " -x (--exclude) A comma separated list of ifType values that should be excluded \n";
266 printf " from the report (default for an empty list is PPP(23).\n"; 278 printf " from the report (default for an empty list is PPP(23).\n";
279 printf " -d (--exclude_ports_by_description) A comma separated list of LocIfDescr values that should be excluded \n";
280 printf " from the report (default is an empty exclusion list). Done using regexp '/^arg/', ex:\n";
281 printf " '-d connect,test' will match with descriptions like 'testing phase' but not 'in testing'.\n";
267 printf " -n (--unused_ports_by_name) A comma separated list of ifDescr values that should be excluded \n"; 282 printf " -n (--unused_ports_by_name) A comma separated list of ifDescr values that should be excluded \n";
268 printf " from the report (default is an empty exclusion list).\n"; 283 printf " from the report (default is an empty exclusion list).\n";
269 printf " -u (--unused_ports) A comma separated list of ifIndex values that should be excluded \n"; 284 printf " -u (--unused_ports) A comma separated list of ifIndex values that should be excluded \n";
@@ -306,6 +321,7 @@ sub process_arguments() {
306 "I" => \$ifXTable, "ifmib" => \$ifXTable, 321 "I" => \$ifXTable, "ifmib" => \$ifXTable,
307 "x:s" => \$opt_x, "exclude:s" => \$opt_x, 322 "x:s" => \$opt_x, "exclude:s" => \$opt_x,
308 "u=s" => \$opt_u, "unused_ports=s" => \$opt_u, 323 "u=s" => \$opt_u, "unused_ports=s" => \$opt_u,
324 "d=s" => \$opt_d, "exclude_ports_by_description=s" => \$opt_d,
309 "n=s" => \$opt_n, "unused_ports_by_name=s" => \$opt_n, 325 "n=s" => \$opt_n, "unused_ports_by_name=s" => \$opt_n,
310 "M=i" => \$maxmsgsize, "maxmsgsize=i" => \$maxmsgsize, 326 "M=i" => \$maxmsgsize, "maxmsgsize=i" => \$maxmsgsize,
311 "t=i" => \$timeout, "timeout=i" => \$timeout, 327 "t=i" => \$timeout, "timeout=i" => \$timeout,
@@ -414,6 +430,11 @@ sub process_arguments() {
414 } 430 }
415 } 431 }
416 432
433 # Exclude interfaces by descriptions
434 if (defined $opt_d) {
435 @exclude_descriptions = split(/,/,$opt_d);
436 }
437
417 # Excluded interface descriptors 438 # Excluded interface descriptors
418 if (defined $opt_n) { 439 if (defined $opt_n) {
419 my @unused = split(/,/,$opt_n); 440 my @unused = split(/,/,$opt_n);
diff --git a/plugins/check_apt.c b/plugins/check_apt.c
index 5c0f6e28..5e4021b5 100644
--- a/plugins/check_apt.c
+++ b/plugins/check_apt.c
@@ -3,7 +3,7 @@
3* Monitoring check_apt plugin 3* Monitoring check_apt plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2006-2008 Monitoring Plugins Development Team 6* Copyright (c) 2006-2024 Monitoring Plugins Development Team
7* 7*
8* Original author: Sean Finney 8* Original author: Sean Finney
9* 9*
@@ -30,7 +30,7 @@
30*****************************************************************************/ 30*****************************************************************************/
31 31
32const char *progname = "check_apt"; 32const char *progname = "check_apt";
33const char *copyright = "2006-2008"; 33const char *copyright = "2006-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
diff --git a/plugins/check_by_ssh.c b/plugins/check_by_ssh.c
index 2a23b397..905b2393 100644
--- a/plugins/check_by_ssh.c
+++ b/plugins/check_by_ssh.c
@@ -1,33 +1,33 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_by_ssh plugin 3 * Monitoring check_by_ssh plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_by_ssh plugin 10 * This file contains the check_by_ssh plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29const char *progname = "check_by_ssh"; 29const char *progname = "check_by_ssh";
30const char *copyright = "2000-2008"; 30const char *copyright = "2000-2024";
31const char *email = "devel@monitoring-plugins.org"; 31const char *email = "devel@monitoring-plugins.org";
32 32
33#include "common.h" 33#include "common.h"
@@ -36,82 +36,80 @@ const char *email = "devel@monitoring-plugins.org";
36#include "utils_cmd.h" 36#include "utils_cmd.h"
37 37
38#ifndef NP_MAXARGS 38#ifndef NP_MAXARGS
39#define NP_MAXARGS 1024 39# define NP_MAXARGS 1024
40#endif 40#endif
41 41
42int process_arguments (int, char **); 42static int process_arguments(int /*argc*/, char ** /*argv*/);
43int validate_arguments (void); 43static int validate_arguments(void);
44void comm_append (const char *); 44static void comm_append(const char * /*str*/);
45void print_help (void); 45static void print_help(void);
46void print_usage (void); 46void print_usage(void);
47 47
48unsigned int commands = 0; 48static unsigned int commands = 0;
49unsigned int services = 0; 49static unsigned int services = 0;
50int skip_stdout = 0; 50static int skip_stdout = 0;
51int skip_stderr = 0; 51static int skip_stderr = 0;
52int warn_on_stderr = 0; 52static int warn_on_stderr = 0;
53bool unknown_timeout = false; 53static bool unknown_timeout = false;
54char *remotecmd = NULL; 54static char *remotecmd = NULL;
55char **commargv = NULL; 55static char **commargv = NULL;
56int commargc = 0; 56static int commargc = 0;
57char *hostname = NULL; 57static char *hostname = NULL;
58char *outputfile = NULL; 58static char *outputfile = NULL;
59char *host_shortname = NULL; 59static char *host_shortname = NULL;
60char **service; 60static char **service;
61bool passive = false; 61static bool passive = false;
62bool verbose = false; 62static bool verbose = false;
63 63
64int 64int main(int argc, char **argv) {
65main (int argc, char **argv)
66{
67 65
68 char *status_text; 66 char *status_text;
69 int cresult; 67 int cresult;
70 int result = STATE_UNKNOWN; 68 int result = STATE_UNKNOWN;
71 time_t local_time; 69 time_t local_time;
72 FILE *fp = NULL; 70 FILE *file_pointer = NULL;
73 output chld_out, chld_err; 71 output chld_out;
72 output chld_err;
74 73
75 remotecmd = ""; 74 remotecmd = "";
76 comm_append(SSH_COMMAND); 75 comm_append(SSH_COMMAND);
77 76
78 setlocale (LC_ALL, ""); 77 setlocale(LC_ALL, "");
79 bindtextdomain (PACKAGE, LOCALEDIR); 78 bindtextdomain(PACKAGE, LOCALEDIR);
80 textdomain (PACKAGE); 79 textdomain(PACKAGE);
81 80
82 /* Parse extra opts if any */ 81 /* Parse extra opts if any */
83 argv=np_extra_opts (&argc, argv, progname); 82 argv = np_extra_opts(&argc, argv, progname);
84 83
85 /* process arguments */ 84 /* process arguments */
86 if (process_arguments (argc, argv) == ERROR) 85 if (process_arguments(argc, argv) == ERROR)
87 usage_va(_("Could not parse arguments")); 86 usage_va(_("Could not parse arguments"));
88 87
89 /* Set signal handling and alarm timeout */ 88 /* Set signal handling and alarm timeout */
90 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 89 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
91 usage_va(_("Cannot catch SIGALRM")); 90 usage_va(_("Cannot catch SIGALRM"));
92 } 91 }
93 alarm (timeout_interval); 92 alarm(timeout_interval);
94 93
95 /* run the command */ 94 /* run the command */
96 if (verbose) { 95 if (verbose) {
97 printf ("Command: %s\n", commargv[0]); 96 printf("Command: %s\n", commargv[0]);
98 for (int i = 1; i < commargc; i++) 97 for (int i = 1; i < commargc; i++)
99 printf ("Argument %i: %s\n", i, commargv[i]); 98 printf("Argument %i: %s\n", i, commargv[i]);
100 } 99 }
101 100
102 result = cmd_run_array (commargv, &chld_out, &chld_err, 0); 101 result = cmd_run_array(commargv, &chld_out, &chld_err, 0);
103 102
104 /* SSH returns 255 if connection attempt fails; include the first line of error output */ 103 /* SSH returns 255 if connection attempt fails; include the first line of error output */
105 if (result == 255 && unknown_timeout) { 104 if (result == 255 && unknown_timeout) {
106 printf (_("SSH connection failed: %s\n"), 105 printf(_("SSH connection failed: %s\n"), chld_err.lines > 0 ? chld_err.line[0] : "(no error output)");
107 chld_err.lines > 0 ? chld_err.line[0] : "(no error output)");
108 return STATE_UNKNOWN; 106 return STATE_UNKNOWN;
109 } 107 }
110 108
111 if (verbose) { 109 if (verbose) {
112 for(size_t i = 0; i < chld_out.lines; i++) 110 for (size_t i = 0; i < chld_out.lines; i++)
113 printf("stdout: %s\n", chld_out.line[i]); 111 printf("stdout: %s\n", chld_out.line[i]);
114 for(size_t i = 0; i < chld_err.lines; i++) 112 for (size_t i = 0; i < chld_err.lines; i++)
115 printf("stderr: %s\n", chld_err.line[i]); 113 printf("stderr: %s\n", chld_err.line[i]);
116 } 114 }
117 115
@@ -121,155 +119,144 @@ main (int argc, char **argv)
121 skip_stderr = chld_err.lines; 119 skip_stderr = chld_err.lines;
122 120
123 /* UNKNOWN or worse if (non-skipped) output found on stderr */ 121 /* UNKNOWN or worse if (non-skipped) output found on stderr */
124 if(chld_err.lines > (size_t)skip_stderr) { 122 if (chld_err.lines > (size_t)skip_stderr) {
125 printf (_("Remote command execution failed: %s\n"), 123 printf(_("Remote command execution failed: %s\n"), chld_err.line[skip_stderr]);
126 chld_err.line[skip_stderr]); 124 if (warn_on_stderr)
127 if ( warn_on_stderr )
128 return max_state_alt(result, STATE_WARNING); 125 return max_state_alt(result, STATE_WARNING);
129 else 126 return max_state_alt(result, STATE_UNKNOWN);
130 return max_state_alt(result, STATE_UNKNOWN);
131 } 127 }
132 128
133 /* this is simple if we're not supposed to be passive. 129 /* this is simple if we're not supposed to be passive.
134 * Wrap up quickly and keep the tricks below */ 130 * Wrap up quickly and keep the tricks below */
135 if(!passive) { 131 if (!passive) {
136 if (chld_out.lines > (size_t)skip_stdout) 132 if (chld_out.lines > (size_t)skip_stdout)
137 for (size_t i = skip_stdout; i < chld_out.lines; i++) 133 for (size_t i = skip_stdout; i < chld_out.lines; i++)
138 puts (chld_out.line[i]); 134 puts(chld_out.line[i]);
139 else 135 else
140 printf (_("%s - check_by_ssh: Remote command '%s' returned status %d\n"), 136 printf(_("%s - check_by_ssh: Remote command '%s' returned status %d\n"), state_text(result), remotecmd, result);
141 state_text(result), remotecmd, result); 137 return result; /* return error status from remote command */
142 return result; /* return error status from remote command */
143 } 138 }
144 139
145
146 /* 140 /*
147 * Passive mode 141 * Passive mode
148 */ 142 */
149 143
150 /* process output */ 144 /* process output */
151 if (!(fp = fopen (outputfile, "a"))) { 145 if (!(file_pointer = fopen(outputfile, "a"))) {
152 printf (_("SSH WARNING: could not open %s\n"), outputfile); 146 printf(_("SSH WARNING: could not open %s\n"), outputfile);
153 exit (STATE_UNKNOWN); 147 exit(STATE_UNKNOWN);
154 } 148 }
155 149
156 local_time = time (NULL); 150 local_time = time(NULL);
157 commands = 0; 151 commands = 0;
158 for(size_t i = skip_stdout; i < chld_out.lines; i++) { 152 for (size_t i = skip_stdout; i < chld_out.lines; i++) {
159 status_text = chld_out.line[i++]; 153 status_text = chld_out.line[i++];
160 if (i == chld_out.lines || strstr (chld_out.line[i], "STATUS CODE: ") == NULL) 154 if (i == chld_out.lines || strstr(chld_out.line[i], "STATUS CODE: ") == NULL)
161 die (STATE_UNKNOWN, _("%s: Error parsing output\n"), progname); 155 die(STATE_UNKNOWN, _("%s: Error parsing output\n"), progname);
162 156
163 if (service[commands] && status_text 157 if (service[commands] && status_text && sscanf(chld_out.line[i], "STATUS CODE: %d", &cresult) == 1) {
164 && sscanf (chld_out.line[i], "STATUS CODE: %d", &cresult) == 1) 158 fprintf(file_pointer, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n", (int)local_time, host_shortname, service[commands++],
165 { 159 cresult, status_text);
166 fprintf (fp, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
167 (int) local_time, host_shortname, service[commands++],
168 cresult, status_text);
169 } 160 }
170 } 161 }
171 162
172 /* Multiple commands and passive checking should always return OK */ 163 /* Multiple commands and passive checking should always return OK */
173 return result; 164 return result;
174} 165}
175 166
176/* process command-line arguments */ 167/* process command-line arguments */
177int 168int process_arguments(int argc, char **argv) {
178process_arguments (int argc, char **argv)
179{
180 int c; 169 int c;
181 char *p1, *p2; 170 char *p1;
171 char *p2;
182 172
183 int option = 0; 173 int option = 0;
184 static struct option longopts[] = { 174 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
185 {"version", no_argument, 0, 'V'}, 175 {"help", no_argument, 0, 'h'},
186 {"help", no_argument, 0, 'h'}, 176 {"verbose", no_argument, 0, 'v'},
187 {"verbose", no_argument, 0, 'v'}, 177 {"fork", no_argument, 0, 'f'},
188 {"fork", no_argument, 0, 'f'}, 178 {"timeout", required_argument, 0, 't'},
189 {"timeout", required_argument, 0, 't'}, 179 {"unknown-timeout", no_argument, 0, 'U'},
190 {"unknown-timeout", no_argument, 0, 'U'}, 180 {"host", required_argument, 0, 'H'}, /* backward compatibility */
191 {"host", required_argument, 0, 'H'}, /* backward compatibility */ 181 {"hostname", required_argument, 0, 'H'},
192 {"hostname", required_argument, 0, 'H'}, 182 {"port", required_argument, 0, 'p'},
193 {"port", required_argument,0,'p'}, 183 {"output", required_argument, 0, 'O'},
194 {"output", required_argument, 0, 'O'}, 184 {"name", required_argument, 0, 'n'},
195 {"name", required_argument, 0, 'n'}, 185 {"services", required_argument, 0, 's'},
196 {"services", required_argument, 0, 's'}, 186 {"identity", required_argument, 0, 'i'},
197 {"identity", required_argument, 0, 'i'}, 187 {"user", required_argument, 0, 'u'},
198 {"user", required_argument, 0, 'u'}, 188 {"logname", required_argument, 0, 'l'},
199 {"logname", required_argument, 0, 'l'}, 189 {"command", required_argument, 0, 'C'},
200 {"command", required_argument, 0, 'C'}, 190 {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */
201 {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */ 191 {"skip-stdout", optional_argument, 0, 'S'},
202 {"skip-stdout", optional_argument, 0, 'S'}, 192 {"skip-stderr", optional_argument, 0, 'E'},
203 {"skip-stderr", optional_argument, 0, 'E'}, 193 {"warn-on-stderr", no_argument, 0, 'W'},
204 {"warn-on-stderr", no_argument, 0, 'W'}, 194 {"proto1", no_argument, 0, '1'},
205 {"proto1", no_argument, 0, '1'}, 195 {"proto2", no_argument, 0, '2'},
206 {"proto2", no_argument, 0, '2'}, 196 {"use-ipv4", no_argument, 0, '4'},
207 {"use-ipv4", no_argument, 0, '4'}, 197 {"use-ipv6", no_argument, 0, '6'},
208 {"use-ipv6", no_argument, 0, '6'}, 198 {"ssh-option", required_argument, 0, 'o'},
209 {"ssh-option", required_argument, 0, 'o'}, 199 {"quiet", no_argument, 0, 'q'},
210 {"quiet", no_argument, 0, 'q'}, 200 {"configfile", optional_argument, 0, 'F'},
211 {"configfile", optional_argument, 0, 'F'}, 201 {0, 0, 0, 0}};
212 {0, 0, 0, 0}
213 };
214 202
215 if (argc < 2) 203 if (argc < 2)
216 return ERROR; 204 return ERROR;
217 205
218 for (c = 1; c < argc; c++) 206 for (c = 1; c < argc; c++)
219 if (strcmp ("-to", argv[c]) == 0) 207 if (strcmp("-to", argv[c]) == 0)
220 strcpy (argv[c], "-t"); 208 strcpy(argv[c], "-t");
221 209
222 while (1) { 210 while (1) {
223 c = getopt_long (argc, argv, "Vvh1246fqt:UH:O:p:i:u:l:C:S::E::n:s:o:F:", longopts, 211 c = getopt_long(argc, argv, "Vvh1246fqt:UH:O:p:i:u:l:C:S::E::n:s:o:F:", longopts, &option);
224 &option);
225 212
226 if (c == -1 || c == EOF) 213 if (c == -1 || c == EOF)
227 break; 214 break;
228 215
229 switch (c) { 216 switch (c) {
230 case 'V': /* version */ 217 case 'V': /* version */
231 print_revision (progname, NP_VERSION); 218 print_revision(progname, NP_VERSION);
232 exit (STATE_UNKNOWN); 219 exit(STATE_UNKNOWN);
233 case 'h': /* help */ 220 case 'h': /* help */
234 print_help (); 221 print_help();
235 exit (STATE_UNKNOWN); 222 exit(STATE_UNKNOWN);
236 case 'v': /* help */ 223 case 'v': /* help */
237 verbose = true; 224 verbose = true;
238 break; 225 break;
239 case 't': /* timeout period */ 226 case 't': /* timeout period */
240 if (!is_integer (optarg)) 227 if (!is_integer(optarg))
241 usage_va(_("Timeout interval must be a positive integer")); 228 usage_va(_("Timeout interval must be a positive integer"));
242 else 229 else
243 timeout_interval = atoi (optarg); 230 timeout_interval = atoi(optarg);
244 break; 231 break;
245 case 'U': 232 case 'U':
246 unknown_timeout = true; 233 unknown_timeout = true;
247 break; 234 break;
248 case 'H': /* host */ 235 case 'H': /* host */
249 hostname = optarg; 236 hostname = optarg;
250 break; 237 break;
251 case 'p': /* port number */ 238 case 'p': /* port number */
252 if (!is_integer (optarg)) 239 if (!is_integer(optarg))
253 usage_va(_("Port must be a positive integer")); 240 usage_va(_("Port must be a positive integer"));
254 comm_append("-p"); 241 comm_append("-p");
255 comm_append(optarg); 242 comm_append(optarg);
256 break; 243 break;
257 case 'O': /* output file */ 244 case 'O': /* output file */
258 outputfile = optarg; 245 outputfile = optarg;
259 passive = true; 246 passive = true;
260 break; 247 break;
261 case 's': /* description of service to check */ 248 case 's': /* description of service to check */
262 p1 = optarg; 249 p1 = optarg;
263 service = realloc (service, (++services) * sizeof(char *)); 250 service = realloc(service, (++services) * sizeof(char *));
264 while ((p2 = index (p1, ':'))) { 251 while ((p2 = index(p1, ':'))) {
265 *p2 = '\0'; 252 *p2 = '\0';
266 service[services - 1] = p1; 253 service[services - 1] = p1;
267 service = realloc (service, (++services) * sizeof(char *)); 254 service = realloc(service, (++services) * sizeof(char *));
268 p1 = p2 + 1; 255 p1 = p2 + 1;
269 } 256 }
270 service[services - 1] = p1; 257 service[services - 1] = p1;
271 break; 258 break;
272 case 'n': /* short name of host in the monitoring configuration */ 259 case 'n': /* short name of host in the monitoring configuration */
273 host_shortname = optarg; 260 host_shortname = optarg;
274 break; 261 break;
275 262
@@ -277,67 +264,67 @@ process_arguments (int argc, char **argv)
277 comm_append("-l"); 264 comm_append("-l");
278 comm_append(optarg); 265 comm_append(optarg);
279 break; 266 break;
280 case 'l': /* login name */ 267 case 'l': /* login name */
281 comm_append("-l"); 268 comm_append("-l");
282 comm_append(optarg); 269 comm_append(optarg);
283 break; 270 break;
284 case 'i': /* identity */ 271 case 'i': /* identity */
285 comm_append("-i"); 272 comm_append("-i");
286 comm_append(optarg); 273 comm_append(optarg);
287 break; 274 break;
288 275
289 case '1': /* Pass these switches directly to ssh */ 276 case '1': /* Pass these switches directly to ssh */
290 comm_append("-1"); 277 comm_append("-1");
291 break; 278 break;
292 case '2': /* 1 to force version 1, 2 to force version 2 */ 279 case '2': /* 1 to force version 1, 2 to force version 2 */
293 comm_append("-2"); 280 comm_append("-2");
294 break; 281 break;
295 case '4': /* -4 for IPv4 */ 282 case '4': /* -4 for IPv4 */
296 comm_append("-4"); 283 comm_append("-4");
297 break; 284 break;
298 case '6': /* -6 for IPv6 */ 285 case '6': /* -6 for IPv6 */
299 comm_append("-6"); 286 comm_append("-6");
300 break; 287 break;
301 case 'f': /* fork to background */ 288 case 'f': /* fork to background */
302 comm_append("-f"); 289 comm_append("-f");
303 break; 290 break;
304 case 'C': /* Command for remote machine */ 291 case 'C': /* Command for remote machine */
305 commands++; 292 commands++;
306 if (commands > 1) 293 if (commands > 1)
307 xasprintf (&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd); 294 xasprintf(&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd);
308 xasprintf (&remotecmd, "%s%s", remotecmd, optarg); 295 xasprintf(&remotecmd, "%s%s", remotecmd, optarg);
309 break; 296 break;
310 case 'S': /* skip n (or all) lines on stdout */ 297 case 'S': /* skip n (or all) lines on stdout */
311 if (optarg == NULL) 298 if (optarg == NULL)
312 skip_stdout = -1; /* skip all output on stdout */ 299 skip_stdout = -1; /* skip all output on stdout */
313 else if (!is_integer (optarg)) 300 else if (!is_integer(optarg))
314 usage_va(_("skip-stdout argument must be an integer")); 301 usage_va(_("skip-stdout argument must be an integer"));
315 else 302 else
316 skip_stdout = atoi (optarg); 303 skip_stdout = atoi(optarg);
317 break; 304 break;
318 case 'E': /* skip n (or all) lines on stderr */ 305 case 'E': /* skip n (or all) lines on stderr */
319 if (optarg == NULL) 306 if (optarg == NULL)
320 skip_stderr = -1; /* skip all output on stderr */ 307 skip_stderr = -1; /* skip all output on stderr */
321 else if (!is_integer (optarg)) 308 else if (!is_integer(optarg))
322 usage_va(_("skip-stderr argument must be an integer")); 309 usage_va(_("skip-stderr argument must be an integer"));
323 else 310 else
324 skip_stderr = atoi (optarg); 311 skip_stderr = atoi(optarg);
325 break; 312 break;
326 case 'W': /* exit with warning if there is an output on stderr */ 313 case 'W': /* exit with warning if there is an output on stderr */
327 warn_on_stderr = 1; 314 warn_on_stderr = 1;
328 break; 315 break;
329 case 'o': /* Extra options for the ssh command */ 316 case 'o': /* Extra options for the ssh command */
330 comm_append("-o"); 317 comm_append("-o");
331 comm_append(optarg); 318 comm_append(optarg);
332 break; 319 break;
333 case 'q': /* Tell the ssh command to be quiet */ 320 case 'q': /* Tell the ssh command to be quiet */
334 comm_append("-q"); 321 comm_append("-q");
335 break; 322 break;
336 case 'F': /* ssh configfile */ 323 case 'F': /* ssh configfile */
337 comm_append("-F"); 324 comm_append("-F");
338 comm_append(optarg); 325 comm_append(optarg);
339 break; 326 break;
340 default: /* help */ 327 default: /* help */
341 usage5(); 328 usage5();
342 } 329 }
343 } 330 }
@@ -345,7 +332,7 @@ process_arguments (int argc, char **argv)
345 c = optind; 332 c = optind;
346 if (hostname == NULL) { 333 if (hostname == NULL) {
347 if (c <= argc) { 334 if (c <= argc) {
348 die (STATE_UNKNOWN, _("%s: You must provide a host name\n"), progname); 335 die(STATE_UNKNOWN, _("%s: You must provide a host name\n"), progname);
349 } 336 }
350 hostname = argv[c++]; 337 hostname = argv[c++];
351 } 338 }
@@ -353,143 +340,130 @@ process_arguments (int argc, char **argv)
353 if (strlen(remotecmd) == 0) { 340 if (strlen(remotecmd) == 0) {
354 for (; c < argc; c++) 341 for (; c < argc; c++)
355 if (strlen(remotecmd) > 0) 342 if (strlen(remotecmd) > 0)
356 xasprintf (&remotecmd, "%s %s", remotecmd, argv[c]); 343 xasprintf(&remotecmd, "%s %s", remotecmd, argv[c]);
357 else 344 else
358 xasprintf (&remotecmd, "%s", argv[c]); 345 xasprintf(&remotecmd, "%s", argv[c]);
359 } 346 }
360 347
361 if (commands > 1 || passive) 348 if (commands > 1 || passive)
362 xasprintf (&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd); 349 xasprintf(&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd);
363 350
364 if (remotecmd == NULL || strlen (remotecmd) <= 1) 351 if (remotecmd == NULL || strlen(remotecmd) <= 1)
365 usage_va(_("No remotecmd")); 352 usage_va(_("No remotecmd"));
366 353
367 comm_append(hostname); 354 comm_append(hostname);
368 comm_append(remotecmd); 355 comm_append(remotecmd);
369 356
370 return validate_arguments (); 357 return validate_arguments();
371} 358}
372 359
373 360void comm_append(const char *str) {
374void
375comm_append (const char *str)
376{
377 361
378 if (++commargc > NP_MAXARGS) 362 if (++commargc > NP_MAXARGS)
379 die(STATE_UNKNOWN, _("%s: Argument limit of %d exceeded\n"), progname, NP_MAXARGS); 363 die(STATE_UNKNOWN, _("%s: Argument limit of %d exceeded\n"), progname, NP_MAXARGS);
380 364
381 if ((commargv = (char **)realloc(commargv, (commargc+1) * sizeof(char *))) == NULL) 365 if ((commargv = (char **)realloc(commargv, (commargc + 1) * sizeof(char *))) == NULL)
382 die(STATE_UNKNOWN, _("Can not (re)allocate 'commargv' buffer\n")); 366 die(STATE_UNKNOWN, _("Can not (re)allocate 'commargv' buffer\n"));
383 367
384 commargv[commargc-1] = strdup(str); 368 commargv[commargc - 1] = strdup(str);
385 commargv[commargc] = NULL; 369 commargv[commargc] = NULL;
386
387} 370}
388 371
389int 372int validate_arguments(void) {
390validate_arguments (void)
391{
392 if (remotecmd == NULL || hostname == NULL) 373 if (remotecmd == NULL || hostname == NULL)
393 return ERROR; 374 return ERROR;
394 375
395 if (passive && commands != services) 376 if (passive && commands != services)
396 die (STATE_UNKNOWN, _("%s: In passive mode, you must provide a service name for each command.\n"), progname); 377 die(STATE_UNKNOWN, _("%s: In passive mode, you must provide a service name for each command.\n"), progname);
397 378
398 if (passive && host_shortname == NULL) 379 if (passive && host_shortname == NULL)
399 die (STATE_UNKNOWN, _("%s: In passive mode, you must provide the host short name from the monitoring configs.\n"), progname); 380 die(STATE_UNKNOWN, _("%s: In passive mode, you must provide the host short name from the monitoring configs.\n"), progname);
400 381
401 return OK; 382 return OK;
402} 383}
403 384
404 385void print_help(void) {
405void 386 print_revision(progname, NP_VERSION);
406print_help (void) 387
407{ 388 printf("Copyright (c) 1999 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
408 print_revision (progname, NP_VERSION); 389 printf(COPYRIGHT, copyright, email);
409 390
410 printf ("Copyright (c) 1999 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n"); 391 printf(_("This plugin uses SSH to execute commands on a remote host"));
411 printf (COPYRIGHT, copyright, email); 392
412 393 printf("\n\n");
413 printf (_("This plugin uses SSH to execute commands on a remote host")); 394
414 395 print_usage();
415 printf ("\n\n"); 396
416 397 printf(UT_HELP_VRSN);
417 print_usage (); 398
418 399 printf(UT_EXTRA_OPTS);
419 printf (UT_HELP_VRSN); 400
420 401 printf(UT_HOST_PORT, 'p', "none");
421 printf (UT_EXTRA_OPTS); 402
422 403 printf(UT_IPv46);
423 printf (UT_HOST_PORT, 'p', "none"); 404
424 405 printf(" %s\n", "-1, --proto1");
425 printf (UT_IPv46); 406 printf(" %s\n", _("tell ssh to use Protocol 1 [optional]"));
426 407 printf(" %s\n", "-2, --proto2");
427 printf (" %s\n", "-1, --proto1"); 408 printf(" %s\n", _("tell ssh to use Protocol 2 [optional]"));
428 printf (" %s\n", _("tell ssh to use Protocol 1 [optional]")); 409 printf(" %s\n", "-S, --skip-stdout[=n]");
429 printf (" %s\n", "-2, --proto2"); 410 printf(" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]"));
430 printf (" %s\n", _("tell ssh to use Protocol 2 [optional]")); 411 printf(" %s\n", "-E, --skip-stderr[=n]");
431 printf (" %s\n", "-S, --skip-stdout[=n]"); 412 printf(" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]"));
432 printf (" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]")); 413 printf(" %s\n", "-W, --warn-on-stderr]");
433 printf (" %s\n", "-E, --skip-stderr[=n]"); 414 printf(" %s\n", _("Exit with an warning, if there is an output on STDERR"));
434 printf (" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]")); 415 printf(" %s\n", "-f");
435 printf (" %s\n", "-W, --warn-on-stderr]"); 416 printf(" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always return OK if ssh is executed"));
436 printf (" %s\n", _("Exit with an warning, if there is an output on STDERR")); 417 printf(" %s\n", "-C, --command='COMMAND STRING'");
437 printf (" %s\n", "-f"); 418 printf(" %s\n", _("command to execute on the remote machine"));
438 printf (" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always return OK if ssh is executed")); 419 printf(" %s\n", "-l, --logname=USERNAME");
439 printf (" %s\n","-C, --command='COMMAND STRING'"); 420 printf(" %s\n", _("SSH user name on remote host [optional]"));
440 printf (" %s\n", _("command to execute on the remote machine")); 421 printf(" %s\n", "-i, --identity=KEYFILE");
441 printf (" %s\n","-l, --logname=USERNAME"); 422 printf(" %s\n", _("identity of an authorized key [optional]"));
442 printf (" %s\n", _("SSH user name on remote host [optional]")); 423 printf(" %s\n", "-O, --output=FILE");
443 printf (" %s\n","-i, --identity=KEYFILE"); 424 printf(" %s\n", _("external command file for monitoring [optional]"));
444 printf (" %s\n", _("identity of an authorized key [optional]")); 425 printf(" %s\n", "-s, --services=LIST");
445 printf (" %s\n","-O, --output=FILE"); 426 printf(" %s\n", _("list of monitoring service names, separated by ':' [optional]"));
446 printf (" %s\n", _("external command file for monitoring [optional]")); 427 printf(" %s\n", "-n, --name=NAME");
447 printf (" %s\n","-s, --services=LIST"); 428 printf(" %s\n", _("short name of host in the monitoring configuration [optional]"));
448 printf (" %s\n", _("list of monitoring service names, separated by ':' [optional]")); 429 printf(" %s\n", "-o, --ssh-option=OPTION");
449 printf (" %s\n","-n, --name=NAME"); 430 printf(" %s\n", _("Call ssh with '-o OPTION' (may be used multiple times) [optional]"));
450 printf (" %s\n", _("short name of host in the monitoring configuration [optional]")); 431 printf(" %s\n", "-F, --configfile");
451 printf (" %s\n","-o, --ssh-option=OPTION"); 432 printf(" %s\n", _("Tell ssh to use this configfile [optional]"));
452 printf (" %s\n", _("Call ssh with '-o OPTION' (may be used multiple times) [optional]")); 433 printf(" %s\n", "-q, --quiet");
453 printf (" %s\n","-F, --configfile"); 434 printf(" %s\n", _("Tell ssh to suppress warning and diagnostic messages [optional]"));
454 printf (" %s\n", _("Tell ssh to use this configfile [optional]")); 435 printf(UT_WARN_CRIT);
455 printf (" %s\n","-q, --quiet"); 436 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
456 printf (" %s\n", _("Tell ssh to suppress warning and diagnostic messages [optional]")); 437 printf(" %s\n", "-U, --unknown-timeout");
457 printf (UT_WARN_CRIT); 438 printf(" %s\n", _("Make connection problems return UNKNOWN instead of CRITICAL"));
458 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 439 printf(UT_VERBOSE);
459 printf (" %s\n","-U, --unknown-timeout"); 440 printf("\n");
460 printf (" %s\n", _("Make connection problems return UNKNOWN instead of CRITICAL")); 441 printf(" %s\n", _("The most common mode of use is to refer to a local identity file with"));
461 printf (UT_VERBOSE); 442 printf(" %s\n", _("the '-i' option. In this mode, the identity pair should have a null"));
443 printf(" %s\n", _("passphrase and the public key should be listed in the authorized_keys"));
444 printf(" %s\n", _("file of the remote host. Usually the key will be restricted to running"));
445 printf(" %s\n", _("only one command on the remote server. If the remote SSH server tracks"));
446 printf(" %s\n", _("invocation arguments, the one remote program may be an agent that can"));
447 printf(" %s\n", _("execute additional commands as proxy"));
448 printf("\n");
449 printf(" %s\n", _("To use passive mode, provide multiple '-C' options, and provide"));
450 printf(" %s\n", _("all of -O, -s, and -n options (servicelist order must match '-C'options)"));
462 printf("\n"); 451 printf("\n");
463 printf (" %s\n", _("The most common mode of use is to refer to a local identity file with")); 452 printf("%s\n", _("Examples:"));
464 printf (" %s\n", _("the '-i' option. In this mode, the identity pair should have a null")); 453 printf(" %s\n", "$ check_by_ssh -H localhost -n lh -s c1:c2:c3 -C uptime -C uptime -C uptime -O /tmp/foo");
465 printf (" %s\n", _("passphrase and the public key should be listed in the authorized_keys")); 454 printf(" %s\n", "$ cat /tmp/foo");
466 printf (" %s\n", _("file of the remote host. Usually the key will be restricted to running")); 455 printf(" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c1;0; up 2 days");
467 printf (" %s\n", _("only one command on the remote server. If the remote SSH server tracks")); 456 printf(" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c2;0; up 2 days");
468 printf (" %s\n", _("invocation arguments, the one remote program may be an agent that can")); 457 printf(" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c3;0; up 2 days");
469 printf (" %s\n", _("execute additional commands as proxy"));
470 printf("\n");
471 printf (" %s\n", _("To use passive mode, provide multiple '-C' options, and provide"));
472 printf (" %s\n", _("all of -O, -s, and -n options (servicelist order must match '-C'options)"));
473 printf ("\n");
474 printf ("%s\n", _("Examples:"));
475 printf (" %s\n", "$ check_by_ssh -H localhost -n lh -s c1:c2:c3 -C uptime -C uptime -C uptime -O /tmp/foo");
476 printf (" %s\n", "$ cat /tmp/foo");
477 printf (" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c1;0; up 2 days");
478 printf (" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c2;0; up 2 days");
479 printf (" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c3;0; up 2 days");
480 458
481 printf(UT_SUPPORT); 459 printf(UT_SUPPORT);
482} 460}
483 461
484 462void print_usage(void) {
485 463 printf("%s\n", _("Usage:"));
486void 464 printf(" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n"
487print_usage (void) 465 " [-S [lines]] [-E [lines]] [-W] [-t timeout] [-i identity]\n"
488{ 466 " [-l user] [-n name] [-s servicelist] [-O outputfile]\n"
489 printf ("%s\n", _("Usage:")); 467 " [-p port] [-o ssh-option] [-F configfile]\n",
490 printf (" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n" 468 progname);
491 " [-S [lines]] [-E [lines]] [-W] [-t timeout] [-i identity]\n"
492 " [-l user] [-n name] [-s servicelist] [-O outputfile]\n"
493 " [-p port] [-o ssh-option] [-F configfile]\n",
494 progname);
495} 469}
diff --git a/plugins/check_cluster.c b/plugins/check_cluster.c
index e1ede9f7..b40c38c7 100644
--- a/plugins/check_cluster.c
+++ b/plugins/check_cluster.c
@@ -1,92 +1,92 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* check_cluster.c - Host and Service Cluster Plugin for Monitoring 3 * check_cluster.c - Host and Service Cluster Plugin for Monitoring
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2004 Ethan Galstad (nagios@nagios.org) 6 * Copyright (c) 2000-2004 Ethan Galstad (nagios@nagios.org)
7* Copyright (c) 2007 Monitoring Plugins Development Team 7 * Copyright (c) 2007-2024 Monitoring Plugins Development Team
8* 8 *
9* This program is free software: you can redistribute it and/or modify 9 * This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 3 of the License, or 11 * the Free Software Foundation, either version 3 of the License, or
12* (at your option) any later version. 12 * (at your option) any later version.
13* 13 *
14* This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details. 17 * GNU General Public License for more details.
18* 18 *
19* You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21* 21 *
22* 22 *
23*****************************************************************************/ 23 *****************************************************************************/
24 24
25const char *progname = "check_cluster"; 25const char *progname = "check_cluster";
26const char *copyright = "2000-2007"; 26const char *copyright = "2000-2024";
27const char *email = "devel@monitoring-plugins.org"; 27const char *email = "devel@monitoring-plugins.org";
28 28
29#include "common.h" 29#include "common.h"
30#include "utils.h" 30#include "utils.h"
31#include "utils_base.h" 31#include "utils_base.h"
32 32
33#define CHECK_SERVICES 1 33enum {
34#define CHECK_HOSTS 2 34 CHECK_SERVICES = 1,
35 CHECK_HOSTS = 2
36};
35 37
36void print_help (void); 38static void print_help(void);
37void print_usage (void); 39void print_usage(void);
38 40
39int total_services_ok=0; 41static int total_services_ok = 0;
40int total_services_warning=0; 42static int total_services_warning = 0;
41int total_services_unknown=0; 43static int total_services_unknown = 0;
42int total_services_critical=0; 44static int total_services_critical = 0;
43 45
44int total_hosts_up=0; 46static int total_hosts_up = 0;
45int total_hosts_down=0; 47static int total_hosts_down = 0;
46int total_hosts_unreachable=0; 48static int total_hosts_unreachable = 0;
47 49
48char *warn_threshold; 50static char *warn_threshold;
49char *crit_threshold; 51static char *crit_threshold;
50 52
51int check_type=CHECK_SERVICES; 53static int check_type = CHECK_SERVICES;
52 54
53char *data_vals=NULL; 55static char *data_vals = NULL;
54char *label=NULL; 56static char *label = NULL;
55 57
56int verbose=0; 58static int verbose = 0;
57 59
58int process_arguments(int,char **); 60static int process_arguments(int /*argc*/, char ** /*argv*/);
59 61
60 62int main(int argc, char **argv) {
61
62int main(int argc, char **argv){
63 char *ptr; 63 char *ptr;
64 int data_val; 64 int data_val;
65 int return_code=STATE_OK; 65 int return_code = STATE_OK;
66 thresholds *thresholds = NULL; 66 thresholds *thresholds = NULL;
67 67
68 setlocale (LC_ALL, ""); 68 setlocale(LC_ALL, "");
69 bindtextdomain (PACKAGE, LOCALEDIR); 69 bindtextdomain(PACKAGE, LOCALEDIR);
70 textdomain (PACKAGE); 70 textdomain(PACKAGE);
71 71
72 /* Parse extra opts if any */ 72 /* Parse extra opts if any */
73 argv=np_extra_opts(&argc, argv, progname); 73 argv = np_extra_opts(&argc, argv, progname);
74 74
75 if(process_arguments(argc,argv)==ERROR) 75 if (process_arguments(argc, argv) == ERROR)
76 usage(_("Could not parse arguments")); 76 usage(_("Could not parse arguments"));
77 77
78 /* Initialize the thresholds */ 78 /* Initialize the thresholds */
79 set_thresholds(&thresholds, warn_threshold, crit_threshold); 79 set_thresholds(&thresholds, warn_threshold, crit_threshold);
80 if(verbose) 80 if (verbose)
81 print_thresholds("check_cluster", thresholds); 81 print_thresholds("check_cluster", thresholds);
82 82
83 /* check the data values */ 83 /* check the data values */
84 for(ptr=strtok(data_vals,",");ptr!=NULL;ptr=strtok(NULL,",")){ 84 for (ptr = strtok(data_vals, ","); ptr != NULL; ptr = strtok(NULL, ",")) {
85 85
86 data_val=atoi(ptr); 86 data_val = atoi(ptr);
87 87
88 if(check_type==CHECK_SERVICES){ 88 if (check_type == CHECK_SERVICES) {
89 switch(data_val){ 89 switch (data_val) {
90 case 0: 90 case 0:
91 total_services_ok++; 91 total_services_ok++;
92 break; 92 break;
@@ -101,10 +101,9 @@ int main(int argc, char **argv){
101 break; 101 break;
102 default: 102 default:
103 break; 103 break;
104 } 104 }
105 } 105 } else {
106 else{ 106 switch (data_val) {
107 switch(data_val){
108 case 0: 107 case 0:
109 total_hosts_up++; 108 total_hosts_up++;
110 break; 109 break;
@@ -116,67 +115,54 @@ int main(int argc, char **argv){
116 break; 115 break;
117 default: 116 default:
118 break; 117 break;
119 } 118 }
120 } 119 }
121 } 120 }
122
123 121
124 /* return the status of the cluster */ 122 /* return the status of the cluster */
125 if(check_type==CHECK_SERVICES){ 123 if (check_type == CHECK_SERVICES) {
126 return_code=get_status(total_services_warning+total_services_unknown+total_services_critical, thresholds); 124 return_code = get_status(total_services_warning + total_services_unknown + total_services_critical, thresholds);
127 printf("CLUSTER %s: %s: %d ok, %d warning, %d unknown, %d critical\n", 125 printf("CLUSTER %s: %s: %d ok, %d warning, %d unknown, %d critical\n", state_text(return_code),
128 state_text(return_code), (label==NULL)?"Service cluster":label, 126 (label == NULL) ? "Service cluster" : label, total_services_ok, total_services_warning, total_services_unknown,
129 total_services_ok,total_services_warning, 127 total_services_critical);
130 total_services_unknown,total_services_critical); 128 } else {
131 } 129 return_code = get_status(total_hosts_down + total_hosts_unreachable, thresholds);
132 else{ 130 printf("CLUSTER %s: %s: %d up, %d down, %d unreachable\n", state_text(return_code), (label == NULL) ? "Host cluster" : label,
133 return_code=get_status(total_hosts_down+total_hosts_unreachable, thresholds); 131 total_hosts_up, total_hosts_down, total_hosts_unreachable);
134 printf("CLUSTER %s: %s: %d up, %d down, %d unreachable\n",
135 state_text(return_code), (label==NULL)?"Host cluster":label,
136 total_hosts_up,total_hosts_down,total_hosts_unreachable);
137 } 132 }
138 133
139 return return_code; 134 return return_code;
140} 135}
141 136
142 137int process_arguments(int argc, char **argv) {
143
144int process_arguments(int argc, char **argv){
145 int c; 138 int c;
146 char *ptr; 139 char *ptr;
147 int option=0; 140 int option = 0;
148 static struct option longopts[]={ 141 static struct option longopts[] = {{"data", required_argument, 0, 'd'}, {"warning", required_argument, 0, 'w'},
149 {"data", required_argument,0,'d'}, 142 {"critical", required_argument, 0, 'c'}, {"label", required_argument, 0, 'l'},
150 {"warning", required_argument,0,'w'}, 143 {"host", no_argument, 0, 'h'}, {"service", no_argument, 0, 's'},
151 {"critical", required_argument,0,'c'}, 144 {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'},
152 {"label", required_argument,0,'l'}, 145 {"help", no_argument, 0, 'H'}, {0, 0, 0, 0}};
153 {"host", no_argument, 0,'h'},
154 {"service", no_argument, 0,'s'},
155 {"verbose", no_argument, 0,'v'},
156 {"version", no_argument, 0,'V'},
157 {"help", no_argument, 0,'H'},
158 {0,0,0,0}
159 };
160 146
161 /* no options were supplied */ 147 /* no options were supplied */
162 if(argc<2) 148 if (argc < 2)
163 return ERROR; 149 return ERROR;
164 150
165 while(1){ 151 while (1) {
166 152
167 c=getopt_long(argc,argv,"hHsvVw:c:d:l:",longopts,&option); 153 c = getopt_long(argc, argv, "hHsvVw:c:d:l:", longopts, &option);
168 154
169 if(c==-1 || c==EOF || c==1) 155 if (c == -1 || c == EOF || c == 1)
170 break; 156 break;
171 157
172 switch(c){ 158 switch (c) {
173 159
174 case 'h': /* host cluster */ 160 case 'h': /* host cluster */
175 check_type=CHECK_HOSTS; 161 check_type = CHECK_HOSTS;
176 break; 162 break;
177 163
178 case 's': /* service cluster */ 164 case 's': /* service cluster */
179 check_type=CHECK_SERVICES; 165 check_type = CHECK_SERVICES;
180 break; 166 break;
181 167
182 case 'w': /* warning threshold */ 168 case 'w': /* warning threshold */
@@ -188,20 +174,20 @@ int process_arguments(int argc, char **argv){
188 break; 174 break;
189 175
190 case 'd': /* data values */ 176 case 'd': /* data values */
191 data_vals=(char *)strdup(optarg); 177 data_vals = (char *)strdup(optarg);
192 /* validate data */ 178 /* validate data */
193 for (ptr=data_vals;ptr!=NULL;ptr+=2){ 179 for (ptr = data_vals; ptr != NULL; ptr += 2) {
194 if (ptr[0]<'0' || ptr[0]>'3') 180 if (ptr[0] < '0' || ptr[0] > '3')
195 return ERROR; 181 return ERROR;
196 if (ptr[1]=='\0') 182 if (ptr[1] == '\0')
197 break; 183 break;
198 if (ptr[1]!=',') 184 if (ptr[1] != ',')
199 return ERROR; 185 return ERROR;
200 } 186 }
201 break; 187 break;
202 188
203 case 'l': /* text label */ 189 case 'l': /* text label */
204 label=(char *)strdup(optarg); 190 label = (char *)strdup(optarg);
205 break; 191 break;
206 192
207 case 'v': /* verbose */ 193 case 'v': /* verbose */
@@ -209,8 +195,8 @@ int process_arguments(int argc, char **argv){
209 break; 195 break;
210 196
211 case 'V': /* version */ 197 case 'V': /* version */
212 print_revision (progname, NP_VERSION); 198 print_revision(progname, NP_VERSION);
213 exit (STATE_UNKNOWN); 199 exit(STATE_UNKNOWN);
214 break; 200 break;
215 201
216 case 'H': /* help */ 202 case 'H': /* help */
@@ -221,20 +207,18 @@ int process_arguments(int argc, char **argv){
221 default: 207 default:
222 return ERROR; 208 return ERROR;
223 break; 209 break;
224 } 210 }
225 } 211 }
226 212
227 if(data_vals==NULL) 213 if (data_vals == NULL)
228 return ERROR; 214 return ERROR;
229 215
230 return OK; 216 return OK;
231} 217}
232 218
233void 219void print_help(void) {
234print_help(void)
235{
236 print_revision(progname, NP_VERSION); 220 print_revision(progname, NP_VERSION);
237 printf ("Copyright (c) 2000-2004 Ethan Galstad (nagios@nagios.org)\n"); 221 printf("Copyright (c) 2000-2004 Ethan Galstad (nagios@nagios.org)\n");
238 printf(COPYRIGHT, copyright, email); 222 printf(COPYRIGHT, copyright, email);
239 223
240 printf(_("Host/Service Cluster Plugin for Monitoring")); 224 printf(_("Host/Service Cluster Plugin for Monitoring"));
@@ -245,21 +229,21 @@ print_help(void)
245 printf("\n"); 229 printf("\n");
246 printf("%s\n", _("Options:")); 230 printf("%s\n", _("Options:"));
247 printf(UT_EXTRA_OPTS); 231 printf(UT_EXTRA_OPTS);
248 printf (" %s\n", "-s, --service"); 232 printf(" %s\n", "-s, --service");
249 printf (" %s\n", _("Check service cluster status")); 233 printf(" %s\n", _("Check service cluster status"));
250 printf (" %s\n", "-h, --host"); 234 printf(" %s\n", "-h, --host");
251 printf (" %s\n", _("Check host cluster status")); 235 printf(" %s\n", _("Check host cluster status"));
252 printf (" %s\n", "-l, --label=STRING"); 236 printf(" %s\n", "-l, --label=STRING");
253 printf (" %s\n", _("Optional prepended text output (i.e. \"Host cluster\")")); 237 printf(" %s\n", _("Optional prepended text output (i.e. \"Host cluster\")"));
254 printf (" %s\n", "-w, --warning=THRESHOLD"); 238 printf(" %s\n", "-w, --warning=THRESHOLD");
255 printf (" %s\n", _("Specifies the range of hosts or services in cluster that must be in a")); 239 printf(" %s\n", _("Specifies the range of hosts or services in cluster that must be in a"));
256 printf (" %s\n", _("non-OK state in order to return a WARNING status level")); 240 printf(" %s\n", _("non-OK state in order to return a WARNING status level"));
257 printf (" %s\n", "-c, --critical=THRESHOLD"); 241 printf(" %s\n", "-c, --critical=THRESHOLD");
258 printf (" %s\n", _("Specifies the range of hosts or services in cluster that must be in a")); 242 printf(" %s\n", _("Specifies the range of hosts or services in cluster that must be in a"));
259 printf (" %s\n", _("non-OK state in order to return a CRITICAL status level")); 243 printf(" %s\n", _("non-OK state in order to return a CRITICAL status level"));
260 printf (" %s\n", "-d, --data=LIST"); 244 printf(" %s\n", "-d, --data=LIST");
261 printf (" %s\n", _("The status codes of the hosts or services in the cluster, separated by")); 245 printf(" %s\n", _("The status codes of the hosts or services in the cluster, separated by"));
262 printf (" %s\n", _("commas")); 246 printf(" %s\n", _("commas"));
263 247
264 printf(UT_VERBOSE); 248 printf(UT_VERBOSE);
265 249
@@ -267,23 +251,18 @@ print_help(void)
267 printf("%s\n", _("Notes:")); 251 printf("%s\n", _("Notes:"));
268 printf(UT_THRESHOLDS_NOTES); 252 printf(UT_THRESHOLDS_NOTES);
269 253
270 printf ("\n"); 254 printf("\n");
271 printf ("%s\n", _("Examples:")); 255 printf("%s\n", _("Examples:"));
272 printf (" %s\n", "check_cluster -s -d 2,0,2,0 -c @3:"); 256 printf(" %s\n", "check_cluster -s -d 2,0,2,0 -c @3:");
273 printf (" %s\n", _("Will alert critical if there are 3 or more service data points in a non-OK") ); 257 printf(" %s\n", _("Will alert critical if there are 3 or more service data points in a non-OK"));
274 printf (" %s\n", _("state.") ); 258 printf(" %s\n", _("state."));
275 259
276 printf(UT_SUPPORT); 260 printf(UT_SUPPORT);
277} 261}
278 262
279 263void print_usage(void) {
280void
281print_usage(void)
282{
283 264
284 printf("%s\n", _("Usage:")); 265 printf("%s\n", _("Usage:"));
285 printf(" %s (-s | -h) -d val1[,val2,...,valn] [-l label]\n", progname); 266 printf(" %s (-s | -h) -d val1[,val2,...,valn] [-l label]\n", progname);
286 printf("[-w threshold] [-c threshold] [-v] [--help]\n"); 267 printf("[-w threshold] [-c threshold] [-v] [--help]\n");
287
288} 268}
289
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index e9c15e64..1d27da28 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -1,40 +1,40 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_curl plugin 3 * Monitoring check_curl plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2019 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_curl plugin 10 * This file contains the check_curl plugin
11* 11 *
12* This plugin tests the HTTP service on the specified host. It can test 12 * This plugin tests the HTTP service on the specified host. It can test
13* normal (http) and secure (https) servers, follow redirects, search for 13 * normal (http) and secure (https) servers, follow redirects, search for
14* strings and regular expressions, check connection times, and report on 14 * strings and regular expressions, check connection times, and report on
15* certificate expiration times. 15 * certificate expiration times.
16* 16 *
17* This plugin uses functions from the curl library, see 17 * This plugin uses functions from the curl library, see
18* http://curl.haxx.se 18 * http://curl.haxx.se
19* 19 *
20* This program is free software: you can redistribute it and/or modify 20 * This program is free software: you can redistribute it and/or modify
21* it under the terms of the GNU General Public License as published by 21 * it under the terms of the GNU General Public License as published by
22* the Free Software Foundation, either version 3 of the License, or 22 * the Free Software Foundation, either version 3 of the License, or
23* (at your option) any later version. 23 * (at your option) any later version.
24* 24 *
25* This program is distributed in the hope that it will be useful, 25 * This program is distributed in the hope that it will be useful,
26* but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28* GNU General Public License for more details. 28 * GNU General Public License for more details.
29* 29 *
30* You should have received a copy of the GNU General Public License 30 * You should have received a copy of the GNU General Public License
31* along with this program. If not, see <http://www.gnu.org/licenses/>. 31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32* 32 *
33* 33 *
34*****************************************************************************/ 34 *****************************************************************************/
35const char *progname = "check_curl"; 35const char *progname = "check_curl";
36 36
37const char *copyright = "2006-2019"; 37const char *copyright = "2006-2024";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include <stdbool.h> 40#include <stdbool.h>
@@ -44,7 +44,7 @@ const char *email = "devel@monitoring-plugins.org";
44#include "utils.h" 44#include "utils.h"
45 45
46#ifndef LIBCURL_PROTOCOL_HTTP 46#ifndef LIBCURL_PROTOCOL_HTTP
47#error libcurl compiled without HTTP support, compiling check_curl plugin does not makes a lot of sense 47# error libcurl compiled without HTTP support, compiling check_curl plugin does not makes a lot of sense
48#endif 48#endif
49 49
50#include "curl/curl.h" 50#include "curl/curl.h"
@@ -58,7 +58,7 @@ const char *email = "devel@monitoring-plugins.org";
58#include <netinet/in.h> 58#include <netinet/in.h>
59 59
60#if defined(HAVE_SSL) && defined(USE_OPENSSL) 60#if defined(HAVE_SSL) && defined(USE_OPENSSL)
61#include <openssl/opensslv.h> 61# include <openssl/opensslv.h>
62#endif 62#endif
63 63
64#include <netdb.h> 64#include <netdb.h>
@@ -66,1092 +66,1049 @@ const char *email = "devel@monitoring-plugins.org";
66#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch)) 66#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch))
67 67
68#define DEFAULT_BUFFER_SIZE 2048 68#define DEFAULT_BUFFER_SIZE 2048
69#define DEFAULT_SERVER_URL "/" 69#define DEFAULT_SERVER_URL "/"
70#define HTTP_EXPECT "HTTP/" 70#define HTTP_EXPECT "HTTP/"
71#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN 71#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN
72enum { 72enum {
73 MAX_IPV4_HOSTLENGTH = 255, 73 MAX_IPV4_HOSTLENGTH = 255,
74 HTTP_PORT = 80, 74 HTTP_PORT = 80,
75 HTTPS_PORT = 443, 75 HTTPS_PORT = 443,
76 MAX_PORT = 65535, 76 MAX_PORT = 65535,
77 DEFAULT_MAX_REDIRS = 15 77 DEFAULT_MAX_REDIRS = 15
78}; 78};
79 79
80enum { 80enum {
81 STICKY_NONE = 0, 81 STICKY_NONE = 0,
82 STICKY_HOST = 1, 82 STICKY_HOST = 1,
83 STICKY_PORT = 2 83 STICKY_PORT = 2
84}; 84};
85 85
86enum { 86enum {
87 FOLLOW_HTTP_CURL = 0, 87 FOLLOW_HTTP_CURL = 0,
88 FOLLOW_LIBCURL = 1 88 FOLLOW_LIBCURL = 1
89}; 89};
90 90
91/* for buffers for header and body */ 91/* for buffers for header and body */
92typedef struct { 92typedef struct {
93 char *buf; 93 char *buf;
94 size_t buflen; 94 size_t buflen;
95 size_t bufsize; 95 size_t bufsize;
96} curlhelp_write_curlbuf; 96} curlhelp_write_curlbuf;
97 97
98/* for buffering the data sent in PUT */ 98/* for buffering the data sent in PUT */
99typedef struct { 99typedef struct {
100 char *buf; 100 char *buf;
101 size_t buflen; 101 size_t buflen;
102 off_t pos; 102 off_t pos;
103} curlhelp_read_curlbuf; 103} curlhelp_read_curlbuf;
104 104
105/* for parsing the HTTP status line */ 105/* for parsing the HTTP status line */
106typedef struct { 106typedef struct {
107 int http_major; /* major version of the protocol, always 1 (HTTP/0.9 107 int http_major; /* major version of the protocol, always 1 (HTTP/0.9
108 * never reached the big internet most likely) */ 108 * never reached the big internet most likely) */
109 int http_minor; /* minor version of the protocol, usually 0 or 1 */ 109 int http_minor; /* minor version of the protocol, usually 0 or 1 */
110 int http_code; /* HTTP return code as in RFC 2145 */ 110 int http_code; /* HTTP return code as in RFC 2145 */
111 int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see 111 int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see
112 * http://support.microsoft.com/kb/318380/en-us */ 112 * http://support.microsoft.com/kb/318380/en-us */
113 const char *msg; /* the human readable message */ 113 const char *msg; /* the human readable message */
114 char *first_line; /* a copy of the first line */ 114 char *first_line; /* a copy of the first line */
115} curlhelp_statusline; 115} curlhelp_statusline;
116 116
117/* to know the underlying SSL library used by libcurl */ 117/* to know the underlying SSL library used by libcurl */
118typedef enum curlhelp_ssl_library { 118typedef enum curlhelp_ssl_library {
119 CURLHELP_SSL_LIBRARY_UNKNOWN, 119 CURLHELP_SSL_LIBRARY_UNKNOWN,
120 CURLHELP_SSL_LIBRARY_OPENSSL, 120 CURLHELP_SSL_LIBRARY_OPENSSL,
121 CURLHELP_SSL_LIBRARY_LIBRESSL, 121 CURLHELP_SSL_LIBRARY_LIBRESSL,
122 CURLHELP_SSL_LIBRARY_GNUTLS, 122 CURLHELP_SSL_LIBRARY_GNUTLS,
123 CURLHELP_SSL_LIBRARY_NSS 123 CURLHELP_SSL_LIBRARY_NSS
124} curlhelp_ssl_library; 124} curlhelp_ssl_library;
125 125
126enum { 126enum {
127 REGS = 2, 127 REGS = 2,
128 MAX_RE_SIZE = 1024 128 MAX_RE_SIZE = 1024
129}; 129};
130#include "regex.h" 130#include "regex.h"
131regex_t preg; 131static regex_t preg;
132regmatch_t pmatch[REGS]; 132static regmatch_t pmatch[REGS];
133char regexp[MAX_RE_SIZE]; 133static char regexp[MAX_RE_SIZE];
134int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE; 134static int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
135int errcode; 135static int errcode;
136bool invert_regex = false; 136static bool invert_regex = false;
137int state_regex = STATE_CRITICAL; 137static int state_regex = STATE_CRITICAL;
138 138
139char *server_address = NULL; 139static char *server_address = NULL;
140char *host_name = NULL; 140static char *host_name = NULL;
141char *server_url = 0; 141static char *server_url = 0;
142char server_ip[DEFAULT_BUFFER_SIZE]; 142static struct curl_slist *server_ips = NULL;
143struct curl_slist *server_ips = NULL; 143static bool specify_port = false;
144bool specify_port = false; 144static unsigned short server_port = HTTP_PORT;
145unsigned short server_port = HTTP_PORT; 145static unsigned short virtual_port = 0;
146unsigned short virtual_port = 0; 146static int host_name_length;
147int host_name_length; 147static char output_header_search[30] = "";
148char output_header_search[30] = ""; 148static char output_string_search[30] = "";
149char output_string_search[30] = ""; 149static char *warning_thresholds = NULL;
150char *warning_thresholds = NULL; 150static char *critical_thresholds = NULL;
151char *critical_thresholds = NULL; 151static int days_till_exp_warn, days_till_exp_crit;
152int days_till_exp_warn, days_till_exp_crit; 152static thresholds *thlds;
153thresholds *thlds; 153static char user_agent[DEFAULT_BUFFER_SIZE];
154char user_agent[DEFAULT_BUFFER_SIZE]; 154static int verbose = 0;
155int verbose = 0; 155static bool show_extended_perfdata = false;
156bool show_extended_perfdata = false; 156static bool show_body = false;
157bool show_body = false; 157static int min_page_len = 0;
158int min_page_len = 0; 158static int max_page_len = 0;
159int max_page_len = 0; 159static int redir_depth = 0;
160int redir_depth = 0; 160static int max_depth = DEFAULT_MAX_REDIRS;
161int max_depth = DEFAULT_MAX_REDIRS; 161static char *http_method = NULL;
162char *http_method = NULL; 162static char *http_post_data = NULL;
163char *http_post_data = NULL; 163static char *http_content_type = NULL;
164char *http_content_type = NULL; 164static CURL *curl;
165CURL *curl; 165static bool curl_global_initialized = false;
166bool curl_global_initialized = false; 166static bool curl_easy_initialized = false;
167bool curl_easy_initialized = false; 167static struct curl_slist *header_list = NULL;
168struct curl_slist *header_list = NULL; 168static bool body_buf_initialized = false;
169bool body_buf_initialized = false; 169static curlhelp_write_curlbuf body_buf;
170curlhelp_write_curlbuf body_buf; 170static bool header_buf_initialized = false;
171bool header_buf_initialized = false; 171static curlhelp_write_curlbuf header_buf;
172curlhelp_write_curlbuf header_buf; 172static bool status_line_initialized = false;
173bool status_line_initialized = false; 173static curlhelp_statusline status_line;
174curlhelp_statusline status_line; 174static bool put_buf_initialized = false;
175bool put_buf_initialized = false; 175static curlhelp_read_curlbuf put_buf;
176curlhelp_read_curlbuf put_buf; 176static char http_header[DEFAULT_BUFFER_SIZE];
177char http_header[DEFAULT_BUFFER_SIZE]; 177static long code;
178long code; 178static long socket_timeout = DEFAULT_SOCKET_TIMEOUT;
179long socket_timeout = DEFAULT_SOCKET_TIMEOUT; 179static double total_time;
180double total_time; 180static double time_connect;
181double time_connect; 181static double time_appconnect;
182double time_appconnect; 182static double time_headers;
183double time_headers; 183static double time_firstbyte;
184double time_firstbyte; 184static char errbuf[MAX_INPUT_BUFFER];
185char errbuf[MAX_INPUT_BUFFER]; 185static CURLcode res;
186CURLcode res; 186static char url[DEFAULT_BUFFER_SIZE];
187char url[DEFAULT_BUFFER_SIZE]; 187static char msg[DEFAULT_BUFFER_SIZE];
188char msg[DEFAULT_BUFFER_SIZE]; 188static char perfstring[DEFAULT_BUFFER_SIZE];
189char perfstring[DEFAULT_BUFFER_SIZE]; 189static char header_expect[MAX_INPUT_BUFFER] = "";
190char header_expect[MAX_INPUT_BUFFER] = ""; 190static char string_expect[MAX_INPUT_BUFFER] = "";
191char string_expect[MAX_INPUT_BUFFER] = ""; 191static char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
192char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; 192static int server_expect_yn = 0;
193int server_expect_yn = 0; 193static char user_auth[MAX_INPUT_BUFFER] = "";
194char user_auth[MAX_INPUT_BUFFER] = ""; 194static char proxy_auth[MAX_INPUT_BUFFER] = "";
195char proxy_auth[MAX_INPUT_BUFFER] = ""; 195static char **http_opt_headers;
196char **http_opt_headers; 196static int http_opt_headers_count = 0;
197int http_opt_headers_count = 0; 197static bool display_html = false;
198bool display_html = false; 198static int onredirect = STATE_OK;
199int onredirect = STATE_OK; 199static int followmethod = FOLLOW_HTTP_CURL;
200int followmethod = FOLLOW_HTTP_CURL; 200static int followsticky = STICKY_NONE;
201int followsticky = STICKY_NONE; 201static bool use_ssl = false;
202bool use_ssl = false; 202static bool check_cert = false;
203bool use_sni = true; 203static bool continue_after_check_cert = false;
204bool check_cert = false;
205bool continue_after_check_cert = false;
206typedef union { 204typedef union {
207 struct curl_slist* to_info; 205 struct curl_slist *to_info;
208 struct curl_certinfo* to_certinfo; 206 struct curl_certinfo *to_certinfo;
209} cert_ptr_union; 207} cert_ptr_union;
210cert_ptr_union cert_ptr; 208static cert_ptr_union cert_ptr;
211int ssl_version = CURL_SSLVERSION_DEFAULT; 209static int ssl_version = CURL_SSLVERSION_DEFAULT;
212char *client_cert = NULL; 210static char *client_cert = NULL;
213char *client_privkey = NULL; 211static char *client_privkey = NULL;
214char *ca_cert = NULL; 212static char *ca_cert = NULL;
215bool verify_peer_and_host = false; 213static bool verify_peer_and_host = false;
216bool is_openssl_callback = false; 214static bool is_openssl_callback = false;
215static bool add_sslctx_verify_fun = false;
217#if defined(HAVE_SSL) && defined(USE_OPENSSL) 216#if defined(HAVE_SSL) && defined(USE_OPENSSL)
218X509 *cert = NULL; 217static X509 *cert = NULL;
219#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 218#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
220bool no_body = false; 219static bool no_body = false;
221int maximum_age = -1; 220static int maximum_age = -1;
222int address_family = AF_UNSPEC; 221static int address_family = AF_UNSPEC;
223curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 222static curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
224int curl_http_version = CURL_HTTP_VERSION_NONE; 223static int curl_http_version = CURL_HTTP_VERSION_NONE;
225bool automatic_decompression = false; 224static bool automatic_decompression = false;
226char *cookie_jar_file = NULL; 225static char *cookie_jar_file = NULL;
227bool haproxy_protocol = false; 226static bool haproxy_protocol = false;
228 227
229bool process_arguments (int, char**); 228static bool process_arguments(int /*argc*/, char ** /*argv*/);
230void handle_curl_option_return_code (CURLcode res, const char* option); 229static void handle_curl_option_return_code(CURLcode res, const char *option);
231int check_http (void); 230static int check_http(void);
232void redir (curlhelp_write_curlbuf*); 231static void redir(curlhelp_write_curlbuf * /*header_buf*/);
233char *perfd_time (double microsec); 232static char *perfd_time(double elapsed_time);
234char *perfd_time_connect (double microsec); 233static char *perfd_time_connect(double elapsed_time_connect);
235char *perfd_time_ssl (double microsec); 234static char *perfd_time_ssl(double elapsed_time_ssl);
236char *perfd_time_firstbyte (double microsec); 235static char *perfd_time_firstbyte(double elapsed_time_firstbyte);
237char *perfd_time_headers (double microsec); 236static char *perfd_time_headers(double elapsed_time_headers);
238char *perfd_time_transfer (double microsec); 237static char *perfd_time_transfer(double elapsed_time_transfer);
239char *perfd_size (int page_len); 238static char *perfd_size(int page_len);
240void print_help (void); 239static void print_help(void);
241void print_usage (void); 240void print_usage(void);
242void print_curl_version (void); 241static void print_curl_version(void);
243int curlhelp_initwritebuffer (curlhelp_write_curlbuf*); 242static int curlhelp_initwritebuffer(curlhelp_write_curlbuf * /*buf*/);
244size_t curlhelp_buffer_write_callback(void*, size_t , size_t , void*); 243static size_t curlhelp_buffer_write_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/, void * /*stream*/);
245void curlhelp_freewritebuffer (curlhelp_write_curlbuf*); 244static void curlhelp_freewritebuffer(curlhelp_write_curlbuf * /*buf*/);
246int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); 245static int curlhelp_initreadbuffer(curlhelp_read_curlbuf * /*buf*/, const char * /*data*/, size_t /*datalen*/);
247size_t curlhelp_buffer_read_callback(void *, size_t , size_t , void *); 246static size_t curlhelp_buffer_read_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/, void * /*stream*/);
248void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); 247static void curlhelp_freereadbuffer(curlhelp_read_curlbuf * /*buf*/);
249curlhelp_ssl_library curlhelp_get_ssl_library (); 248static curlhelp_ssl_library curlhelp_get_ssl_library(void);
250const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library); 249static const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library /*ssl_library*/);
251int net_noopenssl_check_certificate (cert_ptr_union*, int, int); 250int net_noopenssl_check_certificate(cert_ptr_union *, int, int);
252 251
253int curlhelp_parse_statusline (const char*, curlhelp_statusline *); 252static int curlhelp_parse_statusline(const char * /*buf*/, curlhelp_statusline * /*status_line*/);
254void curlhelp_free_statusline (curlhelp_statusline *); 253static void curlhelp_free_statusline(curlhelp_statusline * /*status_line*/);
255char *get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header); 254static char *get_header_value(const struct phr_header *headers, size_t nof_headers, const char *header);
256int check_document_dates (const curlhelp_write_curlbuf *, char (*msg)[DEFAULT_BUFFER_SIZE]); 255static int check_document_dates(const curlhelp_write_curlbuf * /*header_buf*/, char (*msg)[DEFAULT_BUFFER_SIZE]);
257int get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf); 256static int get_content_length(const curlhelp_write_curlbuf *header_buf, const curlhelp_write_curlbuf *body_buf);
258 257
259#if defined(HAVE_SSL) && defined(USE_OPENSSL) 258#if defined(HAVE_SSL) && defined(USE_OPENSSL)
260int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit); 259int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit);
261#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 260#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
262 261
263void remove_newlines (char *); 262static void test_file(char * /*path*/);
264void test_file (char *);
265 263
266int 264int main(int argc, char **argv) {
267main (int argc, char **argv) 265 int result = STATE_UNKNOWN;
268{
269 int result = STATE_UNKNOWN;
270 266
271 setlocale (LC_ALL, ""); 267 setlocale(LC_ALL, "");
272 bindtextdomain (PACKAGE, LOCALEDIR); 268 bindtextdomain(PACKAGE, LOCALEDIR);
273 textdomain (PACKAGE); 269 textdomain(PACKAGE);
274 270
275 /* Parse extra opts if any */ 271 /* Parse extra opts if any */
276 argv = np_extra_opts (&argc, argv, progname); 272 argv = np_extra_opts(&argc, argv, progname);
277 273
278 /* set defaults */ 274 /* set defaults */
279 snprintf( user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s, %s)", 275 snprintf(user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s, %s)", progname, NP_VERSION, VERSION, curl_version());
280 progname, NP_VERSION, VERSION, curl_version());
281 276
282 /* parse arguments */ 277 /* parse arguments */
283 if (process_arguments (argc, argv) == false) 278 if (process_arguments(argc, argv) == false)
284 usage4 (_("Could not parse arguments")); 279 usage4(_("Could not parse arguments"));
285 280
286 if (display_html) 281 if (display_html)
287 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", 282 printf("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", use_ssl ? "https" : "http", host_name ? host_name : server_address,
288 use_ssl ? "https" : "http", 283 virtual_port ? virtual_port : server_port, server_url);
289 host_name ? host_name : server_address,
290 virtual_port ? virtual_port : server_port,
291 server_url);
292 284
293 result = check_http (); 285 result = check_http();
294 return result; 286 return result;
295} 287}
296 288
297#ifdef HAVE_SSL 289#ifdef HAVE_SSL
298#ifdef USE_OPENSSL 290# ifdef USE_OPENSSL
299 291
300int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) 292int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
301{ 293 (void)preverify_ok;
302 (void) preverify_ok; 294 /* TODO: we get all certificates of the chain, so which ones
303 /* TODO: we get all certificates of the chain, so which ones 295 * should we test?
304 * should we test? 296 * TODO: is the last certificate always the server certificate?
305 * TODO: is the last certificate always the server certificate? 297 */
306 */ 298 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
307 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 299# if OPENSSL_VERSION_NUMBER >= 0x10100000L
308#if OPENSSL_VERSION_NUMBER >= 0x10100000L 300 X509_up_ref(cert);
309 X509_up_ref(cert); 301# endif
310#endif 302 if (verbose >= 2) {
311 if (verbose>=2) { 303 puts("* SSL verify callback with certificate:");
312 puts("* SSL verify callback with certificate:"); 304 X509_NAME *subject;
313 X509_NAME *subject, *issuer; 305 X509_NAME *issuer;
314 printf("* issuer:\n"); 306 printf("* issuer:\n");
315 issuer = X509_get_issuer_name( cert ); 307 issuer = X509_get_issuer_name(cert);
316 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE); 308 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
317 printf("* curl verify_callback:\n* subject:\n"); 309 printf("* curl verify_callback:\n* subject:\n");
318 subject = X509_get_subject_name( cert ); 310 subject = X509_get_subject_name(cert);
319 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE); 311 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
320 puts(""); 312 puts("");
321 } 313 }
322 return 1; 314 return 1;
323} 315}
324 316
325CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) 317CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) {
326{ 318 (void)curl; // ignore unused parameter
327 (void) curl; // ignore unused parameter 319 (void)parm; // ignore unused parameter
328 (void) parm; // ignore unused parameter 320 if (add_sslctx_verify_fun) {
329 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); 321 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
322 }
330 323
331 return CURLE_OK; 324 // workaround for issue:
325 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
326 // see discussion https://github.com/openssl/openssl/discussions/22690
327# ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
328 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
329# endif
330
331 return CURLE_OK;
332} 332}
333 333
334#endif /* USE_OPENSSL */ 334# endif /* USE_OPENSSL */
335#endif /* HAVE_SSL */ 335#endif /* HAVE_SSL */
336 336
337/* returns a string "HTTP/1.x" or "HTTP/2" */ 337/* returns a string "HTTP/1.x" or "HTTP/2" */
338static char *string_statuscode (int major, int minor) 338static char *string_statuscode(int major, int minor) {
339{ 339 static char buf[10];
340 static char buf[10]; 340
341 341 switch (major) {
342 switch (major) { 342 case 1:
343 case 1: 343 snprintf(buf, sizeof(buf), "HTTP/%d.%d", major, minor);
344 snprintf (buf, sizeof (buf), "HTTP/%d.%d", major, minor); 344 break;
345 break; 345 case 2:
346 case 2: 346 case 3:
347 case 3: 347 snprintf(buf, sizeof(buf), "HTTP/%d", major);
348 snprintf (buf, sizeof (buf), "HTTP/%d", major); 348 break;
349 break; 349 default:
350 default: 350 /* assuming here HTTP/N with N>=4 */
351 /* assuming here HTTP/N with N>=4 */ 351 snprintf(buf, sizeof(buf), "HTTP/%d", major);
352 snprintf (buf, sizeof (buf), "HTTP/%d", major); 352 break;
353 break; 353 }
354 } 354
355 355 return buf;
356 return buf;
357} 356}
358 357
359/* Checks if the server 'reply' is one of the expected 'statuscodes' */ 358/* Checks if the server 'reply' is one of the expected 'statuscodes' */
360static int 359static int expected_statuscode(const char *reply, const char *statuscodes) {
361expected_statuscode (const char *reply, const char *statuscodes) 360 char *expected;
362{ 361 char *code;
363 char *expected, *code; 362 int result = 0;
364 int result = 0; 363
365 364 if ((expected = strdup(statuscodes)) == NULL)
366 if ((expected = strdup (statuscodes)) == NULL) 365 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
367 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n")); 366
368 367 for (code = strtok(expected, ","); code != NULL; code = strtok(NULL, ","))
369 for (code = strtok (expected, ","); code != NULL; code = strtok (NULL, ",")) 368 if (strstr(reply, code) != NULL) {
370 if (strstr (reply, code) != NULL) { 369 result = 1;
371 result = 1; 370 break;
372 break; 371 }
373 } 372
374 373 free(expected);
375 free (expected); 374 return result;
376 return result;
377} 375}
378 376
379void 377void handle_curl_option_return_code(CURLcode res, const char *option) {
380handle_curl_option_return_code (CURLcode res, const char* option) 378 if (res != CURLE_OK) {
381{ 379 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Error while setting cURL option '%s': cURL returned %d - %s"), option, res,
382 if (res != CURLE_OK) { 380 curl_easy_strerror(res));
383 snprintf (msg, 381 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
384 DEFAULT_BUFFER_SIZE, 382 }
385 _("Error while setting cURL option '%s': cURL returned %d - %s"),
386 option,
387 res,
388 curl_easy_strerror(res));
389 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
390 }
391} 383}
392 384
393int 385int lookup_host(const char *host, char *buf, size_t buflen) {
394lookup_host (const char *host, char *buf, size_t buflen) 386 struct addrinfo hints, *res, *result;
395{ 387 char addrstr[100];
396 struct addrinfo hints, *res, *result; 388 size_t addrstr_len;
397 char addrstr[100]; 389 int errcode;
398 size_t addrstr_len; 390 void *ptr = {0};
399 int errcode; 391 size_t buflen_remaining = buflen - 1;
400 void *ptr = { 0 }; 392
401 size_t buflen_remaining = buflen - 1; 393 memset(&hints, 0, sizeof(hints));
402 394 hints.ai_family = address_family;
403 memset (&hints, 0, sizeof (hints)); 395 hints.ai_socktype = SOCK_STREAM;
404 hints.ai_family = address_family; 396 hints.ai_flags |= AI_CANONNAME;
405 hints.ai_socktype = SOCK_STREAM; 397
406 hints.ai_flags |= AI_CANONNAME; 398 errcode = getaddrinfo(host, NULL, &hints, &result);
407 399 if (errcode != 0)
408 errcode = getaddrinfo (host, NULL, &hints, &result); 400 return errcode;
409 if (errcode != 0) 401
410 return errcode; 402 strcpy(buf, "");
411 403 res = result;
412 strcpy(buf, ""); 404
413 res = result; 405 while (res) {
414 406 switch (res->ai_family) {
415 while (res) { 407 case AF_INET:
416 switch (res->ai_family) { 408 ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
417 case AF_INET: 409 break;
418 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; 410 case AF_INET6:
419 break; 411 ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
420 case AF_INET6: 412 break;
421 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; 413 }
422 break; 414
423 } 415 inet_ntop(res->ai_family, ptr, addrstr, 100);
424 416 if (verbose >= 1) {
425 inet_ntop (res->ai_family, ptr, addrstr, 100); 417 printf("* getaddrinfo IPv%d address: %s\n", res->ai_family == PF_INET6 ? 6 : 4, addrstr);
426 if (verbose >= 1) { 418 }
427 printf ("* getaddrinfo IPv%d address: %s\n", 419
428 res->ai_family == PF_INET6 ? 6 : 4, addrstr); 420 // Append all IPs to buf as a comma-separated string
429 } 421 addrstr_len = strlen(addrstr);
430 422 if (buflen_remaining > addrstr_len + 1) {
431 // Append all IPs to buf as a comma-separated string 423 if (buf[0] != '\0') {
432 addrstr_len = strlen(addrstr); 424 strncat(buf, ",", buflen_remaining);
433 if (buflen_remaining > addrstr_len + 1) { 425 buflen_remaining -= 1;
434 if (buf[0] != '\0') { 426 }
435 strncat(buf, ",", buflen_remaining); 427 strncat(buf, addrstr, buflen_remaining);
436 buflen_remaining -= 1; 428 buflen_remaining -= addrstr_len;
437 } 429 }
438 strncat(buf, addrstr, buflen_remaining); 430
439 buflen_remaining -= addrstr_len; 431 res = res->ai_next;
440 } 432 }
441 433
442 res = res->ai_next; 434 freeaddrinfo(result);
443 } 435
444 436 return 0;
445 freeaddrinfo(result);
446
447 return 0;
448} 437}
449 438
450static void 439static void cleanup(void) {
451cleanup (void) 440 if (status_line_initialized)
452{ 441 curlhelp_free_statusline(&status_line);
453 if (status_line_initialized) curlhelp_free_statusline(&status_line); 442 status_line_initialized = false;
454 status_line_initialized = false; 443 if (curl_easy_initialized)
455 if (curl_easy_initialized) curl_easy_cleanup (curl); 444 curl_easy_cleanup(curl);
456 curl_easy_initialized = false; 445 curl_easy_initialized = false;
457 if (curl_global_initialized) curl_global_cleanup (); 446 if (curl_global_initialized)
458 curl_global_initialized = false; 447 curl_global_cleanup();
459 if (body_buf_initialized) curlhelp_freewritebuffer (&body_buf); 448 curl_global_initialized = false;
460 body_buf_initialized = false; 449 if (body_buf_initialized)
461 if (header_buf_initialized) curlhelp_freewritebuffer (&header_buf); 450 curlhelp_freewritebuffer(&body_buf);
462 header_buf_initialized = false; 451 body_buf_initialized = false;
463 if (put_buf_initialized) curlhelp_freereadbuffer (&put_buf); 452 if (header_buf_initialized)
464 put_buf_initialized = false; 453 curlhelp_freewritebuffer(&header_buf);
454 header_buf_initialized = false;
455 if (put_buf_initialized)
456 curlhelp_freereadbuffer(&put_buf);
457 put_buf_initialized = false;
465} 458}
466 459
467int 460int check_http(void) {
468check_http (void) 461 int result = STATE_OK;
469{ 462 int result_ssl = STATE_OK;
470 int result = STATE_OK; 463 int page_len = 0;
471 int result_ssl = STATE_OK; 464 int i;
472 int page_len = 0; 465 char *force_host_header = NULL;
473 int i; 466 struct curl_slist *host = NULL;
474 char *force_host_header = NULL; 467 char addrstr[DEFAULT_BUFFER_SIZE / 2];
475 struct curl_slist *host = NULL; 468 char dnscache[DEFAULT_BUFFER_SIZE];
476 char addrstr[DEFAULT_BUFFER_SIZE/2]; 469
477 char dnscache[DEFAULT_BUFFER_SIZE]; 470 /* initialize curl */
478 471 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
479 /* initialize curl */ 472 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
480 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 473 curl_global_initialized = true;
481 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 474
482 curl_global_initialized = true; 475 if ((curl = curl_easy_init()) == NULL) {
483 476 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
484 if ((curl = curl_easy_init()) == NULL) { 477 }
485 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 478 curl_easy_initialized = true;
486 } 479
487 curl_easy_initialized = true; 480 /* register cleanup function to shut down libcurl properly */
488 481 atexit(cleanup);
489 /* register cleanup function to shut down libcurl properly */ 482
490 atexit (cleanup); 483 if (verbose >= 1)
491 484 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE");
492 if (verbose >= 1) 485
493 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE"); 486 /* print everything on stdout like check_http would do */
494 487 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR");
495 /* print everything on stdout like check_http would do */ 488
496 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR"); 489 if (automatic_decompression)
497
498 if (automatic_decompression)
499#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) 490#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
500 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), "CURLOPT_ACCEPT_ENCODING"); 491 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), "CURLOPT_ACCEPT_ENCODING");
501#else 492#else
502 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING"); 493 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING");
503#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */ 494#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
504 495
505 /* initialize buffer for body of the answer */ 496 /* initialize buffer for body of the answer */
506 if (curlhelp_initwritebuffer(&body_buf) < 0) 497 if (curlhelp_initwritebuffer(&body_buf) < 0)
507 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 498 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
508 body_buf_initialized = true; 499 body_buf_initialized = true;
509 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_WRITEFUNCTION"); 500 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback),
510 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA"); 501 "CURLOPT_WRITEFUNCTION");
511 502 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA");
512 /* initialize buffer for header of the answer */ 503
513 if (curlhelp_initwritebuffer( &header_buf ) < 0) 504 /* initialize buffer for header of the answer */
514 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); 505 if (curlhelp_initwritebuffer(&header_buf) < 0)
515 header_buf_initialized = true; 506 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n");
516 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_HEADERFUNCTION"); 507 header_buf_initialized = true;
517 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER"); 508 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback),
518 509 "CURLOPT_HEADERFUNCTION");
519 /* set the error buffer */ 510 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER");
520 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER"); 511
521 512 /* set the error buffer */
522 /* set timeouts */ 513 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER");
523 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT"); 514
524 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT"); 515 /* set timeouts */
525 516 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT");
526 /* enable haproxy protocol */ 517 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT");
527 if (haproxy_protocol) { 518
528 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL"); 519 /* enable haproxy protocol */
529 } 520 if (haproxy_protocol) {
530 521 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL");
531 // fill dns resolve cache to make curl connect to the given server_address instead of the host_name, only required for ssl, because we use the host_name later on to make SNI happy 522 }
532 if(use_ssl && host_name != NULL) { 523
533 if ( (res=lookup_host (server_address, addrstr, DEFAULT_BUFFER_SIZE/2)) != 0) { 524 // fill dns resolve cache to make curl connect to the given server_address instead of the host_name, only required for ssl, because we
534 snprintf (msg, 525 // use the host_name later on to make SNI happy
535 DEFAULT_BUFFER_SIZE, 526 if (use_ssl && host_name != NULL) {
536 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), 527 if ((res = lookup_host(server_address, addrstr, DEFAULT_BUFFER_SIZE / 2)) != 0) {
537 server_address, 528 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %d"), server_address, res,
538 res, 529 gai_strerror(res));
539 gai_strerror (res)); 530 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
540 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 531 }
541 } 532 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr);
542 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr); 533 host = curl_slist_append(NULL, dnscache);
543 host = curl_slist_append(NULL, dnscache); 534 curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
544 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 535 if (verbose >= 1)
545 if (verbose>=1) 536 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache);
546 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache); 537 }
547 } 538
548 539 // If server_address is an IPv6 address it must be surround by square brackets
549 // If server_address is an IPv6 address it must be surround by square brackets 540 struct in6_addr tmp_in_addr;
550 struct in6_addr tmp_in_addr; 541 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) {
551 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) { 542 char *new_server_address = malloc(strlen(server_address) + 3);
552 char *new_server_address = malloc(strlen(server_address) + 3); 543 if (new_server_address == NULL) {
553 if (new_server_address == NULL) { 544 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
554 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n"); 545 }
555 } 546 snprintf(new_server_address, strlen(server_address) + 3, "[%s]", server_address);
556 snprintf(new_server_address, strlen(server_address)+3, "[%s]", server_address); 547 free(server_address);
557 free(server_address); 548 server_address = new_server_address;
558 server_address = new_server_address; 549 }
559 } 550
560 551 /* compose URL: use the address we want to connect to, set Host: header later */
561 /* compose URL: use the address we want to connect to, set Host: header later */ 552 snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", use_ssl ? "https" : "http",
562 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", 553 (use_ssl & (host_name != NULL)) ? host_name : server_address, server_port, server_url);
563 use_ssl ? "https" : "http", 554
564 ( use_ssl & ( host_name != NULL ) ) ? host_name : server_address, 555 if (verbose >= 1)
565 server_port, 556 printf("* curl CURLOPT_URL: %s\n", url);
566 server_url 557 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, url), "CURLOPT_URL");
567 ); 558
568 559 /* extract proxy information for legacy proxy https requests */
569 if (verbose>=1) 560 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) {
570 printf ("* curl CURLOPT_URL: %s\n", url); 561 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY");
571 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, url), "CURLOPT_URL"); 562 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT");
572 563 if (verbose >= 2)
573 /* extract proxy information for legacy proxy https requests */ 564 printf("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port);
574 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) { 565 http_method = "GET";
575 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY"); 566 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, server_url), "CURLOPT_URL");
576 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT"); 567 }
577 if (verbose>=2) 568
578 printf ("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port); 569 /* disable body for HEAD request */
579 http_method = "GET"; 570 if (http_method && !strcmp(http_method, "HEAD")) {
580 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, server_url), "CURLOPT_URL"); 571 no_body = true;
581 } 572 }
582 573
583 /* disable body for HEAD request */ 574 /* set HTTP protocol version */
584 if (http_method && !strcmp (http_method, "HEAD" )) { 575 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, curl_http_version), "CURLOPT_HTTP_VERSION");
585 no_body = true; 576
586 } 577 /* set HTTP method */
587 578 if (http_method) {
588 /* set HTTP protocol version */ 579 if (!strcmp(http_method, "POST"))
589 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HTTP_VERSION, curl_http_version), "CURLOPT_HTTP_VERSION"); 580 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POST, 1), "CURLOPT_POST");
590 581 else if (!strcmp(http_method, "PUT"))
591 /* set HTTP method */ 582 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD");
592 if (http_method) { 583 else
593 if (!strcmp(http_method, "POST")) 584 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST");
594 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POST, 1), "CURLOPT_POST"); 585 }
595 else if (!strcmp(http_method, "PUT")) 586
596 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD"); 587 /* check if Host header is explicitly set in options */
597 else 588 if (http_opt_headers_count) {
598 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST"); 589 for (i = 0; i < http_opt_headers_count; i++) {
599 } 590 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) {
600 591 force_host_header = http_opt_headers[i];
601 /* check if Host header is explicitly set in options */ 592 }
602 if (http_opt_headers_count) { 593 }
603 for (i = 0; i < http_opt_headers_count ; i++) { 594 }
604 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) { 595
605 force_host_header = http_opt_headers[i]; 596 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */
606 } 597 if (host_name != NULL && force_host_header == NULL) {
607 } 598 if ((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) {
608 } 599 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port);
609 600 } else {
610 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */ 601 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name);
611 if(host_name != NULL && force_host_header == NULL) { 602 }
612 if((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) { 603 header_list = curl_slist_append(header_list, http_header);
613 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port); 604 }
614 } else { 605
615 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name); 606 /* always close connection, be nice to servers */
616 } 607 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Connection: close");
617 header_list = curl_slist_append (header_list, http_header); 608 header_list = curl_slist_append(header_list, http_header);
618 } 609
619 610 /* attach additional headers supplied by the user */
620 /* always close connection, be nice to servers */ 611 /* optionally send any other header tag */
621 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Connection: close"); 612 if (http_opt_headers_count) {
622 header_list = curl_slist_append (header_list, http_header); 613 for (i = 0; i < http_opt_headers_count; i++) {
623 614 header_list = curl_slist_append(header_list, http_opt_headers[i]);
624 /* attach additional headers supplied by the user */ 615 }
625 /* optionally send any other header tag */ 616 /* This cannot be free'd here because a redirection will then try to access this and segfault */
626 if (http_opt_headers_count) { 617 /* Covered in a testcase in tests/check_http.t */
627 for (i = 0; i < http_opt_headers_count ; i++) { 618 /* free(http_opt_headers); */
628 header_list = curl_slist_append (header_list, http_opt_headers[i]); 619 }
629 } 620
630 /* This cannot be free'd here because a redirection will then try to access this and segfault */ 621 /* set HTTP headers */
631 /* Covered in a testcase in tests/check_http.t */ 622 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list), "CURLOPT_HTTPHEADER");
632 /* free(http_opt_headers); */
633 }
634
635 /* set HTTP headers */
636 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ), "CURLOPT_HTTPHEADER");
637 623
638#ifdef LIBCURL_FEATURE_SSL 624#ifdef LIBCURL_FEATURE_SSL
639 625
640 /* set SSL version, warn about insecure or unsupported versions */ 626 /* set SSL version, warn about insecure or unsupported versions */
641 if (use_ssl) { 627 if (use_ssl) {
642 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION"); 628 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION");
643 } 629 }
644 630
645 /* client certificate and key to present to server (SSL) */ 631 /* client certificate and key to present to server (SSL) */
646 if (client_cert) 632 if (client_cert)
647 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert), "CURLOPT_SSLCERT"); 633 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert), "CURLOPT_SSLCERT");
648 if (client_privkey) 634 if (client_privkey)
649 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY"); 635 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY");
650 if (ca_cert) { 636 if (ca_cert) {
651 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO"); 637 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
652 } 638 }
653 if (ca_cert || verify_peer_and_host) { 639 if (ca_cert || verify_peer_and_host) {
654 /* per default if we have a CA verify both the peer and the 640 /* per default if we have a CA verify both the peer and the
655 * hostname in the certificate, can be switched off later */ 641 * hostname in the certificate, can be switched off later */
656 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER"); 642 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER");
657 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST"); 643 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST");
658 } else { 644 } else {
659 /* backward-compatible behaviour, be tolerant in checks 645 /* backward-compatible behaviour, be tolerant in checks
660 * TODO: depending on more options have aspects we want 646 * TODO: depending on more options have aspects we want
661 * to be less tolerant about ssl verfications 647 * to be less tolerant about ssl verfications
662 */ 648 */
663 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER"); 649 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER");
664 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST"); 650 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST");
665 } 651 }
666 652
667 /* detect SSL library used by libcurl */ 653 /* detect SSL library used by libcurl */
668 ssl_library = curlhelp_get_ssl_library (); 654 ssl_library = curlhelp_get_ssl_library();
669 655
670 /* try hard to get a stack of certificates to verify against */ 656 /* try hard to get a stack of certificates to verify against */
671 if (check_cert) { 657 if (check_cert) {
672#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) 658# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1)
673 /* inform curl to report back certificates */ 659 /* inform curl to report back certificates */
674 switch (ssl_library) { 660 switch (ssl_library) {
675 case CURLHELP_SSL_LIBRARY_OPENSSL: 661 case CURLHELP_SSL_LIBRARY_OPENSSL:
676 case CURLHELP_SSL_LIBRARY_LIBRESSL: 662 case CURLHELP_SSL_LIBRARY_LIBRESSL:
677 /* set callback to extract certificate with OpenSSL context function (works with 663 /* set callback to extract certificate with OpenSSL context function (works with
678 * OpenSSL-style libraries only!) */ 664 * OpenSSL-style libraries only!) */
679#ifdef USE_OPENSSL 665# ifdef USE_OPENSSL
680 /* libcurl and monitoring plugins built with OpenSSL, good */ 666 /* libcurl and monitoring plugins built with OpenSSL, good */
681 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 667 add_sslctx_verify_fun = true;
682 is_openssl_callback = true; 668 is_openssl_callback = true;
683#else /* USE_OPENSSL */ 669# endif /* USE_OPENSSL */
684#endif /* USE_OPENSSL */ 670 /* libcurl is built with OpenSSL, monitoring plugins, so falling
685 /* libcurl is built with OpenSSL, monitoring plugins, so falling 671 * back to manually extracting certificate information */
686 * back to manually extracting certificate information */ 672 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
687 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 673 break;
688 break; 674
689 675 case CURLHELP_SSL_LIBRARY_NSS:
690 case CURLHELP_SSL_LIBRARY_NSS: 676# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
691#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 677 /* NSS: support for CERTINFO is implemented since 7.34.0 */
692 /* NSS: support for CERTINFO is implemented since 7.34.0 */ 678 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
693 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 679# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
694#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 680 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
695 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); 681 curlhelp_get_ssl_library_string(ssl_library));
696#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 682# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
697 break; 683 break;
698 684
699 case CURLHELP_SSL_LIBRARY_GNUTLS: 685 case CURLHELP_SSL_LIBRARY_GNUTLS:
700#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) 686# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0)
701 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */ 687 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */
702 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 688 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
703#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 689# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
704 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); 690 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
705#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 691 curlhelp_get_ssl_library_string(ssl_library));
706 break; 692# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
707 693 break;
708 case CURLHELP_SSL_LIBRARY_UNKNOWN: 694
709 default: 695 case CURLHELP_SSL_LIBRARY_UNKNOWN:
710 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n", curlhelp_get_ssl_library_string (ssl_library)); 696 default:
711 break; 697 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n",
712 } 698 curlhelp_get_ssl_library_string(ssl_library));
713#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 699 break;
714 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */ 700 }
715 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL) 701# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
716 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 702 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */
717 else 703 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL)
718 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl too old and has no CURLOPT_CERTINFO)\n"); 704 add_sslctx_verify_fun = true;
719#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 705 else
720 } 706 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl "
707 "too old and has no CURLOPT_CERTINFO)\n");
708# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
709 }
710
711# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */
712 // ssl ctx function is not available with all ssl backends
713 if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION)
714 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
715# endif
721 716
722#endif /* LIBCURL_FEATURE_SSL */ 717#endif /* LIBCURL_FEATURE_SSL */
723 718
724 /* set default or user-given user agent identification */ 719 /* set default or user-given user agent identification */
725 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent), "CURLOPT_USERAGENT"); 720 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent), "CURLOPT_USERAGENT");
726 721
727 /* proxy-authentication */ 722 /* proxy-authentication */
728 if (strcmp(proxy_auth, "")) 723 if (strcmp(proxy_auth, ""))
729 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXYUSERPWD, proxy_auth), "CURLOPT_PROXYUSERPWD"); 724 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_auth), "CURLOPT_PROXYUSERPWD");
730 725
731 /* authentication */ 726 /* authentication */
732 if (strcmp(user_auth, "")) 727 if (strcmp(user_auth, ""))
733 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth), "CURLOPT_USERPWD"); 728 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERPWD, user_auth), "CURLOPT_USERPWD");
734 729
735 /* TODO: parameter auth method, bitfield of following methods: 730 /* TODO: parameter auth method, bitfield of following methods:
736 * CURLAUTH_BASIC (default) 731 * CURLAUTH_BASIC (default)
737 * CURLAUTH_DIGEST 732 * CURLAUTH_DIGEST
738 * CURLAUTH_DIGEST_IE 733 * CURLAUTH_DIGEST_IE
739 * CURLAUTH_NEGOTIATE 734 * CURLAUTH_NEGOTIATE
740 * CURLAUTH_NTLM 735 * CURLAUTH_NTLM
741 * CURLAUTH_NTLM_WB 736 * CURLAUTH_NTLM_WB
742 * 737 *
743 * convenience tokens for typical sets of methods: 738 * convenience tokens for typical sets of methods:
744 * CURLAUTH_ANYSAFE: most secure, without BASIC 739 * CURLAUTH_ANYSAFE: most secure, without BASIC
745 * or CURLAUTH_ANY: most secure, even BASIC if necessary 740 * or CURLAUTH_ANY: most secure, even BASIC if necessary
746 * 741 *
747 * handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ), "CURLOPT_HTTPAUTH"); 742 * handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ), "CURLOPT_HTTPAUTH");
748 */ 743 */
749 744
750 /* handle redirections */ 745 /* handle redirections */
751 if (onredirect == STATE_DEPENDENT) { 746 if (onredirect == STATE_DEPENDENT) {
752 if( followmethod == FOLLOW_LIBCURL ) { 747 if (followmethod == FOLLOW_LIBCURL) {
753 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1), "CURLOPT_FOLLOWLOCATION"); 748 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1), "CURLOPT_FOLLOWLOCATION");
754 749
755 /* default -1 is infinite, not good, could lead to zombie plugins! 750 /* default -1 is infinite, not good, could lead to zombie plugins!
756 Setting it to one bigger than maximal limit to handle errors nicely below 751 Setting it to one bigger than maximal limit to handle errors nicely below
757 */ 752 */
758 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_MAXREDIRS, max_depth+1), "CURLOPT_MAXREDIRS"); 753 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_MAXREDIRS, max_depth + 1), "CURLOPT_MAXREDIRS");
759 754
760 /* for now allow only http and https (we are a http(s) check plugin in the end) */ 755 /* for now allow only http and https (we are a http(s) check plugin in the end) */
761#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0) 756#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
762 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"), "CURLOPT_REDIR_PROTOCOLS_STR"); 757 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"),
758 "CURLOPT_REDIR_PROTOCOLS_STR");
763#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) 759#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
764 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS), "CURLOPT_REDIRECT_PROTOCOLS"); 760 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS),
761 "CURLOPT_REDIRECT_PROTOCOLS");
765#endif 762#endif
766 763
767 /* TODO: handle the following aspects of redirection, make them 764 /* TODO: handle the following aspects of redirection, make them
768 * command line options too later: 765 * command line options too later:
769 CURLOPT_POSTREDIR: method switch 766 CURLOPT_POSTREDIR: method switch
770 CURLINFO_REDIRECT_URL: custom redirect option 767 CURLINFO_REDIRECT_URL: custom redirect option
771 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols 768 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols
772 CURLINFO_REDIRECT_COUNT: get the number of redirects, print it, maybe a range option here is nice like for expected page size? 769 CURLINFO_REDIRECT_COUNT: get the number of redirects, print it, maybe a range option here is nice like for expected page size?
773 */ 770 */
774 } else { 771 } else {
775 /* old style redirection is handled below */ 772 /* old style redirection is handled below */
776 } 773 }
777 } 774 }
778 775
779 /* no-body */ 776 /* no-body */
780 if (no_body) 777 if (no_body)
781 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY"); 778 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY");
782 779
783 /* IPv4 or IPv6 forced DNS resolution */ 780 /* IPv4 or IPv6 forced DNS resolution */
784 if (address_family == AF_UNSPEC) 781 if (address_family == AF_UNSPEC)
785 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)"); 782 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER),
786 else if (address_family == AF_INET) 783 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
787 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)"); 784 else if (address_family == AF_INET)
788#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 785 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
789 else if (address_family == AF_INET6) 786 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
790 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)"); 787#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
788 else if (address_family == AF_INET6)
789 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6),
790 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
791#endif 791#endif
792 792
793 /* either send http POST data (any data, not only POST)*/ 793 /* either send http POST data (any data, not only POST)*/
794 if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) { 794 if (!strcmp(http_method, "POST") || !strcmp(http_method, "PUT")) {
795 /* set content of payload for POST and PUT */ 795 /* set content of payload for POST and PUT */
796 if (http_content_type) { 796 if (http_content_type) {
797 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", http_content_type); 797 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", http_content_type);
798 header_list = curl_slist_append (header_list, http_header); 798 header_list = curl_slist_append(header_list, http_header);
799 } 799 }
800 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string 800 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string
801 * in case of no POST/PUT data */ 801 * in case of no POST/PUT data */
802 if (!http_post_data) 802 if (!http_post_data)
803 http_post_data = ""; 803 http_post_data = "";
804 if (!strcmp(http_method, "POST")) { 804 if (!strcmp(http_method, "POST")) {
805 /* POST method, set payload with CURLOPT_POSTFIELDS */ 805 /* POST method, set payload with CURLOPT_POSTFIELDS */
806 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS"); 806 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS");
807 } else if (!strcmp(http_method, "PUT")) { 807 } else if (!strcmp(http_method, "PUT")) {
808 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback), "CURLOPT_READFUNCTION"); 808 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback),
809 if (curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)) < 0) 809 "CURLOPT_READFUNCTION");
810 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n"); 810 if (curlhelp_initreadbuffer(&put_buf, http_post_data, strlen(http_post_data)) < 0)
811 put_buf_initialized = true; 811 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
812 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA"); 812 put_buf_initialized = true;
813 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)), "CURLOPT_INFILESIZE"); 813 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA");
814 } 814 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_INFILESIZE, (curl_off_t)strlen(http_post_data)),
815 } 815 "CURLOPT_INFILESIZE");
816 816 }
817 /* cookie handling */ 817 }
818 if (cookie_jar_file != NULL) { 818
819 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR"); 819 /* cookie handling */
820 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE"); 820 if (cookie_jar_file != NULL) {
821 } 821 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR");
822 822 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE");
823 /* do the request */ 823 }
824 res = curl_easy_perform(curl); 824
825 825 /* do the request */
826 if (verbose>=2 && http_post_data) 826 res = curl_easy_perform(curl);
827 printf ("**** REQUEST CONTENT ****\n%s\n", http_post_data); 827
828 828 if (verbose >= 2 && http_post_data)
829 /* free header and server IP resolve lists, we don't need it anymore */ 829 printf("**** REQUEST CONTENT ****\n%s\n", http_post_data);
830 curl_slist_free_all (header_list); header_list = NULL; 830
831 curl_slist_free_all (server_ips); server_ips = NULL; 831 /* free header and server IP resolve lists, we don't need it anymore */
832 if (host) { 832 curl_slist_free_all(header_list);
833 curl_slist_free_all (host); host = NULL; 833 header_list = NULL;
834 } 834 curl_slist_free_all(server_ips);
835 835 server_ips = NULL;
836 /* Curl errors, result in critical Nagios state */ 836 if (host) {
837 if (res != CURLE_OK) { 837 curl_slist_free_all(host);
838 snprintf (msg, 838 host = NULL;
839 DEFAULT_BUFFER_SIZE, 839 }
840 _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 840
841 server_port, 841 /* Curl errors, result in critical Nagios state */
842 res, 842 if (res != CURLE_OK) {
843 errbuf[0] ? errbuf : curl_easy_strerror(res)); 843 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), server_port,
844 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 844 res, errbuf[0] ? errbuf : curl_easy_strerror(res));
845 } 845 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
846 846 }
847 /* certificate checks */ 847
848 /* certificate checks */
848#ifdef LIBCURL_FEATURE_SSL 849#ifdef LIBCURL_FEATURE_SSL
849 if (use_ssl) { 850 if (use_ssl) {
850 if (check_cert) { 851 if (check_cert) {
851 if (is_openssl_callback) { 852 if (is_openssl_callback) {
852#ifdef USE_OPENSSL 853# ifdef USE_OPENSSL
853 /* check certificate with OpenSSL functions, curl has been built against OpenSSL 854 /* check certificate with OpenSSL functions, curl has been built against OpenSSL
854 * and we actually have OpenSSL in the monitoring tools 855 * and we actually have OpenSSL in the monitoring tools
855 */ 856 */
856 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 857 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
857 if (!continue_after_check_cert) { 858 if (!continue_after_check_cert) {
858 return result_ssl; 859 return result_ssl;
859 } 860 }
860#else /* USE_OPENSSL */ 861# else /* USE_OPENSSL */
861 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); 862 die(STATE_CRITICAL,
862#endif /* USE_OPENSSL */ 863 "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n");
863 } else { 864# endif /* USE_OPENSSL */
864 int i; 865 } else {
865 struct curl_slist *slist; 866 int i;
866 867 struct curl_slist *slist;
867 cert_ptr.to_info = NULL; 868
868 res = curl_easy_getinfo (curl, CURLINFO_CERTINFO, &cert_ptr.to_info); 869 cert_ptr.to_info = NULL;
869 if (!res && cert_ptr.to_info) { 870 res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
870#ifdef USE_OPENSSL 871 if (!res && cert_ptr.to_info) {
871 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert parsing 872# ifdef USE_OPENSSL
872 * We only check the first certificate and assume it's the one of the server 873 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert parsing
873 */ 874 * We only check the first certificate and assume it's the one of the server
874 const char* raw_cert = NULL; 875 */
875 for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { 876 const char *raw_cert = NULL;
876 for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) { 877 for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) {
877 if (verbose >= 2) 878 for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) {
878 printf ("%d ** %s\n", i, slist->data); 879 if (verbose >= 2)
879 if (strncmp (slist->data, "Cert:", 5) == 0) { 880 printf("%d ** %s\n", i, slist->data);
880 raw_cert = &slist->data[5]; 881 if (strncmp(slist->data, "Cert:", 5) == 0) {
881 goto GOT_FIRST_CERT; 882 raw_cert = &slist->data[5];
882 } 883 goto GOT_FIRST_CERT;
883 } 884 }
884 } 885 }
885GOT_FIRST_CERT: 886 }
886 if (!raw_cert) { 887 GOT_FIRST_CERT:
887 snprintf (msg, 888 if (!raw_cert) {
888 DEFAULT_BUFFER_SIZE, 889 snprintf(msg, DEFAULT_BUFFER_SIZE,
889 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty")); 890 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty"));
890 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 891 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
891 } 892 }
892 BIO* cert_BIO = BIO_new (BIO_s_mem()); 893 BIO *cert_BIO = BIO_new(BIO_s_mem());
893 BIO_write (cert_BIO, raw_cert, strlen(raw_cert)); 894 BIO_write(cert_BIO, raw_cert, strlen(raw_cert));
894 cert = PEM_read_bio_X509 (cert_BIO, NULL, NULL, NULL); 895 cert = PEM_read_bio_X509(cert_BIO, NULL, NULL, NULL);
895 if (!cert) { 896 if (!cert) {
896 snprintf (msg, 897 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot read certificate from CERTINFO information - BIO error"));
897 DEFAULT_BUFFER_SIZE, 898 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
898 _("Cannot read certificate from CERTINFO information - BIO error")); 899 }
899 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 900 BIO_free(cert_BIO);
900 } 901 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
901 BIO_free (cert_BIO); 902 if (!continue_after_check_cert) {
902 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 903 return result_ssl;
903 if (!continue_after_check_cert) { 904 }
904 return result_ssl; 905# else /* USE_OPENSSL */
905 } 906 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal,
906#else /* USE_OPENSSL */ 907 * so we use the libcurl CURLINFO data
907 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal, 908 */
908 * so we use the libcurl CURLINFO data 909 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit);
909 */ 910 if (!continue_after_check_cert) {
910 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit); 911 return result_ssl;
911 if (!continue_after_check_cert) { 912 }
912 return result_ssl; 913# endif /* USE_OPENSSL */
913 } 914 } else {
914#endif /* USE_OPENSSL */ 915 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), res,
915 } else { 916 curl_easy_strerror(res));
916 snprintf (msg, 917 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
917 DEFAULT_BUFFER_SIZE, 918 }
918 _("Cannot retrieve certificates - cURL returned %d - %s"), 919 }
919 res, 920 }
920 curl_easy_strerror(res)); 921 }
921 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
922 }
923 }
924 }
925 }
926#endif /* LIBCURL_FEATURE_SSL */ 922#endif /* LIBCURL_FEATURE_SSL */
927 923
928 /* we got the data and we executed the request in a given time, so we can append 924 /* we got the data and we executed the request in a given time, so we can append
929 * performance data to the answer always 925 * performance data to the answer always
930 */ 926 */
931 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time), "CURLINFO_TOTAL_TIME"); 927 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time), "CURLINFO_TOTAL_TIME");
932 page_len = get_content_length(&header_buf, &body_buf); 928 page_len = get_content_length(&header_buf, &body_buf);
933 if(show_extended_perfdata) { 929 if (show_extended_perfdata) {
934 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME"); 930 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME");
935 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), "CURLINFO_APPCONNECT_TIME"); 931 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), "CURLINFO_APPCONNECT_TIME");
936 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers), "CURLINFO_PRETRANSFER_TIME"); 932 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers), "CURLINFO_PRETRANSFER_TIME");
937 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte), "CURLINFO_STARTTRANSFER_TIME"); 933 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte),
938 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", 934 "CURLINFO_STARTTRANSFER_TIME");
939 perfd_time(total_time), 935 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", perfd_time(total_time), perfd_size(page_len),
940 perfd_size(page_len), 936 perfd_time_connect(time_connect), use_ssl ? perfd_time_ssl(time_appconnect - time_connect) : "",
941 perfd_time_connect(time_connect), 937 perfd_time_headers(time_headers - time_appconnect), perfd_time_firstbyte(time_firstbyte - time_headers),
942 use_ssl ? perfd_time_ssl (time_appconnect-time_connect) : "", 938 perfd_time_transfer(total_time - time_firstbyte));
943 perfd_time_headers(time_headers - time_appconnect), 939 } else {
944 perfd_time_firstbyte(time_firstbyte - time_headers), 940 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s", perfd_time(total_time), perfd_size(page_len));
945 perfd_time_transfer(total_time-time_firstbyte) 941 }
946 );
947 } else {
948 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s",
949 perfd_time(total_time),
950 perfd_size(page_len)
951 );
952 }
953
954 /* return a CRITICAL status if we couldn't read any data */
955 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
956 die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
957
958 /* get status line of answer, check sanity of HTTP code */
959 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
960 snprintf (msg,
961 DEFAULT_BUFFER_SIZE,
962 "Unparsable status line in %.3g seconds response time|%s\n",
963 total_time,
964 perfstring);
965 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
966 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
967 }
968 status_line_initialized = true;
969
970 /* get result code from cURL */
971 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
972 if (verbose>=2)
973 printf ("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
974
975 /* print status line, header, body if verbose */
976 if (verbose >= 2) {
977 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf,
978 (no_body ? " [[ skipped ]]" : body_buf.buf));
979 }
980
981 /* make sure the status line matches the response we are looking for */
982 if (!expected_statuscode(status_line.first_line, server_expect)) {
983 if (server_port == HTTP_PORT)
984 snprintf(msg,
985 DEFAULT_BUFFER_SIZE,
986 _("Invalid HTTP response received from host: %s\n"),
987 status_line.first_line);
988 else
989 snprintf(msg,
990 DEFAULT_BUFFER_SIZE,
991 _("Invalid HTTP response received from host on port %d: %s\n"),
992 server_port,
993 status_line.first_line);
994 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
995 show_body ? "\n" : "",
996 show_body ? body_buf.buf : "");
997 }
998
999 if( server_expect_yn ) {
1000 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), server_expect);
1001 if (verbose)
1002 printf ("%s\n",msg);
1003 result = STATE_OK;
1004 }
1005 else {
1006 /* illegal return codes result in a critical state */
1007 if (code >= 600 || code < 100) {
1008 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
1009 /* server errors result in a critical state */
1010 } else if (code >= 500) {
1011 result = STATE_CRITICAL;
1012 /* client errors result in a warning state */
1013 } else if (code >= 400) {
1014 result = STATE_WARNING;
1015 /* check redirected page if specified */
1016 } else if (code >= 300) {
1017 if (onredirect == STATE_DEPENDENT) {
1018 if( followmethod == FOLLOW_LIBCURL ) {
1019 code = status_line.http_code;
1020 } else {
1021 /* old check_http style redirection, if we come
1022 * back here, we are in the same status as with
1023 * the libcurl method
1024 */
1025 redir (&header_buf);
1026 }
1027 } else {
1028 /* this is a specific code in the command line to
1029 * be returned when a redirection is encountered
1030 */
1031 }
1032 result = max_state_alt (onredirect, result);
1033 /* all other codes are considered ok */
1034 } else {
1035 result = STATE_OK;
1036 }
1037 }
1038
1039 /* libcurl redirection internally, handle error states here */
1040 if( followmethod == FOLLOW_LIBCURL ) {
1041 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_REDIRECT_COUNT, &redir_depth), "CURLINFO_REDIRECT_COUNT");
1042 if (verbose >= 2)
1043 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
1044 if (redir_depth > max_depth) {
1045 snprintf (msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl",
1046 max_depth);
1047 die (STATE_WARNING, "HTTP WARNING - %s", msg);
1048 }
1049 }
1050
1051 /* check status codes, set exit status accordingly */
1052 if( status_line.http_code != code ) {
1053 die (STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1054 string_statuscode (status_line.http_major, status_line.http_minor),
1055 status_line.http_code, status_line.msg, code);
1056 }
1057
1058 if (maximum_age >= 0) {
1059 result = max_state_alt(check_document_dates(&header_buf, &msg), result);
1060 }
1061
1062 /* Page and Header content checks go here */
1063
1064 if (strlen (header_expect)) {
1065 if (!strstr (header_buf.buf, header_expect)) {
1066
1067 strncpy(&output_header_search[0],header_expect,sizeof(output_header_search));
1068
1069 if(output_header_search[sizeof(output_header_search)-1]!='\0') {
1070 bcopy("...",&output_header_search[sizeof(output_header_search)-4],4);
1071 }
1072 942
1073 char tmp[DEFAULT_BUFFER_SIZE]; 943 /* return a CRITICAL status if we couldn't read any data */
944 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
945 die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
1074 946
1075 snprintf (tmp, 947 /* get status line of answer, check sanity of HTTP code */
1076 DEFAULT_BUFFER_SIZE, 948 if (curlhelp_parse_statusline(header_buf.buf, &status_line) < 0) {
1077 _("%sheader '%s' not found on '%s://%s:%d%s', "), 949 snprintf(msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n", total_time, perfstring);
1078 msg, 950 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
1079 output_header_search, 951 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
1080 use_ssl ? "https" : "http", 952 }
1081 host_name ? host_name : server_address, 953 status_line_initialized = true;
1082 server_port,
1083 server_url);
1084 954
1085 strcpy(msg, tmp); 955 /* get result code from cURL */
956 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
957 if (verbose >= 2)
958 printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
1086 959
1087 result = STATE_CRITICAL; 960 /* print status line, header, body if verbose */
1088 } 961 if (verbose >= 2) {
1089 } 962 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf, (no_body ? " [[ skipped ]]" : body_buf.buf));
963 }
1090 964
1091 if (strlen (string_expect)) { 965 /* make sure the status line matches the response we are looking for */
1092 if (!strstr (body_buf.buf, string_expect)) { 966 if (!expected_statuscode(status_line.first_line, server_expect)) {
967 if (server_port == HTTP_PORT)
968 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line);
969 else
970 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port,
971 status_line.first_line);
972 die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, show_body ? "\n" : "", show_body ? body_buf.buf : "");
973 }
1093 974
1094 strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); 975 if (server_expect_yn) {
976 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), server_expect);
977 if (verbose)
978 printf("%s\n", msg);
979 result = STATE_OK;
980 } else {
981 /* illegal return codes result in a critical state */
982 if (code >= 600 || code < 100) {
983 die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
984 /* server errors result in a critical state */
985 } else if (code >= 500) {
986 result = STATE_CRITICAL;
987 /* client errors result in a warning state */
988 } else if (code >= 400) {
989 result = STATE_WARNING;
990 /* check redirected page if specified */
991 } else if (code >= 300) {
992 if (onredirect == STATE_DEPENDENT) {
993 if (followmethod == FOLLOW_LIBCURL) {
994 code = status_line.http_code;
995 } else {
996 /* old check_http style redirection, if we come
997 * back here, we are in the same status as with
998 * the libcurl method
999 */
1000 redir(&header_buf);
1001 }
1002 } else {
1003 /* this is a specific code in the command line to
1004 * be returned when a redirection is encountered
1005 */
1006 }
1007 result = max_state_alt(onredirect, result);
1008 /* all other codes are considered ok */
1009 } else {
1010 result = STATE_OK;
1011 }
1012 }
1095 1013
1096 if(output_string_search[sizeof(output_string_search)-1]!='\0') { 1014 /* libcurl redirection internally, handle error states here */
1097 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); 1015 if (followmethod == FOLLOW_LIBCURL) {
1098 } 1016 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redir_depth), "CURLINFO_REDIRECT_COUNT");
1017 if (verbose >= 2)
1018 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
1019 if (redir_depth > max_depth) {
1020 snprintf(msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl", max_depth);
1021 die(STATE_WARNING, "HTTP WARNING - %s", msg);
1022 }
1023 }
1024
1025 /* check status codes, set exit status accordingly */
1026 if (status_line.http_code != code) {
1027 die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1028 string_statuscode(status_line.http_major, status_line.http_minor), status_line.http_code, status_line.msg, code);
1029 }
1030
1031 if (maximum_age >= 0) {
1032 result = max_state_alt(check_document_dates(&header_buf, &msg), result);
1033 }
1034
1035 /* Page and Header content checks go here */
1036
1037 if (strlen(header_expect)) {
1038 if (!strstr(header_buf.buf, header_expect)) {
1039
1040 strncpy(&output_header_search[0], header_expect, sizeof(output_header_search));
1041
1042 if (output_header_search[sizeof(output_header_search) - 1] != '\0') {
1043 bcopy("...", &output_header_search[sizeof(output_header_search) - 4], 4);
1044 }
1045
1046 char tmp[DEFAULT_BUFFER_SIZE];
1047
1048 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sheader '%s' not found on '%s://%s:%d%s', "), msg, output_header_search,
1049 use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1050
1051 strcpy(msg, tmp);
1052
1053 result = STATE_CRITICAL;
1054 }
1055 }
1056
1057 if (strlen(string_expect)) {
1058 if (!strstr(body_buf.buf, string_expect)) {
1059
1060 strncpy(&output_string_search[0], string_expect, sizeof(output_string_search));
1061
1062 if (output_string_search[sizeof(output_string_search) - 1] != '\0') {
1063 bcopy("...", &output_string_search[sizeof(output_string_search) - 4], 4);
1064 }
1099 1065
1100 char tmp[DEFAULT_BUFFER_SIZE]; 1066 char tmp[DEFAULT_BUFFER_SIZE];
1101 1067
1102 snprintf (tmp, 1068 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search,
1103 DEFAULT_BUFFER_SIZE, 1069 use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1104 _("%sstring '%s' not found on '%s://%s:%d%s', "),
1105 msg,
1106 output_string_search,
1107 use_ssl ? "https" : "http",
1108 host_name ? host_name : server_address,
1109 server_port,
1110 server_url);
1111 1070
1112 strcpy(msg, tmp); 1071 strcpy(msg, tmp);
1113 1072
1114 result = STATE_CRITICAL; 1073 result = STATE_CRITICAL;
1115 } 1074 }
1116 } 1075 }
1117 1076
1118 if (strlen (regexp)) { 1077 if (strlen(regexp)) {
1119 errcode = regexec (&preg, body_buf.buf, REGS, pmatch, 0); 1078 errcode = regexec(&preg, body_buf.buf, REGS, pmatch, 0);
1120 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) { 1079 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) {
1121 /* OK - No-op to avoid changing the logic around it */ 1080 /* OK - No-op to avoid changing the logic around it */
1122 result = max_state_alt(STATE_OK, result); 1081 result = max_state_alt(STATE_OK, result);
1123 } 1082 } else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1124 else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1125 if (!invert_regex) { 1083 if (!invert_regex) {
1126 char tmp[DEFAULT_BUFFER_SIZE]; 1084 char tmp[DEFAULT_BUFFER_SIZE];
1127 1085
1128 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg); 1086 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg);
1129 strcpy(msg, tmp); 1087 strcpy(msg, tmp);
1130 1088
1131 } else { 1089 } else {
1132 char tmp[DEFAULT_BUFFER_SIZE]; 1090 char tmp[DEFAULT_BUFFER_SIZE];
1133 1091
1134 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg); 1092 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg);
1135 strcpy(msg, tmp); 1093 strcpy(msg, tmp);
1136
1137 } 1094 }
1138 result = state_regex; 1095 result = state_regex;
1139 } else { 1096 } else {
1140 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1097 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1141 1098
1142 char tmp[DEFAULT_BUFFER_SIZE]; 1099 char tmp[DEFAULT_BUFFER_SIZE];
1143 1100
1144 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf); 1101 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf);
1145 strcpy(msg, tmp); 1102 strcpy(msg, tmp);
1146 result = STATE_UNKNOWN; 1103 result = STATE_UNKNOWN;
1147 } 1104 }
1148 } 1105 }
1149 1106
1150 /* make sure the page is of an appropriate size */ 1107 /* make sure the page is of an appropriate size */
1151 if ((max_page_len > 0) && (page_len > max_page_len)) { 1108 if ((max_page_len > 0) && (page_len > max_page_len)) {
1152 char tmp[DEFAULT_BUFFER_SIZE]; 1109 char tmp[DEFAULT_BUFFER_SIZE];
1153 1110
1154 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too large, "), msg, page_len); 1111 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too large, "), msg, page_len);
1155 1112
1156 strcpy(msg, tmp); 1113 strcpy(msg, tmp);
1157 1114
@@ -1160,1283 +1117,1230 @@ GOT_FIRST_CERT:
1160 } else if ((min_page_len > 0) && (page_len < min_page_len)) { 1117 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1161 char tmp[DEFAULT_BUFFER_SIZE]; 1118 char tmp[DEFAULT_BUFFER_SIZE];
1162 1119
1163 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too small, "), msg, page_len); 1120 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too small, "), msg, page_len);
1164 strcpy(msg, tmp); 1121 strcpy(msg, tmp);
1165 result = max_state_alt(STATE_WARNING, result); 1122 result = max_state_alt(STATE_WARNING, result);
1166 } 1123 }
1167 1124
1168 /* -w, -c: check warning and critical level */ 1125 /* -w, -c: check warning and critical level */
1169 result = max_state_alt(get_status(total_time, thlds), result); 1126 result = max_state_alt(get_status(total_time, thlds), result);
1170 1127
1171 /* Cut-off trailing characters */ 1128 /* Cut-off trailing characters */
1172 if (strlen(msg) >= 2) { 1129 if (strlen(msg) >= 2) {
1173 if(msg[strlen(msg)-2] == ',') 1130 if (msg[strlen(msg) - 2] == ',')
1174 msg[strlen(msg)-2] = '\0'; 1131 msg[strlen(msg) - 2] = '\0';
1175 else 1132 else
1176 msg[strlen(msg)-3] = '\0'; 1133 msg[strlen(msg) - 3] = '\0';
1177 } 1134 }
1178 1135
1179 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */ 1136 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */
1180 die (max_state_alt(result, result_ssl), "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s", 1137 die(max_state_alt(result, result_ssl), "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s", state_text(result),
1181 state_text(result), string_statuscode (status_line.http_major, status_line.http_minor), 1138 string_statuscode(status_line.http_major, status_line.http_minor), status_line.http_code, status_line.msg,
1182 status_line.http_code, status_line.msg, 1139 strlen(msg) > 0 ? " - " : "", msg, page_len, total_time, (display_html ? "</A>" : ""), perfstring, (show_body ? body_buf.buf : ""),
1183 strlen(msg) > 0 ? " - " : "", 1140 (show_body ? "\n" : ""));
1184 msg, page_len, total_time, 1141
1185 (display_html ? "</A>" : ""), 1142 return max_state_alt(result, result_ssl);
1186 perfstring,
1187 (show_body ? body_buf.buf : ""),
1188 (show_body ? "\n" : "") );
1189
1190 return max_state_alt(result, result_ssl);
1191} 1143}
1192 1144
1193int 1145int uri_strcmp(const UriTextRangeA range, const char *s) {
1194uri_strcmp (const UriTextRangeA range, const char* s) 1146 if (!range.first)
1195{ 1147 return -1;
1196 if (!range.first) return -1; 1148 if ((size_t)(range.afterLast - range.first) < strlen(s))
1197 if ( (size_t)(range.afterLast - range.first) < strlen (s) ) return -1; 1149 return -1;
1198 return strncmp (s, range.first, min( (size_t)(range.afterLast - range.first), strlen (s))); 1150 return strncmp(s, range.first, min((size_t)(range.afterLast - range.first), strlen(s)));
1199} 1151}
1200 1152
1201char* 1153char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) {
1202uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1154 if (!range.first)
1203{ 1155 return "(null)";
1204 if (!range.first) return "(null)"; 1156 strncpy(buf, range.first, max(buflen - 1, (size_t)(range.afterLast - range.first)));
1205 strncpy (buf, range.first, max (buflen-1, (size_t)(range.afterLast - range.first))); 1157 buf[max(buflen - 1, (size_t)(range.afterLast - range.first))] = '\0';
1206 buf[max (buflen-1, (size_t)(range.afterLast - range.first))] = '\0'; 1158 buf[range.afterLast - range.first] = '\0';
1207 buf[range.afterLast - range.first] = '\0'; 1159 return buf;
1208 return buf;
1209} 1160}
1210 1161
1211void 1162void redir(curlhelp_write_curlbuf *header_buf) {
1212redir (curlhelp_write_curlbuf* header_buf) 1163 char *location = NULL;
1213{ 1164 curlhelp_statusline status_line;
1214 char *location = NULL; 1165 struct phr_header headers[255];
1215 curlhelp_statusline status_line; 1166 size_t nof_headers = 255;
1216 struct phr_header headers[255]; 1167 size_t msglen;
1217 size_t nof_headers = 255; 1168 char buf[DEFAULT_BUFFER_SIZE];
1218 size_t msglen; 1169 char ipstr[INET_ADDR_MAX_SIZE];
1219 char buf[DEFAULT_BUFFER_SIZE]; 1170 int new_port;
1220 char ipstr[INET_ADDR_MAX_SIZE]; 1171 char *new_host;
1221 int new_port; 1172 char *new_url;
1222 char *new_host; 1173
1223 char *new_url; 1174 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
1224 1175 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
1225 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
1226 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
1227 headers, &nof_headers, 0);
1228 1176
1229 if (res == -1) { 1177 if (res == -1) {
1230 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 1178 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
1231 } 1179 }
1232 1180
1233 location = get_header_value (headers, nof_headers, "location"); 1181 location = get_header_value(headers, nof_headers, "location");
1234 1182
1235 if (verbose >= 2) 1183 if (verbose >= 2)
1236 printf(_("* Seen redirect location %s\n"), location); 1184 printf(_("* Seen redirect location %s\n"), location);
1237 1185
1238 if (++redir_depth > max_depth) 1186 if (++redir_depth > max_depth)
1239 die (STATE_WARNING, 1187 die(STATE_WARNING, _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), max_depth, location,
1240 _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), 1188 (display_html ? "</A>" : ""));
1241 max_depth, location, (display_html ? "</A>" : "")); 1189
1242 1190 UriParserStateA state;
1243 UriParserStateA state; 1191 UriUriA uri;
1244 UriUriA uri; 1192 state.uri = &uri;
1245 state.uri = &uri; 1193 if (uriParseUriA(&state, location) != URI_SUCCESS) {
1246 if (uriParseUriA (&state, location) != URI_SUCCESS) { 1194 if (state.errorCode == URI_ERROR_SYNTAX) {
1247 if (state.errorCode == URI_ERROR_SYNTAX) { 1195 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), location, (display_html ? "</A>" : ""));
1248 die (STATE_UNKNOWN, 1196 } else if (state.errorCode == URI_ERROR_MALLOC) {
1249 _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), 1197 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n"));
1250 location, (display_html ? "</A>" : "")); 1198 }
1251 } else if (state.errorCode == URI_ERROR_MALLOC) { 1199 }
1252 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); 1200
1253 } 1201 if (verbose >= 2) {
1254 } 1202 printf(_("** scheme: %s\n"), uri_string(uri.scheme, buf, DEFAULT_BUFFER_SIZE));
1255 1203 printf(_("** host: %s\n"), uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1256 if (verbose >= 2) { 1204 printf(_("** port: %s\n"), uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1257 printf (_("** scheme: %s\n"), 1205 if (uri.hostData.ip4) {
1258 uri_string (uri.scheme, buf, DEFAULT_BUFFER_SIZE)); 1206 inet_ntop(AF_INET, uri.hostData.ip4->data, ipstr, sizeof(ipstr));
1259 printf (_("** host: %s\n"), 1207 printf(_("** IPv4: %s\n"), ipstr);
1260 uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1208 }
1261 printf (_("** port: %s\n"), 1209 if (uri.hostData.ip6) {
1262 uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1210 inet_ntop(AF_INET, uri.hostData.ip6->data, ipstr, sizeof(ipstr));
1263 if (uri.hostData.ip4) { 1211 printf(_("** IPv6: %s\n"), ipstr);
1264 inet_ntop (AF_INET, uri.hostData.ip4->data, ipstr, sizeof (ipstr)); 1212 }
1265 printf (_("** IPv4: %s\n"), ipstr); 1213 if (uri.pathHead) {
1266 } 1214 printf(_("** path: "));
1267 if (uri.hostData.ip6) { 1215 const UriPathSegmentA *p = uri.pathHead;
1268 inet_ntop (AF_INET, uri.hostData.ip6->data, ipstr, sizeof (ipstr)); 1216 for (; p; p = p->next) {
1269 printf (_("** IPv6: %s\n"), ipstr); 1217 printf("/%s", uri_string(p->text, buf, DEFAULT_BUFFER_SIZE));
1270 } 1218 }
1271 if (uri.pathHead) { 1219 puts("");
1272 printf (_("** path: ")); 1220 }
1273 const UriPathSegmentA* p = uri.pathHead; 1221 if (uri.query.first) {
1274 for (; p; p = p->next) { 1222 printf(_("** query: %s\n"), uri_string(uri.query, buf, DEFAULT_BUFFER_SIZE));
1275 printf ("/%s", uri_string (p->text, buf, DEFAULT_BUFFER_SIZE)); 1223 }
1276 } 1224 if (uri.fragment.first) {
1277 puts (""); 1225 printf(_("** fragment: %s\n"), uri_string(uri.fragment, buf, DEFAULT_BUFFER_SIZE));
1278 } 1226 }
1279 if (uri.query.first) { 1227 }
1280 printf (_("** query: %s\n"), 1228
1281 uri_string (uri.query, buf, DEFAULT_BUFFER_SIZE)); 1229 if (uri.scheme.first) {
1282 } 1230 if (!uri_strcmp(uri.scheme, "https"))
1283 if (uri.fragment.first) { 1231 use_ssl = true;
1284 printf (_("** fragment: %s\n"), 1232 else
1285 uri_string (uri.fragment, buf, DEFAULT_BUFFER_SIZE)); 1233 use_ssl = false;
1286 } 1234 }
1287 } 1235
1288 1236 /* we do a sloppy test here only, because uriparser would have failed
1289 if (uri.scheme.first) { 1237 * above, if the port would be invalid, we just check for MAX_PORT
1290 if (!uri_strcmp (uri.scheme, "https")) 1238 */
1291 use_ssl = true; 1239 if (uri.portText.first) {
1292 else 1240 new_port = atoi(uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1293 use_ssl = false; 1241 } else {
1294 } 1242 new_port = HTTP_PORT;
1295 1243 if (use_ssl)
1296 /* we do a sloppy test here only, because uriparser would have failed 1244 new_port = HTTPS_PORT;
1297 * above, if the port would be invalid, we just check for MAX_PORT 1245 }
1298 */ 1246 if (new_port > MAX_PORT)
1299 if (uri.portText.first) { 1247 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), MAX_PORT, location, display_html ? "</A>" : "");
1300 new_port = atoi (uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1248
1301 } else { 1249 /* by RFC 7231 relative URLs in Location should be taken relative to
1302 new_port = HTTP_PORT; 1250 * the original URL, so we try to form a new absolute URL here
1303 if (use_ssl) 1251 */
1304 new_port = HTTPS_PORT; 1252 if (!uri.scheme.first && !uri.hostText.first) {
1305 } 1253 new_host = strdup(host_name ? host_name : server_address);
1306 if (new_port > MAX_PORT) 1254 new_port = server_port;
1307 die (STATE_UNKNOWN, 1255 if (use_ssl)
1308 _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), 1256 uri_string(uri.scheme, "https", DEFAULT_BUFFER_SIZE);
1309 MAX_PORT, location, display_html ? "</A>" : ""); 1257 } else {
1310 1258 new_host = strdup(uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1311 /* by RFC 7231 relative URLs in Location should be taken relative to 1259 }
1312 * the original URL, so we try to form a new absolute URL here 1260
1313 */ 1261 /* compose new path */
1314 if (!uri.scheme.first && !uri.hostText.first) { 1262 /* TODO: handle fragments and query part of URL */
1315 new_host = strdup (host_name ? host_name : server_address); 1263 new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE);
1316 new_port = server_port; 1264 if (uri.pathHead) {
1317 if(use_ssl) 1265 const UriPathSegmentA *p = uri.pathHead;
1318 uri_string (uri.scheme, "https", DEFAULT_BUFFER_SIZE); 1266 for (; p; p = p->next) {
1319 } else { 1267 strncat(new_url, "/", DEFAULT_BUFFER_SIZE);
1320 new_host = strdup (uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1268 strncat(new_url, uri_string(p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE - 1);
1321 } 1269 }
1322 1270 }
1323 /* compose new path */ 1271
1324 /* TODO: handle fragments and query part of URL */ 1272 if (server_port == new_port && !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1325 new_url = (char *)calloc( 1, DEFAULT_BUFFER_SIZE); 1273 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && !strcmp(server_url, new_url))
1326 if (uri.pathHead) { 1274 die(STATE_CRITICAL, _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), use_ssl ? "https" : "http",
1327 const UriPathSegmentA* p = uri.pathHead; 1275 new_host, new_port, new_url, (display_html ? "</A>" : ""));
1328 for (; p; p = p->next) { 1276
1329 strncat (new_url, "/", DEFAULT_BUFFER_SIZE); 1277 /* set new values for redirected request */
1330 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE-1); 1278
1331 } 1279 if (!(followsticky & STICKY_HOST)) {
1332 } 1280 free(server_address);
1333 1281 server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1334 if (server_port==new_port && 1282 }
1335 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1283 if (!(followsticky & STICKY_PORT)) {
1336 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1284 server_port = (unsigned short)new_port;
1337 !strcmp(server_url, new_url)) 1285 }
1338 die (STATE_CRITICAL, 1286
1339 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), 1287 free(host_name);
1340 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : "")); 1288 host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1341 1289
1342 /* set new values for redirected request */ 1290 /* reset virtual port */
1343 1291 virtual_port = server_port;
1344 if (!(followsticky & STICKY_HOST)) { 1292
1345 free (server_address); 1293 free(new_host);
1346 server_address = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1294 free(server_url);
1347 } 1295 server_url = new_url;
1348 if (!(followsticky & STICKY_PORT)) { 1296
1349 server_port = (unsigned short)new_port; 1297 uriFreeUriMembersA(&uri);
1350 } 1298
1351 1299 if (verbose)
1352 free (host_name); 1300 printf(_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port,
1353 host_name = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1301 server_url);
1354 1302
1355 /* reset virtual port */ 1303 /* TODO: the hash component MUST be taken from the original URL and
1356 virtual_port = server_port; 1304 * attached to the URL in Location
1357 1305 */
1358 free(new_host); 1306
1359 free (server_url); 1307 cleanup();
1360 server_url = new_url; 1308 check_http();
1361
1362 uriFreeUriMembersA (&uri);
1363
1364 if (verbose)
1365 printf (_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http",
1366 host_name ? host_name : server_address, server_port, server_url);
1367
1368 /* TODO: the hash component MUST be taken from the original URL and
1369 * attached to the URL in Location
1370 */
1371
1372 cleanup ();
1373 check_http ();
1374} 1309}
1375 1310
1376/* check whether a file exists */ 1311/* check whether a file exists */
1377void 1312void test_file(char *path) {
1378test_file (char *path) 1313 if (access(path, R_OK) == 0)
1379{ 1314 return;
1380 if (access(path, R_OK) == 0) 1315 usage2(_("file does not exist or is not readable"), path);
1381 return;
1382 usage2 (_("file does not exist or is not readable"), path);
1383} 1316}
1384 1317
1385bool 1318bool process_arguments(int argc, char **argv) {
1386process_arguments (int argc, char **argv) 1319 char *p;
1387{ 1320 int c = 1;
1388 char *p; 1321 char *temp;
1389 int c = 1; 1322
1390 char *temp; 1323 enum {
1391 1324 INVERT_REGEX = CHAR_MAX + 1,
1392 enum { 1325 SNI_OPTION,
1393 INVERT_REGEX = CHAR_MAX + 1, 1326 MAX_REDIRS_OPTION,
1394 SNI_OPTION, 1327 CONTINUE_AFTER_CHECK_CERT,
1395 MAX_REDIRS_OPTION, 1328 CA_CERT_OPTION,
1396 CONTINUE_AFTER_CHECK_CERT, 1329 HTTP_VERSION_OPTION,
1397 CA_CERT_OPTION, 1330 AUTOMATIC_DECOMPRESSION,
1398 HTTP_VERSION_OPTION, 1331 COOKIE_JAR,
1399 AUTOMATIC_DECOMPRESSION, 1332 HAPROXY_PROTOCOL,
1400 COOKIE_JAR, 1333 STATE_REGEX
1401 HAPROXY_PROTOCOL, 1334 };
1402 STATE_REGEX 1335
1403 }; 1336 int option = 0;
1404 1337 int got_plus = 0;
1405 int option = 0; 1338 static struct option longopts[] = {STD_LONG_OPTS,
1406 int got_plus = 0; 1339 {"link", no_argument, 0, 'L'},
1407 static struct option longopts[] = { 1340 {"nohtml", no_argument, 0, 'n'},
1408 STD_LONG_OPTS, 1341 {"ssl", optional_argument, 0, 'S'},
1409 {"link", no_argument, 0, 'L'}, 1342 {"sni", no_argument, 0, SNI_OPTION},
1410 {"nohtml", no_argument, 0, 'n'}, 1343 {"post", required_argument, 0, 'P'},
1411 {"ssl", optional_argument, 0, 'S'}, 1344 {"method", required_argument, 0, 'j'},
1412 {"sni", no_argument, 0, SNI_OPTION}, 1345 {"IP-address", required_argument, 0, 'I'},
1413 {"post", required_argument, 0, 'P'}, 1346 {"url", required_argument, 0, 'u'},
1414 {"method", required_argument, 0, 'j'}, 1347 {"port", required_argument, 0, 'p'},
1415 {"IP-address", required_argument, 0, 'I'}, 1348 {"authorization", required_argument, 0, 'a'},
1416 {"url", required_argument, 0, 'u'}, 1349 {"proxy-authorization", required_argument, 0, 'b'},
1417 {"port", required_argument, 0, 'p'}, 1350 {"header-string", required_argument, 0, 'd'},
1418 {"authorization", required_argument, 0, 'a'}, 1351 {"string", required_argument, 0, 's'},
1419 {"proxy-authorization", required_argument, 0, 'b'}, 1352 {"expect", required_argument, 0, 'e'},
1420 {"header-string", required_argument, 0, 'd'}, 1353 {"regex", required_argument, 0, 'r'},
1421 {"string", required_argument, 0, 's'}, 1354 {"ereg", required_argument, 0, 'r'},
1422 {"expect", required_argument, 0, 'e'}, 1355 {"eregi", required_argument, 0, 'R'},
1423 {"regex", required_argument, 0, 'r'}, 1356 {"linespan", no_argument, 0, 'l'},
1424 {"ereg", required_argument, 0, 'r'}, 1357 {"onredirect", required_argument, 0, 'f'},
1425 {"eregi", required_argument, 0, 'R'}, 1358 {"certificate", required_argument, 0, 'C'},
1426 {"linespan", no_argument, 0, 'l'}, 1359 {"client-cert", required_argument, 0, 'J'},
1427 {"onredirect", required_argument, 0, 'f'}, 1360 {"private-key", required_argument, 0, 'K'},
1428 {"certificate", required_argument, 0, 'C'}, 1361 {"ca-cert", required_argument, 0, CA_CERT_OPTION},
1429 {"client-cert", required_argument, 0, 'J'}, 1362 {"verify-cert", no_argument, 0, 'D'},
1430 {"private-key", required_argument, 0, 'K'}, 1363 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT},
1431 {"ca-cert", required_argument, 0, CA_CERT_OPTION}, 1364 {"useragent", required_argument, 0, 'A'},
1432 {"verify-cert", no_argument, 0, 'D'}, 1365 {"header", required_argument, 0, 'k'},
1433 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT}, 1366 {"no-body", no_argument, 0, 'N'},
1434 {"useragent", required_argument, 0, 'A'}, 1367 {"max-age", required_argument, 0, 'M'},
1435 {"header", required_argument, 0, 'k'}, 1368 {"content-type", required_argument, 0, 'T'},
1436 {"no-body", no_argument, 0, 'N'}, 1369 {"pagesize", required_argument, 0, 'm'},
1437 {"max-age", required_argument, 0, 'M'}, 1370 {"invert-regex", no_argument, NULL, INVERT_REGEX},
1438 {"content-type", required_argument, 0, 'T'}, 1371 {"state-regex", required_argument, 0, STATE_REGEX},
1439 {"pagesize", required_argument, 0, 'm'}, 1372 {"use-ipv4", no_argument, 0, '4'},
1440 {"invert-regex", no_argument, NULL, INVERT_REGEX}, 1373 {"use-ipv6", no_argument, 0, '6'},
1441 {"state-regex", required_argument, 0, STATE_REGEX}, 1374 {"extended-perfdata", no_argument, 0, 'E'},
1442 {"use-ipv4", no_argument, 0, '4'}, 1375 {"show-body", no_argument, 0, 'B'},
1443 {"use-ipv6", no_argument, 0, '6'}, 1376 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
1444 {"extended-perfdata", no_argument, 0, 'E'}, 1377 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1445 {"show-body", no_argument, 0, 'B'}, 1378 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1446 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION}, 1379 {"cookie-jar", required_argument, 0, COOKIE_JAR},
1447 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1380 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL},
1448 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION}, 1381 {0, 0, 0, 0}};
1449 {"cookie-jar", required_argument, 0, COOKIE_JAR}, 1382
1450 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL}, 1383 if (argc < 2)
1451 {0, 0, 0, 0} 1384 return false;
1452 }; 1385
1453 1386 /* support check_http compatible arguments */
1454 if (argc < 2) 1387 for (c = 1; c < argc; c++) {
1455 return false; 1388 if (strcmp("-to", argv[c]) == 0)
1456 1389 strcpy(argv[c], "-t");
1457 /* support check_http compatible arguments */ 1390 if (strcmp("-hn", argv[c]) == 0)
1458 for (c = 1; c < argc; c++) { 1391 strcpy(argv[c], "-H");
1459 if (strcmp ("-to", argv[c]) == 0) 1392 if (strcmp("-wt", argv[c]) == 0)
1460 strcpy (argv[c], "-t"); 1393 strcpy(argv[c], "-w");
1461 if (strcmp ("-hn", argv[c]) == 0) 1394 if (strcmp("-ct", argv[c]) == 0)
1462 strcpy (argv[c], "-H"); 1395 strcpy(argv[c], "-c");
1463 if (strcmp ("-wt", argv[c]) == 0) 1396 if (strcmp("-nohtml", argv[c]) == 0)
1464 strcpy (argv[c], "-w"); 1397 strcpy(argv[c], "-n");
1465 if (strcmp ("-ct", argv[c]) == 0) 1398 }
1466 strcpy (argv[c], "-c"); 1399
1467 if (strcmp ("-nohtml", argv[c]) == 0) 1400 server_url = strdup(DEFAULT_SERVER_URL);
1468 strcpy (argv[c], "-n"); 1401
1469 } 1402 while (1) {
1470 1403 c = getopt_long(argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:DnlLS::m:M:NEB", longopts, &option);
1471 server_url = strdup(DEFAULT_SERVER_URL); 1404 if (c == -1 || c == EOF || c == 1)
1472 1405 break;
1473 while (1) { 1406
1474 c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:DnlLS::m:M:NEB", longopts, &option); 1407 switch (c) {
1475 if (c == -1 || c == EOF || c == 1) 1408 case 'h':
1476 break; 1409 print_help();
1477 1410 exit(STATE_UNKNOWN);
1478 switch (c) { 1411 break;
1479 case 'h': 1412 case 'V':
1480 print_help(); 1413 print_revision(progname, NP_VERSION);
1481 exit(STATE_UNKNOWN); 1414 print_curl_version();
1482 break; 1415 exit(STATE_UNKNOWN);
1483 case 'V': 1416 break;
1484 print_revision(progname, NP_VERSION); 1417 case 'v':
1485 print_curl_version(); 1418 verbose++;
1486 exit(STATE_UNKNOWN); 1419 break;
1487 break; 1420 case 't': /* timeout period */
1488 case 'v': 1421 if (!is_intnonneg(optarg))
1489 verbose++; 1422 usage2(_("Timeout interval must be a positive integer"), optarg);
1490 break; 1423 else
1491 case 't': /* timeout period */ 1424 socket_timeout = (int)strtol(optarg, NULL, 10);
1492 if (!is_intnonneg (optarg)) 1425 break;
1493 usage2 (_("Timeout interval must be a positive integer"), optarg); 1426 case 'c': /* critical time threshold */
1494 else 1427 critical_thresholds = optarg;
1495 socket_timeout = (int)strtol (optarg, NULL, 10); 1428 break;
1496 break; 1429 case 'w': /* warning time threshold */
1497 case 'c': /* critical time threshold */ 1430 warning_thresholds = optarg;
1498 critical_thresholds = optarg; 1431 break;
1499 break; 1432 case 'H': /* virtual host */
1500 case 'w': /* warning time threshold */ 1433 host_name = strdup(optarg);
1501 warning_thresholds = optarg; 1434 if (host_name[0] == '[') {
1502 break; 1435 if ((p = strstr(host_name, "]:")) != NULL) { /* [IPv6]:port */
1503 case 'H': /* virtual host */ 1436 virtual_port = atoi(p + 2);
1504 host_name = strdup (optarg); 1437 /* cut off the port */
1505 if (host_name[0] == '[') { 1438 host_name_length = strlen(host_name) - strlen(p) - 1;
1506 if ((p = strstr (host_name, "]:")) != NULL) { /* [IPv6]:port */ 1439 free(host_name);
1507 virtual_port = atoi (p + 2); 1440 host_name = strndup(optarg, host_name_length);
1508 /* cut off the port */ 1441 }
1509 host_name_length = strlen (host_name) - strlen (p) - 1; 1442 } else if ((p = strchr(host_name, ':')) != NULL && strchr(++p, ':') == NULL) { /* IPv4:port or host:port */
1510 free (host_name); 1443 virtual_port = atoi(p);
1511 host_name = strndup (optarg, host_name_length); 1444 /* cut off the port */
1512 } 1445 host_name_length = strlen(host_name) - strlen(p) - 1;
1513 } else if ((p = strchr (host_name, ':')) != NULL 1446 free(host_name);
1514 && strchr (++p, ':') == NULL) { /* IPv4:port or host:port */ 1447 host_name = strndup(optarg, host_name_length);
1515 virtual_port = atoi (p); 1448 }
1516 /* cut off the port */ 1449 break;
1517 host_name_length = strlen (host_name) - strlen (p) - 1; 1450 case 'I': /* internet address */
1518 free (host_name); 1451 server_address = strdup(optarg);
1519 host_name = strndup (optarg, host_name_length); 1452 break;
1520 } 1453 case 'u': /* URL path */
1521 break; 1454 server_url = strdup(optarg);
1522 case 'I': /* internet address */ 1455 break;
1523 server_address = strdup (optarg); 1456 case 'p': /* Server port */
1524 break; 1457 if (!is_intnonneg(optarg))
1525 case 'u': /* URL path */ 1458 usage2(_("Invalid port number, expecting a non-negative number"), optarg);
1526 server_url = strdup (optarg); 1459 else {
1527 break; 1460 if (strtol(optarg, NULL, 10) > MAX_PORT)
1528 case 'p': /* Server port */ 1461 usage2(_("Invalid port number, supplied port number is too big"), optarg);
1529 if (!is_intnonneg (optarg)) 1462 server_port = (unsigned short)strtol(optarg, NULL, 10);
1530 usage2 (_("Invalid port number, expecting a non-negative number"), optarg); 1463 specify_port = true;
1531 else { 1464 }
1532 if( strtol(optarg, NULL, 10) > MAX_PORT) 1465 break;
1533 usage2 (_("Invalid port number, supplied port number is too big"), optarg); 1466 case 'a': /* authorization info */
1534 server_port = (unsigned short)strtol(optarg, NULL, 10); 1467 strncpy(user_auth, optarg, MAX_INPUT_BUFFER - 1);
1535 specify_port = true; 1468 user_auth[MAX_INPUT_BUFFER - 1] = 0;
1536 } 1469 break;
1537 break; 1470 case 'b': /* proxy-authorization info */
1538 case 'a': /* authorization info */ 1471 strncpy(proxy_auth, optarg, MAX_INPUT_BUFFER - 1);
1539 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1); 1472 proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
1540 user_auth[MAX_INPUT_BUFFER - 1] = 0; 1473 break;
1541 break; 1474 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
1542 case 'b': /* proxy-authorization info */ 1475 if (!http_post_data)
1543 strncpy (proxy_auth, optarg, MAX_INPUT_BUFFER - 1); 1476 http_post_data = strdup(optarg);
1544 proxy_auth[MAX_INPUT_BUFFER - 1] = 0; 1477 if (!http_method)
1545 break; 1478 http_method = strdup("POST");
1546 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */ 1479 break;
1547 if (! http_post_data) 1480 case 'j': /* Set HTTP method */
1548 http_post_data = strdup (optarg); 1481 if (http_method)
1549 if (! http_method) 1482 free(http_method);
1550 http_method = strdup("POST"); 1483 http_method = strdup(optarg);
1551 break; 1484 break;
1552 case 'j': /* Set HTTP method */ 1485 case 'A': /* useragent */
1553 if (http_method) 1486 strncpy(user_agent, optarg, DEFAULT_BUFFER_SIZE);
1554 free(http_method); 1487 user_agent[DEFAULT_BUFFER_SIZE - 1] = '\0';
1555 http_method = strdup (optarg); 1488 break;
1556 break; 1489 case 'k': /* Additional headers */
1557 case 'A': /* useragent */ 1490 if (http_opt_headers_count == 0)
1558 strncpy (user_agent, optarg, DEFAULT_BUFFER_SIZE); 1491 http_opt_headers = malloc(sizeof(char *) * (++http_opt_headers_count));
1559 user_agent[DEFAULT_BUFFER_SIZE-1] = '\0'; 1492 else
1560 break; 1493 http_opt_headers = realloc(http_opt_headers, sizeof(char *) * (++http_opt_headers_count));
1561 case 'k': /* Additional headers */ 1494 http_opt_headers[http_opt_headers_count - 1] = optarg;
1562 if (http_opt_headers_count == 0) 1495 break;
1563 http_opt_headers = malloc (sizeof (char *) * (++http_opt_headers_count)); 1496 case 'L': /* show html link */
1564 else 1497 display_html = true;
1565 http_opt_headers = realloc (http_opt_headers, sizeof (char *) * (++http_opt_headers_count)); 1498 break;
1566 http_opt_headers[http_opt_headers_count - 1] = optarg; 1499 case 'n': /* do not show html link */
1567 break; 1500 display_html = false;
1568 case 'L': /* show html link */ 1501 break;
1569 display_html = true; 1502 case 'C': /* Check SSL cert validity */
1570 break;
1571 case 'n': /* do not show html link */
1572 display_html = false;
1573 break;
1574 case 'C': /* Check SSL cert validity */
1575#ifdef LIBCURL_FEATURE_SSL 1503#ifdef LIBCURL_FEATURE_SSL
1576 if ((temp=strchr(optarg,','))!=NULL) { 1504 if ((temp = strchr(optarg, ',')) != NULL) {
1577 *temp='\0'; 1505 *temp = '\0';
1578 if (!is_intnonneg (optarg)) 1506 if (!is_intnonneg(optarg))
1579 usage2 (_("Invalid certificate expiration period"), optarg); 1507 usage2(_("Invalid certificate expiration period"), optarg);
1580 days_till_exp_warn = atoi(optarg); 1508 days_till_exp_warn = atoi(optarg);
1581 *temp=','; 1509 *temp = ',';
1582 temp++; 1510 temp++;
1583 if (!is_intnonneg (temp)) 1511 if (!is_intnonneg(temp))
1584 usage2 (_("Invalid certificate expiration period"), temp); 1512 usage2(_("Invalid certificate expiration period"), temp);
1585 days_till_exp_crit = atoi (temp); 1513 days_till_exp_crit = atoi(temp);
1586 } 1514 } else {
1587 else { 1515 days_till_exp_crit = 0;
1588 days_till_exp_crit=0; 1516 if (!is_intnonneg(optarg))
1589 if (!is_intnonneg (optarg)) 1517 usage2(_("Invalid certificate expiration period"), optarg);
1590 usage2 (_("Invalid certificate expiration period"), optarg); 1518 days_till_exp_warn = atoi(optarg);
1591 days_till_exp_warn = atoi (optarg); 1519 }
1592 } 1520 check_cert = true;
1593 check_cert = true; 1521 goto enable_ssl;
1594 goto enable_ssl;
1595#endif 1522#endif
1596 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */ 1523 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */
1597#ifdef HAVE_SSL 1524#ifdef HAVE_SSL
1598 continue_after_check_cert = true; 1525 continue_after_check_cert = true;
1599 break; 1526 break;
1600#endif 1527#endif
1601 case 'J': /* use client certificate */ 1528 case 'J': /* use client certificate */
1602#ifdef LIBCURL_FEATURE_SSL 1529#ifdef LIBCURL_FEATURE_SSL
1603 test_file(optarg); 1530 test_file(optarg);
1604 client_cert = optarg; 1531 client_cert = optarg;
1605 goto enable_ssl; 1532 goto enable_ssl;
1606#endif 1533#endif
1607 case 'K': /* use client private key */ 1534 case 'K': /* use client private key */
1608#ifdef LIBCURL_FEATURE_SSL 1535#ifdef LIBCURL_FEATURE_SSL
1609 test_file(optarg); 1536 test_file(optarg);
1610 client_privkey = optarg; 1537 client_privkey = optarg;
1611 goto enable_ssl; 1538 goto enable_ssl;
1612#endif 1539#endif
1613#ifdef LIBCURL_FEATURE_SSL 1540#ifdef LIBCURL_FEATURE_SSL
1614 case CA_CERT_OPTION: /* use CA chain file */ 1541 case CA_CERT_OPTION: /* use CA chain file */
1615 test_file(optarg); 1542 test_file(optarg);
1616 ca_cert = optarg; 1543 ca_cert = optarg;
1617 goto enable_ssl; 1544 goto enable_ssl;
1618#endif 1545#endif
1619#ifdef LIBCURL_FEATURE_SSL 1546#ifdef LIBCURL_FEATURE_SSL
1620 case 'D': /* verify peer certificate & host */ 1547 case 'D': /* verify peer certificate & host */
1621 verify_peer_and_host = true; 1548 verify_peer_and_host = true;
1622 break; 1549 break;
1623#endif 1550#endif
1624 case 'S': /* use SSL */ 1551 case 'S': /* use SSL */
1625#ifdef LIBCURL_FEATURE_SSL 1552#ifdef LIBCURL_FEATURE_SSL
1626 enable_ssl: 1553 enable_ssl:
1627 use_ssl = true; 1554 use_ssl = true;
1628 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default. 1555 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
1629 * Only set if it's non-zero. This helps when we include multiple 1556 * Only set if it's non-zero. This helps when we include multiple
1630 * parameters, like -S and -C combinations */ 1557 * parameters, like -S and -C combinations */
1631 ssl_version = CURL_SSLVERSION_DEFAULT; 1558 ssl_version = CURL_SSLVERSION_DEFAULT;
1632 if (c=='S' && optarg != NULL) { 1559 if (c == 'S' && optarg != NULL) {
1633 char *plus_ptr = strchr(optarg, '+'); 1560 char *plus_ptr = strchr(optarg, '+');
1634 if (plus_ptr) { 1561 if (plus_ptr) {
1635 got_plus = 1; 1562 got_plus = 1;
1636 *plus_ptr = '\0'; 1563 *plus_ptr = '\0';
1637 } 1564 }
1638 1565
1639 if (optarg[0] == '2') 1566 if (optarg[0] == '2')
1640 ssl_version = CURL_SSLVERSION_SSLv2; 1567 ssl_version = CURL_SSLVERSION_SSLv2;
1641 else if (optarg[0] == '3') 1568 else if (optarg[0] == '3')
1642 ssl_version = CURL_SSLVERSION_SSLv3; 1569 ssl_version = CURL_SSLVERSION_SSLv3;
1643 else if (!strcmp (optarg, "1") || !strcmp (optarg, "1.0")) 1570 else if (!strcmp(optarg, "1") || !strcmp(optarg, "1.0"))
1644#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1571# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1645 ssl_version = CURL_SSLVERSION_TLSv1_0; 1572 ssl_version = CURL_SSLVERSION_TLSv1_0;
1646#else 1573# else
1647 ssl_version = CURL_SSLVERSION_DEFAULT; 1574 ssl_version = CURL_SSLVERSION_DEFAULT;
1648#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1575# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1649 else if (!strcmp (optarg, "1.1")) 1576 else if (!strcmp(optarg, "1.1"))
1650#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1577# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1651 ssl_version = CURL_SSLVERSION_TLSv1_1; 1578 ssl_version = CURL_SSLVERSION_TLSv1_1;
1652#else 1579# else
1653 ssl_version = CURL_SSLVERSION_DEFAULT; 1580 ssl_version = CURL_SSLVERSION_DEFAULT;
1654#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1581# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1655 else if (!strcmp (optarg, "1.2")) 1582 else if (!strcmp(optarg, "1.2"))
1656#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1583# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1657 ssl_version = CURL_SSLVERSION_TLSv1_2; 1584 ssl_version = CURL_SSLVERSION_TLSv1_2;
1658#else 1585# else
1659 ssl_version = CURL_SSLVERSION_DEFAULT; 1586 ssl_version = CURL_SSLVERSION_DEFAULT;
1660#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1587# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1661 else if (!strcmp (optarg, "1.3")) 1588 else if (!strcmp(optarg, "1.3"))
1662#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) 1589# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0)
1663 ssl_version = CURL_SSLVERSION_TLSv1_3; 1590 ssl_version = CURL_SSLVERSION_TLSv1_3;
1664#else 1591# else
1665 ssl_version = CURL_SSLVERSION_DEFAULT; 1592 ssl_version = CURL_SSLVERSION_DEFAULT;
1666#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */ 1593# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
1667 else 1594 else
1668 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)")); 1595 usage4(_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)"));
1669 } 1596 }
1670#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) 1597# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
1671 if (got_plus) { 1598 if (got_plus) {
1672 switch (ssl_version) { 1599 switch (ssl_version) {
1673 case CURL_SSLVERSION_TLSv1_3: 1600 case CURL_SSLVERSION_TLSv1_3:
1674 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1601 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1675 break; 1602 break;
1676 case CURL_SSLVERSION_TLSv1_2: 1603 case CURL_SSLVERSION_TLSv1_2:
1677 case CURL_SSLVERSION_TLSv1_1: 1604 case CURL_SSLVERSION_TLSv1_1:
1678 case CURL_SSLVERSION_TLSv1_0: 1605 case CURL_SSLVERSION_TLSv1_0:
1679 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT; 1606 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT;
1680 break; 1607 break;
1681 } 1608 }
1682 } else { 1609 } else {
1683 switch (ssl_version) { 1610 switch (ssl_version) {
1684 case CURL_SSLVERSION_TLSv1_3: 1611 case CURL_SSLVERSION_TLSv1_3:
1685 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1612 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1686 break; 1613 break;
1687 case CURL_SSLVERSION_TLSv1_2: 1614 case CURL_SSLVERSION_TLSv1_2:
1688 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2; 1615 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2;
1689 break; 1616 break;
1690 case CURL_SSLVERSION_TLSv1_1: 1617 case CURL_SSLVERSION_TLSv1_1:
1691 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1; 1618 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1;
1692 break; 1619 break;
1693 case CURL_SSLVERSION_TLSv1_0: 1620 case CURL_SSLVERSION_TLSv1_0:
1694 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0; 1621 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0;
1695 break; 1622 break;
1696 } 1623 }
1697 } 1624 }
1698#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ 1625# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */
1699 if (verbose >= 2) 1626 if (verbose >= 2)
1700 printf(_("* Set SSL/TLS version to %d\n"), ssl_version); 1627 printf(_("* Set SSL/TLS version to %d\n"), ssl_version);
1701 if (!specify_port) 1628 if (!specify_port)
1702 server_port = HTTPS_PORT; 1629 server_port = HTTPS_PORT;
1703 break; 1630 break;
1704#else /* LIBCURL_FEATURE_SSL */ 1631#else /* LIBCURL_FEATURE_SSL */
1705 /* -C -J and -K fall through to here without SSL */ 1632 /* -C -J and -K fall through to here without SSL */
1706 usage4 (_("Invalid option - SSL is not available")); 1633 usage4(_("Invalid option - SSL is not available"));
1707 break; 1634 break;
1708 case SNI_OPTION: /* --sni is parsed, but ignored, the default is true with libcurl */ 1635 case SNI_OPTION: /* --sni is parsed, but ignored, the default is true with libcurl */
1709 use_sni = true; 1636 use_sni = true;
1710 break; 1637 break;
1711#endif /* LIBCURL_FEATURE_SSL */ 1638#endif /* LIBCURL_FEATURE_SSL */
1712 case MAX_REDIRS_OPTION: 1639 case MAX_REDIRS_OPTION:
1713 if (!is_intnonneg (optarg)) 1640 if (!is_intnonneg(optarg))
1714 usage2 (_("Invalid max_redirs count"), optarg); 1641 usage2(_("Invalid max_redirs count"), optarg);
1715 else { 1642 else {
1716 max_depth = atoi (optarg); 1643 max_depth = atoi(optarg);
1717 } 1644 }
1718 break; 1645 break;
1719 case 'f': /* onredirect */ 1646 case 'f': /* onredirect */
1720 if (!strcmp (optarg, "ok")) 1647 if (!strcmp(optarg, "ok"))
1721 onredirect = STATE_OK; 1648 onredirect = STATE_OK;
1722 else if (!strcmp (optarg, "warning")) 1649 else if (!strcmp(optarg, "warning"))
1723 onredirect = STATE_WARNING; 1650 onredirect = STATE_WARNING;
1724 else if (!strcmp (optarg, "critical")) 1651 else if (!strcmp(optarg, "critical"))
1725 onredirect = STATE_CRITICAL; 1652 onredirect = STATE_CRITICAL;
1726 else if (!strcmp (optarg, "unknown")) 1653 else if (!strcmp(optarg, "unknown"))
1727 onredirect = STATE_UNKNOWN; 1654 onredirect = STATE_UNKNOWN;
1728 else if (!strcmp (optarg, "follow")) 1655 else if (!strcmp(optarg, "follow"))
1729 onredirect = STATE_DEPENDENT; 1656 onredirect = STATE_DEPENDENT;
1730 else if (!strcmp (optarg, "stickyport")) 1657 else if (!strcmp(optarg, "stickyport"))
1731 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST|STICKY_PORT; 1658 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST | STICKY_PORT;
1732 else if (!strcmp (optarg, "sticky")) 1659 else if (!strcmp(optarg, "sticky"))
1733 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST; 1660 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST;
1734 else if (!strcmp (optarg, "follow")) 1661 else if (!strcmp(optarg, "follow"))
1735 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE; 1662 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE;
1736 else if (!strcmp (optarg, "curl")) 1663 else if (!strcmp(optarg, "curl"))
1737 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL; 1664 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL;
1738 else usage2 (_("Invalid onredirect option"), optarg); 1665 else
1739 if (verbose >= 2) 1666 usage2(_("Invalid onredirect option"), optarg);
1740 printf(_("* Following redirects set to %s\n"), state_text(onredirect)); 1667 if (verbose >= 2)
1741 break; 1668 printf(_("* Following redirects set to %s\n"), state_text(onredirect));
1742 case 'd': /* string or substring */ 1669 break;
1743 strncpy (header_expect, optarg, MAX_INPUT_BUFFER - 1); 1670 case 'd': /* string or substring */
1744 header_expect[MAX_INPUT_BUFFER - 1] = 0; 1671 strncpy(header_expect, optarg, MAX_INPUT_BUFFER - 1);
1745 break; 1672 header_expect[MAX_INPUT_BUFFER - 1] = 0;
1746 case 's': /* string or substring */ 1673 break;
1747 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); 1674 case 's': /* string or substring */
1748 string_expect[MAX_INPUT_BUFFER - 1] = 0; 1675 strncpy(string_expect, optarg, MAX_INPUT_BUFFER - 1);
1749 break; 1676 string_expect[MAX_INPUT_BUFFER - 1] = 0;
1750 case 'e': /* string or substring */ 1677 break;
1751 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1); 1678 case 'e': /* string or substring */
1752 server_expect[MAX_INPUT_BUFFER - 1] = 0; 1679 strncpy(server_expect, optarg, MAX_INPUT_BUFFER - 1);
1753 server_expect_yn = 1; 1680 server_expect[MAX_INPUT_BUFFER - 1] = 0;
1754 break; 1681 server_expect_yn = 1;
1755 case 'T': /* Content-type */ 1682 break;
1756 http_content_type = strdup (optarg); 1683 case 'T': /* Content-type */
1757 break; 1684 http_content_type = strdup(optarg);
1758 case 'l': /* linespan */ 1685 break;
1759 cflags &= ~REG_NEWLINE; 1686 case 'l': /* linespan */
1760 break; 1687 cflags &= ~REG_NEWLINE;
1761 case 'R': /* regex */ 1688 break;
1762 cflags |= REG_ICASE; 1689 case 'R': /* regex */
1690 cflags |= REG_ICASE;
1763 // fall through 1691 // fall through
1764 case 'r': /* regex */ 1692 case 'r': /* regex */
1765 strncpy (regexp, optarg, MAX_RE_SIZE - 1); 1693 strncpy(regexp, optarg, MAX_RE_SIZE - 1);
1766 regexp[MAX_RE_SIZE - 1] = 0; 1694 regexp[MAX_RE_SIZE - 1] = 0;
1767 errcode = regcomp (&preg, regexp, cflags); 1695 errcode = regcomp(&preg, regexp, cflags);
1768 if (errcode != 0) { 1696 if (errcode != 0) {
1769 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1697 (void)regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1770 printf (_("Could Not Compile Regular Expression: %s"), errbuf); 1698 printf(_("Could Not Compile Regular Expression: %s"), errbuf);
1771 return false; 1699 return false;
1772 } 1700 }
1773 break; 1701 break;
1774 case INVERT_REGEX: 1702 case INVERT_REGEX:
1775 invert_regex = true; 1703 invert_regex = true;
1776 break; 1704 break;
1777 case STATE_REGEX: 1705 case STATE_REGEX:
1778 if (!strcmp (optarg, "critical")) 1706 if (!strcasecmp(optarg, "critical"))
1779 state_regex = STATE_CRITICAL; 1707 state_regex = STATE_CRITICAL;
1780 else if (!strcmp (optarg, "warning")) 1708 else if (!strcasecmp(optarg, "warning"))
1781 state_regex = STATE_WARNING; 1709 state_regex = STATE_WARNING;
1782 else usage2 (_("Invalid state-regex option"), optarg); 1710 else
1783 break; 1711 usage2(_("Invalid state-regex option"), optarg);
1784 case '4': 1712 break;
1785 address_family = AF_INET; 1713 case '4':
1786 break; 1714 address_family = AF_INET;
1787 case '6': 1715 break;
1788#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 1716 case '6':
1789 address_family = AF_INET6; 1717#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
1718 address_family = AF_INET6;
1790#else 1719#else
1791 usage4 (_("IPv6 support not available")); 1720 usage4(_("IPv6 support not available"));
1792#endif 1721#endif
1793 break; 1722 break;
1794 case 'm': /* min_page_length */ 1723 case 'm': /* min_page_length */
1795 { 1724 {
1796 char *tmp; 1725 char *tmp;
1797 if (strchr(optarg, ':') != (char *)NULL) { 1726 if (strchr(optarg, ':') != (char *)NULL) {
1798 /* range, so get two values, min:max */ 1727 /* range, so get two values, min:max */
1799 tmp = strtok(optarg, ":"); 1728 tmp = strtok(optarg, ":");
1800 if (tmp == NULL) { 1729 if (tmp == NULL) {
1801 printf("Bad format: try \"-m min:max\"\n"); 1730 printf("Bad format: try \"-m min:max\"\n");
1802 exit (STATE_WARNING); 1731 exit(STATE_WARNING);
1803 } else 1732 } else
1804 min_page_len = atoi(tmp); 1733 min_page_len = atoi(tmp);
1805 1734
1806 tmp = strtok(NULL, ":"); 1735 tmp = strtok(NULL, ":");
1807 if (tmp == NULL) { 1736 if (tmp == NULL) {
1808 printf("Bad format: try \"-m min:max\"\n"); 1737 printf("Bad format: try \"-m min:max\"\n");
1809 exit (STATE_WARNING); 1738 exit(STATE_WARNING);
1810 } else 1739 } else
1811 max_page_len = atoi(tmp); 1740 max_page_len = atoi(tmp);
1812 } else 1741 } else
1813 min_page_len = atoi (optarg); 1742 min_page_len = atoi(optarg);
1814 break; 1743 break;
1815 } 1744 }
1816 case 'N': /* no-body */ 1745 case 'N': /* no-body */
1817 no_body = true; 1746 no_body = true;
1818 break; 1747 break;
1819 case 'M': /* max-age */ 1748 case 'M': /* max-age */
1820 { 1749 {
1821 int L = strlen(optarg); 1750 int L = strlen(optarg);
1822 if (L && optarg[L-1] == 'm') 1751 if (L && optarg[L - 1] == 'm')
1823 maximum_age = atoi (optarg) * 60; 1752 maximum_age = atoi(optarg) * 60;
1824 else if (L && optarg[L-1] == 'h') 1753 else if (L && optarg[L - 1] == 'h')
1825 maximum_age = atoi (optarg) * 60 * 60; 1754 maximum_age = atoi(optarg) * 60 * 60;
1826 else if (L && optarg[L-1] == 'd') 1755 else if (L && optarg[L - 1] == 'd')
1827 maximum_age = atoi (optarg) * 60 * 60 * 24; 1756 maximum_age = atoi(optarg) * 60 * 60 * 24;
1828 else if (L && (optarg[L-1] == 's' || 1757 else if (L && (optarg[L - 1] == 's' || isdigit(optarg[L - 1])))
1829 isdigit (optarg[L-1]))) 1758 maximum_age = atoi(optarg);
1830 maximum_age = atoi (optarg); 1759 else {
1831 else { 1760 fprintf(stderr, "unparsable max-age: %s\n", optarg);
1832 fprintf (stderr, "unparsable max-age: %s\n", optarg); 1761 exit(STATE_WARNING);
1833 exit (STATE_WARNING); 1762 }
1834 } 1763 if (verbose >= 2)
1835 if (verbose >= 2) 1764 printf("* Maximal age of document set to %d seconds\n", maximum_age);
1836 printf ("* Maximal age of document set to %d seconds\n", maximum_age); 1765 } break;
1837 } 1766 case 'E': /* show extended perfdata */
1838 break; 1767 show_extended_perfdata = true;
1839 case 'E': /* show extended perfdata */ 1768 break;
1840 show_extended_perfdata = true; 1769 case 'B': /* print body content after status line */
1841 break; 1770 show_body = true;
1842 case 'B': /* print body content after status line */ 1771 break;
1843 show_body = true; 1772 case HTTP_VERSION_OPTION:
1844 break; 1773 curl_http_version = CURL_HTTP_VERSION_NONE;
1845 case HTTP_VERSION_OPTION: 1774 if (strcmp(optarg, "1.0") == 0) {
1846 curl_http_version = CURL_HTTP_VERSION_NONE; 1775 curl_http_version = CURL_HTTP_VERSION_1_0;
1847 if (strcmp (optarg, "1.0") == 0) { 1776 } else if (strcmp(optarg, "1.1") == 0) {
1848 curl_http_version = CURL_HTTP_VERSION_1_0; 1777 curl_http_version = CURL_HTTP_VERSION_1_1;
1849 } else if (strcmp (optarg, "1.1") == 0) { 1778 } else if ((strcmp(optarg, "2.0") == 0) || (strcmp(optarg, "2") == 0)) {
1850 curl_http_version = CURL_HTTP_VERSION_1_1;
1851 } else if ((strcmp (optarg, "2.0") == 0) || (strcmp (optarg, "2") == 0)) {
1852#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) 1779#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0)
1853 curl_http_version = CURL_HTTP_VERSION_2_0; 1780 curl_http_version = CURL_HTTP_VERSION_2_0;
1854#else 1781#else
1855 curl_http_version = CURL_HTTP_VERSION_NONE; 1782 curl_http_version = CURL_HTTP_VERSION_NONE;
1856#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */ 1783#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */
1857 } else { 1784 } else {
1858 fprintf (stderr, "unknown http-version parameter: %s\n", optarg); 1785 fprintf(stderr, "unknown http-version parameter: %s\n", optarg);
1859 exit (STATE_WARNING); 1786 exit(STATE_WARNING);
1860 } 1787 }
1861 break; 1788 break;
1862 case AUTOMATIC_DECOMPRESSION: 1789 case AUTOMATIC_DECOMPRESSION:
1863 automatic_decompression = true; 1790 automatic_decompression = true;
1864 break; 1791 break;
1865 case COOKIE_JAR: 1792 case COOKIE_JAR:
1866 cookie_jar_file = optarg; 1793 cookie_jar_file = optarg;
1867 break; 1794 break;
1868 case HAPROXY_PROTOCOL: 1795 case HAPROXY_PROTOCOL:
1869 haproxy_protocol = true; 1796 haproxy_protocol = true;
1870 break; 1797 break;
1871 case '?': 1798 case '?':
1872 /* print short usage statement if args not parsable */ 1799 /* print short usage statement if args not parsable */
1873 usage5 (); 1800 usage5();
1874 break; 1801 break;
1875 } 1802 }
1876 } 1803 }
1877 1804
1878 c = optind; 1805 c = optind;
1879 1806
1880 if (server_address == NULL && c < argc) 1807 if (server_address == NULL && c < argc)
1881 server_address = strdup (argv[c++]); 1808 server_address = strdup(argv[c++]);
1882 1809
1883 if (host_name == NULL && c < argc) 1810 if (host_name == NULL && c < argc)
1884 host_name = strdup (argv[c++]); 1811 host_name = strdup(argv[c++]);
1885 1812
1886 if (server_address == NULL) { 1813 if (server_address == NULL) {
1887 if (host_name == NULL) 1814 if (host_name == NULL)
1888 usage4 (_("You must specify a server address or host name")); 1815 usage4(_("You must specify a server address or host name"));
1889 else 1816 else
1890 server_address = strdup (host_name); 1817 server_address = strdup(host_name);
1891 } 1818 }
1892 1819
1893 set_thresholds(&thlds, warning_thresholds, critical_thresholds); 1820 set_thresholds(&thlds, warning_thresholds, critical_thresholds);
1894 1821
1895 if (critical_thresholds && thlds->critical->end>(double)socket_timeout) 1822 if (critical_thresholds && thlds->critical->end > (double)socket_timeout)
1896 socket_timeout = (int)thlds->critical->end + 1; 1823 socket_timeout = (int)thlds->critical->end + 1;
1897 if (verbose >= 2) 1824 if (verbose >= 2)
1898 printf ("* Socket timeout set to %ld seconds\n", socket_timeout); 1825 printf("* Socket timeout set to %ld seconds\n", socket_timeout);
1899 1826
1900 if (http_method == NULL) 1827 if (http_method == NULL)
1901 http_method = strdup ("GET"); 1828 http_method = strdup("GET");
1902 1829
1903 if (client_cert && !client_privkey) 1830 if (client_cert && !client_privkey)
1904 usage4 (_("If you use a client certificate you must also specify a private key file")); 1831 usage4(_("If you use a client certificate you must also specify a private key file"));
1905 1832
1906 if (virtual_port == 0) 1833 if (virtual_port == 0)
1907 virtual_port = server_port; 1834 virtual_port = server_port;
1908 else { 1835 else {
1909 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT)) 1836 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT))
1910 if(!specify_port) 1837 if (!specify_port)
1911 server_port = virtual_port; 1838 server_port = virtual_port;
1912 } 1839 }
1913 1840
1914 return true; 1841 return true;
1915} 1842}
1916 1843
1917char *perfd_time (double elapsed_time) 1844char *perfd_time(double elapsed_time) {
1918{ 1845 return fperfdata("time", elapsed_time, "s", thlds->warning ? true : false, thlds->warning ? thlds->warning->end : 0,
1919 return fperfdata ("time", elapsed_time, "s", 1846 thlds->critical ? true : false, thlds->critical ? thlds->critical->end : 0, true, 0, true, socket_timeout);
1920 thlds->warning?true:false, thlds->warning?thlds->warning->end:0,
1921 thlds->critical?true:false, thlds->critical?thlds->critical->end:0,
1922 true, 0, true, socket_timeout);
1923} 1847}
1924 1848
1925char *perfd_time_connect (double elapsed_time_connect) 1849char *perfd_time_connect(double elapsed_time_connect) {
1926{ 1850 return fperfdata("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1927 return fperfdata ("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1928} 1851}
1929 1852
1930char *perfd_time_ssl (double elapsed_time_ssl) 1853char *perfd_time_ssl(double elapsed_time_ssl) {
1931{ 1854 return fperfdata("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1932 return fperfdata ("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1933} 1855}
1934 1856
1935char *perfd_time_headers (double elapsed_time_headers) 1857char *perfd_time_headers(double elapsed_time_headers) {
1936{ 1858 return fperfdata("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1937 return fperfdata ("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1938} 1859}
1939 1860
1940char *perfd_time_firstbyte (double elapsed_time_firstbyte) 1861char *perfd_time_firstbyte(double elapsed_time_firstbyte) {
1941{ 1862 return fperfdata("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1942 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1943} 1863}
1944 1864
1945char *perfd_time_transfer (double elapsed_time_transfer) 1865char *perfd_time_transfer(double elapsed_time_transfer) {
1946{ 1866 return fperfdata("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1947 return fperfdata ("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1948} 1867}
1949 1868
1950char *perfd_size (int page_len) 1869char *perfd_size(int page_len) {
1951{ 1870 return perfdata("size", page_len, "B", (min_page_len > 0 ? true : false), min_page_len, (min_page_len > 0 ? true : false), 0, true, 0,
1952 return perfdata ("size", page_len, "B", 1871 false, 0);
1953 (min_page_len>0?true:false), min_page_len,
1954 (min_page_len>0?true:false), 0,
1955 true, 0, false, 0);
1956} 1872}
1957 1873
1958void 1874void print_help(void) {
1959print_help (void) 1875 print_revision(progname, NP_VERSION);
1960{
1961 print_revision (progname, NP_VERSION);
1962 1876
1963 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1877 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1964 printf (COPYRIGHT, copyright, email); 1878 printf(COPYRIGHT, copyright, email);
1965 1879
1966 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test")); 1880 printf("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
1967 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for")); 1881 printf("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
1968 printf ("%s\n", _("strings and regular expressions, check connection times, and report on")); 1882 printf("%s\n", _("strings and regular expressions, check connection times, and report on"));
1969 printf ("%s\n", _("certificate expiration times.")); 1883 printf("%s\n", _("certificate expiration times."));
1970 printf ("\n"); 1884 printf("\n");
1971 printf ("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http")); 1885 printf("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http"));
1972 printf ("%s\n", _("as possible.")); 1886 printf("%s\n", _("as possible."));
1973 1887
1974 printf ("\n\n"); 1888 printf("\n\n");
1975 1889
1976 print_usage (); 1890 print_usage();
1977 1891
1978 printf (_("NOTE: One or both of -H and -I must be specified")); 1892 printf(_("NOTE: One or both of -H and -I must be specified"));
1979 1893
1980 printf ("\n"); 1894 printf("\n");
1981 1895
1982 printf (UT_HELP_VRSN); 1896 printf(UT_HELP_VRSN);
1983 printf (UT_EXTRA_OPTS); 1897 printf(UT_EXTRA_OPTS);
1984 1898
1985 printf (" %s\n", "-H, --hostname=ADDRESS"); 1899 printf(" %s\n", "-H, --hostname=ADDRESS");
1986 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)")); 1900 printf(" %s\n", _("Host name argument for servers using host headers (virtual host)"));
1987 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)")); 1901 printf(" %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
1988 printf (" %s\n", "-I, --IP-address=ADDRESS"); 1902 printf(" %s\n", "-I, --IP-address=ADDRESS");
1989 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup).")); 1903 printf(" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
1990 printf (" %s\n", "-p, --port=INTEGER"); 1904 printf(" %s\n", "-p, --port=INTEGER");
1991 printf (" %s", _("Port number (default: ")); 1905 printf(" %s", _("Port number (default: "));
1992 printf ("%d)\n", HTTP_PORT); 1906 printf("%d)\n", HTTP_PORT);
1993 1907
1994 printf (UT_IPv46); 1908 printf(UT_IPv46);
1995 1909
1996#ifdef LIBCURL_FEATURE_SSL 1910#ifdef LIBCURL_FEATURE_SSL
1997 printf (" %s\n", "-S, --ssl=VERSION[+]"); 1911 printf(" %s\n", "-S, --ssl=VERSION[+]");
1998 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents")); 1912 printf(" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
1999 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,")); 1913 printf(" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,"));
2000 printf (" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted.")); 1914 printf(" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted."));
2001 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl")); 1915 printf(" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl"));
2002 printf (" %s\n", "--sni"); 1916 printf(" %s\n", "--sni");
2003 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 1917 printf(" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
2004#if LIBCURL_VERSION_NUM >= 0x071801 1918# if LIBCURL_VERSION_NUM >= 0x071801
2005 printf (" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and")); 1919 printf(" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and"));
2006 printf (" %s\n", _(" SNI only really works since TLSv1.0")); 1920 printf(" %s\n", _(" SNI only really works since TLSv1.0"));
2007#else 1921# else
2008 printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1")); 1922 printf(" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1"));
2009#endif 1923# endif
2010 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 1924 printf(" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
2011 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443.")); 1925 printf(" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443."));
2012 printf (" %s\n", _("A STATE_WARNING is returned if the certificate has a validity less than the")); 1926 printf(" %s\n", _("A STATE_WARNING is returned if the certificate has a validity less than the"));
2013 printf (" %s\n", _("first agument's value. If there is a second argument and the certificate's")); 1927 printf(" %s\n", _("first agument's value. If there is a second argument and the certificate's"));
2014 printf (" %s\n", _("validity is less than its value, a STATE_CRITICAL is returned.")); 1928 printf(" %s\n", _("validity is less than its value, a STATE_CRITICAL is returned."));
2015 printf (" %s\n", _("(When this option is used the URL is not checked by default. You can use")); 1929 printf(" %s\n", _("(When this option is used the URL is not checked by default. You can use"));
2016 printf (" %s\n", _(" --continue-after-certificate to override this behavior)")); 1930 printf(" %s\n", _(" --continue-after-certificate to override this behavior)"));
2017 printf (" %s\n", "--continue-after-certificate"); 1931 printf(" %s\n", "--continue-after-certificate");
2018 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check.")); 1932 printf(" %s\n", _("Allows the HTTP check to continue after performing the certificate check."));
2019 printf (" %s\n", _("Does nothing unless -C is used.")); 1933 printf(" %s\n", _("Does nothing unless -C is used."));
2020 printf (" %s\n", "-J, --client-cert=FILE"); 1934 printf(" %s\n", "-J, --client-cert=FILE");
2021 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); 1935 printf(" %s\n", _("Name of file that contains the client certificate (PEM format)"));
2022 printf (" %s\n", _("to be used in establishing the SSL session")); 1936 printf(" %s\n", _("to be used in establishing the SSL session"));
2023 printf (" %s\n", "-K, --private-key=FILE"); 1937 printf(" %s\n", "-K, --private-key=FILE");
2024 printf (" %s\n", _("Name of file containing the private key (PEM format)")); 1938 printf(" %s\n", _("Name of file containing the private key (PEM format)"));
2025 printf (" %s\n", _("matching the client certificate")); 1939 printf(" %s\n", _("matching the client certificate"));
2026 printf (" %s\n", "--ca-cert=FILE"); 1940 printf(" %s\n", "--ca-cert=FILE");
2027 printf (" %s\n", _("CA certificate file to verify peer against")); 1941 printf(" %s\n", _("CA certificate file to verify peer against"));
2028 printf (" %s\n", "-D, --verify-cert"); 1942 printf(" %s\n", "-D, --verify-cert");
2029 printf (" %s\n", _("Verify the peer's SSL certificate and hostname")); 1943 printf(" %s\n", _("Verify the peer's SSL certificate and hostname"));
2030#endif 1944#endif
2031 1945
2032 printf (" %s\n", "-e, --expect=STRING"); 1946 printf(" %s\n", "-e, --expect=STRING");
2033 printf (" %s\n", _("Comma-delimited list of strings, at least one of them is expected in")); 1947 printf(" %s\n", _("Comma-delimited list of strings, at least one of them is expected in"));
2034 printf (" %s", _("the first (status) line of the server response (default: ")); 1948 printf(" %s", _("the first (status) line of the server response (default: "));
2035 printf ("%s)\n", HTTP_EXPECT); 1949 printf("%s)\n", HTTP_EXPECT);
2036 printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)")); 1950 printf(" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)"));
2037 printf (" %s\n", "-d, --header-string=STRING"); 1951 printf(" %s\n", "-d, --header-string=STRING");
2038 printf (" %s\n", _("String to expect in the response headers")); 1952 printf(" %s\n", _("String to expect in the response headers"));
2039 printf (" %s\n", "-s, --string=STRING"); 1953 printf(" %s\n", "-s, --string=STRING");
2040 printf (" %s\n", _("String to expect in the content")); 1954 printf(" %s\n", _("String to expect in the content"));
2041 printf (" %s\n", "-u, --url=PATH"); 1955 printf(" %s\n", "-u, --url=PATH");
2042 printf (" %s\n", _("URL to GET or POST (default: /)")); 1956 printf(" %s\n", _("URL to GET or POST (default: /)"));
2043 printf (" %s\n", "-P, --post=STRING"); 1957 printf(" %s\n", "-P, --post=STRING");
2044 printf (" %s\n", _("URL decoded http POST data")); 1958 printf(" %s\n", _("URL decoded http POST data"));
2045 printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)"); 1959 printf(" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)");
2046 printf (" %s\n", _("Set HTTP method.")); 1960 printf(" %s\n", _("Set HTTP method."));
2047 printf (" %s\n", "-N, --no-body"); 1961 printf(" %s\n", "-N, --no-body");
2048 printf (" %s\n", _("Don't wait for document body: stop reading after headers.")); 1962 printf(" %s\n", _("Don't wait for document body: stop reading after headers."));
2049 printf (" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)")); 1963 printf(" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)"));
2050 printf (" %s\n", "-M, --max-age=SECONDS"); 1964 printf(" %s\n", "-M, --max-age=SECONDS");
2051 printf (" %s\n", _("Warn if document is more than SECONDS old. the number can also be of")); 1965 printf(" %s\n", _("Warn if document is more than SECONDS old. the number can also be of"));
2052 printf (" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days.")); 1966 printf(" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days."));
2053 printf (" %s\n", "-T, --content-type=STRING"); 1967 printf(" %s\n", "-T, --content-type=STRING");
2054 printf (" %s\n", _("specify Content-Type header media type when POSTing\n")); 1968 printf(" %s\n", _("specify Content-Type header media type when POSTing\n"));
2055 printf (" %s\n", "-l, --linespan"); 1969 printf(" %s\n", "-l, --linespan");
2056 printf (" %s\n", _("Allow regex to span newlines (must precede -r or -R)")); 1970 printf(" %s\n", _("Allow regex to span newlines (must precede -r or -R)"));
2057 printf (" %s\n", "-r, --regex, --ereg=STRING"); 1971 printf(" %s\n", "-r, --regex, --ereg=STRING");
2058 printf (" %s\n", _("Search page for regex STRING")); 1972 printf(" %s\n", _("Search page for regex STRING"));
2059 printf (" %s\n", "-R, --eregi=STRING"); 1973 printf(" %s\n", "-R, --eregi=STRING");
2060 printf (" %s\n", _("Search page for case-insensitive regex STRING")); 1974 printf(" %s\n", _("Search page for case-insensitive regex STRING"));
2061 printf (" %s\n", "--invert-regex"); 1975 printf(" %s\n", "--invert-regex");
2062 printf (" %s\n", _("Return STATE if found, OK if not (STATE is CRITICAL, per default)")); 1976 printf(" %s\n", _("Return STATE if found, OK if not (STATE is CRITICAL, per default)"));
2063 printf (" %s\n", _("can be changed with --state--regex)")); 1977 printf(" %s\n", _("can be changed with --state--regex)"));
2064 printf (" %s\n", "--regex-state=STATE"); 1978 printf(" %s\n", "--state-regex=STATE");
2065 printf (" %s\n", _("Return STATE if regex is found, OK if not\n")); 1979 printf(" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of \"critical\",\"warning\""));
2066 printf (" %s\n", "-a, --authorization=AUTH_PAIR"); 1980 printf(" %s\n", "-a, --authorization=AUTH_PAIR");
2067 printf (" %s\n", _("Username:password on sites with basic authentication")); 1981 printf(" %s\n", _("Username:password on sites with basic authentication"));
2068 printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR"); 1982 printf(" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
2069 printf (" %s\n", _("Username:password on proxy-servers with basic authentication")); 1983 printf(" %s\n", _("Username:password on proxy-servers with basic authentication"));
2070 printf (" %s\n", "-A, --useragent=STRING"); 1984 printf(" %s\n", "-A, --useragent=STRING");
2071 printf (" %s\n", _("String to be sent in http header as \"User Agent\"")); 1985 printf(" %s\n", _("String to be sent in http header as \"User Agent\""));
2072 printf (" %s\n", "-k, --header=STRING"); 1986 printf(" %s\n", "-k, --header=STRING");
2073 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers")); 1987 printf(" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
2074 printf (" %s\n", "-E, --extended-perfdata"); 1988 printf(" %s\n", "-E, --extended-perfdata");
2075 printf (" %s\n", _("Print additional performance data")); 1989 printf(" %s\n", _("Print additional performance data"));
2076 printf (" %s\n", "-B, --show-body"); 1990 printf(" %s\n", "-B, --show-body");
2077 printf (" %s\n", _("Print body content below status line")); 1991 printf(" %s\n", _("Print body content below status line"));
2078 printf (" %s\n", "-L, --link"); 1992 printf(" %s\n", "-L, --link");
2079 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)")); 1993 printf(" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
2080 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>"); 1994 printf(" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>");
2081 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); 1995 printf(" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the"));
2082 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); 1996 printf(" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
2083 printf (" %s\n", _("follow uses the old redirection algorithm of check_http.")); 1997 printf(" %s\n", _("follow uses the old redirection algorithm of check_http."));
2084 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl.")); 1998 printf(" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl."));
2085 printf (" %s\n", "--max-redirs=INTEGER"); 1999 printf(" %s\n", "--max-redirs=INTEGER");
2086 printf (" %s", _("Maximal number of redirects (default: ")); 2000 printf(" %s", _("Maximal number of redirects (default: "));
2087 printf ("%d)\n", DEFAULT_MAX_REDIRS); 2001 printf("%d)\n", DEFAULT_MAX_REDIRS);
2088 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); 2002 printf(" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
2089 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)")); 2003 printf(" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
2090 printf ("\n"); 2004 printf("\n");
2091 printf (" %s\n", "--http-version=VERSION"); 2005 printf(" %s\n", "--http-version=VERSION");
2092 printf (" %s\n", _("Connect via specific HTTP protocol.")); 2006 printf(" %s\n", _("Connect via specific HTTP protocol."));
2093 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)")); 2007 printf(" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)"));
2094 printf (" %s\n", "--enable-automatic-decompression"); 2008 printf(" %s\n", "--enable-automatic-decompression");
2095 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING).")); 2009 printf(" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING)."));
2096 printf(" %s\n", "--haproxy-protocol"); 2010 printf(" %s\n", "--haproxy-protocol");
2097 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL).")); 2011 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL)."));
2098 printf (" %s\n", "--cookie-jar=FILE"); 2012 printf(" %s\n", "--cookie-jar=FILE");
2099 printf (" %s\n", _("Store cookies in the cookie jar and send them out when requested.")); 2013 printf(" %s\n", _("Store cookies in the cookie jar and send them out when requested."));
2100 printf ("\n"); 2014 printf("\n");
2101 2015
2102 printf (UT_WARN_CRIT); 2016 printf(UT_WARN_CRIT);
2103 2017
2104 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 2018 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
2105 2019
2106 printf (UT_VERBOSE); 2020 printf(UT_VERBOSE);
2107 2021
2108 printf ("\n"); 2022 printf("\n");
2109 printf ("%s\n", _("Notes:")); 2023 printf("%s\n", _("Notes:"));
2110 printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host.")); 2024 printf(" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
2111 printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL")); 2025 printf(" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
2112 printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response")); 2026 printf(" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response"));
2113 printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are")); 2027 printf(" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
2114 printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN")); 2028 printf(" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
2115 printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument.")); 2029 printf(" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
2116 2030
2117#ifdef LIBCURL_FEATURE_SSL 2031#ifdef LIBCURL_FEATURE_SSL
2118 printf ("\n"); 2032 printf("\n");
2119 printf (" %s\n", _("This plugin can also check whether an SSL enabled web server is able to")); 2033 printf(" %s\n", _("This plugin can also check whether an SSL enabled web server is able to"));
2120 printf (" %s\n", _("serve content (optionally within a specified time) or whether the X509 ")); 2034 printf(" %s\n", _("serve content (optionally within a specified time) or whether the X509 "));
2121 printf (" %s\n", _("certificate is still valid for the specified number of days.")); 2035 printf(" %s\n", _("certificate is still valid for the specified number of days."));
2122 printf ("\n"); 2036 printf("\n");
2123 printf (" %s\n", _("Please note that this plugin does not check if the presented server")); 2037 printf(" %s\n", _("Please note that this plugin does not check if the presented server"));
2124 printf (" %s\n", _("certificate matches the hostname of the server, or if the certificate")); 2038 printf(" %s\n", _("certificate matches the hostname of the server, or if the certificate"));
2125 printf (" %s\n", _("has a valid chain of trust to one of the locally installed CAs.")); 2039 printf(" %s\n", _("has a valid chain of trust to one of the locally installed CAs."));
2126 printf ("\n"); 2040 printf("\n");
2127 printf ("%s\n", _("Examples:")); 2041 printf("%s\n", _("Examples:"));
2128 printf (" %s\n\n", "CHECK CONTENT: check_curl -w 5 -c 10 --ssl -H www.verisign.com"); 2042 printf(" %s\n\n", "CHECK CONTENT: check_curl -w 5 -c 10 --ssl -H www.verisign.com");
2129 printf (" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,")); 2043 printf(" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,"));
2130 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds")); 2044 printf(" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
2131 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,")); 2045 printf(" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
2132 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2046 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2133 printf ("\n"); 2047 printf("\n");
2134 printf (" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 14"); 2048 printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 14");
2135 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,")); 2049 printf(" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,"));
2136 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than")); 2050 printf(" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
2137 printf (" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when")); 2051 printf(" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when"));
2138 printf (" %s\n\n", _("the certificate is expired.")); 2052 printf(" %s\n\n", _("the certificate is expired."));
2139 printf ("\n"); 2053 printf("\n");
2140 printf (" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 30,14"); 2054 printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 30,14");
2141 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 30 days,")); 2055 printf(" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 30 days,"));
2142 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than")); 2056 printf(" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
2143 printf (" %s\n", _("30 days, but more than 14 days, a STATE_WARNING is returned.")); 2057 printf(" %s\n", _("30 days, but more than 14 days, a STATE_WARNING is returned."));
2144 printf (" %s\n", _("A STATE_CRITICAL will be returned when certificate expires in less than 14 days")); 2058 printf(" %s\n", _("A STATE_CRITICAL will be returned when certificate expires in less than 14 days"));
2145#endif 2059#endif
2146 2060
2147 printf ("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:"); 2061 printf("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:");
2148 printf (" %s\n", _("It is recommended to use an environment proxy like:")); 2062 printf(" %s\n", _("It is recommended to use an environment proxy like:"));
2149 printf (" %s\n", _("http_proxy=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org")); 2063 printf(" %s\n", _("http_proxy=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org"));
2150 printf (" %s\n", _("legacy proxy requests in check_http style still work:")); 2064 printf(" %s\n", _("legacy proxy requests in check_http style still work:"));
2151 printf (" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u http://www.monitoring-plugins.org/ -H www.monitoring-plugins.org")); 2065 printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u http://www.monitoring-plugins.org/ -H www.monitoring-plugins.org"));
2152 2066
2153#ifdef LIBCURL_FEATURE_SSL 2067#ifdef LIBCURL_FEATURE_SSL
2154 printf ("\n %s\n", "CHECK SSL WEBSERVER CONTENT VIA PROXY USING HTTP 1.1 CONNECT: "); 2068 printf("\n %s\n", "CHECK SSL WEBSERVER CONTENT VIA PROXY USING HTTP 1.1 CONNECT: ");
2155 printf (" %s\n", _("It is recommended to use an environment proxy like:")); 2069 printf(" %s\n", _("It is recommended to use an environment proxy like:"));
2156 printf (" %s\n", _("https_proxy=http://192.168.100.35:3128 ./check_curl -H www.verisign.com -S")); 2070 printf(" %s\n", _("https_proxy=http://192.168.100.35:3128 ./check_curl -H www.verisign.com -S"));
2157 printf (" %s\n", _("legacy proxy requests in check_http style still work:")); 2071 printf(" %s\n", _("legacy proxy requests in check_http style still work:"));
2158 printf (" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u https://www.verisign.com/ -S -j CONNECT -H www.verisign.com ")); 2072 printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u https://www.verisign.com/ -S -j CONNECT -H www.verisign.com "));
2159 printf (" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> -S(sl) -j CONNECT -H <webserver>")); 2073 printf(" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> -S(sl) -j CONNECT -H <webserver>"));
2160 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds")); 2074 printf(" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
2161 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,")); 2075 printf(" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
2162 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2076 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2163 2077
2164#endif 2078#endif
2165 2079
2166 printf (UT_SUPPORT); 2080 printf(UT_SUPPORT);
2167
2168} 2081}
2169 2082
2170 2083void print_usage(void) {
2171 2084 printf("%s\n", _("Usage:"));
2172void 2085 printf(" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n", progname);
2173print_usage (void) 2086 printf(" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
2174{ 2087 printf(" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
2175 printf ("%s\n", _("Usage:")); 2088 printf(" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n");
2176 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); 2089 printf(" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
2177 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n"); 2090 printf(" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
2178 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n"); 2091 printf(" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n");
2179 printf (" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n"); 2092 printf(" [-T <content-type>] [-j method]\n");
2180 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 2093 printf(" [--http-version=<version>] [--enable-automatic-decompression]\n");
2181 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 2094 printf(" [--cookie-jar=<cookie jar file>\n");
2182 printf (" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n"); 2095 printf(" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n", progname);
2183 printf (" [-T <content-type>] [-j method]\n"); 2096 printf(" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2184 printf (" [--http-version=<version>] [--enable-automatic-decompression]\n"); 2097 printf("\n");
2185 printf (" [--cookie-jar=<cookie jar file>\n");
2186 printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
2187 printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2188 printf ("\n");
2189#ifdef LIBCURL_FEATURE_SSL 2098#ifdef LIBCURL_FEATURE_SSL
2190 printf ("%s\n", _("In the first form, make an HTTP request.")); 2099 printf("%s\n", _("In the first form, make an HTTP request."));
2191 printf ("%s\n\n", _("In the second form, connect to the server and check the TLS certificate.")); 2100 printf("%s\n\n", _("In the second form, connect to the server and check the TLS certificate."));
2192#endif 2101#endif
2193 printf ("%s\n", _("WARNING: check_curl is experimental. Please use"));
2194 printf ("%s\n\n", _("check_http if you need a stable version."));
2195} 2102}
2196 2103
2197void 2104void print_curl_version(void) { printf("%s\n", curl_version()); }
2198print_curl_version (void)
2199{
2200 printf( "%s\n", curl_version());
2201}
2202 2105
2203int 2106int curlhelp_initwritebuffer(curlhelp_write_curlbuf *buf) {
2204curlhelp_initwritebuffer (curlhelp_write_curlbuf *buf) 2107 buf->bufsize = DEFAULT_BUFFER_SIZE;
2205{ 2108 buf->buflen = 0;
2206 buf->bufsize = DEFAULT_BUFFER_SIZE; 2109 buf->buf = (char *)malloc((size_t)buf->bufsize);
2207 buf->buflen = 0; 2110 if (buf->buf == NULL)
2208 buf->buf = (char *)malloc ((size_t)buf->bufsize); 2111 return -1;
2209 if (buf->buf == NULL) return -1; 2112 return 0;
2210 return 0;
2211} 2113}
2212 2114
2213size_t curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *stream) 2115size_t curlhelp_buffer_write_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
2214{ 2116 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2215 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2216 2117
2217 while (buf->bufsize < buf->buflen + size * nmemb + 1) { 2118 while (buf->bufsize < buf->buflen + size * nmemb + 1) {
2218 buf->bufsize = buf->bufsize * 2; 2119 buf->bufsize = buf->bufsize * 2;
2219 buf->buf = (char *)realloc (buf->buf, buf->bufsize); 2120 buf->buf = (char *)realloc(buf->buf, buf->bufsize);
2220 if (buf->buf == NULL) { 2121 if (buf->buf == NULL) {
2221 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno)); 2122 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno));
2222 return -1; 2123 return -1;
2223 } 2124 }
2224 } 2125 }
2225 2126
2226 memcpy (buf->buf + buf->buflen, buffer, size * nmemb); 2127 memcpy(buf->buf + buf->buflen, buffer, size * nmemb);
2227 buf->buflen += size * nmemb; 2128 buf->buflen += size * nmemb;
2228 buf->buf[buf->buflen] = '\0'; 2129 buf->buf[buf->buflen] = '\0';
2229 2130
2230 return (int)(size * nmemb); 2131 return (int)(size * nmemb);
2231} 2132}
2232 2133
2233size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) 2134size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
2234{ 2135 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2235 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2236 2136
2237 size_t n = min (nmemb * size, buf->buflen - buf->pos); 2137 size_t n = min(nmemb * size, buf->buflen - buf->pos);
2238 2138
2239 memcpy (buffer, buf->buf + buf->pos, n); 2139 memcpy(buffer, buf->buf + buf->pos, n);
2240 buf->pos += n; 2140 buf->pos += n;
2241 2141
2242 return (int)n; 2142 return (int)n;
2243} 2143}
2244 2144
2245void 2145void curlhelp_freewritebuffer(curlhelp_write_curlbuf *buf) {
2246curlhelp_freewritebuffer (curlhelp_write_curlbuf *buf) 2146 free(buf->buf);
2247{ 2147 buf->buf = NULL;
2248 free (buf->buf);
2249 buf->buf = NULL;
2250} 2148}
2251 2149
2252int 2150int curlhelp_initreadbuffer(curlhelp_read_curlbuf *buf, const char *data, size_t datalen) {
2253curlhelp_initreadbuffer (curlhelp_read_curlbuf *buf, const char *data, size_t datalen) 2151 buf->buflen = datalen;
2254{ 2152 buf->buf = (char *)malloc((size_t)buf->buflen);
2255 buf->buflen = datalen; 2153 if (buf->buf == NULL)
2256 buf->buf = (char *)malloc ((size_t)buf->buflen); 2154 return -1;
2257 if (buf->buf == NULL) return -1; 2155 memcpy(buf->buf, data, datalen);
2258 memcpy (buf->buf, data, datalen); 2156 buf->pos = 0;
2259 buf->pos = 0; 2157 return 0;
2260 return 0;
2261} 2158}
2262 2159
2263void 2160void curlhelp_freereadbuffer(curlhelp_read_curlbuf *buf) {
2264curlhelp_freereadbuffer (curlhelp_read_curlbuf *buf) 2161 free(buf->buf);
2265{ 2162 buf->buf = NULL;
2266 free (buf->buf);
2267 buf->buf = NULL;
2268} 2163}
2269 2164
2270/* TODO: where to put this, it's actually part of sstrings2 (logically)? 2165/* TODO: where to put this, it's actually part of sstrings2 (logically)?
2271 */ 2166 */
2272const char* 2167const char *strrstr2(const char *haystack, const char *needle) {
2273strrstr2(const char *haystack, const char *needle) 2168 int counter;
2274{ 2169 size_t len;
2275 int counter; 2170 const char *prev_pos;
2276 size_t len; 2171 const char *pos;
2277 const char *prev_pos; 2172
2278 const char *pos; 2173 if (haystack == NULL || needle == NULL)
2279 2174 return NULL;
2280 if (haystack == NULL || needle == NULL) 2175
2281 return NULL; 2176 if (haystack[0] == '\0' || needle[0] == '\0')
2282 2177 return NULL;
2283 if (haystack[0] == '\0' || needle[0] == '\0') 2178
2284 return NULL; 2179 counter = 0;
2285 2180 prev_pos = NULL;
2286 counter = 0; 2181 pos = haystack;
2287 prev_pos = NULL; 2182 len = strlen(needle);
2288 pos = haystack; 2183 for (;;) {
2289 len = strlen (needle); 2184 pos = strstr(pos, needle);
2290 for (;;) { 2185 if (pos == NULL) {
2291 pos = strstr (pos, needle); 2186 if (counter == 0)
2292 if (pos == NULL) { 2187 return NULL;
2293 if (counter == 0) 2188 return prev_pos;
2294 return NULL; 2189 }
2295 else 2190 counter++;
2296 return prev_pos; 2191 prev_pos = pos;
2297 } 2192 pos += len;
2298 counter++; 2193 if (*pos == '\0')
2299 prev_pos = pos; 2194 return prev_pos;
2300 pos += len; 2195 }
2301 if (*pos == '\0') return prev_pos;
2302 }
2303} 2196}
2304 2197
2305int 2198int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) {
2306curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line) 2199 char *first_line_end;
2307{ 2200 char *p;
2308 char *first_line_end; 2201 size_t first_line_len;
2309 char *p; 2202 char *pp;
2310 size_t first_line_len; 2203 const char *start;
2311 char *pp; 2204 char *first_line_buf;
2312 const char *start; 2205
2313 char *first_line_buf; 2206 /* find last start of a new header */
2314 2207 start = strrstr2(buf, "\r\nHTTP/");
2315 /* find last start of a new header */ 2208 if (start != NULL) {
2316 start = strrstr2 (buf, "\r\nHTTP/"); 2209 start += 2;
2317 if (start != NULL) { 2210 buf = start;
2318 start += 2; 2211 }
2319 buf = start;
2320 }
2321
2322 first_line_end = strstr(buf, "\r\n");
2323 if (first_line_end == NULL) return -1;
2324
2325 first_line_len = (size_t)(first_line_end - buf);
2326 status_line->first_line = (char *)malloc (first_line_len + 1);
2327 if (status_line->first_line == NULL) return -1;
2328 memcpy (status_line->first_line, buf, first_line_len);
2329 status_line->first_line[first_line_len] = '\0';
2330 first_line_buf = strdup( status_line->first_line );
2331
2332 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
2333
2334 p = strtok(first_line_buf, "/");
2335 if( p == NULL ) { free( first_line_buf ); return -1; }
2336 if( strcmp( p, "HTTP" ) != 0 ) { free( first_line_buf ); return -1; }
2337
2338 p = strtok( NULL, " " );
2339 if( p == NULL ) { free( first_line_buf ); return -1; }
2340 if( strchr( p, '.' ) != NULL ) {
2341
2342 /* HTTP 1.x case */
2343 strtok( p, "." );
2344 status_line->http_major = (int)strtol( p, &pp, 10 );
2345 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2346 strtok( NULL, " " );
2347 status_line->http_minor = (int)strtol( p, &pp, 10 );
2348 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2349 p += 4; /* 1.x SP */
2350 } else {
2351 /* HTTP 2 case */
2352 status_line->http_major = (int)strtol( p, &pp, 10 );
2353 status_line->http_minor = 0;
2354 p += 2; /* 2 SP */
2355 }
2356
2357 /* status code: "404" or "404.1", then SP */
2358
2359 p = strtok( p, " " );
2360 if( p == NULL ) { free( first_line_buf ); return -1; }
2361 if( strchr( p, '.' ) != NULL ) {
2362 char *ppp;
2363 ppp = strtok( p, "." );
2364 status_line->http_code = (int)strtol( ppp, &pp, 10 );
2365 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2366 ppp = strtok( NULL, "" );
2367 status_line->http_subcode = (int)strtol( ppp, &pp, 10 );
2368 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2369 p += 6; /* 400.1 SP */
2370 } else {
2371 status_line->http_code = (int)strtol( p, &pp, 10 );
2372 status_line->http_subcode = -1;
2373 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2374 p += 4; /* 400 SP */
2375 }
2376
2377 /* Human readable message: "Not Found" CRLF */
2378
2379 p = strtok( p, "" );
2380 if( p == NULL ) { status_line->msg = ""; return 0; }
2381 status_line->msg = status_line->first_line + ( p - first_line_buf );
2382 free( first_line_buf );
2383
2384 return 0;
2385}
2386 2212
2387void 2213 first_line_end = strstr(buf, "\r\n");
2388curlhelp_free_statusline (curlhelp_statusline *status_line) 2214 if (first_line_end == NULL)
2389{ 2215 return -1;
2390 free (status_line->first_line); 2216
2391} 2217 first_line_len = (size_t)(first_line_end - buf);
2218 status_line->first_line = (char *)malloc(first_line_len + 1);
2219 if (status_line->first_line == NULL)
2220 return -1;
2221 memcpy(status_line->first_line, buf, first_line_len);
2222 status_line->first_line[first_line_len] = '\0';
2223 first_line_buf = strdup(status_line->first_line);
2224
2225 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
2226
2227 p = strtok(first_line_buf, "/");
2228 if (p == NULL) {
2229 free(first_line_buf);
2230 return -1;
2231 }
2232 if (strcmp(p, "HTTP") != 0) {
2233 free(first_line_buf);
2234 return -1;
2235 }
2236
2237 p = strtok(NULL, " ");
2238 if (p == NULL) {
2239 free(first_line_buf);
2240 return -1;
2241 }
2242 if (strchr(p, '.') != NULL) {
2243
2244 /* HTTP 1.x case */
2245 strtok(p, ".");
2246 status_line->http_major = (int)strtol(p, &pp, 10);
2247 if (*pp != '\0') {
2248 free(first_line_buf);
2249 return -1;
2250 }
2251 strtok(NULL, " ");
2252 status_line->http_minor = (int)strtol(p, &pp, 10);
2253 if (*pp != '\0') {
2254 free(first_line_buf);
2255 return -1;
2256 }
2257 p += 4; /* 1.x SP */
2258 } else {
2259 /* HTTP 2 case */
2260 status_line->http_major = (int)strtol(p, &pp, 10);
2261 status_line->http_minor = 0;
2262 p += 2; /* 2 SP */
2263 }
2392 2264
2393void 2265 /* status code: "404" or "404.1", then SP */
2394remove_newlines (char *s)
2395{
2396 char *p;
2397 2266
2398 for (p = s; *p != '\0'; p++) 2267 p = strtok(p, " ");
2399 if (*p == '\r' || *p == '\n') 2268 if (p == NULL) {
2400 *p = ' '; 2269 free(first_line_buf);
2270 return -1;
2271 }
2272 if (strchr(p, '.') != NULL) {
2273 char *ppp;
2274 ppp = strtok(p, ".");
2275 status_line->http_code = (int)strtol(ppp, &pp, 10);
2276 if (*pp != '\0') {
2277 free(first_line_buf);
2278 return -1;
2279 }
2280 ppp = strtok(NULL, "");
2281 status_line->http_subcode = (int)strtol(ppp, &pp, 10);
2282 if (*pp != '\0') {
2283 free(first_line_buf);
2284 return -1;
2285 }
2286 p += 6; /* 400.1 SP */
2287 } else {
2288 status_line->http_code = (int)strtol(p, &pp, 10);
2289 status_line->http_subcode = -1;
2290 if (*pp != '\0') {
2291 free(first_line_buf);
2292 return -1;
2293 }
2294 p += 4; /* 400 SP */
2295 }
2296
2297 /* Human readable message: "Not Found" CRLF */
2298
2299 p = strtok(p, "");
2300 if (p == NULL) {
2301 status_line->msg = "";
2302 return 0;
2303 }
2304 status_line->msg = status_line->first_line + (p - first_line_buf);
2305 free(first_line_buf);
2306
2307 return 0;
2401} 2308}
2402 2309
2403char * 2310void curlhelp_free_statusline(curlhelp_statusline *status_line) { free(status_line->first_line); }
2404get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header) 2311
2405{ 2312char *get_header_value(const struct phr_header *headers, const size_t nof_headers, const char *header) {
2406 for(size_t i = 0; i < nof_headers; i++ ) { 2313 for (size_t i = 0; i < nof_headers; i++) {
2407 if(headers[i].name != NULL && strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) { 2314 if (headers[i].name != NULL && strncasecmp(header, headers[i].name, max(headers[i].name_len, 4)) == 0) {
2408 return strndup( headers[i].value, headers[i].value_len ); 2315 return strndup(headers[i].value, headers[i].value_len);
2409 } 2316 }
2410 } 2317 }
2411 return NULL; 2318 return NULL;
2412} 2319}
2413 2320
2414int 2321int check_document_dates(const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) {
2415check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) 2322 char *server_date = NULL;
2416{ 2323 char *document_date = NULL;
2417 char *server_date = NULL; 2324 int date_result = STATE_OK;
2418 char *document_date = NULL; 2325 curlhelp_statusline status_line;
2419 int date_result = STATE_OK; 2326 struct phr_header headers[255];
2420 curlhelp_statusline status_line; 2327 size_t nof_headers = 255;
2421 struct phr_header headers[255]; 2328 size_t msglen;
2422 size_t nof_headers = 255; 2329
2423 size_t msglen; 2330 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2424 2331 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
2425 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2426 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2427 headers, &nof_headers, 0);
2428 2332
2429 if (res == -1) { 2333 if (res == -1) {
2430 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2334 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2431 } 2335 }
2432 2336
2433 server_date = get_header_value (headers, nof_headers, "date"); 2337 server_date = get_header_value(headers, nof_headers, "date");
2434 document_date = get_header_value (headers, nof_headers, "last-modified"); 2338 document_date = get_header_value(headers, nof_headers, "last-modified");
2435 2339
2436 if (!server_date || !*server_date) { 2340 if (!server_date || !*server_date) {
2437 char tmp[DEFAULT_BUFFER_SIZE]; 2341 char tmp[DEFAULT_BUFFER_SIZE];
2438 2342
2439 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg); 2343 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg);
2440 strcpy(*msg, tmp); 2344 strcpy(*msg, tmp);
2441 2345
2442 date_result = max_state_alt(STATE_UNKNOWN, date_result); 2346 date_result = max_state_alt(STATE_UNKNOWN, date_result);
@@ -2444,34 +2348,34 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2444 } else if (!document_date || !*document_date) { 2348 } else if (!document_date || !*document_date) {
2445 char tmp[DEFAULT_BUFFER_SIZE]; 2349 char tmp[DEFAULT_BUFFER_SIZE];
2446 2350
2447 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg); 2351 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg);
2448 strcpy(*msg, tmp); 2352 strcpy(*msg, tmp);
2449 2353
2450 date_result = max_state_alt(STATE_CRITICAL, date_result); 2354 date_result = max_state_alt(STATE_CRITICAL, date_result);
2451 2355
2452 } else { 2356 } else {
2453 time_t srv_data = curl_getdate (server_date, NULL); 2357 time_t srv_data = curl_getdate(server_date, NULL);
2454 time_t doc_data = curl_getdate (document_date, NULL); 2358 time_t doc_data = curl_getdate(document_date, NULL);
2455 if (verbose >= 2) 2359 if (verbose >= 2)
2456 printf ("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, document_date, (int)doc_data); 2360 printf("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, document_date, (int)doc_data);
2457 if (srv_data <= 0) { 2361 if (srv_data <= 0) {
2458 char tmp[DEFAULT_BUFFER_SIZE]; 2362 char tmp[DEFAULT_BUFFER_SIZE];
2459 2363
2460 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), *msg, server_date); 2364 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), *msg, server_date);
2461 strcpy(*msg, tmp); 2365 strcpy(*msg, tmp);
2462 2366
2463 date_result = max_state_alt(STATE_CRITICAL, date_result); 2367 date_result = max_state_alt(STATE_CRITICAL, date_result);
2464 } else if (doc_data <= 0) { 2368 } else if (doc_data <= 0) {
2465 char tmp[DEFAULT_BUFFER_SIZE]; 2369 char tmp[DEFAULT_BUFFER_SIZE];
2466 2370
2467 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date); 2371 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date);
2468 strcpy(*msg, tmp); 2372 strcpy(*msg, tmp);
2469 2373
2470 date_result = max_state_alt(STATE_CRITICAL, date_result); 2374 date_result = max_state_alt(STATE_CRITICAL, date_result);
2471 } else if (doc_data > srv_data + 30) { 2375 } else if (doc_data > srv_data + 30) {
2472 char tmp[DEFAULT_BUFFER_SIZE]; 2376 char tmp[DEFAULT_BUFFER_SIZE];
2473 2377
2474 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data); 2378 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data);
2475 strcpy(*msg, tmp); 2379 strcpy(*msg, tmp);
2476 2380
2477 date_result = max_state_alt(STATE_CRITICAL, date_result); 2381 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2480,14 +2384,14 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2480 if (n > (60 * 60 * 24 * 2)) { 2384 if (n > (60 * 60 * 24 * 2)) {
2481 char tmp[DEFAULT_BUFFER_SIZE]; 2385 char tmp[DEFAULT_BUFFER_SIZE];
2482 2386
2483 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), *msg, ((float) n) / (60 * 60 * 24)); 2387 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), *msg, ((float)n) / (60 * 60 * 24));
2484 strcpy(*msg, tmp); 2388 strcpy(*msg, tmp);
2485 2389
2486 date_result = max_state_alt(STATE_CRITICAL, date_result); 2390 date_result = max_state_alt(STATE_CRITICAL, date_result);
2487 } else { 2391 } else {
2488 char tmp[DEFAULT_BUFFER_SIZE]; 2392 char tmp[DEFAULT_BUFFER_SIZE];
2489 2393
2490 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60); 2394 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60);
2491 strcpy(*msg, tmp); 2395 strcpy(*msg, tmp);
2492 2396
2493 date_result = max_state_alt(STATE_CRITICAL, date_result); 2397 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2495,132 +2399,128 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2495 } 2399 }
2496 } 2400 }
2497 2401
2498 if (server_date) free (server_date); 2402 if (server_date)
2499 if (document_date) free (document_date); 2403 free(server_date);
2404 if (document_date)
2405 free(document_date);
2500 2406
2501 return date_result; 2407 return date_result;
2502} 2408}
2503 2409
2410int get_content_length(const curlhelp_write_curlbuf *header_buf, const curlhelp_write_curlbuf *body_buf) {
2411 size_t content_length = 0;
2412 struct phr_header headers[255];
2413 size_t nof_headers = 255;
2414 size_t msglen;
2415 char *content_length_s = NULL;
2416 curlhelp_statusline status_line;
2504 2417
2505int 2418 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2506get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf) 2419 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
2507{
2508 size_t content_length = 0;
2509 struct phr_header headers[255];
2510 size_t nof_headers = 255;
2511 size_t msglen;
2512 char *content_length_s = NULL;
2513 curlhelp_statusline status_line;
2514
2515 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2516 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2517 headers, &nof_headers, 0);
2518 2420
2519 if (res == -1) { 2421 if (res == -1) {
2520 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2422 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2521 } 2423 }
2522 2424
2523 content_length_s = get_header_value (headers, nof_headers, "content-length"); 2425 content_length_s = get_header_value(headers, nof_headers, "content-length");
2524 if (!content_length_s) { 2426 if (!content_length_s) {
2525 return header_buf->buflen + body_buf->buflen; 2427 return header_buf->buflen + body_buf->buflen;
2526 } 2428 }
2527 content_length_s += strspn (content_length_s, " \t"); 2429 content_length_s += strspn(content_length_s, " \t");
2528 content_length = atoi (content_length_s); 2430 content_length = atoi(content_length_s);
2529 if (content_length != body_buf->buflen) { 2431 if (content_length != body_buf->buflen) {
2530 /* TODO: should we warn if the actual and the reported body length don't match? */ 2432 /* TODO: should we warn if the actual and the reported body length don't match? */
2531 } 2433 }
2532 2434
2533 if (content_length_s) free (content_length_s); 2435 if (content_length_s)
2436 free(content_length_s);
2534 2437
2535 return header_buf->buflen + body_buf->buflen; 2438 return header_buf->buflen + body_buf->buflen;
2536} 2439}
2537 2440
2538/* TODO: is there a better way in libcurl to check for the SSL library? */ 2441/* TODO: is there a better way in libcurl to check for the SSL library? */
2539curlhelp_ssl_library 2442curlhelp_ssl_library curlhelp_get_ssl_library(void) {
2540curlhelp_get_ssl_library () 2443 curl_version_info_data *version_data;
2541{ 2444 char *ssl_version;
2542 curl_version_info_data* version_data; 2445 char *library;
2543 char *ssl_version; 2446 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
2544 char *library; 2447
2545 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 2448 version_data = curl_version_info(CURLVERSION_NOW);
2546 2449 if (version_data == NULL)
2547 version_data = curl_version_info (CURLVERSION_NOW); 2450 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2548 if (version_data == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2451
2549 2452 ssl_version = strdup(version_data->ssl_version);
2550 ssl_version = strdup (version_data->ssl_version); 2453 if (ssl_version == NULL)
2551 if (ssl_version == NULL ) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2454 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2552 2455
2553 library = strtok (ssl_version, "/"); 2456 library = strtok(ssl_version, "/");
2554 if (library == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2457 if (library == NULL)
2555 2458 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2556 if (strcmp (library, "OpenSSL") == 0) 2459
2557 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL; 2460 if (strcmp(library, "OpenSSL") == 0)
2558 else if (strcmp (library, "LibreSSL") == 0) 2461 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL;
2559 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL; 2462 else if (strcmp(library, "LibreSSL") == 0)
2560 else if (strcmp (library, "GnuTLS") == 0) 2463 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL;
2561 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS; 2464 else if (strcmp(library, "GnuTLS") == 0)
2562 else if (strcmp (library, "NSS") == 0) 2465 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS;
2563 ssl_library = CURLHELP_SSL_LIBRARY_NSS; 2466 else if (strcmp(library, "NSS") == 0)
2564 2467 ssl_library = CURLHELP_SSL_LIBRARY_NSS;
2565 if (verbose >= 2) 2468
2566 printf ("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library); 2469 if (verbose >= 2)
2567 2470 printf("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library);
2568 free (ssl_version); 2471
2569 2472 free(ssl_version);
2570 return ssl_library; 2473
2474 return ssl_library;
2571} 2475}
2572 2476
2573const char* 2477const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library ssl_library) {
2574curlhelp_get_ssl_library_string (curlhelp_ssl_library ssl_library) 2478 switch (ssl_library) {
2575{ 2479 case CURLHELP_SSL_LIBRARY_OPENSSL:
2576 switch (ssl_library) { 2480 return "OpenSSL";
2577 case CURLHELP_SSL_LIBRARY_OPENSSL: 2481 case CURLHELP_SSL_LIBRARY_LIBRESSL:
2578 return "OpenSSL"; 2482 return "LibreSSL";
2579 case CURLHELP_SSL_LIBRARY_LIBRESSL: 2483 case CURLHELP_SSL_LIBRARY_GNUTLS:
2580 return "LibreSSL"; 2484 return "GnuTLS";
2581 case CURLHELP_SSL_LIBRARY_GNUTLS: 2485 case CURLHELP_SSL_LIBRARY_NSS:
2582 return "GnuTLS"; 2486 return "NSS";
2583 case CURLHELP_SSL_LIBRARY_NSS: 2487 case CURLHELP_SSL_LIBRARY_UNKNOWN:
2584 return "NSS"; 2488 default:
2585 case CURLHELP_SSL_LIBRARY_UNKNOWN: 2489 return "unknown";
2586 default: 2490 }
2587 return "unknown";
2588 }
2589} 2491}
2590 2492
2591#ifdef LIBCURL_FEATURE_SSL 2493#ifdef LIBCURL_FEATURE_SSL
2592#ifndef USE_OPENSSL 2494# ifndef USE_OPENSSL
2593time_t 2495time_t parse_cert_date(const char *s) {
2594parse_cert_date (const char *s) 2496 struct tm tm;
2595{ 2497 time_t date;
2596 struct tm tm; 2498 char *res;
2597 time_t date; 2499
2598 char *res; 2500 if (!s)
2599 2501 return -1;
2600 if (!s) return -1; 2502
2601 2503 /* Jan 17 14:25:12 2020 GMT */
2602 /* Jan 17 14:25:12 2020 GMT */ 2504 res = strptime(s, "%Y-%m-%d %H:%M:%S GMT", &tm);
2603 res = strptime (s, "%Y-%m-%d %H:%M:%S GMT", &tm); 2505 /* Sep 11 12:00:00 2020 GMT */
2604 /* Sep 11 12:00:00 2020 GMT */ 2506 if (res == NULL)
2605 if (res == NULL) strptime (s, "%Y %m %d %H:%M:%S GMT", &tm); 2507 strptime(s, "%Y %m %d %H:%M:%S GMT", &tm);
2606 date = mktime (&tm); 2508 date = mktime(&tm);
2607 2509
2608 return date; 2510 return date;
2609} 2511}
2610 2512
2611/* TODO: this needs cleanup in the sslutils.c, maybe we the #else case to 2513/* TODO: this needs cleanup in the sslutils.c, maybe we the #else case to
2612 * OpenSSL could be this function 2514 * OpenSSL could be this function
2613 */ 2515 */
2614int 2516int net_noopenssl_check_certificate(cert_ptr_union *cert_ptr, int days_till_exp_warn, int days_till_exp_crit) {
2615net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_warn, int days_till_exp_crit) 2517 int i;
2616{ 2518 struct curl_slist *slist;
2617 int i; 2519 int cname_found = 0;
2618 struct curl_slist* slist; 2520 char *start_date_str = NULL;
2619 int cname_found = 0; 2521 char *end_date_str = NULL;
2620 char* start_date_str = NULL; 2522 time_t start_date;
2621 char* end_date_str = NULL; 2523 time_t end_date;
2622 time_t start_date;
2623 time_t end_date;
2624 char *tz; 2524 char *tz;
2625 float time_left; 2525 float time_left;
2626 int days_left; 2526 int days_left;
@@ -2628,66 +2528,64 @@ net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_war
2628 char timestamp[50] = ""; 2528 char timestamp[50] = "";
2629 int status = STATE_UNKNOWN; 2529 int status = STATE_UNKNOWN;
2630 2530
2631 if (verbose >= 2) 2531 if (verbose >= 2)
2632 printf ("**** REQUEST CERTIFICATES ****\n"); 2532 printf("**** REQUEST CERTIFICATES ****\n");
2633 2533
2634 for (i = 0; i < cert_ptr->to_certinfo->num_of_certs; i++) { 2534 for (i = 0; i < cert_ptr->to_certinfo->num_of_certs; i++) {
2635 for (slist = cert_ptr->to_certinfo->certinfo[i]; slist; slist = slist->next) { 2535 for (slist = cert_ptr->to_certinfo->certinfo[i]; slist; slist = slist->next) {
2636 /* find first common name in subject, 2536 /* find first common name in subject,
2637 * TODO: check alternative subjects for 2537 * TODO: check alternative subjects for
2638 * TODO: have a decent parser here and not a hack 2538 * TODO: have a decent parser here and not a hack
2639 * multi-host certificate, check wildcards 2539 * multi-host certificate, check wildcards
2640 */ 2540 */
2641 if (strncasecmp (slist->data, "Subject:", 8) == 0) { 2541 if (strncasecmp(slist->data, "Subject:", 8) == 0) {
2642 int d = 3; 2542 int d = 3;
2643 char* p = strstr (slist->data, "CN="); 2543 char *p = strstr(slist->data, "CN=");
2644 if (p == NULL) { 2544 if (p == NULL) {
2645 d = 5; 2545 d = 5;
2646 p = strstr (slist->data, "CN = "); 2546 p = strstr(slist->data, "CN = ");
2647 } 2547 }
2648 if (p != NULL) { 2548 if (p != NULL) {
2649 if (strncmp (host_name, p+d, strlen (host_name)) == 0) { 2549 if (strncmp(host_name, p + d, strlen(host_name)) == 0) {
2650 cname_found = 1; 2550 cname_found = 1;
2651 } 2551 }
2652 } 2552 }
2653 } else if (strncasecmp (slist->data, "Start Date:", 11) == 0) { 2553 } else if (strncasecmp(slist->data, "Start Date:", 11) == 0) {
2654 start_date_str = &slist->data[11]; 2554 start_date_str = &slist->data[11];
2655 } else if (strncasecmp (slist->data, "Expire Date:", 12) == 0) { 2555 } else if (strncasecmp(slist->data, "Expire Date:", 12) == 0) {
2656 end_date_str = &slist->data[12]; 2556 end_date_str = &slist->data[12];
2657 } else if (strncasecmp (slist->data, "Cert:", 5) == 0) { 2557 } else if (strncasecmp(slist->data, "Cert:", 5) == 0) {
2658 goto HAVE_FIRST_CERT; 2558 goto HAVE_FIRST_CERT;
2659 } 2559 }
2660 if (verbose >= 2) 2560 if (verbose >= 2)
2661 printf ("%d ** %s\n", i, slist->data); 2561 printf("%d ** %s\n", i, slist->data);
2662 } 2562 }
2663 } 2563 }
2664HAVE_FIRST_CERT: 2564HAVE_FIRST_CERT:
2665 2565
2666 if (verbose >= 2) 2566 if (verbose >= 2)
2667 printf ("**** REQUEST CERTIFICATES ****\n"); 2567 printf("**** REQUEST CERTIFICATES ****\n");
2668 2568
2669 if (!cname_found) { 2569 if (!cname_found) {
2670 printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject.")); 2570 printf("%s\n", _("CRITICAL - Cannot retrieve certificate subject."));
2671 return STATE_CRITICAL; 2571 return STATE_CRITICAL;
2672 } 2572 }
2673 2573
2674 start_date = parse_cert_date (start_date_str); 2574 start_date = parse_cert_date(start_date_str);
2675 if (start_date <= 0) { 2575 if (start_date <= 0) {
2676 snprintf (msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Start Date' in certificate: '%s'"), 2576 snprintf(msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Start Date' in certificate: '%s'"), start_date_str);
2677 start_date_str); 2577 puts(msg);
2678 puts (msg); 2578 return STATE_WARNING;
2679 return STATE_WARNING; 2579 }
2680 } 2580
2681 2581 end_date = parse_cert_date(end_date_str);
2682 end_date = parse_cert_date (end_date_str); 2582 if (end_date <= 0) {
2683 if (end_date <= 0) { 2583 snprintf(msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), start_date_str);
2684 snprintf (msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), 2584 puts(msg);
2685 start_date_str); 2585 return STATE_WARNING;
2686 puts (msg); 2586 }
2687 return STATE_WARNING; 2587
2688 } 2588 time_left = difftime(end_date, time(NULL));
2689
2690 time_left = difftime (end_date, time(NULL));
2691 days_left = time_left / 86400; 2589 days_left = time_left / 86400;
2692 tz = getenv("TZ"); 2590 tz = getenv("TZ");
2693 setenv("TZ", "GMT", 1); 2591 setenv("TZ", "GMT", 1);
@@ -2700,30 +2598,31 @@ HAVE_FIRST_CERT:
2700 tzset(); 2598 tzset();
2701 2599
2702 if (days_left > 0 && days_left <= days_till_exp_warn) { 2600 if (days_left > 0 && days_left <= days_till_exp_warn) {
2703 printf (_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", host_name, days_left, timestamp); 2601 printf(_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL",
2602 host_name, days_left, timestamp);
2704 if (days_left > days_till_exp_crit) 2603 if (days_left > days_till_exp_crit)
2705 status = STATE_WARNING; 2604 status = STATE_WARNING;
2706 else 2605 else
2707 status = STATE_CRITICAL; 2606 status = STATE_CRITICAL;
2708 } else if (days_left == 0 && time_left > 0) { 2607 } else if (days_left == 0 && time_left > 0) {
2709 if (time_left >= 3600) 2608 if (time_left >= 3600)
2710 time_remaining = (int) time_left / 3600; 2609 time_remaining = (int)time_left / 3600;
2711 else 2610 else
2712 time_remaining = (int) time_left / 60; 2611 time_remaining = (int)time_left / 60;
2713 2612
2714 printf (_("%s - Certificate '%s' expires in %u %s (%s)\n"), 2613 printf(_("%s - Certificate '%s' expires in %u %s (%s)\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name,
2715 (days_left>days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name, time_remaining, 2614 time_remaining, time_left >= 3600 ? "hours" : "minutes", timestamp);
2716 time_left >= 3600 ? "hours" : "minutes", timestamp);
2717 2615
2718 if ( days_left > days_till_exp_crit) 2616 if (days_left > days_till_exp_crit)
2719 status = STATE_WARNING; 2617 status = STATE_WARNING;
2720 else 2618 else
2721 status = STATE_CRITICAL; 2619 status = STATE_CRITICAL;
2722 } else if (time_left < 0) { 2620 } else if (time_left < 0) {
2723 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp); 2621 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp);
2724 status=STATE_CRITICAL; 2622 status = STATE_CRITICAL;
2725 } else if (days_left == 0) { 2623 } else if (days_left == 0) {
2726 printf (_("%s - Certificate '%s' just expired (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", host_name, timestamp); 2624 printf(_("%s - Certificate '%s' just expired (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name,
2625 timestamp);
2727 if (days_left > days_till_exp_crit) 2626 if (days_left > days_till_exp_crit)
2728 status = STATE_WARNING; 2627 status = STATE_WARNING;
2729 else 2628 else
@@ -2734,5 +2633,5 @@ HAVE_FIRST_CERT:
2734 } 2633 }
2735 return status; 2634 return status;
2736} 2635}
2737#endif /* USE_OPENSSL */ 2636# endif /* USE_OPENSSL */
2738#endif /* LIBCURL_FEATURE_SSL */ 2637#endif /* LIBCURL_FEATURE_SSL */
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c
index 29c85206..96575672 100644
--- a/plugins/check_dbi.c
+++ b/plugins/check_dbi.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dbi plugin 3 * Monitoring check_dbi plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2011 Monitoring Plugins Development Team 6 * Copyright (c) 2011-2024 Monitoring Plugins Development Team
7* Author: Sebastian 'tokkee' Harl <sh@teamix.net> 7 * Original Author: Sebastian 'tokkee' Harl <sh@teamix.net>
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_dbi plugin 11 * This file contains the check_dbi plugin
12* 12 *
13* Runs an arbitrary (SQL) command and checks the result. 13 * Runs an arbitrary (SQL) command and checks the result.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_dbi"; 32const char *progname = "check_dbi";
33const char *copyright = "2011"; 33const char *copyright = "2011-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -43,7 +43,7 @@ const char *email = "devel@monitoring-plugins.org";
43 43
44/* required for NAN */ 44/* required for NAN */
45#ifndef _ISOC99_SOURCE 45#ifndef _ISOC99_SOURCE
46#define _ISOC99_SOURCE 46# define _ISOC99_SOURCE
47#endif 47#endif
48 48
49#include <assert.h> 49#include <assert.h>
@@ -70,42 +70,40 @@ typedef struct {
70 char *value; 70 char *value;
71} driver_option_t; 71} driver_option_t;
72 72
73char *host = NULL; 73static char *host = NULL;
74int verbose = 0; 74static int verbose = 0;
75 75
76char *warning_range = NULL; 76static char *warning_range = NULL;
77char *critical_range = NULL; 77static char *critical_range = NULL;
78thresholds *dbi_thresholds = NULL; 78static thresholds *dbi_thresholds = NULL;
79 79
80char *expect = NULL; 80static char *expect = NULL;
81 81
82regex_t expect_re; 82static regex_t expect_re;
83char *expect_re_str = NULL; 83static char *expect_re_str = NULL;
84int expect_re_cflags = 0; 84static int expect_re_cflags = 0;
85 85
86np_dbi_metric_t metric = METRIC_QUERY_RESULT; 86static np_dbi_metric_t metric = METRIC_QUERY_RESULT;
87np_dbi_type_t type = TYPE_NUMERIC; 87static np_dbi_type_t type = TYPE_NUMERIC;
88 88
89char *np_dbi_driver = NULL; 89static char *np_dbi_driver = NULL;
90driver_option_t *np_dbi_options = NULL; 90static driver_option_t *np_dbi_options = NULL;
91int np_dbi_options_num = 0; 91static int np_dbi_options_num = 0;
92char *np_dbi_database = NULL; 92static char *np_dbi_database = NULL;
93char *np_dbi_query = NULL; 93static char *np_dbi_query = NULL;
94 94
95int process_arguments (int, char **); 95static int process_arguments(int, char **);
96int validate_arguments (void); 96static int validate_arguments(void);
97void print_usage (void); 97void print_usage(void);
98void print_help (void); 98static void print_help(void);
99 99
100double timediff (struct timeval, struct timeval); 100static double timediff(struct timeval, struct timeval);
101 101
102void np_dbi_print_error (dbi_conn, char *, ...); 102static void np_dbi_print_error(dbi_conn, char *, ...);
103 103
104int do_query (dbi_conn, const char **, double *, double *); 104static int do_query(dbi_conn, const char **, double *, double *);
105 105
106int 106int main(int argc, char **argv) {
107main (int argc, char **argv)
108{
109 int status = STATE_UNKNOWN; 107 int status = STATE_UNKNOWN;
110 108
111 dbi_driver driver; 109 dbi_driver driver;
@@ -113,7 +111,8 @@ main (int argc, char **argv)
113 111
114 unsigned int server_version; 112 unsigned int server_version;
115 113
116 struct timeval start_timeval, end_timeval; 114 struct timeval start_timeval;
115 struct timeval end_timeval;
117 double conn_time = 0.0; 116 double conn_time = 0.0;
118 double query_time = 0.0; 117 double query_time = 0.0;
119 118
@@ -122,59 +121,58 @@ main (int argc, char **argv)
122 121
123 int i; 122 int i;
124 123
125 setlocale (LC_ALL, ""); 124 setlocale(LC_ALL, "");
126 bindtextdomain (PACKAGE, LOCALEDIR); 125 bindtextdomain(PACKAGE, LOCALEDIR);
127 textdomain (PACKAGE); 126 textdomain(PACKAGE);
128 127
129 /* Parse extra opts if any */ 128 /* Parse extra opts if any */
130 argv = np_extra_opts (&argc, argv, progname); 129 argv = np_extra_opts(&argc, argv, progname);
131 130
132 if (process_arguments (argc, argv) == ERROR) 131 if (process_arguments(argc, argv) == ERROR)
133 usage4 (_("Could not parse arguments")); 132 usage4(_("Could not parse arguments"));
134 133
135 /* Set signal handling and alarm */ 134 /* Set signal handling and alarm */
136 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 135 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
137 usage4 (_("Cannot catch SIGALRM")); 136 usage4(_("Cannot catch SIGALRM"));
138 } 137 }
139 alarm (timeout_interval); 138 alarm(timeout_interval);
140 139
141 if (verbose > 2) 140 if (verbose > 2)
142 printf ("Initializing DBI\n"); 141 printf("Initializing DBI\n");
143 142
144 dbi_inst *instance_p = { 0 }; 143 dbi_inst *instance_p = {0};
145 144
146 if (dbi_initialize_r(NULL, instance_p) < 0) { 145 if (dbi_initialize_r(NULL, instance_p) < 0) {
147 printf ("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); 146 printf("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n");
148 return STATE_UNKNOWN; 147 return STATE_UNKNOWN;
149 } 148 }
150 149
151 if (instance_p == NULL) { 150 if (instance_p == NULL) {
152 printf ("UNKNOWN - failed to initialize DBI.\n"); 151 printf("UNKNOWN - failed to initialize DBI.\n");
153 return STATE_UNKNOWN; 152 return STATE_UNKNOWN;
154 } 153 }
155 154
156 if (verbose) 155 if (verbose)
157 printf ("Opening DBI driver '%s'\n", np_dbi_driver); 156 printf("Opening DBI driver '%s'\n", np_dbi_driver);
158 157
159 driver = dbi_driver_open_r(np_dbi_driver, instance_p); 158 driver = dbi_driver_open_r(np_dbi_driver, instance_p);
160 if (! driver) { 159 if (!driver) {
161 printf ("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", 160 printf("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", np_dbi_driver);
162 np_dbi_driver);
163 161
164 printf ("Known drivers:\n"); 162 printf("Known drivers:\n");
165 for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) { 163 for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) {
166 printf (" - %s\n", dbi_driver_get_name (driver)); 164 printf(" - %s\n", dbi_driver_get_name(driver));
167 } 165 }
168 return STATE_UNKNOWN; 166 return STATE_UNKNOWN;
169 } 167 }
170 168
171 /* make a connection to the database */ 169 /* make a connection to the database */
172 gettimeofday (&start_timeval, NULL); 170 gettimeofday(&start_timeval, NULL);
173 171
174 conn = dbi_conn_open (driver); 172 conn = dbi_conn_open(driver);
175 if (! conn) { 173 if (!conn) {
176 printf ("UNKNOWN - failed top open connection object.\n"); 174 printf("UNKNOWN - failed top open connection object.\n");
177 dbi_conn_close (conn); 175 dbi_conn_close(conn);
178 return STATE_UNKNOWN; 176 return STATE_UNKNOWN;
179 } 177 }
180 178
@@ -182,210 +180,190 @@ main (int argc, char **argv)
182 const char *opt; 180 const char *opt;
183 181
184 if (verbose > 1) 182 if (verbose > 1)
185 printf ("Setting DBI driver option '%s' to '%s'\n", 183 printf("Setting DBI driver option '%s' to '%s'\n", np_dbi_options[i].key, np_dbi_options[i].value);
186 np_dbi_options[i].key, np_dbi_options[i].value);
187 184
188 if (! dbi_conn_set_option (conn, np_dbi_options[i].key, np_dbi_options[i].value)) 185 if (!dbi_conn_set_option(conn, np_dbi_options[i].key, np_dbi_options[i].value))
189 continue; 186 continue;
190 /* else: status != 0 */ 187 /* else: status != 0 */
191 188
192 np_dbi_print_error (conn, "UNKNOWN - failed to set option '%s' to '%s'", 189 np_dbi_print_error(conn, "UNKNOWN - failed to set option '%s' to '%s'", np_dbi_options[i].key, np_dbi_options[i].value);
193 np_dbi_options[i].key, np_dbi_options[i].value); 190 printf("Known driver options:\n");
194 printf ("Known driver options:\n");
195 191
196 for (opt = dbi_conn_get_option_list (conn, NULL); opt; 192 for (opt = dbi_conn_get_option_list(conn, NULL); opt; opt = dbi_conn_get_option_list(conn, opt)) {
197 opt = dbi_conn_get_option_list (conn, opt)) { 193 printf(" - %s\n", opt);
198 printf (" - %s\n", opt);
199 } 194 }
200 dbi_conn_close (conn); 195 dbi_conn_close(conn);
201 return STATE_UNKNOWN; 196 return STATE_UNKNOWN;
202 } 197 }
203 198
204 if (host) { 199 if (host) {
205 if (verbose > 1) 200 if (verbose > 1)
206 printf ("Setting DBI driver option 'host' to '%s'\n", host); 201 printf("Setting DBI driver option 'host' to '%s'\n", host);
207 dbi_conn_set_option (conn, "host", host); 202 dbi_conn_set_option(conn, "host", host);
208 } 203 }
209 204
210 if (verbose) { 205 if (verbose) {
211 const char *dbname, *host; 206 const char *dbname;
207 const char *host;
212 208
213 dbname = dbi_conn_get_option (conn, "dbname"); 209 dbname = dbi_conn_get_option(conn, "dbname");
214 host = dbi_conn_get_option (conn, "host"); 210 host = dbi_conn_get_option(conn, "host");
215 211
216 if (! dbname) 212 if (!dbname)
217 dbname = "<unspecified>"; 213 dbname = "<unspecified>";
218 if (! host) 214 if (!host)
219 host = "<unspecified>"; 215 host = "<unspecified>";
220 216
221 printf ("Connecting to database '%s' at host '%s'\n", 217 printf("Connecting to database '%s' at host '%s'\n", dbname, host);
222 dbname, host);
223 } 218 }
224 219
225 if (dbi_conn_connect (conn) < 0) { 220 if (dbi_conn_connect(conn) < 0) {
226 np_dbi_print_error (conn, "UNKNOWN - failed to connect to database"); 221 np_dbi_print_error(conn, "UNKNOWN - failed to connect to database");
227 return STATE_UNKNOWN; 222 return STATE_UNKNOWN;
228 } 223 }
229 224
230 gettimeofday (&end_timeval, NULL); 225 gettimeofday(&end_timeval, NULL);
231 conn_time = timediff (start_timeval, end_timeval); 226 conn_time = timediff(start_timeval, end_timeval);
232 227
233 server_version = dbi_conn_get_engine_version (conn); 228 server_version = dbi_conn_get_engine_version(conn);
234 if (verbose) 229 if (verbose)
235 printf ("Connected to server version %u\n", server_version); 230 printf("Connected to server version %u\n", server_version);
236 231
237 if (metric == METRIC_SERVER_VERSION) 232 if (metric == METRIC_SERVER_VERSION)
238 status = get_status (server_version, dbi_thresholds); 233 status = get_status(server_version, dbi_thresholds);
239 234
240 if (verbose) 235 if (verbose)
241 printf ("Time elapsed: %f\n", conn_time); 236 printf("Time elapsed: %f\n", conn_time);
242 237
243 if (metric == METRIC_CONN_TIME) 238 if (metric == METRIC_CONN_TIME)
244 status = get_status (conn_time, dbi_thresholds); 239 status = get_status(conn_time, dbi_thresholds);
245 240
246 /* select a database */ 241 /* select a database */
247 if (np_dbi_database) { 242 if (np_dbi_database) {
248 if (verbose > 1) 243 if (verbose > 1)
249 printf ("Selecting database '%s'\n", np_dbi_database); 244 printf("Selecting database '%s'\n", np_dbi_database);
250 245
251 if (dbi_conn_select_db (conn, np_dbi_database)) { 246 if (dbi_conn_select_db(conn, np_dbi_database)) {
252 np_dbi_print_error (conn, "UNKNOWN - failed to select database '%s'", 247 np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", np_dbi_database);
253 np_dbi_database);
254 return STATE_UNKNOWN; 248 return STATE_UNKNOWN;
255 } 249 }
256 } 250 }
257 251
258 if (np_dbi_query) { 252 if (np_dbi_query) {
259 /* execute query */ 253 /* execute query */
260 status = do_query (conn, &query_val_str, &query_val, &query_time); 254 status = do_query(conn, &query_val_str, &query_val, &query_time);
261 if (status != STATE_OK) 255 if (status != STATE_OK)
262 /* do_query prints an error message in this case */ 256 /* do_query prints an error message in this case */
263 return status; 257 return status;
264 258
265 if (metric == METRIC_QUERY_RESULT) { 259 if (metric == METRIC_QUERY_RESULT) {
266 if (expect) { 260 if (expect) {
267 if ((! query_val_str) || strcmp (query_val_str, expect)) 261 if ((!query_val_str) || strcmp(query_val_str, expect))
268 status = STATE_CRITICAL; 262 status = STATE_CRITICAL;
269 else 263 else
270 status = STATE_OK; 264 status = STATE_OK;
271 } 265 } else if (expect_re_str) {
272 else if (expect_re_str) {
273 int err; 266 int err;
274 267
275 err = regexec (&expect_re, query_val_str, 0, NULL, /* flags = */ 0); 268 err = regexec(&expect_re, query_val_str, 0, NULL, /* flags = */ 0);
276 if (! err) 269 if (!err)
277 status = STATE_OK; 270 status = STATE_OK;
278 else if (err == REG_NOMATCH) 271 else if (err == REG_NOMATCH)
279 status = STATE_CRITICAL; 272 status = STATE_CRITICAL;
280 else { 273 else {
281 char errmsg[1024]; 274 char errmsg[1024];
282 regerror (err, &expect_re, errmsg, sizeof (errmsg)); 275 regerror(err, &expect_re, errmsg, sizeof(errmsg));
283 printf ("ERROR - failed to execute regular expression: %s\n", 276 printf("ERROR - failed to execute regular expression: %s\n", errmsg);
284 errmsg);
285 status = STATE_CRITICAL; 277 status = STATE_CRITICAL;
286 } 278 }
287 } 279 } else
288 else 280 status = get_status(query_val, dbi_thresholds);
289 status = get_status (query_val, dbi_thresholds); 281 } else if (metric == METRIC_QUERY_TIME)
290 } 282 status = get_status(query_time, dbi_thresholds);
291 else if (metric == METRIC_QUERY_TIME)
292 status = get_status (query_time, dbi_thresholds);
293 } 283 }
294 284
295 if (verbose) 285 if (verbose)
296 printf("Closing connection\n"); 286 printf("Closing connection\n");
297 dbi_conn_close (conn); 287 dbi_conn_close(conn);
298 288
299 /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error 289 /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error
300 * which should have been reported and handled (abort) before 290 * which should have been reported and handled (abort) before
301 * ... unless we expected a string to be returned */ 291 * ... unless we expected a string to be returned */
302 assert ((metric != METRIC_QUERY_RESULT) || (! isnan (query_val)) 292 assert((metric != METRIC_QUERY_RESULT) || (!isnan(query_val)) || (type == TYPE_STRING));
303 || (type == TYPE_STRING));
304 293
305 assert ((type != TYPE_STRING) || (expect || expect_re_str)); 294 assert((type != TYPE_STRING) || (expect || expect_re_str));
306 295
307 printf ("%s - connection time: %fs", state_text (status), conn_time); 296 printf("%s - connection time: %fs", state_text(status), conn_time);
308 if (np_dbi_query) { 297 if (np_dbi_query) {
309 if (type == TYPE_STRING) { 298 if (type == TYPE_STRING) {
310 assert (expect || expect_re_str); 299 assert(expect || expect_re_str);
311 printf (", '%s' returned '%s' in %fs", np_dbi_query, 300 printf(", '%s' returned '%s' in %fs", np_dbi_query, query_val_str ? query_val_str : "<nothing>", query_time);
312 query_val_str ? query_val_str : "<nothing>", query_time);
313 if (status != STATE_OK) { 301 if (status != STATE_OK) {
314 if (expect) 302 if (expect)
315 printf (" (expected '%s')", expect); 303 printf(" (expected '%s')", expect);
316 else if (expect_re_str) 304 else if (expect_re_str)
317 printf (" (expected regex /%s/%s)", expect_re_str, 305 printf(" (expected regex /%s/%s)", expect_re_str, ((expect_re_cflags & REG_ICASE) ? "i" : ""));
318 ((expect_re_cflags & REG_ICASE) ? "i" : ""));
319 } 306 }
320 } 307 } else if (isnan(query_val))
321 else if (isnan (query_val)) 308 printf(", '%s' query execution time: %fs", np_dbi_query, query_time);
322 printf (", '%s' query execution time: %fs", np_dbi_query, query_time);
323 else 309 else
324 printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); 310 printf(", '%s' returned %f in %fs", np_dbi_query, query_val, query_time);
325 } 311 }
326 312
327 printf (" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time, 313 printf(" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time,
328 ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", 314 ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "",
329 ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "", 315 ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "", server_version,
330 server_version, 316 ((metric == METRIC_SERVER_VERSION) && warning_range) ? warning_range : "",
331 ((metric == METRIC_SERVER_VERSION) && warning_range) ? warning_range : "", 317 ((metric == METRIC_SERVER_VERSION) && critical_range) ? critical_range : "");
332 ((metric == METRIC_SERVER_VERSION) && critical_range) ? critical_range : "");
333 if (np_dbi_query) { 318 if (np_dbi_query) {
334 if (! isnan (query_val)) /* this is also true when -e is used */ 319 if (!isnan(query_val)) /* this is also true when -e is used */
335 printf (" query=%f;%s;%s;;", query_val, 320 printf(" query=%f;%s;%s;;", query_val, ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "",
336 ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", 321 ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : "");
337 ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : ""); 322 printf(" querytime=%fs;%s;%s;0;", query_time, ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "",
338 printf (" querytime=%fs;%s;%s;0;", query_time, 323 ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : "");
339 ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "",
340 ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : "");
341 } 324 }
342 printf ("\n"); 325 printf("\n");
343 return status; 326 return status;
344} 327}
345 328
346/* process command-line arguments */ 329/* process command-line arguments */
347int 330int process_arguments(int argc, char **argv) {
348process_arguments (int argc, char **argv)
349{
350 int c; 331 int c;
351 332
352 int option = 0; 333 int option = 0;
353 static struct option longopts[] = { 334 static struct option longopts[] = {STD_LONG_OPTS,
354 STD_LONG_OPTS, 335
355 336 {"expect", required_argument, 0, 'e'},
356 {"expect", required_argument, 0, 'e'}, 337 {"regex", required_argument, 0, 'r'},
357 {"regex", required_argument, 0, 'r'}, 338 {"regexi", required_argument, 0, 'R'},
358 {"regexi", required_argument, 0, 'R'}, 339 {"metric", required_argument, 0, 'm'},
359 {"metric", required_argument, 0, 'm'}, 340 {"driver", required_argument, 0, 'd'},
360 {"driver", required_argument, 0, 'd'}, 341 {"option", required_argument, 0, 'o'},
361 {"option", required_argument, 0, 'o'}, 342 {"query", required_argument, 0, 'q'},
362 {"query", required_argument, 0, 'q'}, 343 {"database", required_argument, 0, 'D'},
363 {"database", required_argument, 0, 'D'}, 344 {0, 0, 0, 0}};
364 {0, 0, 0, 0}
365 };
366 345
367 while (1) { 346 while (1) {
368 c = getopt_long (argc, argv, "Vvht:c:w:e:r:R:m:H:d:o:q:D:", 347 c = getopt_long(argc, argv, "Vvht:c:w:e:r:R:m:H:d:o:q:D:", longopts, &option);
369 longopts, &option);
370 348
371 if (c == EOF) 349 if (c == EOF)
372 break; 350 break;
373 351
374 switch (c) { 352 switch (c) {
375 case '?': /* usage */ 353 case '?': /* usage */
376 usage5 (); 354 usage5();
377 case 'h': /* help */ 355 case 'h': /* help */
378 print_help (); 356 print_help();
379 exit (STATE_UNKNOWN); 357 exit(STATE_UNKNOWN);
380 case 'V': /* version */ 358 case 'V': /* version */
381 print_revision (progname, NP_VERSION); 359 print_revision(progname, NP_VERSION);
382 exit (STATE_UNKNOWN); 360 exit(STATE_UNKNOWN);
383 361
384 case 'c': /* critical range */ 362 case 'c': /* critical range */
385 critical_range = optarg; 363 critical_range = optarg;
386 type = TYPE_NUMERIC; 364 type = TYPE_NUMERIC;
387 break; 365 break;
388 case 'w': /* warning range */ 366 case 'w': /* warning range */
389 warning_range = optarg; 367 warning_range = optarg;
390 type = TYPE_NUMERIC; 368 type = TYPE_NUMERIC;
391 break; 369 break;
@@ -396,47 +374,45 @@ process_arguments (int argc, char **argv)
396 case 'R': 374 case 'R':
397 expect_re_cflags = REG_ICASE; 375 expect_re_cflags = REG_ICASE;
398 /* fall through */ 376 /* fall through */
399 case 'r': 377 case 'r': {
400 { 378 int err;
401 int err;
402 379
403 expect_re_cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 380 expect_re_cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
404 expect_re_str = optarg; 381 expect_re_str = optarg;
405 type = TYPE_STRING; 382 type = TYPE_STRING;
406 383
407 err = regcomp (&expect_re, expect_re_str, expect_re_cflags); 384 err = regcomp(&expect_re, expect_re_str, expect_re_cflags);
408 if (err) { 385 if (err) {
409 char errmsg[1024]; 386 char errmsg[1024];
410 regerror (err, &expect_re, errmsg, sizeof (errmsg)); 387 regerror(err, &expect_re, errmsg, sizeof(errmsg));
411 printf ("ERROR - failed to compile regular expression: %s\n", 388 printf("ERROR - failed to compile regular expression: %s\n", errmsg);
412 errmsg); 389 return ERROR;
413 return ERROR;
414 }
415 break;
416 } 390 }
391 break;
392 }
417 393
418 case 'm': 394 case 'm':
419 if (! strcasecmp (optarg, "CONN_TIME")) 395 if (!strcasecmp(optarg, "CONN_TIME"))
420 metric = METRIC_CONN_TIME; 396 metric = METRIC_CONN_TIME;
421 else if (! strcasecmp (optarg, "SERVER_VERSION")) 397 else if (!strcasecmp(optarg, "SERVER_VERSION"))
422 metric = METRIC_SERVER_VERSION; 398 metric = METRIC_SERVER_VERSION;
423 else if (! strcasecmp (optarg, "QUERY_RESULT")) 399 else if (!strcasecmp(optarg, "QUERY_RESULT"))
424 metric = METRIC_QUERY_RESULT; 400 metric = METRIC_QUERY_RESULT;
425 else if (! strcasecmp (optarg, "QUERY_TIME")) 401 else if (!strcasecmp(optarg, "QUERY_TIME"))
426 metric = METRIC_QUERY_TIME; 402 metric = METRIC_QUERY_TIME;
427 else 403 else
428 usage2 (_("Invalid metric"), optarg); 404 usage2(_("Invalid metric"), optarg);
429 break; 405 break;
430 case 't': /* timeout */ 406 case 't': /* timeout */
431 if (!is_intnonneg (optarg)) 407 if (!is_intnonneg(optarg))
432 usage2 (_("Timeout interval must be a positive integer"), optarg); 408 usage2(_("Timeout interval must be a positive integer"), optarg);
433 else 409 else
434 timeout_interval = atoi (optarg); 410 timeout_interval = atoi(optarg);
435 411
436 break; 412 break;
437 case 'H': /* host */ 413 case 'H': /* host */
438 if (!is_host (optarg)) 414 if (!is_host(optarg))
439 usage2 (_("Invalid hostname/address"), optarg); 415 usage2(_("Invalid hostname/address"), optarg);
440 else 416 else
441 host = optarg; 417 host = optarg;
442 break; 418 break;
@@ -447,36 +423,34 @@ process_arguments (int argc, char **argv)
447 case 'd': 423 case 'd':
448 np_dbi_driver = optarg; 424 np_dbi_driver = optarg;
449 break; 425 break;
450 case 'o': 426 case 'o': {
451 { 427 driver_option_t *new;
452 driver_option_t *new;
453 428
454 char *k, *v; 429 char *k;
430 char *v;
455 431
456 k = optarg; 432 k = optarg;
457 v = strchr (k, (int)'='); 433 v = strchr(k, (int)'=');
458 434
459 if (! v) 435 if (!v)
460 usage2 (_("Option must be '<key>=<value>'"), optarg); 436 usage2(_("Option must be '<key>=<value>'"), optarg);
461 437
462 *v = '\0'; 438 *v = '\0';
463 ++v; 439 ++v;
464 440
465 new = realloc (np_dbi_options, 441 new = realloc(np_dbi_options, (np_dbi_options_num + 1) * sizeof(*new));
466 (np_dbi_options_num + 1) * sizeof (*new)); 442 if (!new) {
467 if (! new) { 443 printf("UNKNOWN - failed to reallocate memory\n");
468 printf ("UNKNOWN - failed to reallocate memory\n"); 444 exit(STATE_UNKNOWN);
469 exit (STATE_UNKNOWN); 445 }
470 }
471 446
472 np_dbi_options = new; 447 np_dbi_options = new;
473 new = np_dbi_options + np_dbi_options_num; 448 new = np_dbi_options + np_dbi_options_num;
474 ++np_dbi_options_num; 449 ++np_dbi_options_num;
475 450
476 new->key = k; 451 new->key = k;
477 new->value = v; 452 new->value = v;
478 } 453 } break;
479 break;
480 case 'q': 454 case 'q':
481 np_dbi_query = optarg; 455 np_dbi_query = optarg;
482 break; 456 break;
@@ -486,341 +460,314 @@ process_arguments (int argc, char **argv)
486 } 460 }
487 } 461 }
488 462
489 set_thresholds (&dbi_thresholds, warning_range, critical_range); 463 set_thresholds(&dbi_thresholds, warning_range, critical_range);
490 464
491 return validate_arguments (); 465 return validate_arguments();
492} 466}
493 467
494int 468int validate_arguments(void) {
495validate_arguments () 469 if (!np_dbi_driver)
496{ 470 usage("Must specify a DBI driver");
497 if (! np_dbi_driver)
498 usage ("Must specify a DBI driver");
499 471
500 if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) 472 if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) && (!np_dbi_query))
501 && (! np_dbi_query)) 473 usage("Must specify a query to execute (metric == QUERY_RESULT)");
502 usage ("Must specify a query to execute (metric == QUERY_RESULT)");
503 474
504 if ((metric != METRIC_CONN_TIME) 475 if ((metric != METRIC_CONN_TIME) && (metric != METRIC_SERVER_VERSION) && (metric != METRIC_QUERY_RESULT) &&
505 && (metric != METRIC_SERVER_VERSION) 476 (metric != METRIC_QUERY_TIME))
506 && (metric != METRIC_QUERY_RESULT) 477 usage("Invalid metric specified");
507 && (metric != METRIC_QUERY_TIME))
508 usage ("Invalid metric specified");
509 478
510 if (expect && (warning_range || critical_range || expect_re_str)) 479 if (expect && (warning_range || critical_range || expect_re_str))
511 usage ("Do not mix -e and -w/-c/-r/-R"); 480 usage("Do not mix -e and -w/-c/-r/-R");
512 481
513 if (expect_re_str && (warning_range || critical_range || expect)) 482 if (expect_re_str && (warning_range || critical_range || expect))
514 usage ("Do not mix -r/-R and -w/-c/-e"); 483 usage("Do not mix -r/-R and -w/-c/-e");
515 484
516 if (expect && (metric != METRIC_QUERY_RESULT)) 485 if (expect && (metric != METRIC_QUERY_RESULT))
517 usage ("Option -e requires metric QUERY_RESULT"); 486 usage("Option -e requires metric QUERY_RESULT");
518 487
519 if (expect_re_str && (metric != METRIC_QUERY_RESULT)) 488 if (expect_re_str && (metric != METRIC_QUERY_RESULT))
520 usage ("Options -r/-R require metric QUERY_RESULT"); 489 usage("Options -r/-R require metric QUERY_RESULT");
521 490
522 return OK; 491 return OK;
523} 492}
524 493
525void 494void print_help(void) {
526print_help (void) 495 print_revision(progname, NP_VERSION);
527{
528 print_revision (progname, NP_VERSION);
529 496
530 printf (COPYRIGHT, copyright, email); 497 printf(COPYRIGHT, copyright, email);
531 498
532 printf (_("This program connects to an (SQL) database using DBI and checks the\n" 499 printf(_("This program connects to an (SQL) database using DBI and checks the\n"
533 "specified metric against threshold levels. The default metric is\n" 500 "specified metric against threshold levels. The default metric is\n"
534 "the result of the specified query.\n")); 501 "the result of the specified query.\n"));
535 502
536 printf ("\n\n"); 503 printf("\n\n");
537 504
538 print_usage (); 505 print_usage();
539 506
540 printf (UT_HELP_VRSN); 507 printf(UT_HELP_VRSN);
541/* include this conditionally to avoid 'zero-length printf format string' 508/* include this conditionally to avoid 'zero-length printf format string'
542 * compiler warnings */ 509 * compiler warnings */
543#ifdef NP_EXTRA_OPTS 510#ifdef NP_EXTRA_OPTS
544 printf (UT_EXTRA_OPTS); 511 printf(UT_EXTRA_OPTS);
545#endif 512#endif
546 printf ("\n"); 513 printf("\n");
547 514
548 printf (" %s\n", "-d, --driver=STRING"); 515 printf(" %s\n", "-d, --driver=STRING");
549 printf (" %s\n", _("DBI driver to use")); 516 printf(" %s\n", _("DBI driver to use"));
550 printf (" %s\n", "-o, --option=STRING"); 517 printf(" %s\n", "-o, --option=STRING");
551 printf (" %s\n", _("DBI driver options")); 518 printf(" %s\n", _("DBI driver options"));
552 printf (" %s\n", "-q, --query=STRING"); 519 printf(" %s\n", "-q, --query=STRING");
553 printf (" %s\n", _("query to execute")); 520 printf(" %s\n", _("query to execute"));
554 printf ("\n"); 521 printf("\n");
555 522
556 printf (UT_WARN_CRIT_RANGE); 523 printf(UT_WARN_CRIT_RANGE);
557 printf (" %s\n", "-e, --expect=STRING"); 524 printf(" %s\n", "-e, --expect=STRING");
558 printf (" %s\n", _("String to expect as query result")); 525 printf(" %s\n", _("String to expect as query result"));
559 printf (" %s\n", _("Do not mix with -w, -c, -r, or -R!")); 526 printf(" %s\n", _("Do not mix with -w, -c, -r, or -R!"));
560 printf (" %s\n", "-r, --regex=REGEX"); 527 printf(" %s\n", "-r, --regex=REGEX");
561 printf (" %s\n", _("Extended POSIX regular expression to check query result against")); 528 printf(" %s\n", _("Extended POSIX regular expression to check query result against"));
562 printf (" %s\n", _("Do not mix with -w, -c, -e, or -R!")); 529 printf(" %s\n", _("Do not mix with -w, -c, -e, or -R!"));
563 printf (" %s\n", "-R, --regexi=REGEX"); 530 printf(" %s\n", "-R, --regexi=REGEX");
564 printf (" %s\n", _("Case-insensitive extended POSIX regex to check query result against")); 531 printf(" %s\n", _("Case-insensitive extended POSIX regex to check query result against"));
565 printf (" %s\n", _("Do not mix with -w, -c, -e, or -r!")); 532 printf(" %s\n", _("Do not mix with -w, -c, -e, or -r!"));
566 printf (" %s\n", "-m, --metric=METRIC"); 533 printf(" %s\n", "-m, --metric=METRIC");
567 printf (" %s\n", _("Metric to check thresholds against. Available metrics:")); 534 printf(" %s\n", _("Metric to check thresholds against. Available metrics:"));
568 printf (" CONN_TIME - %s\n", _("time used for setting up the database connection")); 535 printf(" CONN_TIME - %s\n", _("time used for setting up the database connection"));
569 printf (" QUERY_RESULT - %s\n", _("result (first column of first row) of the query")); 536 printf(" QUERY_RESULT - %s\n", _("result (first column of first row) of the query"));
570 printf (" QUERY_TIME - %s\n", _("time used to execute the query")); 537 printf(" QUERY_TIME - %s\n", _("time used to execute the query"));
571 printf (" %s\n", _("(ignore the query result)")); 538 printf(" %s\n", _("(ignore the query result)"));
572 printf ("\n"); 539 printf("\n");
573 540
574 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 541 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
575 542
576 printf (UT_VERBOSE); 543 printf(UT_VERBOSE);
577 544
578 printf ("\n"); 545 printf("\n");
579 printf (" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates")); 546 printf(" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates"));
580 printf (" %s\n\n", _("on a query, one has to be specified (-q option).")); 547 printf(" %s\n\n", _("on a query, one has to be specified (-q option)."));
581 548
582 printf (" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,")); 549 printf(" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,"));
583 printf (" %s\n", _("executes the specified query. The first column of the first row of the")); 550 printf(" %s\n", _("executes the specified query. The first column of the first row of the"));
584 printf (" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the")); 551 printf(" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the"));
585 printf (" %s\n", _("warning and critical ranges. The result from the query has to be numeric")); 552 printf(" %s\n", _("warning and critical ranges. The result from the query has to be numeric"));
586 printf (" %s\n\n", _("(strings representing numbers are fine).")); 553 printf(" %s\n\n", _("(strings representing numbers are fine)."));
587 554
588 printf (" %s\n", _("The number and type of required DBI driver options depends on the actual")); 555 printf(" %s\n", _("The number and type of required DBI driver options depends on the actual"));
589 printf (" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/")); 556 printf(" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/"));
590 printf (" %s\n\n", _("for details.")); 557 printf(" %s\n\n", _("for details."));
591 558
592 printf (" %s\n", _("Examples:")); 559 printf(" %s\n", _("Examples:"));
593 printf (" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n"); 560 printf(" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n");
594 printf (" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n"); 561 printf(" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n");
595 printf (" Warning if more than five connections; critical if more than ten.\n\n"); 562 printf(" Warning if more than five connections; critical if more than ten.\n\n");
596 563
597 printf (" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n"); 564 printf(" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n");
598 printf (" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n"); 565 printf(" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n");
599 printf (" Warning if less than 5 or more than 20 users are logged in; critical\n"); 566 printf(" Warning if less than 5 or more than 20 users are logged in; critical\n");
600 printf (" if more than 50 users.\n\n"); 567 printf(" if more than 50 users.\n\n");
601 568
602 printf (" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n"); 569 printf(" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n");
603 printf (" -m CONN_TIME -w 0.5 -c 2\n"); 570 printf(" -m CONN_TIME -w 0.5 -c 2\n");
604 printf (" Warning if connecting to the database takes more than half of a second;\n"); 571 printf(" Warning if connecting to the database takes more than half of a second;\n");
605 printf (" critical if it takes more than 2 seconds.\n\n"); 572 printf(" critical if it takes more than 2 seconds.\n\n");
606 573
607 printf (" check_dbi -d mysql -H localhost -o username=user \\\n"); 574 printf(" check_dbi -d mysql -H localhost -o username=user \\\n");
608 printf (" -q 'SELECT concat(@@version, \" \", @@version_comment)' \\\n"); 575 printf(" -q 'SELECT concat(@@version, \" \", @@version_comment)' \\\n");
609 printf (" -r '^5\\.[01].*MySQL Enterprise Server'\n"); 576 printf(" -r '^5\\.[01].*MySQL Enterprise Server'\n");
610 printf (" Critical if the database server is not a MySQL enterprise server in either\n"); 577 printf(" Critical if the database server is not a MySQL enterprise server in either\n");
611 printf (" version 5.0.x or 5.1.x.\n\n"); 578 printf(" version 5.0.x or 5.1.x.\n\n");
612 579
613 printf (" check_dbi -d pgsql -u username=user -m SERVER_VERSION \\\n"); 580 printf(" check_dbi -d pgsql -u username=user -m SERVER_VERSION \\\n");
614 printf (" -w 090000:090099 -c 090000:090199\n"); 581 printf(" -w 090000:090099 -c 090000:090199\n");
615 printf (" Warn if the PostgreSQL server version is not 9.0.x; critical if the version\n"); 582 printf(" Warn if the PostgreSQL server version is not 9.0.x; critical if the version\n");
616 printf (" is less than 9.x or higher than 9.1.x.\n"); 583 printf(" is less than 9.x or higher than 9.1.x.\n");
617 584
618 printf (UT_SUPPORT); 585 printf(UT_SUPPORT);
619} 586}
620 587
621void 588void print_usage(void) {
622print_usage (void) 589 printf("%s\n", _("Usage:"));
623{ 590 printf("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname);
624 printf ("%s\n", _("Usage:")); 591 printf(" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n");
625 printf ("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname); 592 printf(" [-e <string>] [-r|-R <regex>]\n");
626 printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n");
627 printf (" [-e <string>] [-r|-R <regex>]\n");
628} 593}
629 594
630#define CHECK_IGNORE_ERROR(s) \ 595#define CHECK_IGNORE_ERROR(s) \
631 do { \ 596 do { \
632 if (metric != METRIC_QUERY_RESULT) \ 597 if (metric != METRIC_QUERY_RESULT) \
633 return (s); \ 598 return (s); \
634 } while (0) 599 } while (0)
635 600
636const char * 601const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_type) {
637get_field_str (dbi_conn conn, dbi_result res, unsigned short field_type)
638{
639 const char *str; 602 const char *str;
640 603
641 if (field_type != DBI_TYPE_STRING) { 604 if (field_type != DBI_TYPE_STRING) {
642 printf ("CRITICAL - result value is not a string\n"); 605 printf("CRITICAL - result value is not a string\n");
643 return NULL; 606 return NULL;
644 } 607 }
645 608
646 str = dbi_result_get_string_idx (res, 1); 609 str = dbi_result_get_string_idx(res, 1);
647 if ((! str) || (strcmp (str, "ERROR") == 0)) { 610 if ((!str) || (strcmp(str, "ERROR") == 0)) {
648 CHECK_IGNORE_ERROR (NULL); 611 CHECK_IGNORE_ERROR(NULL);
649 np_dbi_print_error (conn, "CRITICAL - failed to fetch string value"); 612 np_dbi_print_error(conn, "CRITICAL - failed to fetch string value");
650 return NULL; 613 return NULL;
651 } 614 }
652 615
653 if ((verbose && (type == TYPE_STRING)) || (verbose > 2)) 616 if ((verbose && (type == TYPE_STRING)) || (verbose > 2))
654 printf ("Query returned string '%s'\n", str); 617 printf("Query returned string '%s'\n", str);
655 return str; 618 return str;
656} 619}
657 620
658double 621double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type) {
659get_field (dbi_conn conn, dbi_result res, unsigned short *field_type)
660{
661 double val = NAN; 622 double val = NAN;
662 623
663 if (*field_type == DBI_TYPE_INTEGER) { 624 if (*field_type == DBI_TYPE_INTEGER) {
664 val = (double)dbi_result_get_longlong_idx (res, 1); 625 val = (double)dbi_result_get_longlong_idx(res, 1);
665 } 626 } else if (*field_type == DBI_TYPE_DECIMAL) {
666 else if (*field_type == DBI_TYPE_DECIMAL) { 627 val = dbi_result_get_double_idx(res, 1);
667 val = dbi_result_get_double_idx (res, 1); 628 } else if (*field_type == DBI_TYPE_STRING) {
668 }
669 else if (*field_type == DBI_TYPE_STRING) {
670 const char *val_str; 629 const char *val_str;
671 char *endptr = NULL; 630 char *endptr = NULL;
672 631
673 val_str = get_field_str (conn, res, *field_type); 632 val_str = get_field_str(conn, res, *field_type);
674 if (! val_str) { 633 if (!val_str) {
675 CHECK_IGNORE_ERROR (NAN); 634 CHECK_IGNORE_ERROR(NAN);
676 *field_type = DBI_TYPE_ERROR; 635 *field_type = DBI_TYPE_ERROR;
677 return NAN; 636 return NAN;
678 } 637 }
679 638
680 val = strtod (val_str, &endptr); 639 val = strtod(val_str, &endptr);
681 if (endptr == val_str) { 640 if (endptr == val_str) {
682 CHECK_IGNORE_ERROR (NAN); 641 CHECK_IGNORE_ERROR(NAN);
683 printf ("CRITICAL - result value is not a numeric: %s\n", val_str); 642 printf("CRITICAL - result value is not a numeric: %s\n", val_str);
684 *field_type = DBI_TYPE_ERROR; 643 *field_type = DBI_TYPE_ERROR;
685 return NAN; 644 return NAN;
686 } 645 }
687 else if ((endptr != NULL) && (*endptr != '\0')) { 646 if ((endptr != NULL) && (*endptr != '\0')) {
688 if (verbose) 647 if (verbose)
689 printf ("Garbage after value: %s\n", endptr); 648 printf("Garbage after value: %s\n", endptr);
690 } 649 }
691 } 650 } else {
692 else { 651 CHECK_IGNORE_ERROR(NAN);
693 CHECK_IGNORE_ERROR (NAN); 652 printf("CRITICAL - cannot parse value of type %s (%i)\n",
694 printf ("CRITICAL - cannot parse value of type %s (%i)\n", 653 (*field_type == DBI_TYPE_BINARY) ? "BINARY"
695 (*field_type == DBI_TYPE_BINARY) 654 : (*field_type == DBI_TYPE_DATETIME) ? "DATETIME"
696 ? "BINARY" 655 : "<unknown>",
697 : (*field_type == DBI_TYPE_DATETIME) 656 *field_type);
698 ? "DATETIME"
699 : "<unknown>",
700 *field_type);
701 *field_type = DBI_TYPE_ERROR; 657 *field_type = DBI_TYPE_ERROR;
702 return NAN; 658 return NAN;
703 } 659 }
704 return val; 660 return val;
705} 661}
706 662
707double 663double get_query_result(dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val) {
708get_query_result (dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val)
709{
710 unsigned short field_type; 664 unsigned short field_type;
711 double val = NAN; 665 double val = NAN;
712 666
713 if (dbi_result_get_numrows (res) == DBI_ROW_ERROR) { 667 if (dbi_result_get_numrows(res) == DBI_ROW_ERROR) {
714 CHECK_IGNORE_ERROR (STATE_OK); 668 CHECK_IGNORE_ERROR(STATE_OK);
715 np_dbi_print_error (conn, "CRITICAL - failed to fetch rows"); 669 np_dbi_print_error(conn, "CRITICAL - failed to fetch rows");
716 return STATE_CRITICAL; 670 return STATE_CRITICAL;
717 } 671 }
718 672
719 if (dbi_result_get_numrows (res) < 1) { 673 if (dbi_result_get_numrows(res) < 1) {
720 CHECK_IGNORE_ERROR (STATE_OK); 674 CHECK_IGNORE_ERROR(STATE_OK);
721 printf ("WARNING - no rows returned\n"); 675 printf("WARNING - no rows returned\n");
722 return STATE_WARNING; 676 return STATE_WARNING;
723 } 677 }
724 678
725 if (dbi_result_get_numfields (res) == DBI_FIELD_ERROR) { 679 if (dbi_result_get_numfields(res) == DBI_FIELD_ERROR) {
726 CHECK_IGNORE_ERROR (STATE_OK); 680 CHECK_IGNORE_ERROR(STATE_OK);
727 np_dbi_print_error (conn, "CRITICAL - failed to fetch fields"); 681 np_dbi_print_error(conn, "CRITICAL - failed to fetch fields");
728 return STATE_CRITICAL; 682 return STATE_CRITICAL;
729 } 683 }
730 684
731 if (dbi_result_get_numfields (res) < 1) { 685 if (dbi_result_get_numfields(res) < 1) {
732 CHECK_IGNORE_ERROR (STATE_OK); 686 CHECK_IGNORE_ERROR(STATE_OK);
733 printf ("WARNING - no fields returned\n"); 687 printf("WARNING - no fields returned\n");
734 return STATE_WARNING; 688 return STATE_WARNING;
735 } 689 }
736 690
737 if (dbi_result_first_row (res) != 1) { 691 if (dbi_result_first_row(res) != 1) {
738 CHECK_IGNORE_ERROR (STATE_OK); 692 CHECK_IGNORE_ERROR(STATE_OK);
739 np_dbi_print_error (conn, "CRITICAL - failed to fetch first row"); 693 np_dbi_print_error(conn, "CRITICAL - failed to fetch first row");
740 return STATE_CRITICAL; 694 return STATE_CRITICAL;
741 } 695 }
742 696
743 field_type = dbi_result_get_field_type_idx (res, 1); 697 field_type = dbi_result_get_field_type_idx(res, 1);
744 if (field_type != DBI_TYPE_ERROR) { 698 if (field_type != DBI_TYPE_ERROR) {
745 if (type == TYPE_STRING) 699 if (type == TYPE_STRING)
746 /* the value will be freed in dbi_result_free */ 700 /* the value will be freed in dbi_result_free */
747 *res_val_str = strdup (get_field_str (conn, res, field_type)); 701 *res_val_str = strdup(get_field_str(conn, res, field_type));
748 else 702 else
749 val = get_field (conn, res, &field_type); 703 val = get_field(conn, res, &field_type);
750 } 704 }
751 705
752 *res_val = val; 706 *res_val = val;
753 707
754 if (field_type == DBI_TYPE_ERROR) { 708 if (field_type == DBI_TYPE_ERROR) {
755 CHECK_IGNORE_ERROR (STATE_OK); 709 CHECK_IGNORE_ERROR(STATE_OK);
756 np_dbi_print_error (conn, "CRITICAL - failed to fetch data"); 710 np_dbi_print_error(conn, "CRITICAL - failed to fetch data");
757 return STATE_CRITICAL; 711 return STATE_CRITICAL;
758 } 712 }
759 713
760 dbi_result_free (res); 714 dbi_result_free(res);
761 return STATE_OK; 715 return STATE_OK;
762} 716}
763 717
764#undef CHECK_IGNORE_ERROR 718#undef CHECK_IGNORE_ERROR
765 719
766int 720int do_query(dbi_conn conn, const char **res_val_str, double *res_val, double *res_time) {
767do_query (dbi_conn conn, const char **res_val_str, double *res_val, double *res_time)
768{
769 dbi_result res; 721 dbi_result res;
770 722
771 struct timeval timeval_start, timeval_end; 723 struct timeval timeval_start;
724 struct timeval timeval_end;
772 int status = STATE_OK; 725 int status = STATE_OK;
773 726
774 assert (np_dbi_query); 727 assert(np_dbi_query);
775 728
776 if (verbose) 729 if (verbose)
777 printf ("Executing query '%s'\n", np_dbi_query); 730 printf("Executing query '%s'\n", np_dbi_query);
778 731
779 gettimeofday (&timeval_start, NULL); 732 gettimeofday(&timeval_start, NULL);
780 733
781 res = dbi_conn_query (conn, np_dbi_query); 734 res = dbi_conn_query(conn, np_dbi_query);
782 if (! res) { 735 if (!res) {
783 np_dbi_print_error (conn, "CRITICAL - failed to execute query '%s'", np_dbi_query); 736 np_dbi_print_error(conn, "CRITICAL - failed to execute query '%s'", np_dbi_query);
784 return STATE_CRITICAL; 737 return STATE_CRITICAL;
785 } 738 }
786 739
787 status = get_query_result (conn, res, res_val_str, res_val); 740 status = get_query_result(conn, res, res_val_str, res_val);
788 741
789 gettimeofday (&timeval_end, NULL); 742 gettimeofday(&timeval_end, NULL);
790 *res_time = timediff (timeval_start, timeval_end); 743 *res_time = timediff(timeval_start, timeval_end);
791 744
792 if (verbose) 745 if (verbose)
793 printf ("Time elapsed: %f\n", *res_time); 746 printf("Time elapsed: %f\n", *res_time);
794 747
795 return status; 748 return status;
796} 749}
797 750
798double 751double timediff(struct timeval start, struct timeval end) {
799timediff (struct timeval start, struct timeval end)
800{
801 double diff; 752 double diff;
802 753
803 while (start.tv_usec > end.tv_usec) { 754 while (start.tv_usec > end.tv_usec) {
804 --end.tv_sec; 755 --end.tv_sec;
805 end.tv_usec += 1000000; 756 end.tv_usec += 1000000;
806 } 757 }
807 diff = (double)(end.tv_sec - start.tv_sec) 758 diff = (double)(end.tv_sec - start.tv_sec) + (double)(end.tv_usec - start.tv_usec) / 1000000.0;
808 + (double)(end.tv_usec - start.tv_usec) / 1000000.0;
809 return diff; 759 return diff;
810} 760}
811 761
812void 762void np_dbi_print_error(dbi_conn conn, char *fmt, ...) {
813np_dbi_print_error (dbi_conn conn, char *fmt, ...)
814{
815 const char *errmsg = NULL; 763 const char *errmsg = NULL;
816 va_list ap; 764 va_list ap;
817 765
818 va_start (ap, fmt); 766 va_start(ap, fmt);
819 767
820 dbi_conn_error (conn, &errmsg); 768 dbi_conn_error(conn, &errmsg);
821 vprintf (fmt, ap); 769 vprintf(fmt, ap);
822 printf (": %s\n", errmsg); 770 printf(": %s\n", errmsg);
823 771
824 va_end (ap); 772 va_end(ap);
825} 773}
826
diff --git a/plugins/check_dig.c b/plugins/check_dig.c
index be7a6101..2bbd1e05 100644
--- a/plugins/check_dig.c
+++ b/plugins/check_dig.c
@@ -1,30 +1,30 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dig plugin 3 * Monitoring check_dig plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2002-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_dig plugin 10 * This file contains the check_dig plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29/* Hackers note: 29/* Hackers note:
30 * There are typecasts to (char *) from _("foo bar") in this file. 30 * There are typecasts to (char *) from _("foo bar") in this file.
@@ -33,7 +33,7 @@
33 * because on some architectures those strings are in non-writable memory */ 33 * because on some architectures those strings are in non-writable memory */
34 34
35const char *progname = "check_dig"; 35const char *progname = "check_dig";
36const char *copyright = "2002-2008"; 36const char *copyright = "2002-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
@@ -41,340 +41,312 @@ const char *email = "devel@monitoring-plugins.org";
41#include "utils.h" 41#include "utils.h"
42#include "runcmd.h" 42#include "runcmd.h"
43 43
44int process_arguments (int, char **); 44static int process_arguments(int /*argc*/, char ** /*argv*/);
45int validate_arguments (void); 45static int validate_arguments(void);
46void print_help (void); 46static void print_help(void);
47void print_usage (void); 47void print_usage(void);
48 48
49#define UNDEFINED 0 49#define UNDEFINED 0
50#define DEFAULT_PORT 53 50#define DEFAULT_PORT 53
51#define DEFAULT_TRIES 2 51#define DEFAULT_TRIES 2
52 52
53char *query_address = NULL; 53static char *query_address = NULL;
54char *record_type = "A"; 54static char *record_type = "A";
55char *expected_address = NULL; 55static char *expected_address = NULL;
56char *dns_server = NULL; 56static char *dns_server = NULL;
57char *dig_args = ""; 57static char *dig_args = "";
58char *query_transport = ""; 58static char *query_transport = "";
59bool verbose = false; 59static bool verbose = false;
60int server_port = DEFAULT_PORT; 60static int server_port = DEFAULT_PORT;
61int number_tries = DEFAULT_TRIES; 61static int number_tries = DEFAULT_TRIES;
62double warning_interval = UNDEFINED; 62static double warning_interval = UNDEFINED;
63double critical_interval = UNDEFINED; 63static double critical_interval = UNDEFINED;
64struct timeval tv; 64static struct timeval tv;
65 65
66int 66int main(int argc, char **argv) {
67main (int argc, char **argv) 67 char *command_line;
68{ 68 output chld_out;
69 char *command_line; 69 output chld_err;
70 output chld_out, chld_err; 70 char *msg = NULL;
71 char *msg = NULL; 71 size_t i;
72 size_t i; 72 char *t;
73 char *t; 73 long microsec;
74 long microsec; 74 double elapsed_time;
75 double elapsed_time; 75 int result = STATE_UNKNOWN;
76 int result = STATE_UNKNOWN; 76 int timeout_interval_dig;
77 int timeout_interval_dig; 77
78 78 setlocale(LC_ALL, "");
79 setlocale (LC_ALL, ""); 79 bindtextdomain(PACKAGE, LOCALEDIR);
80 bindtextdomain (PACKAGE, LOCALEDIR); 80 textdomain(PACKAGE);
81 textdomain (PACKAGE); 81
82 82 /* Set signal handling and alarm */
83 /* Set signal handling and alarm */ 83 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR)
84 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) 84 usage_va(_("Cannot catch SIGALRM"));
85 usage_va(_("Cannot catch SIGALRM")); 85
86 86 /* Parse extra opts if any */
87 /* Parse extra opts if any */ 87 argv = np_extra_opts(&argc, argv, progname);
88 argv=np_extra_opts (&argc, argv, progname); 88
89 89 if (process_arguments(argc, argv) == ERROR)
90 if (process_arguments (argc, argv) == ERROR) 90 usage_va(_("Could not parse arguments"));
91 usage_va(_("Could not parse arguments")); 91
92 92 /* dig applies the timeout to each try, so we need to work around this */
93 /* dig applies the timeout to each try, so we need to work around this */ 93 timeout_interval_dig = timeout_interval / number_tries + number_tries;
94 timeout_interval_dig = timeout_interval / number_tries + number_tries; 94
95 95 /* get the command to run */
96 /* get the command to run */ 96 xasprintf(&command_line, "%s %s %s -p %d @%s %s %s +retry=%d +time=%d", PATH_TO_DIG, dig_args, query_transport, server_port, dns_server,
97 xasprintf (&command_line, "%s %s %s -p %d @%s %s %s +retry=%d +time=%d", 97 query_address, record_type, number_tries, timeout_interval_dig);
98 PATH_TO_DIG, dig_args, query_transport, server_port, dns_server, query_address, record_type, number_tries, timeout_interval_dig); 98
99 99 alarm(timeout_interval);
100 alarm (timeout_interval); 100 gettimeofday(&tv, NULL);
101 gettimeofday (&tv, NULL); 101
102 102 if (verbose) {
103 if (verbose) { 103 printf("%s\n", command_line);
104 printf ("%s\n", command_line); 104 if (expected_address != NULL) {
105 if(expected_address != NULL) { 105 printf(_("Looking for: '%s'\n"), expected_address);
106 printf (_("Looking for: '%s'\n"), expected_address); 106 } else {
107 } else { 107 printf(_("Looking for: '%s'\n"), query_address);
108 printf (_("Looking for: '%s'\n"), query_address); 108 }
109 } 109 }
110 } 110
111 111 /* run the command */
112 /* run the command */ 112 if (np_runcmd(command_line, &chld_out, &chld_err, 0) != 0) {
113 if(np_runcmd(command_line, &chld_out, &chld_err, 0) != 0) { 113 result = STATE_WARNING;
114 result = STATE_WARNING; 114 msg = (char *)_("dig returned an error status");
115 msg = (char *)_("dig returned an error status"); 115 }
116 } 116
117 117 for (i = 0; i < chld_out.lines; i++) {
118 for(i = 0; i < chld_out.lines; i++) { 118 /* the server is responding, we just got the host name... */
119 /* the server is responding, we just got the host name... */ 119 if (strstr(chld_out.line[i], ";; ANSWER SECTION:")) {
120 if (strstr (chld_out.line[i], ";; ANSWER SECTION:")) { 120
121 121 /* loop through the whole 'ANSWER SECTION' */
122 /* loop through the whole 'ANSWER SECTION' */ 122 for (; i < chld_out.lines; i++) {
123 for(; i < chld_out.lines; i++) { 123 /* get the host address */
124 /* get the host address */ 124 if (verbose)
125 if (verbose) 125 printf("%s\n", chld_out.line[i]);
126 printf ("%s\n", chld_out.line[i]); 126
127 127 if (strcasestr(chld_out.line[i], (expected_address == NULL ? query_address : expected_address)) != NULL) {
128 if (strcasestr (chld_out.line[i], (expected_address == NULL ? query_address : expected_address)) != NULL) { 128 msg = chld_out.line[i];
129 msg = chld_out.line[i]; 129 result = STATE_OK;
130 result = STATE_OK; 130
131 131 /* Translate output TAB -> SPACE */
132 /* Translate output TAB -> SPACE */ 132 t = msg;
133 t = msg; 133 while ((t = strchr(t, '\t')) != NULL)
134 while ((t = strchr(t, '\t')) != NULL) *t = ' '; 134 *t = ' ';
135 break; 135 break;
136 } 136 }
137 } 137 }
138 138
139 if (result == STATE_UNKNOWN) { 139 if (result == STATE_UNKNOWN) {
140 msg = (char *)_("Server not found in ANSWER SECTION"); 140 msg = (char *)_("Server not found in ANSWER SECTION");
141 result = STATE_WARNING; 141 result = STATE_WARNING;
142 } 142 }
143 143
144 /* we found the answer section, so break out of the loop */ 144 /* we found the answer section, so break out of the loop */
145 break; 145 break;
146 } 146 }
147 } 147 }
148 148
149 if (result == STATE_UNKNOWN) { 149 if (result == STATE_UNKNOWN) {
150 msg = (char *)_("No ANSWER SECTION found"); 150 msg = (char *)_("No ANSWER SECTION found");
151 result = STATE_CRITICAL; 151 result = STATE_CRITICAL;
152 } 152 }
153 153
154 /* If we get anything on STDERR, at least set warning */ 154 /* If we get anything on STDERR, at least set warning */
155 if(chld_err.buflen > 0) { 155 if (chld_err.buflen > 0) {
156 result = max_state(result, STATE_WARNING); 156 result = max_state(result, STATE_WARNING);
157 if(!msg) for(i = 0; i < chld_err.lines; i++) { 157 if (!msg)
158 msg = strchr(chld_err.line[0], ':'); 158 for (i = 0; i < chld_err.lines; i++) {
159 if(msg) { 159 msg = strchr(chld_err.line[0], ':');
160 msg++; 160 if (msg) {
161 break; 161 msg++;
162 } 162 break;
163 } 163 }
164 } 164 }
165 165 }
166 microsec = deltime (tv); 166
167 elapsed_time = (double)microsec / 1.0e6; 167 microsec = deltime(tv);
168 168 elapsed_time = (double)microsec / 1.0e6;
169 if (critical_interval > UNDEFINED && elapsed_time > critical_interval) 169
170 result = STATE_CRITICAL; 170 if (critical_interval > UNDEFINED && elapsed_time > critical_interval)
171 171 result = STATE_CRITICAL;
172 else if (warning_interval > UNDEFINED && elapsed_time > warning_interval) 172
173 result = STATE_WARNING; 173 else if (warning_interval > UNDEFINED && elapsed_time > warning_interval)
174 174 result = STATE_WARNING;
175 printf ("DNS %s - %.3f seconds response time (%s)|%s\n", 175
176 state_text (result), elapsed_time, 176 printf("DNS %s - %.3f seconds response time (%s)|%s\n", state_text(result), elapsed_time,
177 msg ? msg : _("Probably a non-existent host/domain"), 177 msg ? msg : _("Probably a non-existent host/domain"),
178 fperfdata("time", elapsed_time, "s", 178 fperfdata("time", elapsed_time, "s", (warning_interval > UNDEFINED ? true : false), warning_interval,
179 (warning_interval>UNDEFINED ? true:false), 179 (critical_interval > UNDEFINED ? true : false), critical_interval, true, 0, false, 0));
180 warning_interval, 180 return result;
181 (critical_interval>UNDEFINED ? true:false),
182 critical_interval,
183 true, 0, false, 0));
184 return result;
185} 181}
186 182
187
188
189/* process command-line arguments */ 183/* process command-line arguments */
190int 184int process_arguments(int argc, char **argv) {
191process_arguments (int argc, char **argv) 185 int c;
192{ 186
193 int c; 187 int option = 0;
194 188 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
195 int option = 0; 189 {"query_address", required_argument, 0, 'l'},
196 static struct option longopts[] = { 190 {"warning", required_argument, 0, 'w'},
197 {"hostname", required_argument, 0, 'H'}, 191 {"critical", required_argument, 0, 'c'},
198 {"query_address", required_argument, 0, 'l'}, 192 {"timeout", required_argument, 0, 't'},
199 {"warning", required_argument, 0, 'w'}, 193 {"dig-arguments", required_argument, 0, 'A'},
200 {"critical", required_argument, 0, 'c'}, 194 {"verbose", no_argument, 0, 'v'},
201 {"timeout", required_argument, 0, 't'}, 195 {"version", no_argument, 0, 'V'},
202 {"dig-arguments", required_argument, 0, 'A'}, 196 {"help", no_argument, 0, 'h'},
203 {"verbose", no_argument, 0, 'v'}, 197 {"record_type", required_argument, 0, 'T'},
204 {"version", no_argument, 0, 'V'}, 198 {"expected_address", required_argument, 0, 'a'},
205 {"help", no_argument, 0, 'h'}, 199 {"port", required_argument, 0, 'p'},
206 {"record_type", required_argument, 0, 'T'}, 200 {"use-ipv4", no_argument, 0, '4'},
207 {"expected_address", required_argument, 0, 'a'}, 201 {"use-ipv6", no_argument, 0, '6'},
208 {"port", required_argument, 0, 'p'}, 202 {0, 0, 0, 0}};
209 {"use-ipv4", no_argument, 0, '4'}, 203
210 {"use-ipv6", no_argument, 0, '6'}, 204 if (argc < 2)
211 {0, 0, 0, 0} 205 return ERROR;
212 }; 206
213 207 while (1) {
214 if (argc < 2) 208 c = getopt_long(argc, argv, "hVvt:l:H:w:c:T:p:a:A:46", longopts, &option);
215 return ERROR; 209
216 210 if (c == -1 || c == EOF)
217 while (1) { 211 break;
218 c = getopt_long (argc, argv, "hVvt:l:H:w:c:T:p:a:A:46", longopts, &option); 212
219 213 switch (c) {
220 if (c == -1 || c == EOF) 214 case 'h': /* help */
221 break; 215 print_help();
222 216 exit(STATE_UNKNOWN);
223 switch (c) { 217 case 'V': /* version */
224 case 'h': /* help */ 218 print_revision(progname, NP_VERSION);
225 print_help (); 219 exit(STATE_UNKNOWN);
226 exit (STATE_UNKNOWN); 220 case 'H': /* hostname */
227 case 'V': /* version */ 221 host_or_die(optarg);
228 print_revision (progname, NP_VERSION); 222 dns_server = optarg;
229 exit (STATE_UNKNOWN); 223 break;
230 case 'H': /* hostname */ 224 case 'p': /* server port */
231 host_or_die(optarg); 225 if (is_intpos(optarg)) {
232 dns_server = optarg; 226 server_port = atoi(optarg);
233 break; 227 } else {
234 case 'p': /* server port */ 228 usage_va(_("Port must be a positive integer - %s"), optarg);
235 if (is_intpos (optarg)) { 229 }
236 server_port = atoi (optarg); 230 break;
237 } 231 case 'l': /* address to lookup */
238 else { 232 query_address = optarg;
239 usage_va(_("Port must be a positive integer - %s"), optarg); 233 break;
240 } 234 case 'w': /* warning */
241 break; 235 if (is_nonnegative(optarg)) {
242 case 'l': /* address to lookup */ 236 warning_interval = strtod(optarg, NULL);
243 query_address = optarg; 237 } else {
244 break; 238 usage_va(_("Warning interval must be a positive integer - %s"), optarg);
245 case 'w': /* warning */ 239 }
246 if (is_nonnegative (optarg)) { 240 break;
247 warning_interval = strtod (optarg, NULL); 241 case 'c': /* critical */
248 } 242 if (is_nonnegative(optarg)) {
249 else { 243 critical_interval = strtod(optarg, NULL);
250 usage_va(_("Warning interval must be a positive integer - %s"), optarg); 244 } else {
251 } 245 usage_va(_("Critical interval must be a positive integer - %s"), optarg);
252 break; 246 }
253 case 'c': /* critical */ 247 break;
254 if (is_nonnegative (optarg)) { 248 case 't': /* timeout */
255 critical_interval = strtod (optarg, NULL); 249 if (is_intnonneg(optarg)) {
256 } 250 timeout_interval = atoi(optarg);
257 else { 251 } else {
258 usage_va(_("Critical interval must be a positive integer - %s"), optarg); 252 usage_va(_("Timeout interval must be a positive integer - %s"), optarg);
259 } 253 }
260 break; 254 break;
261 case 't': /* timeout */ 255 case 'A': /* dig arguments */
262 if (is_intnonneg (optarg)) { 256 dig_args = strdup(optarg);
263 timeout_interval = atoi (optarg); 257 break;
264 } 258 case 'v': /* verbose */
265 else { 259 verbose = true;
266 usage_va(_("Timeout interval must be a positive integer - %s"), optarg); 260 break;
267 } 261 case 'T':
268 break; 262 record_type = optarg;
269 case 'A': /* dig arguments */ 263 break;
270 dig_args = strdup(optarg); 264 case 'a':
271 break; 265 expected_address = optarg;
272 case 'v': /* verbose */ 266 break;
273 verbose = true; 267 case '4':
274 break; 268 query_transport = "-4";
275 case 'T': 269 break;
276 record_type = optarg; 270 case '6':
277 break; 271 query_transport = "-6";
278 case 'a': 272 break;
279 expected_address = optarg; 273 default: /* usage5 */
280 break; 274 usage5();
281 case '4': 275 }
282 query_transport = "-4"; 276 }
283 break; 277
284 case '6': 278 c = optind;
285 query_transport = "-6"; 279 if (dns_server == NULL) {
286 break; 280 if (c < argc) {
287 default: /* usage5 */ 281 host_or_die(argv[c]);
288 usage5(); 282 dns_server = argv[c];
289 } 283 } else {
290 } 284 if (strcmp(query_transport, "-6") == 0)
291 285 dns_server = strdup("::1");
292 c = optind; 286 else
293 if (dns_server == NULL) { 287 dns_server = strdup("127.0.0.1");
294 if (c < argc) { 288 }
295 host_or_die(argv[c]); 289 }
296 dns_server = argv[c]; 290
297 } 291 return validate_arguments();
298 else {
299 if (strcmp(query_transport,"-6") == 0)
300 dns_server = strdup("::1");
301 else
302 dns_server = strdup ("127.0.0.1");
303 }
304 }
305
306 return validate_arguments ();
307} 292}
308 293
309 294int validate_arguments(void) {
310 295 if (query_address != NULL)
311int 296 return OK;
312validate_arguments (void) 297 return ERROR;
313{
314 if (query_address != NULL)
315 return OK;
316 else
317 return ERROR;
318} 298}
319 299
300void print_help(void) {
301 char *myport;
320 302
303 xasprintf(&myport, "%d", DEFAULT_PORT);
321 304
322void 305 print_revision(progname, NP_VERSION);
323print_help (void)
324{
325 char *myport;
326 306
327 xasprintf (&myport, "%d", DEFAULT_PORT); 307 printf("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
308 printf(COPYRIGHT, copyright, email);
328 309
329 print_revision (progname, NP_VERSION); 310 printf(_("This plugin tests the DNS service on the specified host using dig"));
330 311
331 printf ("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n"); 312 printf("\n\n");
332 printf (COPYRIGHT, copyright, email);
333 313
334 printf (_("This plugin tests the DNS service on the specified host using dig")); 314 print_usage();
335 315
336 printf ("\n\n"); 316 printf(UT_HELP_VRSN);
337 317
338 print_usage (); 318 printf(UT_EXTRA_OPTS);
339 319
340 printf (UT_HELP_VRSN); 320 printf(UT_HOST_PORT, 'p', myport);
341 321
342 printf (UT_EXTRA_OPTS); 322 printf(" %s\n", "-4, --use-ipv4");
323 printf(" %s\n", _("Force dig to only use IPv4 query transport"));
324 printf(" %s\n", "-6, --use-ipv6");
325 printf(" %s\n", _("Force dig to only use IPv6 query transport"));
326 printf(" %s\n", "-l, --query_address=STRING");
327 printf(" %s\n", _("Machine name to lookup"));
328 printf(" %s\n", "-T, --record_type=STRING");
329 printf(" %s\n", _("Record type to lookup (default: A)"));
330 printf(" %s\n", "-a, --expected_address=STRING");
331 printf(" %s\n", _("An address expected to be in the answer section. If not set, uses whatever"));
332 printf(" %s\n", _("was in -l"));
333 printf(" %s\n", "-A, --dig-arguments=STRING");
334 printf(" %s\n", _("Pass STRING as argument(s) to dig"));
335 printf(UT_WARN_CRIT);
336 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
337 printf(UT_VERBOSE);
343 338
344 printf (UT_HOST_PORT, 'p', myport); 339 printf("\n");
340 printf("%s\n", _("Examples:"));
341 printf(" %s\n", "check_dig -H DNSSERVER -l www.example.com -A \"+tcp\"");
342 printf(" %s\n", "This will send a tcp query to DNSSERVER for www.example.com");
345 343
346 printf (" %s\n","-4, --use-ipv4"); 344 printf(UT_SUPPORT);
347 printf (" %s\n",_("Force dig to only use IPv4 query transport"));
348 printf (" %s\n","-6, --use-ipv6");
349 printf (" %s\n",_("Force dig to only use IPv6 query transport"));
350 printf (" %s\n","-l, --query_address=STRING");
351 printf (" %s\n",_("Machine name to lookup"));
352 printf (" %s\n","-T, --record_type=STRING");
353 printf (" %s\n",_("Record type to lookup (default: A)"));
354 printf (" %s\n","-a, --expected_address=STRING");
355 printf (" %s\n",_("An address expected to be in the answer section. If not set, uses whatever"));
356 printf (" %s\n",_("was in -l"));
357 printf (" %s\n","-A, --dig-arguments=STRING");
358 printf (" %s\n",_("Pass STRING as argument(s) to dig"));
359 printf (UT_WARN_CRIT);
360 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
361 printf (UT_VERBOSE);
362
363 printf ("\n");
364 printf ("%s\n", _("Examples:"));
365 printf (" %s\n", "check_dig -H DNSSERVER -l www.example.com -A \"+tcp\"");
366 printf (" %s\n", "This will send a tcp query to DNSSERVER for www.example.com");
367
368 printf (UT_SUPPORT);
369} 345}
370 346
371 347void print_usage(void) {
372 348 printf("%s\n", _("Usage:"));
373void 349 printf("%s -l <query_address> [-H <host>] [-p <server port>]\n", progname);
374print_usage (void) 350 printf(" [-T <query type>] [-w <warning interval>] [-c <critical interval>]\n");
375{ 351 printf(" [-t <timeout>] [-a <expected answer address>] [-v]\n");
376 printf ("%s\n", _("Usage:"));
377 printf ("%s -l <query_address> [-H <host>] [-p <server port>]\n", progname);
378 printf (" [-T <query type>] [-w <warning interval>] [-c <critical interval>]\n");
379 printf (" [-t <timeout>] [-a <expected answer address>] [-v]\n");
380} 352}
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 24de2d45..d1d1b92a 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -1,43 +1,42 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_disk plugin 3 * Monitoring check_disk plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2008 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_disk plugin 10 * This file contains the check_disk plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29const char *progname = "check_disk"; 29const char *progname = "check_disk";
30const char *program_name = "check_disk"; /* Required for coreutils libs */ 30const char *program_name = "check_disk"; /* Required for coreutils libs */
31const char *copyright = "1999-2008"; 31const char *copyright = "1999-2024";
32const char *email = "devel@monitoring-plugins.org"; 32const char *email = "devel@monitoring-plugins.org";
33 33
34
35#include "common.h" 34#include "common.h"
36#ifdef HAVE_SYS_STAT_H 35#ifdef HAVE_SYS_STAT_H
37# include <sys/stat.h> 36# include <sys/stat.h>
38#endif 37#endif
39#if HAVE_INTTYPES_H 38#if HAVE_INTTYPES_H
40# include <inttypes.h> 39# include <inttypes.h>
41#endif 40#endif
42#include <assert.h> 41#include <assert.h>
43#include "popen.h" 42#include "popen.h"
@@ -48,14 +47,14 @@ const char *email = "devel@monitoring-plugins.org";
48#include "mountlist.h" 47#include "mountlist.h"
49#include <float.h> 48#include <float.h>
50#if HAVE_LIMITS_H 49#if HAVE_LIMITS_H
51# include <limits.h> 50# include <limits.h>
52#endif 51#endif
53#include "regex.h" 52#include "regex.h"
54 53
55#ifdef __CYGWIN__ 54#ifdef __CYGWIN__
56# include <windows.h> 55# include <windows.h>
57# undef ERROR 56# undef ERROR
58# define ERROR -1 57# define ERROR -1
59#endif 58#endif
60 59
61/* If nonzero, show even filesystems with zero size or 60/* If nonzero, show even filesystems with zero size or
@@ -108,1054 +107,1007 @@ static struct mount_entry *mount_list;
108 107
109/* For long options that have no equivalent short option, use a 108/* For long options that have no equivalent short option, use a
110 non-character as a pseudo short option, starting with CHAR_MAX + 1. */ 109 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
111enum 110enum {
112{ 111 SYNC_OPTION = CHAR_MAX + 1,
113 SYNC_OPTION = CHAR_MAX + 1, 112 NO_SYNC_OPTION,
114 NO_SYNC_OPTION, 113 BLOCK_SIZE_OPTION
115 BLOCK_SIZE_OPTION
116}; 114};
117 115
118#ifdef _AIX 116#ifdef _AIX
119#pragma alloca 117# pragma alloca
120#endif 118#endif
121 119
122int process_arguments (int, char **); 120static int process_arguments(int /*argc*/, char ** /*argv*/);
123void print_path (const char *mypath); 121static void set_all_thresholds(struct parameter_list *path);
124void set_all_thresholds (struct parameter_list *path); 122static void print_help(void);
125int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, char *); 123void print_usage(void);
126void print_help (void); 124static double calculate_percent(uintmax_t, uintmax_t);
127void print_usage (void); 125static bool stat_path(struct parameter_list *p);
128double calculate_percent(uintmax_t, uintmax_t); 126static void get_stats(struct parameter_list *p, struct fs_usage *fsp);
129bool stat_path (struct parameter_list *p); 127static void get_path_stats(struct parameter_list *p, struct fs_usage *fsp);
130void get_stats (struct parameter_list *p, struct fs_usage *fsp); 128
131void get_path_stats (struct parameter_list *p, struct fs_usage *fsp); 129static char *units;
132 130static uintmax_t mult = 1024 * 1024;
133char *exclude_device; 131static int verbose = 0;
134char *units; 132static bool erronly = false;
135uintmax_t mult = 1024 * 1024; 133static bool display_mntp = false;
136int verbose = 0; 134static bool exact_match = false;
137bool erronly = false; 135static bool ignore_missing = false;
138bool display_mntp = false; 136static bool freespace_ignore_reserved = false;
139bool exact_match = false; 137static bool display_inodes_perfdata = false;
140bool ignore_missing = false; 138static char *warn_freespace_units = NULL;
141bool freespace_ignore_reserved = false; 139static char *crit_freespace_units = NULL;
142bool display_inodes_perfdata = false; 140static char *warn_freespace_percent = NULL;
143char *warn_freespace_units = NULL; 141static char *crit_freespace_percent = NULL;
144char *crit_freespace_units = NULL; 142static char *warn_usedspace_units = NULL;
145char *warn_freespace_percent = NULL; 143static char *crit_usedspace_units = NULL;
146char *crit_freespace_percent = NULL; 144static char *warn_usedspace_percent = NULL;
147char *warn_usedspace_units = NULL; 145static char *crit_usedspace_percent = NULL;
148char *crit_usedspace_units = NULL; 146static char *warn_usedinodes_percent = NULL;
149char *warn_usedspace_percent = NULL; 147static char *crit_usedinodes_percent = NULL;
150char *crit_usedspace_percent = NULL; 148static char *warn_freeinodes_percent = NULL;
151char *warn_usedinodes_percent = NULL; 149static char *crit_freeinodes_percent = NULL;
152char *crit_usedinodes_percent = NULL; 150static bool path_selected = false;
153char *warn_freeinodes_percent = NULL; 151static bool path_ignored = false;
154char *crit_freeinodes_percent = NULL; 152static char *group = NULL;
155bool path_selected = false; 153static struct stat *stat_buf;
156bool path_ignored = false; 154static struct name_list *seen = NULL;
157char *group = NULL; 155
158struct stat *stat_buf; 156int main(int argc, char **argv) {
159struct name_list *seen = NULL; 157 int result = STATE_UNKNOWN;
160 158 int disk_result = STATE_UNKNOWN;
161 159 char *output;
162int 160 char *ignored;
163main (int argc, char **argv) 161 char *details;
164{ 162 char *perf;
165 int result = STATE_UNKNOWN; 163 char *perf_ilabel;
166 int disk_result = STATE_UNKNOWN; 164 char *preamble = " - free space:";
167 char *output; 165 char *ignored_preamble = " - ignored paths:";
168 char *ignored; 166 char *flag_header;
169 char *details; 167 int temp_result;
170 char *perf; 168
171 char *perf_ilabel; 169 struct mount_entry *me;
172 char *preamble = " - free space:"; 170 struct fs_usage fsp;
173 char *ignored_preamble = " - ignored paths:"; 171 struct parameter_list *temp_list;
174 char *flag_header; 172 struct parameter_list *path;
175 int temp_result;
176
177 struct mount_entry *me;
178 struct fs_usage fsp;
179 struct parameter_list *temp_list, *path;
180 173
181#ifdef __CYGWIN__ 174#ifdef __CYGWIN__
182 char mountdir[32]; 175 char mountdir[32];
183#endif 176#endif
184 177
185 output = strdup (""); 178 output = strdup("");
186 ignored = strdup (""); 179 ignored = strdup("");
187 details = strdup (""); 180 details = strdup("");
188 perf = strdup (""); 181 perf = strdup("");
189 perf_ilabel = strdup (""); 182 perf_ilabel = strdup("");
190 stat_buf = malloc(sizeof *stat_buf); 183 stat_buf = malloc(sizeof *stat_buf);
191 184
192 setlocale (LC_ALL, ""); 185 setlocale(LC_ALL, "");
193 bindtextdomain (PACKAGE, LOCALEDIR); 186 bindtextdomain(PACKAGE, LOCALEDIR);
194 textdomain (PACKAGE); 187 textdomain(PACKAGE);
195 188
196 mount_list = read_file_system_list (0); 189 mount_list = read_file_system_list(0);
197 190
198 /* Parse extra opts if any */ 191 /* Parse extra opts if any */
199 argv = np_extra_opts (&argc, argv, progname); 192 argv = np_extra_opts(&argc, argv, progname);
200 193
201 if (process_arguments (argc, argv) == ERROR) 194 if (process_arguments(argc, argv) == ERROR)
202 usage4 (_("Could not parse arguments")); 195 usage4(_("Could not parse arguments"));
203 196
204 /* If a list of paths has not been selected, find entire 197 /* If a list of paths has not been selected, find entire
205 mount list and create list of paths 198 mount list and create list of paths
206 */ 199 */
207 if (path_selected == false && path_ignored == false) { 200 if (path_selected == false && path_ignored == false) {
208 for (me = mount_list; me; me = me->me_next) { 201 for (me = mount_list; me; me = me->me_next) {
209 if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) { 202 if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
210 path = np_add_parameter(&path_select_list, me->me_mountdir); 203 path = np_add_parameter(&path_select_list, me->me_mountdir);
211 } 204 }
212 path->best_match = me; 205 path->best_match = me;
213 path->group = group; 206 path->group = group;
214 set_all_thresholds(path); 207 set_all_thresholds(path);
215 } 208 }
216 } 209 }
217 210
218 if (path_ignored == false) { 211 if (path_ignored == false) {
219 np_set_best_match(path_select_list, mount_list, exact_match); 212 np_set_best_match(path_select_list, mount_list, exact_match);
220 } 213 }
221 214
222 /* Error if no match found for specified paths */ 215 /* Error if no match found for specified paths */
223 temp_list = path_select_list; 216 temp_list = path_select_list;
224 217
225 while (path_select_list) { 218 while (path_select_list) {
226 if (! path_select_list->best_match && ignore_missing == true) { 219 if (!path_select_list->best_match && ignore_missing == true) {
227 /* If the first element will be deleted, the temp_list must be updated with the new start address as well */ 220 /* If the first element will be deleted, the temp_list must be updated with the new start address as well */
228 if (path_select_list == temp_list) { 221 if (path_select_list == temp_list) {
229 temp_list = path_select_list->name_next; 222 temp_list = path_select_list->name_next;
230 } 223 }
231 /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */ 224 /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */
232 xasprintf (&ignored, "%s %s;", ignored, path_select_list->name); 225 xasprintf(&ignored, "%s %s;", ignored, path_select_list->name);
233 /* Delete the path from the list so that it is not stat-checked later in the code. */ 226 /* Delete the path from the list so that it is not stat-checked later in the code. */
234 path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev); 227 path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev);
235 } else if (! path_select_list->best_match) { 228 } else if (!path_select_list->best_match) {
236 /* Without --ignore-missing option, exit with Critical state. */ 229 /* Without --ignore-missing option, exit with Critical state. */
237 die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name); 230 die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name);
238 } else { 231 } else {
239 /* Continue jumping through the list */ 232 /* Continue jumping through the list */
240 path_select_list = path_select_list->name_next; 233 path_select_list = path_select_list->name_next;
241 } 234 }
242 } 235 }
243 236
244 path_select_list = temp_list; 237 path_select_list = temp_list;
245 238
246 if (! path_select_list && ignore_missing == true) { 239 if (!path_select_list && ignore_missing == true) {
247 result = STATE_OK; 240 result = STATE_OK;
248 if (verbose >= 2) { 241 if (verbose >= 2) {
249 printf ("None of the provided paths were found\n"); 242 printf("None of the provided paths were found\n");
250 } 243 }
251 } 244 }
252 245
253 /* Process for every path in list */ 246 /* Process for every path in list */
254 for (path = path_select_list; path; path=path->name_next) { 247 for (path = path_select_list; path; path = path->name_next) {
255 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) 248 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
256 printf("Thresholds(pct) for %s warn: %f crit %f\n", 249 printf("Thresholds(pct) for %s warn: %f crit %f\n", path->name, path->freespace_percent->warning->end,
257 path->name, 250 path->freespace_percent->critical->end);
258 path->freespace_percent->warning->end, 251
259 path->freespace_percent->critical->end); 252 if (verbose >= 3 && path->group != NULL)
260 253 printf("Group of %s: %s\n", path->name, path->group);
261 if (verbose >= 3 && path->group != NULL) 254
262 printf("Group of %s: %s\n",path->name,path->group); 255 /* reset disk result */
263 256 disk_result = STATE_UNKNOWN;
264 /* reset disk result */ 257
265 disk_result = STATE_UNKNOWN; 258 me = path->best_match;
266 259
267 me = path->best_match; 260 if (!me) {
268 261 continue;
269 if (!me) { 262 }
270 continue;
271 }
272 263
273#ifdef __CYGWIN__ 264#ifdef __CYGWIN__
274 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) 265 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
275 continue; 266 continue;
276 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10); 267 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
277 if (GetDriveType(mountdir) != DRIVE_FIXED) 268 if (GetDriveType(mountdir) != DRIVE_FIXED)
278 me->me_remote = 1; 269 me->me_remote = 1;
279#endif 270#endif
280 /* Filters */ 271 /* Filters */
281 272
282 /* Remove filesystems already seen */ 273 /* Remove filesystems already seen */
283 if (np_seen_name(seen, me->me_mountdir)) { 274 if (np_seen_name(seen, me->me_mountdir)) {
284 continue; 275 continue;
285 } 276 }
286 np_add_name(&seen, me->me_mountdir); 277 np_add_name(&seen, me->me_mountdir);
287 278
288 if (path->group == NULL) { 279 if (path->group == NULL) {
289 /* Skip remote filesystems if we're not interested in them */ 280 /* Skip remote filesystems if we're not interested in them */
290 if (me->me_remote && show_local_fs) { 281 if (me->me_remote && show_local_fs) {
291 if (stat_remote_fs) { 282 if (stat_remote_fs) {
292 if (!stat_path(path) && ignore_missing == true) { 283 if (!stat_path(path) && ignore_missing == true) {
293 result = STATE_OK; 284 result = STATE_OK;
294 xasprintf (&ignored, "%s %s;", ignored, path->name); 285 xasprintf(&ignored, "%s %s;", ignored, path->name);
295 } 286 }
296 } 287 }
297 continue; 288 continue;
298 /* Skip pseudo fs's if we haven't asked for all fs's */ 289 /* Skip pseudo fs's if we haven't asked for all fs's */
299 } else if (me->me_dummy && !show_all_fs) { 290 }
300 continue; 291 if (me->me_dummy && !show_all_fs) {
301 /* Skip excluded fstypes */ 292 continue;
302 } else if (fs_exclude_list && np_find_regmatch (fs_exclude_list, me->me_type)) { 293 /* Skip excluded fstypes */
303 continue; 294 }
304 /* Skip excluded fs's */ 295 if (fs_exclude_list && np_find_regmatch(fs_exclude_list, me->me_type)) {
305 } else if (dp_exclude_list && 296 continue;
306 (np_find_name (dp_exclude_list, me->me_devname) || 297 /* Skip excluded fs's */
307 np_find_name (dp_exclude_list, me->me_mountdir))) { 298 }
308 continue; 299 if (dp_exclude_list && (np_find_name(dp_exclude_list, me->me_devname) || np_find_name(dp_exclude_list, me->me_mountdir))) {
309 /* Skip not included fstypes */ 300 continue;
310 } else if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) { 301 /* Skip not included fstypes */
311 continue; 302 }
312 } 303 if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) {
313 } 304 continue;
314 305 }
315 if (!stat_path(path)) { 306 }
316 if (ignore_missing == true) { 307
317 result = STATE_OK; 308 if (!stat_path(path)) {
318 xasprintf (&ignored, "%s %s;", ignored, path->name); 309 if (ignore_missing == true) {
319 } 310 result = STATE_OK;
320 continue; 311 xasprintf(&ignored, "%s %s;", ignored, path->name);
321 } 312 }
322 get_fs_usage (me->me_mountdir, me->me_devname, &fsp); 313 continue;
323 314 }
324 if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { 315 get_fs_usage(me->me_mountdir, me->me_devname, &fsp);
325 get_stats (path, &fsp); 316
326 317 if (fsp.fsu_blocks && strcmp("none", me->me_mountdir)) {
327 if (verbose >= 3) { 318 get_stats(path, &fsp);
328 printf ("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n", 319
329 me->me_mountdir, 320 if (verbose >= 3) {
330 path->dused_pct, 321 printf("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f "
331 path->dfree_pct, 322 "free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
332 path->dused_units, 323 me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
333 path->dfree_units, 324 path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult);
334 path->dtotal_units, 325 }
335 path->dused_inodes_percent, 326
336 path->dfree_inodes_percent, 327 /* Threshold comparisons */
337 fsp.fsu_blocksize, 328
338 mult); 329 temp_result = get_status(path->dfree_units, path->freespace_units);
339 } 330 if (verbose >= 3)
340 331 printf("Freespace_units result=%d\n", temp_result);
341 /* Threshold comparisons */ 332 disk_result = max_state(disk_result, temp_result);
342
343 temp_result = get_status(path->dfree_units, path->freespace_units);
344 if (verbose >=3) printf("Freespace_units result=%d\n", temp_result);
345 disk_result = max_state( disk_result, temp_result );
346
347 temp_result = get_status(path->dfree_pct, path->freespace_percent);
348 if (verbose >=3) printf("Freespace%% result=%d\n", temp_result);
349 disk_result = max_state( disk_result, temp_result );
350
351 temp_result = get_status(path->dused_units, path->usedspace_units);
352 if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result);
353 disk_result = max_state( disk_result, temp_result );
354
355 temp_result = get_status(path->dused_pct, path->usedspace_percent);
356 if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result);
357 disk_result = max_state( disk_result, temp_result );
358
359 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
360 if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result);
361 disk_result = max_state( disk_result, temp_result );
362
363 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
364 if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result);
365 disk_result = max_state( disk_result, temp_result );
366
367 result = max_state(result, disk_result);
368
369 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
370 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
371 data. Assumption that start=0. Roll on new syntax...
372 */
373
374 /* *_high_tide must be reinitialized at each run */
375 uint64_t warning_high_tide = UINT64_MAX;
376
377 if (path->freespace_units->warning != NULL) {
378 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
379 }
380 if (path->freespace_percent->warning != NULL) {
381 warning_high_tide = min( warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end/100) * (path->dtotal_units * mult)) );
382 }
383
384 uint64_t critical_high_tide = UINT64_MAX;
385
386 if (path->freespace_units->critical != NULL) {
387 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
388 }
389 if (path->freespace_percent->critical != NULL) {
390 critical_high_tide = min( critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end/100) * (path->dtotal_units * mult)) );
391 }
392
393 /* Nb: *_high_tide are unset when == UINT64_MAX */
394 xasprintf (&perf, "%s %s", perf,
395 perfdata_uint64 (
396 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
397 path->dused_units * mult, "B",
398 (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
399 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide,
400 true, 0,
401 true, path->dtotal_units * mult));
402
403 if (display_inodes_perfdata) {
404 /* *_high_tide must be reinitialized at each run */
405 warning_high_tide = UINT64_MAX;
406 critical_high_tide = UINT64_MAX;
407
408 if (path->freeinodes_percent->warning != NULL) {
409 warning_high_tide = (uint64_t) fabs( min( (double) warning_high_tide, (double) (1.0 - path->freeinodes_percent->warning->end/100)*path->inodes_total ));
410 }
411 if (path->freeinodes_percent->critical != NULL) {
412 critical_high_tide = (uint64_t) fabs( min( (double) critical_high_tide, (double) (1.0 - path->freeinodes_percent->critical->end/100)*path->inodes_total ));
413 }
414
415 xasprintf (&perf_ilabel, "%s (inodes)", (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
416 /* Nb: *_high_tide are unset when == UINT64_MAX */
417 xasprintf (&perf, "%s %s", perf,
418 perfdata_uint64 (perf_ilabel,
419 path->inodes_used, "",
420 (warning_high_tide != UINT64_MAX ? true : false), warning_high_tide,
421 (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide,
422 true, 0,
423 true, path->inodes_total));
424 }
425
426 if (disk_result==STATE_OK && erronly && !verbose)
427 continue;
428
429 if(disk_result && verbose >= 1) {
430 xasprintf(&flag_header, " %s [", state_text (disk_result));
431 } else {
432 xasprintf(&flag_header, "");
433 }
434 xasprintf (&output, "%s%s %s %llu%s (%.1f%%",
435 output, flag_header,
436 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
437 path->dfree_units,
438 units,
439 path->dfree_pct);
440 if (path->dused_inodes_percent < 0) {
441 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
442 } else {
443 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
444 }
445 free(flag_header);
446 }
447 }
448
449 if (verbose >= 2)
450 xasprintf (&output, "%s%s", output, details);
451
452 if (strcmp(output, "") == 0 && ! erronly) {
453 preamble = "";
454 xasprintf (&output, " - No disks were found for provided parameters");
455 }
456
457 printf ("DISK %s%s%s%s%s|%s\n", state_text (result), ((erronly && result==STATE_OK)) ? "" : preamble, output, (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
458 return result;
459}
460 333
334 temp_result = get_status(path->dfree_pct, path->freespace_percent);
335 if (verbose >= 3)
336 printf("Freespace%% result=%d\n", temp_result);
337 disk_result = max_state(disk_result, temp_result);
338
339 temp_result = get_status(path->dused_units, path->usedspace_units);
340 if (verbose >= 3)
341 printf("Usedspace_units result=%d\n", temp_result);
342 disk_result = max_state(disk_result, temp_result);
343
344 temp_result = get_status(path->dused_pct, path->usedspace_percent);
345 if (verbose >= 3)
346 printf("Usedspace_percent result=%d\n", temp_result);
347 disk_result = max_state(disk_result, temp_result);
348
349 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
350 if (verbose >= 3)
351 printf("Usedinodes_percent result=%d\n", temp_result);
352 disk_result = max_state(disk_result, temp_result);
353
354 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
355 if (verbose >= 3)
356 printf("Freeinodes_percent result=%d\n", temp_result);
357 disk_result = max_state(disk_result, temp_result);
358
359 result = max_state(result, disk_result);
360
361 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
362 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
363 data. Assumption that start=0. Roll on new syntax...
364 */
365
366 /* *_high_tide must be reinitialized at each run */
367 uint64_t warning_high_tide = UINT64_MAX;
368
369 if (path->freespace_units->warning != NULL) {
370 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
371 }
372 if (path->freespace_percent->warning != NULL) {
373 warning_high_tide =
374 min(warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end / 100) * (path->dtotal_units * mult)));
375 }
376
377 uint64_t critical_high_tide = UINT64_MAX;
378
379 if (path->freespace_units->critical != NULL) {
380 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
381 }
382 if (path->freespace_percent->critical != NULL) {
383 critical_high_tide =
384 min(critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end / 100) * (path->dtotal_units * mult)));
385 }
386
387 /* Nb: *_high_tide are unset when == UINT64_MAX */
388 xasprintf(&perf, "%s %s", perf,
389 perfdata_uint64((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
390 path->dused_units * mult, "B", (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
391 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide, true, 0, true,
392 path->dtotal_units * mult));
393
394 if (display_inodes_perfdata) {
395 /* *_high_tide must be reinitialized at each run */
396 warning_high_tide = UINT64_MAX;
397 critical_high_tide = UINT64_MAX;
398
399 if (path->freeinodes_percent->warning != NULL) {
400 warning_high_tide = (uint64_t)fabs(
401 min((double)warning_high_tide, (double)(1.0 - path->freeinodes_percent->warning->end / 100) * path->inodes_total));
402 }
403 if (path->freeinodes_percent->critical != NULL) {
404 critical_high_tide = (uint64_t)fabs(min(
405 (double)critical_high_tide, (double)(1.0 - path->freeinodes_percent->critical->end / 100) * path->inodes_total));
406 }
407
408 xasprintf(&perf_ilabel, "%s (inodes)",
409 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
410 /* Nb: *_high_tide are unset when == UINT64_MAX */
411 xasprintf(&perf, "%s %s", perf,
412 perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX ? true : false),
413 warning_high_tide, (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide, true, 0,
414 true, path->inodes_total));
415 }
416
417 if (disk_result == STATE_OK && erronly && !verbose)
418 continue;
419
420 if (disk_result && verbose >= 1) {
421 xasprintf(&flag_header, " %s [", state_text(disk_result));
422 } else {
423 xasprintf(&flag_header, "");
424 }
425 xasprintf(&output, "%s%s %s %llu%s (%.1f%%", output, flag_header,
426 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, path->dfree_units, units,
427 path->dfree_pct);
428 if (path->dused_inodes_percent < 0) {
429 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
430 } else {
431 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
432 }
433 free(flag_header);
434 }
435 }
436
437 if (verbose >= 2)
438 xasprintf(&output, "%s%s", output, details);
439
440 if (strcmp(output, "") == 0 && !erronly) {
441 preamble = "";
442 xasprintf(&output, " - No disks were found for provided parameters");
443 }
444
445 printf("DISK %s%s%s%s%s|%s\n", state_text(result), ((erronly && result == STATE_OK)) ? "" : preamble, output,
446 (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
447 return result;
448}
461 449
462double calculate_percent(uintmax_t value, uintmax_t total) { 450double calculate_percent(uintmax_t value, uintmax_t total) {
463 double pct = -1; 451 double pct = -1;
464 if(value <= DBL_MAX && total != 0) { 452 if (value <= DBL_MAX && total != 0) {
465 pct = (double)value / total * 100.0; 453 pct = (double)value / total * 100.0;
466 } 454 }
467 return pct; 455 return pct;
468} 456}
469 457
470/* process command-line arguments */ 458/* process command-line arguments */
471int 459int process_arguments(int argc, char **argv) {
472process_arguments (int argc, char **argv) 460 int c;
473{ 461 int err;
474 int c, err; 462 struct parameter_list *se;
475 struct parameter_list *se; 463 struct parameter_list *temp_list = NULL;
476 struct parameter_list *temp_list = NULL, *previous = NULL; 464 struct parameter_list *previous = NULL;
477 struct mount_entry *me; 465 struct mount_entry *me;
478 regex_t re; 466 regex_t re;
479 int cflags = REG_NOSUB | REG_EXTENDED; 467 int cflags = REG_NOSUB | REG_EXTENDED;
480 int default_cflags = cflags; 468 int default_cflags = cflags;
481 char errbuf[MAX_INPUT_BUFFER]; 469 char errbuf[MAX_INPUT_BUFFER];
482 int fnd = 0; 470 int fnd = 0;
483 471
484 int option = 0; 472 int option = 0;
485 static struct option longopts[] = { 473 static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
486 {"timeout", required_argument, 0, 't'}, 474 {"warning", required_argument, 0, 'w'},
487 {"warning", required_argument, 0, 'w'}, 475 {"critical", required_argument, 0, 'c'},
488 {"critical", required_argument, 0, 'c'}, 476 {"iwarning", required_argument, 0, 'W'},
489 {"iwarning", required_argument, 0, 'W'}, 477 /* Dang, -C is taken. We might want to reshuffle this. */
490 /* Dang, -C is taken. We might want to reshuffle this. */ 478 {"icritical", required_argument, 0, 'K'},
491 {"icritical", required_argument, 0, 'K'}, 479 {"kilobytes", no_argument, 0, 'k'},
492 {"kilobytes", no_argument, 0, 'k'}, 480 {"megabytes", no_argument, 0, 'm'},
493 {"megabytes", no_argument, 0, 'm'}, 481 {"units", required_argument, 0, 'u'},
494 {"units", required_argument, 0, 'u'}, 482 {"path", required_argument, 0, 'p'},
495 {"path", required_argument, 0, 'p'}, 483 {"partition", required_argument, 0, 'p'},
496 {"partition", required_argument, 0, 'p'}, 484 {"exclude_device", required_argument, 0, 'x'},
497 {"exclude_device", required_argument, 0, 'x'}, 485 {"exclude-type", required_argument, 0, 'X'},
498 {"exclude-type", required_argument, 0, 'X'}, 486 {"include-type", required_argument, 0, 'N'},
499 {"include-type", required_argument, 0, 'N'}, 487 {"group", required_argument, 0, 'g'},
500 {"group", required_argument, 0, 'g'}, 488 {"eregi-path", required_argument, 0, 'R'},
501 {"eregi-path", required_argument, 0, 'R'}, 489 {"eregi-partition", required_argument, 0, 'R'},
502 {"eregi-partition", required_argument, 0, 'R'}, 490 {"ereg-path", required_argument, 0, 'r'},
503 {"ereg-path", required_argument, 0, 'r'}, 491 {"ereg-partition", required_argument, 0, 'r'},
504 {"ereg-partition", required_argument, 0, 'r'}, 492 {"freespace-ignore-reserved", no_argument, 0, 'f'},
505 {"freespace-ignore-reserved", no_argument, 0, 'f'}, 493 {"ignore-ereg-path", required_argument, 0, 'i'},
506 {"ignore-ereg-path", required_argument, 0, 'i'}, 494 {"ignore-ereg-partition", required_argument, 0, 'i'},
507 {"ignore-ereg-partition", required_argument, 0, 'i'}, 495 {"ignore-eregi-path", required_argument, 0, 'I'},
508 {"ignore-eregi-path", required_argument, 0, 'I'}, 496 {"ignore-eregi-partition", required_argument, 0, 'I'},
509 {"ignore-eregi-partition", required_argument, 0, 'I'}, 497 {"ignore-missing", no_argument, 0, 'n'},
510 {"ignore-missing", no_argument, 0, 'n'}, 498 {"local", no_argument, 0, 'l'},
511 {"local", no_argument, 0, 'l'}, 499 {"stat-remote-fs", no_argument, 0, 'L'},
512 {"stat-remote-fs", no_argument, 0, 'L'}, 500 {"iperfdata", no_argument, 0, 'P'},
513 {"iperfdata", no_argument, 0, 'P'}, 501 {"mountpoint", no_argument, 0, 'M'},
514 {"mountpoint", no_argument, 0, 'M'}, 502 {"errors-only", no_argument, 0, 'e'},
515 {"errors-only", no_argument, 0, 'e'}, 503 {"exact-match", no_argument, 0, 'E'},
516 {"exact-match", no_argument, 0, 'E'}, 504 {"all", no_argument, 0, 'A'},
517 {"all", no_argument, 0, 'A'}, 505 {"verbose", no_argument, 0, 'v'},
518 {"verbose", no_argument, 0, 'v'}, 506 {"quiet", no_argument, 0, 'q'},
519 {"quiet", no_argument, 0, 'q'}, 507 {"clear", no_argument, 0, 'C'},
520 {"clear", no_argument, 0, 'C'}, 508 {"version", no_argument, 0, 'V'},
521 {"version", no_argument, 0, 'V'}, 509 {"help", no_argument, 0, 'h'},
522 {"help", no_argument, 0, 'h'}, 510 {0, 0, 0, 0}};
523 {0, 0, 0, 0} 511
524 }; 512 if (argc < 2)
525 513 return ERROR;
526 if (argc < 2) 514
527 return ERROR; 515 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
528 516
529 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED); 517 for (c = 1; c < argc; c++)
530 518 if (strcmp("-to", argv[c]) == 0)
531 for (c = 1; c < argc; c++) 519 strcpy(argv[c], "-t");
532 if (strcmp ("-to", argv[c]) == 0) 520
533 strcpy (argv[c], "-t"); 521 while (1) {
534 522 c = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
535 while (1) { 523
536 c = getopt_long (argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option); 524 if (c == -1 || c == EOF)
537 525 break;
538 if (c == -1 || c == EOF) 526
539 break; 527 switch (c) {
540 528 case 't': /* timeout period */
541 switch (c) { 529 if (is_integer(optarg)) {
542 case 't': /* timeout period */ 530 timeout_interval = atoi(optarg);
543 if (is_integer (optarg)) { 531 break;
544 timeout_interval = atoi (optarg); 532 } else {
545 break; 533 usage2(_("Timeout interval must be a positive integer"), optarg);
546 } 534 }
547 else { 535
548 usage2 (_("Timeout interval must be a positive integer"), optarg); 536 /* See comments for 'c' */
549 } 537 case 'w': /* warning threshold */
550
551 /* See comments for 'c' */
552 case 'w': /* warning threshold */
553 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 538 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
554 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg); 539 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg);
555 } 540 }
556 541
557 if (strstr(optarg, "%")) { 542 if (strstr(optarg, "%")) {
558 if (*optarg == '@') { 543 if (*optarg == '@') {
559 warn_freespace_percent = optarg; 544 warn_freespace_percent = optarg;
560 } else { 545 } else {
561 xasprintf(&warn_freespace_percent, "@%s", optarg); 546 xasprintf(&warn_freespace_percent, "@%s", optarg);
562 } 547 }
563 } else { 548 } else {
564 if (*optarg == '@') { 549 if (*optarg == '@') {
565 warn_freespace_units = optarg; 550 warn_freespace_units = optarg;
566 } else { 551 } else {
567 xasprintf(&warn_freespace_units, "@%s", optarg); 552 xasprintf(&warn_freespace_units, "@%s", optarg);
568 } 553 }
569 } 554 }
570 break; 555 break;
571 556
572 /* Awful mistake where the range values do not make sense. Normally, 557 /* Awful mistake where the range values do not make sense. Normally,
573 you alert if the value is within the range, but since we are using 558 you alert if the value is within the range, but since we are using
574 freespace, we have to alert if outside the range. Thus we artificially 559 freespace, we have to alert if outside the range. Thus we artificially
575 force @ at the beginning of the range, so that it is backwards compatible 560 force @ at the beginning of the range, so that it is backwards compatible
576 */ 561 */
577 case 'c': /* critical threshold */ 562 case 'c': /* critical threshold */
578 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 563 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
579 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg); 564 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg);
580 } 565 }
581 566
582 if (strstr(optarg, "%")) { 567 if (strstr(optarg, "%")) {
583 if (*optarg == '@') { 568 if (*optarg == '@') {
584 crit_freespace_percent = optarg; 569 crit_freespace_percent = optarg;
585 } else { 570 } else {
586 xasprintf(&crit_freespace_percent, "@%s", optarg); 571 xasprintf(&crit_freespace_percent, "@%s", optarg);
587 } 572 }
588 } else { 573 } else {
589 if (*optarg == '@') { 574 if (*optarg == '@') {
590 crit_freespace_units = optarg; 575 crit_freespace_units = optarg;
591 } else { 576 } else {
592 xasprintf(&crit_freespace_units, "@%s", optarg); 577 xasprintf(&crit_freespace_units, "@%s", optarg);
593 } 578 }
594 } 579 }
595 break; 580 break;
596
597 case 'W': /* warning inode threshold */
598 if (*optarg == '@') {
599 warn_freeinodes_percent = optarg;
600 } else {
601 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
602 }
603 break;
604 case 'K': /* critical inode threshold */
605 if (*optarg == '@') {
606 crit_freeinodes_percent = optarg;
607 } else {
608 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
609 }
610 break;
611 case 'u':
612 if (units)
613 free(units);
614 if (! strcasecmp (optarg, "bytes")) {
615 mult = (uintmax_t)1;
616 units = strdup ("B");
617 } else if (!strcmp(optarg, "KiB")) {
618 mult = (uintmax_t)1024;
619 units = strdup ("KiB");
620 } else if (! strcmp (optarg, "kB")) {
621 mult = (uintmax_t)1000;
622 units = strdup ("kB");
623 } else if (!strcmp(optarg, "MiB")) {
624 mult = (uintmax_t)1024 * 1024;
625 units = strdup ("MiB");
626 } else if (! strcmp (optarg, "MB")) {
627 mult = (uintmax_t)1000 * 1000;
628 units = strdup ("MB");
629 } else if (!strcmp(optarg, "GiB")) {
630 mult = (uintmax_t)1024 * 1024 * 1024;
631 units = strdup ("GiB");
632 } else if (! strcmp (optarg, "GB")){
633 mult = (uintmax_t)1000 * 1000 * 1000;
634 units = strdup ("GB");
635 } else if (!strcmp(optarg, "TiB")) {
636 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
637 units = strdup ("TiB");
638 } else if (! strcmp (optarg, "TB")) {
639 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
640 units = strdup ("TB");
641 } else if (!strcmp(optarg, "PiB")) {
642 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
643 units = strdup ("PiB");
644 } else if (! strcmp (optarg, "PB")){
645 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
646 units = strdup ("PB");
647 } else {
648 die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
649 }
650 if (units == NULL)
651 die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
652 break;
653 case 'k': /* display mountpoint */
654 mult = 1024;
655 if (units)
656 free(units);
657 units = strdup ("kiB");
658 break;
659 case 'm': /* display mountpoint */
660 mult = 1024 * 1024;
661 if (units)
662 free(units);
663 units = strdup ("MiB");
664 break;
665 case 'L':
666 stat_remote_fs = 1;
667 /* fallthrough */
668 case 'l':
669 show_local_fs = 1;
670 break;
671 case 'P':
672 display_inodes_perfdata = 1;
673 break;
674 case 'p': /* select path */
675 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
676 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
677 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
678 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
679 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
680 }
681
682 /* add parameter if not found. overwrite thresholds if path has already been added */
683 if (! (se = np_find_parameter(path_select_list, optarg))) {
684 se = np_add_parameter(&path_select_list, optarg);
685
686 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
687 path_ignored = true;
688 break;
689 }
690 }
691 se->group = group;
692 set_all_thresholds(se);
693
694 /* With autofs, it is required to stat() the path before re-populating the mount_list */
695 if (!stat_path(se)) {
696 break;
697 }
698 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
699 * pointers are copied around. One of the reason it wasn't done yet is that other parts
700 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
701 mount_list = read_file_system_list (0);
702 np_set_best_match(se, mount_list, exact_match);
703
704 path_selected = true;
705 break;
706 case 'x': /* exclude path or partition */
707 np_add_name(&dp_exclude_list, optarg);
708 break;
709 case 'X': /* exclude file system type */
710 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
711 if (err != 0) {
712 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
713 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
714 }
715 break;
716 case 'N': /* include file system type */
717 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
718 if (err != 0) {
719 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
720 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
721 }
722 break;
723 case 'v': /* verbose */
724 verbose++;
725 break;
726 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
727 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
728 erronly = true;
729 break;
730 case 'e':
731 erronly = true;
732 break;
733 case 'E':
734 if (path_selected)
735 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
736 exact_match = true;
737 break;
738 case 'f':
739 freespace_ignore_reserved = true;
740 break;
741 case 'g':
742 if (path_selected)
743 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
744 group = optarg;
745 break;
746 case 'I':
747 cflags |= REG_ICASE;
748 // Intentional fallthrough
749 case 'i':
750 if (!path_selected)
751 die (STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"), _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
752 err = regcomp(&re, optarg, cflags);
753 if (err != 0) {
754 regerror (err, &re, errbuf, MAX_INPUT_BUFFER);
755 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
756 }
757
758 temp_list = path_select_list;
759
760 previous = NULL;
761 while (temp_list) {
762 if (temp_list->best_match) {
763 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
764
765 if (verbose >=3)
766 printf("ignoring %s matching regex\n", temp_list->name);
767
768 temp_list = np_del_parameter(temp_list, previous);
769 /* pointer to first element needs to be updated if first item gets deleted */
770 if (previous == NULL)
771 path_select_list = temp_list;
772 } else {
773 previous = temp_list;
774 temp_list = temp_list->name_next;
775 }
776 } else {
777 previous = temp_list;
778 temp_list = temp_list->name_next;
779 }
780 }
781
782
783 cflags = default_cflags;
784 break;
785
786 case 'n':
787 ignore_missing = true;
788 break;
789 case 'A':
790 optarg = strdup(".*");
791 // Intentional fallthrough
792 case 'R':
793 cflags |= REG_ICASE;
794 // Intentional fallthrough
795 case 'r':
796 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
797 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
798 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
799 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
800 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
801 }
802
803 err = regcomp(&re, optarg, cflags);
804 if (err != 0) {
805 regerror (err, &re, errbuf, MAX_INPUT_BUFFER);
806 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
807 }
808
809 for (me = mount_list; me; me = me->me_next) {
810 if (np_regex_match_mount_entry(me, &re)) {
811 fnd = true;
812 if (verbose >= 3)
813 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
814
815 /* add parameter if not found. overwrite thresholds if path has already been added */
816 if (! (se = np_find_parameter(path_select_list, me->me_mountdir))) {
817 se = np_add_parameter(&path_select_list, me->me_mountdir);
818 }
819 se->group = group;
820 set_all_thresholds(se);
821 }
822 }
823
824 if (!fnd && ignore_missing == true) {
825 path_ignored = true;
826 path_selected = true;
827 break;
828 } else if (!fnd)
829 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"),
830 _("Regular expression did not match any path or disk"), optarg);
831
832 fnd = false;
833 path_selected = true;
834 np_set_best_match(path_select_list, mount_list, exact_match);
835 cflags = default_cflags;
836
837 break;
838 case 'M': /* display mountpoint */
839 display_mntp = true;
840 break;
841 case 'C':
842 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
843 if (path_selected == false) {
844 struct parameter_list *path;
845 for (me = mount_list; me; me = me->me_next) {
846 if (! (path = np_find_parameter(path_select_list, me->me_mountdir)))
847 path = np_add_parameter(&path_select_list, me->me_mountdir);
848 path->best_match = me;
849 path->group = group;
850 set_all_thresholds(path);
851 }
852 }
853 warn_freespace_units = NULL;
854 crit_freespace_units = NULL;
855 warn_usedspace_units = NULL;
856 crit_usedspace_units = NULL;
857 warn_freespace_percent = NULL;
858 crit_freespace_percent = NULL;
859 warn_usedspace_percent = NULL;
860 crit_usedspace_percent = NULL;
861 warn_usedinodes_percent = NULL;
862 crit_usedinodes_percent = NULL;
863 warn_freeinodes_percent = NULL;
864 crit_freeinodes_percent = NULL;
865
866 path_selected = false;
867 group = NULL;
868 break;
869 case 'V': /* version */
870 print_revision (progname, NP_VERSION);
871 exit (STATE_UNKNOWN);
872 case 'h': /* help */
873 print_help ();
874 exit (STATE_UNKNOWN);
875 case '?': /* help */
876 usage (_("Unknown argument"));
877 }
878 }
879
880 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
881 c = optind;
882 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
883 warn_usedspace_percent = argv[c++];
884
885 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
886 crit_usedspace_percent = argv[c++];
887
888 if (argc > c) {
889 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
890 path_selected = true;
891 set_all_thresholds(se);
892 }
893
894 if (units == NULL) {
895 units = strdup ("MiB");
896 mult = (uintmax_t)1024 * 1024;
897 }
898
899 return true;
900}
901 581
582 case 'W': /* warning inode threshold */
583 if (*optarg == '@') {
584 warn_freeinodes_percent = optarg;
585 } else {
586 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
587 }
588 break;
589 case 'K': /* critical inode threshold */
590 if (*optarg == '@') {
591 crit_freeinodes_percent = optarg;
592 } else {
593 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
594 }
595 break;
596 case 'u':
597 if (units)
598 free(units);
599 if (!strcasecmp(optarg, "bytes")) {
600 mult = (uintmax_t)1;
601 units = strdup("B");
602 } else if (!strcmp(optarg, "KiB")) {
603 mult = (uintmax_t)1024;
604 units = strdup("KiB");
605 } else if (!strcmp(optarg, "kB")) {
606 mult = (uintmax_t)1000;
607 units = strdup("kB");
608 } else if (!strcmp(optarg, "MiB")) {
609 mult = (uintmax_t)1024 * 1024;
610 units = strdup("MiB");
611 } else if (!strcmp(optarg, "MB")) {
612 mult = (uintmax_t)1000 * 1000;
613 units = strdup("MB");
614 } else if (!strcmp(optarg, "GiB")) {
615 mult = (uintmax_t)1024 * 1024 * 1024;
616 units = strdup("GiB");
617 } else if (!strcmp(optarg, "GB")) {
618 mult = (uintmax_t)1000 * 1000 * 1000;
619 units = strdup("GB");
620 } else if (!strcmp(optarg, "TiB")) {
621 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
622 units = strdup("TiB");
623 } else if (!strcmp(optarg, "TB")) {
624 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
625 units = strdup("TB");
626 } else if (!strcmp(optarg, "PiB")) {
627 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
628 units = strdup("PiB");
629 } else if (!strcmp(optarg, "PB")) {
630 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
631 units = strdup("PB");
632 } else {
633 die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
634 }
635 if (units == NULL)
636 die(STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
637 break;
638 case 'k': /* display mountpoint */
639 mult = 1024;
640 if (units)
641 free(units);
642 units = strdup("kiB");
643 break;
644 case 'm': /* display mountpoint */
645 mult = 1024 * 1024;
646 if (units)
647 free(units);
648 units = strdup("MiB");
649 break;
650 case 'L':
651 stat_remote_fs = 1;
652 /* fallthrough */
653 case 'l':
654 show_local_fs = 1;
655 break;
656 case 'P':
657 display_inodes_perfdata = 1;
658 break;
659 case 'p': /* select path */
660 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
661 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
662 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
663 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
664 }
902 665
666 /* add parameter if not found. overwrite thresholds if path has already been added */
667 if (!(se = np_find_parameter(path_select_list, optarg))) {
668 se = np_add_parameter(&path_select_list, optarg);
903 669
904void 670 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
905print_path (const char *mypath) 671 path_ignored = true;
906{ 672 break;
907 if (mypath == NULL) 673 }
908 printf ("\n"); 674 }
909 else 675 se->group = group;
910 printf (_(" for %s\n"), mypath); 676 set_all_thresholds(se);
911} 677
678 /* With autofs, it is required to stat() the path before re-populating the mount_list */
679 if (!stat_path(se)) {
680 break;
681 }
682 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
683 * pointers are copied around. One of the reason it wasn't done yet is that other parts
684 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
685 mount_list = read_file_system_list(0);
686 np_set_best_match(se, mount_list, exact_match);
687
688 path_selected = true;
689 break;
690 case 'x': /* exclude path or partition */
691 np_add_name(&dp_exclude_list, optarg);
692 break;
693 case 'X': /* exclude file system type */
694 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
695 if (err != 0) {
696 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
697 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
698 }
699 break;
700 case 'N': /* include file system type */
701 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
702 if (err != 0) {
703 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
704 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
705 }
706 break;
707 case 'v': /* verbose */
708 verbose++;
709 break;
710 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
711 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
712 erronly = true;
713 break;
714 case 'e':
715 erronly = true;
716 break;
717 case 'E':
718 if (path_selected)
719 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
720 exact_match = true;
721 break;
722 case 'f':
723 freespace_ignore_reserved = true;
724 break;
725 case 'g':
726 if (path_selected)
727 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
728 group = optarg;
729 break;
730 case 'I':
731 cflags |= REG_ICASE;
732 // Intentional fallthrough
733 case 'i':
734 if (!path_selected)
735 die(STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"),
736 _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
737 err = regcomp(&re, optarg, cflags);
738 if (err != 0) {
739 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
740 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
741 }
912 742
743 temp_list = path_select_list;
744
745 previous = NULL;
746 while (temp_list) {
747 if (temp_list->best_match) {
748 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
749
750 if (verbose >= 3)
751 printf("ignoring %s matching regex\n", temp_list->name);
752
753 temp_list = np_del_parameter(temp_list, previous);
754 /* pointer to first element needs to be updated if first item gets deleted */
755 if (previous == NULL)
756 path_select_list = temp_list;
757 } else {
758 previous = temp_list;
759 temp_list = temp_list->name_next;
760 }
761 } else {
762 previous = temp_list;
763 temp_list = temp_list->name_next;
764 }
765 }
913 766
914void 767 cflags = default_cflags;
915set_all_thresholds (struct parameter_list *path) 768 break;
916{ 769
917 if (path->freespace_units != NULL) free(path->freespace_units); 770 case 'n':
918 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units); 771 ignore_missing = true;
919 if (path->freespace_percent != NULL) free (path->freespace_percent); 772 break;
920 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent); 773 case 'A':
921 if (path->usedspace_units != NULL) free (path->usedspace_units); 774 optarg = strdup(".*");
922 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units); 775 // Intentional fallthrough
923 if (path->usedspace_percent != NULL) free (path->usedspace_percent); 776 case 'R':
924 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent); 777 cflags |= REG_ICASE;
925 if (path->usedinodes_percent != NULL) free (path->usedinodes_percent); 778 // Intentional fallthrough
926 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent); 779 case 'r':
927 if (path->freeinodes_percent != NULL) free (path->freeinodes_percent); 780 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
928 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent); 781 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
929} 782 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
783 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
784 _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
785 }
930 786
931void 787 err = regcomp(&re, optarg, cflags);
932print_help (void) 788 if (err != 0) {
933{ 789 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
934 print_revision (progname, NP_VERSION); 790 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
935 791 }
936 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
937 printf (COPYRIGHT, copyright, email);
938
939 printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
940 printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
941
942 printf ("\n\n");
943
944 print_usage ();
945
946 printf (UT_HELP_VRSN);
947 printf (UT_EXTRA_OPTS);
948
949 printf (" %s\n", "-w, --warning=INTEGER");
950 printf (" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
951 printf (" %s\n", "-w, --warning=PERCENT%");
952 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
953 printf (" %s\n", "-c, --critical=INTEGER");
954 printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
955 printf (" %s\n", "-c, --critical=PERCENT%");
956 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
957 printf (" %s\n", "-W, --iwarning=PERCENT%");
958 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
959 printf (" %s\n", "-K, --icritical=PERCENT%");
960 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
961 printf (" %s\n", "-p, --path=PATH, --partition=PARTITION");
962 printf (" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
963 printf (" %s\n", "-x, --exclude_device=PATH <STRING>");
964 printf (" %s\n", _("Ignore device (only works if -p unspecified)"));
965 printf (" %s\n", "-C, --clear");
966 printf (" %s\n", _("Clear thresholds"));
967 printf (" %s\n", "-E, --exact-match");
968 printf (" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
969 printf (" %s\n", "-e, --errors-only");
970 printf (" %s\n", _("Display only devices/mountpoints with errors"));
971 printf (" %s\n", "-f, --freespace-ignore-reserved");
972 printf (" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
973 printf (" %s\n", "-P, --iperfdata");
974 printf (" %s\n", _("Display inode usage in perfdata"));
975 printf (" %s\n", "-g, --group=NAME");
976 printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
977 printf (" %s\n", "-k, --kilobytes");
978 printf (" %s\n", _("Same as '--units kB'"));
979 printf (" %s\n", "-l, --local");
980 printf (" %s\n", _("Only check local filesystems"));
981 printf (" %s\n", "-L, --stat-remote-fs");
982 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
983 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
984 printf (" %s\n", "-M, --mountpoint");
985 printf (" %s\n", _("Display the (block) device instead of the mount point"));
986 printf (" %s\n", "-m, --megabytes");
987 printf (" %s\n", _("Same as '--units MB'"));
988 printf (" %s\n", "-A, --all");
989 printf (" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
990 printf (" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
991 printf (" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)"));
992 printf (" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
993 printf (" %s\n", _("Regular expression for path or partition (may be repeated)"));
994 printf (" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
995 printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
996 printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
997 printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
998 printf (" %s\n", "-n, --ignore-missing");
999 printf (" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
1000 printf (" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
1001 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1002 printf (" %s\n", "-u, --units=STRING");
1003 printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
1004 printf (UT_VERBOSE);
1005 printf (" %s\n", "-X, --exclude-type=TYPE_REGEX");
1006 printf (" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
1007 printf (" %s\n", "-N, --include-type=TYPE_REGEX");
1008 printf (" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
1009
1010 printf ("\n");
1011 printf ("%s\n", _("General usage hints:"));
1012 printf (" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
1013 printf (" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
1014 printf (" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\""));
1015
1016
1017
1018 printf ("\n");
1019 printf ("%s\n", _("Examples:"));
1020 printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
1021 printf (" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
1022 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
1023 printf (" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
1024 printf (" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together"));
1025 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
1026 printf (" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
1027
1028 printf (UT_SUPPORT);
1029}
1030 792
793 for (me = mount_list; me; me = me->me_next) {
794 if (np_regex_match_mount_entry(me, &re)) {
795 fnd = true;
796 if (verbose >= 3)
797 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
798
799 /* add parameter if not found. overwrite thresholds if path has already been added */
800 if (!(se = np_find_parameter(path_select_list, me->me_mountdir))) {
801 se = np_add_parameter(&path_select_list, me->me_mountdir);
802 }
803 se->group = group;
804 set_all_thresholds(se);
805 }
806 }
1031 807
808 if (!fnd && ignore_missing == true) {
809 path_ignored = true;
810 path_selected = true;
811 break;
812 }
813 if (!fnd)
814 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
815
816 fnd = false;
817 path_selected = true;
818 np_set_best_match(path_select_list, mount_list, exact_match);
819 cflags = default_cflags;
820
821 break;
822 case 'M': /* display mountpoint */
823 display_mntp = true;
824 break;
825 case 'C':
826 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
827 if (path_selected == false) {
828 struct parameter_list *path;
829 for (me = mount_list; me; me = me->me_next) {
830 if (!(path = np_find_parameter(path_select_list, me->me_mountdir)))
831 path = np_add_parameter(&path_select_list, me->me_mountdir);
832 path->best_match = me;
833 path->group = group;
834 set_all_thresholds(path);
835 }
836 }
837 warn_freespace_units = NULL;
838 crit_freespace_units = NULL;
839 warn_usedspace_units = NULL;
840 crit_usedspace_units = NULL;
841 warn_freespace_percent = NULL;
842 crit_freespace_percent = NULL;
843 warn_usedspace_percent = NULL;
844 crit_usedspace_percent = NULL;
845 warn_usedinodes_percent = NULL;
846 crit_usedinodes_percent = NULL;
847 warn_freeinodes_percent = NULL;
848 crit_freeinodes_percent = NULL;
849
850 path_selected = false;
851 group = NULL;
852 break;
853 case 'V': /* version */
854 print_revision(progname, NP_VERSION);
855 exit(STATE_UNKNOWN);
856 case 'h': /* help */
857 print_help();
858 exit(STATE_UNKNOWN);
859 case '?': /* help */
860 usage(_("Unknown argument"));
861 }
862 }
863
864 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
865 c = optind;
866 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
867 warn_usedspace_percent = argv[c++];
868
869 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
870 crit_usedspace_percent = argv[c++];
871
872 if (argc > c) {
873 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
874 path_selected = true;
875 set_all_thresholds(se);
876 }
877
878 if (units == NULL) {
879 units = strdup("MiB");
880 mult = (uintmax_t)1024 * 1024;
881 }
882
883 return true;
884}
1032 885
1033void 886void set_all_thresholds(struct parameter_list *path) {
1034print_usage (void) 887 if (path->freespace_units != NULL)
1035{ 888 free(path->freespace_units);
1036 printf ("%s\n", _("Usage:")); 889 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
1037 printf (" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K inode_percentage_limit } {-p path | -x device}\n", progname); 890 if (path->freespace_percent != NULL)
1038 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); 891 free(path->freespace_percent);
1039 printf ("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n"); 892 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
893 if (path->usedspace_units != NULL)
894 free(path->usedspace_units);
895 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
896 if (path->usedspace_percent != NULL)
897 free(path->usedspace_percent);
898 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
899 if (path->usedinodes_percent != NULL)
900 free(path->usedinodes_percent);
901 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
902 if (path->freeinodes_percent != NULL)
903 free(path->freeinodes_percent);
904 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
1040} 905}
1041 906
1042bool 907void print_help(void) {
1043stat_path (struct parameter_list *p) 908 print_revision(progname, NP_VERSION);
1044{ 909
1045 /* Stat entry to check that dir exists and is accessible */ 910 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1046 if (verbose >= 3) 911 printf(COPYRIGHT, copyright, email);
1047 printf("calling stat on %s\n", p->name); 912
1048 if (stat (p->name, &stat_buf[0])) { 913 printf("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
1049 if (verbose >= 3) 914 printf("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
1050 printf("stat failed on %s\n", p->name); 915
1051 if (ignore_missing == true) { 916 printf("\n\n");
1052 return false; 917
1053 } else { 918 print_usage();
1054 printf("DISK %s - ", _("CRITICAL")); 919
1055 die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno)); 920 printf(UT_HELP_VRSN);
1056 } 921 printf(UT_EXTRA_OPTS);
1057 } 922
1058 return true; 923 printf(" %s\n", "-w, --warning=INTEGER");
924 printf(" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
925 printf(" %s\n", "-w, --warning=PERCENT%");
926 printf(" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
927 printf(" %s\n", "-c, --critical=INTEGER");
928 printf(" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
929 printf(" %s\n", "-c, --critical=PERCENT%");
930 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
931 printf(" %s\n", "-W, --iwarning=PERCENT%");
932 printf(" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
933 printf(" %s\n", "-K, --icritical=PERCENT%");
934 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
935 printf(" %s\n", "-p, --path=PATH, --partition=PARTITION");
936 printf(" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
937 printf(" %s\n", "-x, --exclude_device=PATH <STRING>");
938 printf(" %s\n", _("Ignore device (only works if -p unspecified)"));
939 printf(" %s\n", "-C, --clear");
940 printf(" %s\n", _("Clear thresholds"));
941 printf(" %s\n", "-E, --exact-match");
942 printf(" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
943 printf(" %s\n", "-e, --errors-only");
944 printf(" %s\n", _("Display only devices/mountpoints with errors"));
945 printf(" %s\n", "-f, --freespace-ignore-reserved");
946 printf(" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
947 printf(" %s\n", "-P, --iperfdata");
948 printf(" %s\n", _("Display inode usage in perfdata"));
949 printf(" %s\n", "-g, --group=NAME");
950 printf(" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
951 printf(" %s\n", "-k, --kilobytes");
952 printf(" %s\n", _("Same as '--units kB'"));
953 printf(" %s\n", "-l, --local");
954 printf(" %s\n", _("Only check local filesystems"));
955 printf(" %s\n", "-L, --stat-remote-fs");
956 printf(" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
957 printf(" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
958 printf(" %s\n", "-M, --mountpoint");
959 printf(" %s\n", _("Display the (block) device instead of the mount point"));
960 printf(" %s\n", "-m, --megabytes");
961 printf(" %s\n", _("Same as '--units MB'"));
962 printf(" %s\n", "-A, --all");
963 printf(" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
964 printf(" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
965 printf(" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)"));
966 printf(" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
967 printf(" %s\n", _("Regular expression for path or partition (may be repeated)"));
968 printf(" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
969 printf(" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
970 printf(" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
971 printf(" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
972 printf(" %s\n", "-n, --ignore-missing");
973 printf(" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
974 printf(" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
975 printf(UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
976 printf(" %s\n", "-u, --units=STRING");
977 printf(" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
978 printf(UT_VERBOSE);
979 printf(" %s\n", "-X, --exclude-type=TYPE_REGEX");
980 printf(" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
981 printf(" %s\n", "-N, --include-type=TYPE_REGEX");
982 printf(" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
983
984 printf("\n");
985 printf("%s\n", _("General usage hints:"));
986 printf(" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
987 printf(" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
988 printf(" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\""));
989
990 printf("\n");
991 printf("%s\n", _("Examples:"));
992 printf(" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
993 printf(" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
994 printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
995 printf(" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
996 printf(" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together"));
997 printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
998 printf(" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
999
1000 printf(UT_SUPPORT);
1059} 1001}
1060 1002
1003void print_usage(void) {
1004 printf("%s\n", _("Usage:"));
1005 printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K "
1006 "inode_percentage_limit } {-p path | -x device}\n",
1007 progname);
1008 printf("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n");
1009 printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
1010}
1061 1011
1062void 1012bool stat_path(struct parameter_list *p) {
1063get_stats (struct parameter_list *p, struct fs_usage *fsp) { 1013 /* Stat entry to check that dir exists and is accessible */
1064 struct parameter_list *p_list; 1014 if (verbose >= 3)
1065 struct fs_usage tmpfsp; 1015 printf("calling stat on %s\n", p->name);
1066 int first = 1; 1016 if (stat(p->name, &stat_buf[0])) {
1017 if (verbose >= 3)
1018 printf("stat failed on %s\n", p->name);
1019 if (ignore_missing == true) {
1020 return false;
1021 }
1022 printf("DISK %s - ", _("CRITICAL"));
1023 die(STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
1024 }
1025 return true;
1026}
1027
1028void get_stats(struct parameter_list *p, struct fs_usage *fsp) {
1029 struct parameter_list *p_list;
1030 struct fs_usage tmpfsp;
1031 int first = 1;
1067 1032
1068 if (p->group == NULL) { 1033 if (p->group == NULL) {
1069 get_path_stats(p,fsp); 1034 get_path_stats(p, fsp);
1070 } else { 1035 } else {
1071 /* find all group members */ 1036 /* find all group members */
1072 for (p_list = path_select_list; p_list; p_list=p_list->name_next) { 1037 for (p_list = path_select_list; p_list; p_list = p_list->name_next) {
1073#ifdef __CYGWIN__ 1038#ifdef __CYGWIN__
1074 if (strncmp(p_list->name, "/cygdrive/", 10) != 0) 1039 if (strncmp(p_list->name, "/cygdrive/", 10) != 0)
1075 continue; 1040 continue;
1076#endif 1041#endif
1077 if (p_list->group && ! (strcmp(p_list->group, p->group))) { 1042 if (p_list->group && !(strcmp(p_list->group, p->group))) {
1078 if (! stat_path(p_list)) 1043 if (!stat_path(p_list))
1079 continue; 1044 continue;
1080 get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp); 1045 get_fs_usage(p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);
1081 get_path_stats(p_list, &tmpfsp); 1046 get_path_stats(p_list, &tmpfsp);
1082 if (verbose >= 3) 1047 if (verbose >= 3)
1083 printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n", 1048 printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n",
1084 p_list->group, 1049 p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
1085 tmpfsp.fsu_blocks, 1050 p_list->dfree_units, p_list->dtotal_units, mult);
1086 tmpfsp.fsu_blocksize, 1051
1087 p_list->best_match->me_mountdir, 1052 /* prevent counting the first FS of a group twice since its parameter_list entry
1088 p_list->dused_units, 1053 * is used to carry the information of all file systems of the entire group */
1089 p_list->dfree_units, 1054 if (!first) {
1090 p_list->dtotal_units, 1055 p->total += p_list->total;
1091 mult); 1056 p->available += p_list->available;
1092 1057 p->available_to_root += p_list->available_to_root;
1093 /* prevent counting the first FS of a group twice since its parameter_list entry 1058 p->used += p_list->used;
1094 * is used to carry the information of all file systems of the entire group */ 1059
1095 if (! first) { 1060 p->dused_units += p_list->dused_units;
1096 p->total += p_list->total; 1061 p->dfree_units += p_list->dfree_units;
1097 p->available += p_list->available; 1062 p->dtotal_units += p_list->dtotal_units;
1098 p->available_to_root += p_list->available_to_root; 1063 p->inodes_total += p_list->inodes_total;
1099 p->used += p_list->used; 1064 p->inodes_free += p_list->inodes_free;
1100 1065 p->inodes_free_to_root += p_list->inodes_free_to_root;
1101 p->dused_units += p_list->dused_units; 1066 p->inodes_used += p_list->inodes_used;
1102 p->dfree_units += p_list->dfree_units; 1067 }
1103 p->dtotal_units += p_list->dtotal_units; 1068 first = 0;
1104 p->inodes_total += p_list->inodes_total; 1069 }
1105 p->inodes_free += p_list->inodes_free; 1070 if (verbose >= 3)
1106 p->inodes_free_to_root += p_list->inodes_free_to_root; 1071 printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", p->group,
1107 p->inodes_used += p_list->inodes_used; 1072 p->dused_units, p->dfree_units, p->dtotal_units, tmpfsp.fsu_blocksize, mult);
1108 } 1073 }
1109 first = 0; 1074 /* modify devname and mountdir for output */
1110 } 1075 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1111 if (verbose >= 3) 1076 }
1112 printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", 1077 /* finally calculate percentages for either plain FS or summed up group */
1113 p->group, 1078 p->dused_pct = calculate_percent(p->used, p->used + p->available); /* used + available can never be > uintmax */
1114 p->dused_units, 1079 p->dfree_pct = 100.0 - p->dused_pct;
1115 p->dfree_units, 1080 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1116 p->dtotal_units, 1081 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1117 tmpfsp.fsu_blocksize,
1118 mult);
1119 }
1120 /* modify devname and mountdir for output */
1121 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1122 }
1123 /* finally calculate percentages for either plain FS or summed up group */
1124 p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
1125 p->dfree_pct = 100.0 - p->dused_pct;
1126 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1127 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1128
1129} 1082}
1130 1083
1131void 1084void get_path_stats(struct parameter_list *p, struct fs_usage *fsp) {
1132get_path_stats (struct parameter_list *p, struct fs_usage *fsp) { 1085 p->available = fsp->fsu_bavail;
1133 p->available = fsp->fsu_bavail; 1086 p->available_to_root = fsp->fsu_bfree;
1134 p->available_to_root = fsp->fsu_bfree; 1087 p->used = fsp->fsu_blocks - fsp->fsu_bfree;
1135 p->used = fsp->fsu_blocks - fsp->fsu_bfree; 1088 if (freespace_ignore_reserved) {
1136 if (freespace_ignore_reserved) { 1089 /* option activated : we subtract the root-reserved space from the total */
1137 /* option activated : we subtract the root-reserved space from the total */ 1090 p->total = fsp->fsu_blocks - p->available_to_root + p->available;
1138 p->total = fsp->fsu_blocks - p->available_to_root + p->available; 1091 } else {
1139 } else { 1092 /* default behaviour : take all the blocks into account */
1140 /* default behaviour : take all the blocks into account */ 1093 p->total = fsp->fsu_blocks;
1141 p->total = fsp->fsu_blocks; 1094 }
1142 } 1095
1143 1096 p->dused_units = p->used * fsp->fsu_blocksize / mult;
1144 p->dused_units = p->used*fsp->fsu_blocksize/mult; 1097 p->dfree_units = p->available * fsp->fsu_blocksize / mult;
1145 p->dfree_units = p->available*fsp->fsu_blocksize/mult; 1098 p->dtotal_units = p->total * fsp->fsu_blocksize / mult;
1146 p->dtotal_units = p->total*fsp->fsu_blocksize/mult; 1099 /* Free file nodes. Not sure the workaround is required, but in case...*/
1147 /* Free file nodes. Not sure the workaround is required, but in case...*/ 1100 p->inodes_free = fsp->fsu_ffree;
1148 p->inodes_free = fsp->fsu_ffree; 1101 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
1149 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */ 1102 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
1150 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree; 1103 if (freespace_ignore_reserved) {
1151 if (freespace_ignore_reserved) { 1104 /* option activated : we subtract the root-reserved inodes from the total */
1152 /* option activated : we subtract the root-reserved inodes from the total */ 1105 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */
1153 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */ 1106 /* for others, fsp->fsu_ffree == fsp->fsu_favail */
1154 /* for others, fsp->fsu_ffree == fsp->fsu_favail */ 1107 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free;
1155 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free; 1108 } else {
1156 } else { 1109 /* default behaviour : take all the inodes into account */
1157 /* default behaviour : take all the inodes into account */ 1110 p->inodes_total = fsp->fsu_files;
1158 p->inodes_total = fsp->fsu_files; 1111 }
1159 } 1112 np_add_name(&seen, p->best_match->me_mountdir);
1160 np_add_name(&seen, p->best_match->me_mountdir);
1161} 1113}
diff --git a/plugins/check_dns.c b/plugins/check_dns.c
index 468bc958..e1e7c00e 100644
--- a/plugins/check_dns.c
+++ b/plugins/check_dns.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dns plugin 3 * Monitoring check_dns plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_dns plugin 10 * This file contains the check_dns plugin
11* 11 *
12* LIMITATION: nslookup on Solaris 7 can return output over 2 lines, which 12 * LIMITATION: nslookup on Solaris 7 can return output over 2 lines, which
13* will not be picked up by this plugin 13 * will not be picked up by this plugin
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_dns"; 32const char *progname = "check_dns";
33const char *copyright = "2000-2008"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -39,579 +39,534 @@ const char *email = "devel@monitoring-plugins.org";
39#include "netutils.h" 39#include "netutils.h"
40#include "runcmd.h" 40#include "runcmd.h"
41 41
42int process_arguments (int, char **); 42static int process_arguments(int /*argc*/, char ** /*argv*/);
43int validate_arguments (void); 43static int validate_arguments(void);
44int error_scan (char *, bool *); 44static int error_scan(char * /*input_buffer*/, bool *);
45bool ip_match_cidr(const char *, const char *); 45static bool ip_match_cidr(const char * /*addr*/, const char * /*cidr_ro*/);
46unsigned long ip2long(const char *); 46static unsigned long ip2long(const char * /*src*/);
47void print_help (void); 47static void print_help(void);
48void print_usage (void); 48void print_usage(void);
49 49
50#define ADDRESS_LENGTH 256 50#define ADDRESS_LENGTH 256
51char query_address[ADDRESS_LENGTH] = ""; 51static char query_address[ADDRESS_LENGTH] = "";
52char dns_server[ADDRESS_LENGTH] = ""; 52static char dns_server[ADDRESS_LENGTH] = "";
53char ptr_server[ADDRESS_LENGTH] = ""; 53static char ptr_server[ADDRESS_LENGTH] = "";
54bool verbose = false; 54static bool verbose = false;
55char **expected_address = NULL; 55static char **expected_address = NULL;
56int expected_address_cnt = 0; 56static int expected_address_cnt = 0;
57bool expect_nxdomain = false; 57static bool expect_nxdomain = false;
58 58
59bool expect_authority = false; 59static bool expect_authority = false;
60bool all_match = false; 60static bool all_match = false;
61thresholds *time_thresholds = NULL; 61static thresholds *time_thresholds = NULL;
62 62
63static int 63static int qstrcmp(const void *p1, const void *p2) {
64qstrcmp(const void *p1, const void *p2)
65{
66 /* The actual arguments to this function are "pointers to 64 /* The actual arguments to this function are "pointers to
67 pointers to char", but strcmp() arguments are "pointers 65 pointers to char", but strcmp() arguments are "pointers
68 to char", hence the following cast plus dereference */ 66 to char", hence the following cast plus dereference */
69 return strcmp(* (char * const *) p1, * (char * const *) p2); 67 return strcmp(*(char *const *)p1, *(char *const *)p2);
70} 68}
71 69
70int main(int argc, char **argv) {
71 char *command_line = NULL;
72 char input_buffer[MAX_INPUT_BUFFER];
73 char *address = NULL; /* comma separated str with addrs/ptrs (sorted) */
74 char **addresses = NULL;
75 int n_addresses = 0;
76 char *msg = NULL;
77 char *temp_buffer = NULL;
78 bool non_authoritative = false;
79 int result = STATE_UNKNOWN;
80 double elapsed_time;
81 long microsec;
82 struct timeval tv;
83 bool parse_address = false; /* This flag scans for Address: but only after Name: */
84 output chld_out;
85 output chld_err;
86 bool is_nxdomain = false;
87
88 setlocale(LC_ALL, "");
89 bindtextdomain(PACKAGE, LOCALEDIR);
90 textdomain(PACKAGE);
91
92 /* Set signal handling and alarm */
93 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
94 usage_va(_("Cannot catch SIGALRM"));
95 }
96
97 /* Parse extra opts if any */
98 argv = np_extra_opts(&argc, argv, progname);
99
100 if (process_arguments(argc, argv) == ERROR) {
101 usage_va(_("Could not parse arguments"));
102 }
103
104 /* get the command to run */
105 xasprintf(&command_line, "%s %s %s", NSLOOKUP_COMMAND, query_address, dns_server);
106
107 alarm(timeout_interval);
108 gettimeofday(&tv, NULL);
109
110 if (verbose)
111 printf("%s\n", command_line);
112
113 /* run the command */
114 if ((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) {
115 msg = (char *)_("nslookup returned an error status");
116 result = STATE_WARNING;
117 }
118
119 /* scan stdout */
120 for (size_t i = 0; i < chld_out.lines; i++) {
121 if (addresses == NULL)
122 addresses = malloc(sizeof(*addresses) * 10);
123 else if (!(n_addresses % 10))
124 addresses = realloc(addresses, sizeof(*addresses) * (n_addresses + 10));
125
126 if (verbose)
127 puts(chld_out.line[i]);
128
129 if (strcasestr(chld_out.line[i], ".in-addr.arpa") || strcasestr(chld_out.line[i], ".ip6.arpa")) {
130 if ((temp_buffer = strstr(chld_out.line[i], "name = ")))
131 addresses[n_addresses++] = strdup(temp_buffer + 7);
132 else {
133 msg = (char *)_("Warning plugin error");
134 result = STATE_WARNING;
135 }
136 }
137
138 /* bug ID: 2946553 - Older versions of bind will use all available dns
139 servers, we have to match the one specified */
140 if (strstr(chld_out.line[i], "Server:") && strlen(dns_server) > 0) {
141 temp_buffer = strchr(chld_out.line[i], ':');
142 temp_buffer++;
143
144 /* Strip leading tabs */
145 for (; *temp_buffer != '\0' && *temp_buffer == '\t'; temp_buffer++)
146 /* NOOP */;
147
148 strip(temp_buffer);
149 if (temp_buffer == NULL || strlen(temp_buffer) == 0) {
150 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty server string\n"), NSLOOKUP_COMMAND);
151 }
152
153 if (strcmp(temp_buffer, dns_server) != 0) {
154 die(STATE_CRITICAL, _("DNS CRITICAL - No response from DNS %s\n"), dns_server);
155 }
156 }
157
158 /* the server is responding, we just got the host name... */
159 if (strstr(chld_out.line[i], "Name:"))
160 parse_address = true;
161 else if (parse_address && (strstr(chld_out.line[i], "Address:") || strstr(chld_out.line[i], "Addresses:"))) {
162 temp_buffer = index(chld_out.line[i], ':');
163 temp_buffer++;
164
165 /* Strip leading spaces */
166 while (*temp_buffer == ' ')
167 temp_buffer++;
168
169 strip(temp_buffer);
170 if (temp_buffer == NULL || strlen(temp_buffer) == 0) {
171 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty host name string\n"), NSLOOKUP_COMMAND);
172 }
173
174 addresses[n_addresses++] = strdup(temp_buffer);
175 } else if (strstr(chld_out.line[i], _("Non-authoritative answer:"))) {
176 non_authoritative = true;
177 }
178
179 result = error_scan(chld_out.line[i], &is_nxdomain);
180 if (result != STATE_OK) {
181 msg = strchr(chld_out.line[i], ':');
182 if (msg)
183 msg++;
184 break;
185 }
186 }
187
188 /* scan stderr */
189 for (size_t i = 0; i < chld_err.lines; i++) {
190 if (verbose)
191 puts(chld_err.line[i]);
192
193 if (error_scan(chld_err.line[i], &is_nxdomain) != STATE_OK) {
194 result = max_state(result, error_scan(chld_err.line[i], &is_nxdomain));
195 msg = strchr(input_buffer, ':');
196 if (msg)
197 msg++;
198 else
199 msg = input_buffer;
200 }
201 }
202
203 if (is_nxdomain && !expect_nxdomain) {
204 die(STATE_CRITICAL, _("Domain '%s' was not found by the server\n"), query_address);
205 }
72 206
73int 207 if (addresses) {
74main (int argc, char **argv) 208 int i;
75{ 209 int slen;
76 char *command_line = NULL; 210 char *adrp;
77 char input_buffer[MAX_INPUT_BUFFER]; 211 qsort(addresses, n_addresses, sizeof(*addresses), qstrcmp);
78 char *address = NULL; /* comma separated str with addrs/ptrs (sorted) */ 212 for (i = 0, slen = 1; i < n_addresses; i++) {
79 char **addresses = NULL; 213 slen += strlen(addresses[i]) + 1;
80 int n_addresses = 0; 214 }
81 char *msg = NULL; 215 adrp = address = malloc(slen);
82 char *temp_buffer = NULL; 216 for (i = 0; i < n_addresses; i++) {
83 bool non_authoritative = false; 217 if (i)
84 int result = STATE_UNKNOWN; 218 *adrp++ = ',';
85 double elapsed_time; 219 strcpy(adrp, addresses[i]);
86 long microsec; 220 adrp += strlen(addresses[i]);
87 struct timeval tv; 221 }
88 bool parse_address = false; /* This flag scans for Address: but only after Name: */ 222 *adrp = 0;
89 output chld_out, chld_err; 223 } else
90 bool is_nxdomain = false; 224 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' msg parsing exited with no address\n"), NSLOOKUP_COMMAND);
91 225
92 setlocale (LC_ALL, ""); 226 /* compare to expected address */
93 bindtextdomain (PACKAGE, LOCALEDIR); 227 if (result == STATE_OK && expected_address_cnt > 0) {
94 textdomain (PACKAGE); 228 result = STATE_CRITICAL;
95 229 temp_buffer = "";
96 /* Set signal handling and alarm */ 230 unsigned long expect_match = (1 << expected_address_cnt) - 1;
97 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) { 231 unsigned long addr_match = (1 << n_addresses) - 1;
98 usage_va(_("Cannot catch SIGALRM")); 232
99 } 233 for (int i = 0; i < expected_address_cnt; i++) {
100 234 int j;
101 /* Parse extra opts if any */ 235 /* check if we get a match on 'raw' ip or cidr */
102 argv=np_extra_opts (&argc, argv, progname); 236 for (j = 0; j < n_addresses; j++) {
103 237 if (strcmp(addresses[j], expected_address[i]) == 0 || ip_match_cidr(addresses[j], expected_address[i])) {
104 if (process_arguments (argc, argv) == ERROR) { 238 result = STATE_OK;
105 usage_va(_("Could not parse arguments")); 239 addr_match &= ~(1 << j);
106 } 240 expect_match &= ~(1 << i);
107 241 }
108 /* get the command to run */ 242 }
109 xasprintf (&command_line, "%s %s %s", NSLOOKUP_COMMAND, query_address, dns_server); 243
110 244 /* prepare an error string */
111 alarm (timeout_interval); 245 xasprintf(&temp_buffer, "%s%s; ", temp_buffer, expected_address[i]);
112 gettimeofday (&tv, NULL); 246 }
113 247 /* check if expected_address must cover all in addresses and none may be missing */
114 if (verbose) 248 if (all_match && (expect_match != 0 || addr_match != 0))
115 printf ("%s\n", command_line); 249 result = STATE_CRITICAL;
116 250 if (result == STATE_CRITICAL) {
117 /* run the command */ 251 /* Strip off last semicolon... */
118 if((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) { 252 temp_buffer[strlen(temp_buffer) - 2] = '\0';
119 msg = (char *)_("nslookup returned an error status"); 253 xasprintf(&msg, _("expected '%s' but got '%s'"), temp_buffer, address);
120 result = STATE_WARNING; 254 }
121 } 255 }
122 256
123 /* scan stdout */ 257 if (expect_nxdomain) {
124 for(size_t i = 0; i < chld_out.lines; i++) { 258 if (!is_nxdomain) {
125 if (addresses == NULL) 259 result = STATE_CRITICAL;
126 addresses = malloc(sizeof(*addresses)*10); 260 xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), query_address, address);
127 else if (!(n_addresses % 10)) 261 } else {
128 addresses = realloc(addresses,sizeof(*addresses) * (n_addresses + 10)); 262 if (address != NULL)
129 263 free(address);
130 if (verbose) 264 address = "NXDOMAIN";
131 puts(chld_out.line[i]); 265 }
132 266 }
133 if (strcasestr (chld_out.line[i], ".in-addr.arpa") || strcasestr (chld_out.line[i], ".ip6.arpa")) { 267
134 if ((temp_buffer = strstr (chld_out.line[i], "name = "))) 268 /* check if authoritative */
135 addresses[n_addresses++] = strdup (temp_buffer + 7); 269 if (result == STATE_OK && expect_authority && non_authoritative) {
136 else { 270 result = STATE_CRITICAL;
137 msg = (char *)_("Warning plugin error"); 271 xasprintf(&msg, _("server %s is not authoritative for %s"), dns_server, query_address);
138 result = STATE_WARNING; 272 }
139 } 273
140 } 274 microsec = deltime(tv);
141 275 elapsed_time = (double)microsec / 1.0e6;
142 /* bug ID: 2946553 - Older versions of bind will use all available dns 276
143 servers, we have to match the one specified */ 277 if (result == STATE_OK) {
144 if (strstr (chld_out.line[i], "Server:") && strlen(dns_server) > 0) { 278 result = get_status(elapsed_time, time_thresholds);
145 temp_buffer = strchr (chld_out.line[i], ':'); 279 if (result == STATE_OK) {
146 temp_buffer++; 280 printf("DNS %s: ", _("OK"));
147 281 } else if (result == STATE_WARNING) {
148 /* Strip leading tabs */ 282 printf("DNS %s: ", _("WARNING"));
149 for (; *temp_buffer != '\0' && *temp_buffer == '\t'; temp_buffer++) 283 } else if (result == STATE_CRITICAL) {
150 /* NOOP */; 284 printf("DNS %s: ", _("CRITICAL"));
151 285 }
152 strip(temp_buffer); 286 printf(ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), elapsed_time);
153 if (temp_buffer==NULL || strlen(temp_buffer)==0) { 287 printf(_(". %s returns %s"), query_address, address);
154 die (STATE_CRITICAL, 288 if ((time_thresholds->warning != NULL) && (time_thresholds->critical != NULL)) {
155 _("DNS CRITICAL - '%s' returned empty server string\n"), 289 printf("|%s\n", fperfdata("time", elapsed_time, "s", true, time_thresholds->warning->end, true, time_thresholds->critical->end,
156 NSLOOKUP_COMMAND); 290 true, 0, false, 0));
157 } 291 } else if ((time_thresholds->warning == NULL) && (time_thresholds->critical != NULL)) {
158 292 printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, true, time_thresholds->critical->end, true, 0, false, 0));
159 if (strcmp(temp_buffer, dns_server) != 0) { 293 } else if ((time_thresholds->warning != NULL) && (time_thresholds->critical == NULL)) {
160 die (STATE_CRITICAL, _("DNS CRITICAL - No response from DNS %s\n"), dns_server); 294 printf("|%s\n", fperfdata("time", elapsed_time, "s", true, time_thresholds->warning->end, false, 0, true, 0, false, 0));
161 } 295 } else
162 } 296 printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, false, 0));
163 297 } else if (result == STATE_WARNING)
164 /* the server is responding, we just got the host name... */ 298 printf(_("DNS WARNING - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
165 if (strstr (chld_out.line[i], "Name:")) 299 else if (result == STATE_CRITICAL)
166 parse_address = true; 300 printf(_("DNS CRITICAL - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
167 else if (parse_address && (strstr (chld_out.line[i], "Address:") || 301 else
168 strstr (chld_out.line[i], "Addresses:"))) { 302 printf(_("DNS UNKNOWN - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
169 temp_buffer = index (chld_out.line[i], ':'); 303
170 temp_buffer++; 304 return result;
171
172 /* Strip leading spaces */
173 while (*temp_buffer == ' ')
174 temp_buffer++;
175
176 strip(temp_buffer);
177 if (temp_buffer==NULL || strlen(temp_buffer)==0) {
178 die (STATE_CRITICAL,
179 _("DNS CRITICAL - '%s' returned empty host name string\n"),
180 NSLOOKUP_COMMAND);
181 }
182
183 addresses[n_addresses++] = strdup(temp_buffer);
184 }
185 else if (strstr (chld_out.line[i], _("Non-authoritative answer:"))) {
186 non_authoritative = true;
187 }
188
189
190 result = error_scan (chld_out.line[i], &is_nxdomain);
191 if (result != STATE_OK) {
192 msg = strchr (chld_out.line[i], ':');
193 if(msg) msg++;
194 break;
195 }
196 }
197
198 /* scan stderr */
199 for(size_t i = 0; i < chld_err.lines; i++) {
200 if (verbose)
201 puts(chld_err.line[i]);
202
203 if (error_scan (chld_err.line[i], &is_nxdomain) != STATE_OK) {
204 result = max_state (result, error_scan (chld_err.line[i], &is_nxdomain));
205 msg = strchr(input_buffer, ':');
206 if(msg)
207 msg++;
208 else
209 msg = input_buffer;
210 }
211 }
212
213 if (is_nxdomain && !expect_nxdomain) {
214 die (STATE_CRITICAL, _("Domain '%s' was not found by the server\n"), query_address);
215 }
216
217 if (addresses) {
218 int i,slen;
219 char *adrp;
220 qsort(addresses, n_addresses, sizeof(*addresses), qstrcmp);
221 for(i=0, slen=1; i < n_addresses; i++) {
222 slen += strlen(addresses[i])+1;
223 }
224 adrp = address = malloc(slen);
225 for(i=0; i < n_addresses; i++) {
226 if (i) *adrp++ = ',';
227 strcpy(adrp, addresses[i]);
228 adrp += strlen(addresses[i]);
229 }
230 *adrp = 0;
231 } else
232 die (STATE_CRITICAL,
233 _("DNS CRITICAL - '%s' msg parsing exited with no address\n"),
234 NSLOOKUP_COMMAND);
235
236 /* compare to expected address */
237 if (result == STATE_OK && expected_address_cnt > 0) {
238 result = STATE_CRITICAL;
239 temp_buffer = "";
240 unsigned long expect_match = (1 << expected_address_cnt) - 1;
241 unsigned long addr_match = (1 << n_addresses) - 1;
242
243 for (int i=0; i<expected_address_cnt; i++) {
244 int j;
245 /* check if we get a match on 'raw' ip or cidr */
246 for (j=0; j<n_addresses; j++) {
247 if ( strcmp(addresses[j], expected_address[i]) == 0
248 || ip_match_cidr(addresses[j], expected_address[i]) ) {
249 result = STATE_OK;
250 addr_match &= ~(1 << j);
251 expect_match &= ~(1 << i);
252 }
253 }
254
255 /* prepare an error string */
256 xasprintf(&temp_buffer, "%s%s; ", temp_buffer, expected_address[i]);
257 }
258 /* check if expected_address must cover all in addresses and none may be missing */
259 if (all_match && (expect_match != 0 || addr_match != 0))
260 result = STATE_CRITICAL;
261 if (result == STATE_CRITICAL) {
262 /* Strip off last semicolon... */
263 temp_buffer[strlen(temp_buffer)-2] = '\0';
264 xasprintf(&msg, _("expected '%s' but got '%s'"), temp_buffer, address);
265 }
266 }
267
268 if (expect_nxdomain) {
269 if (!is_nxdomain) {
270 result = STATE_CRITICAL;
271 xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), query_address, address);
272 } else {
273 if (address != NULL) free(address);
274 address = "NXDOMAIN";
275 }
276 }
277
278 /* check if authoritative */
279 if (result == STATE_OK && expect_authority && non_authoritative) {
280 result = STATE_CRITICAL;
281 xasprintf(&msg, _("server %s is not authoritative for %s"), dns_server, query_address);
282 }
283
284 microsec = deltime (tv);
285 elapsed_time = (double)microsec / 1.0e6;
286
287 if (result == STATE_OK) {
288 result = get_status(elapsed_time, time_thresholds);
289 if (result == STATE_OK) {
290 printf ("DNS %s: ", _("OK"));
291 } else if (result == STATE_WARNING) {
292 printf ("DNS %s: ", _("WARNING"));
293 } else if (result == STATE_CRITICAL) {
294 printf ("DNS %s: ", _("CRITICAL"));
295 }
296 printf (ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), elapsed_time);
297 printf (_(". %s returns %s"), query_address, address);
298 if ((time_thresholds->warning != NULL) && (time_thresholds->critical != NULL)) {
299 printf ("|%s\n", fperfdata ("time", elapsed_time, "s",
300 true, time_thresholds->warning->end,
301 true, time_thresholds->critical->end,
302 true, 0, false, 0));
303 } else if ((time_thresholds->warning == NULL) && (time_thresholds->critical != NULL)) {
304 printf ("|%s\n", fperfdata ("time", elapsed_time, "s",
305 false, 0,
306 true, time_thresholds->critical->end,
307 true, 0, false, 0));
308 } else if ((time_thresholds->warning != NULL) && (time_thresholds->critical == NULL)) {
309 printf ("|%s\n", fperfdata ("time", elapsed_time, "s",
310 true, time_thresholds->warning->end,
311 false, 0,
312 true, 0, false, 0));
313 } else
314 printf ("|%s\n", fperfdata ("time", elapsed_time, "s", false, 0, false, 0, true, 0, false, 0));
315 }
316 else if (result == STATE_WARNING)
317 printf (_("DNS WARNING - %s\n"),
318 !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
319 else if (result == STATE_CRITICAL)
320 printf (_("DNS CRITICAL - %s\n"),
321 !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
322 else
323 printf (_("DNS UNKNOWN - %s\n"),
324 !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
325
326 return result;
327} 305}
328 306
329bool ip_match_cidr(const char *addr, const char *cidr_ro) { 307bool ip_match_cidr(const char *addr, const char *cidr_ro) {
330 char *subnet, *mask_c, *cidr = strdup(cidr_ro); 308 char *subnet;
331 int mask; 309 char *mask_c;
332 subnet = strtok(cidr, "/"); 310 char *cidr = strdup(cidr_ro);
333 mask_c = strtok(NULL, "\0"); 311 int mask;
334 if (!subnet || !mask_c) { 312 subnet = strtok(cidr, "/");
335 return false; 313 mask_c = strtok(NULL, "\0");
314 if (!subnet || !mask_c) {
315 return false;
336 } 316 }
337 mask = atoi(mask_c); 317 mask = atoi(mask_c);
338 318
339 /* https://www.cryptobells.com/verifying-ips-in-a-subnet-in-php/ */ 319 /* https://www.cryptobells.com/verifying-ips-in-a-subnet-in-php/ */
340 return (ip2long(addr) & ~((1 << (32 - mask)) - 1)) == (ip2long(subnet) >> (32 - mask)) << (32 - mask); 320 return (ip2long(addr) & ~((1 << (32 - mask)) - 1)) == (ip2long(subnet) >> (32 - mask)) << (32 - mask);
341} 321}
342 322
343unsigned long 323unsigned long ip2long(const char *src) {
344ip2long(const char* src) { 324 unsigned long ip[4];
345 unsigned long ip[4]; 325 /* http://computer-programming-forum.com/47-c-language/1376ffb92a12c471.htm */
346 /* http://computer-programming-forum.com/47-c-language/1376ffb92a12c471.htm */ 326 return (sscanf(src, "%3lu.%3lu.%3lu.%3lu", &ip[0], &ip[1], &ip[2], &ip[3]) == 4 && ip[0] < 256 && ip[1] < 256 && ip[2] < 256 &&
347 return (sscanf(src, "%3lu.%3lu.%3lu.%3lu", 327 ip[3] < 256)
348 &ip[0], &ip[1], &ip[2], &ip[3]) == 4 && 328 ? ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3]
349 ip[0] < 256 && ip[1] < 256 && 329 : 0;
350 ip[2] < 256 && ip[3] < 256)
351 ? ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3]
352 : 0;
353} 330}
354 331
355int 332int error_scan(char *input_buffer, bool *is_nxdomain) {
356error_scan (char *input_buffer, bool *is_nxdomain)
357{
358
359 const int nxdomain = strstr (input_buffer, "Non-existent") ||
360 strstr (input_buffer, "** server can't find") ||
361 strstr (input_buffer, "** Can't find") ||
362 strstr (input_buffer, "NXDOMAIN");
363 if (nxdomain) *is_nxdomain = true;
364
365 /* the DNS lookup timed out */
366 if (strstr (input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) ||
367 strstr (input_buffer, _("Consider using the `dig' or `host' programs instead. Run nslookup with")) ||
368 strstr (input_buffer, _("the `-sil[ent]' option to prevent this message from appearing.")))
369 return STATE_OK;
370
371 /* DNS server is not running... */
372 else if (strstr (input_buffer, "No response from server"))
373 die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
374 else if (strstr (input_buffer, "no servers could be reached"))
375 die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
376
377 /* Host name is valid, but server doesn't have records... */
378 else if (strstr (input_buffer, "No records"))
379 die (STATE_CRITICAL, _("DNS %s has no records\n"), dns_server);
380
381 /* Connection was refused */
382 else if (strstr (input_buffer, "Connection refused") ||
383 strstr (input_buffer, "Couldn't find server") ||
384 strstr (input_buffer, "Refused") ||
385 (strstr (input_buffer, "** server can't find") &&
386 strstr (input_buffer, ": REFUSED")))
387 die (STATE_CRITICAL, _("Connection to DNS %s was refused\n"), dns_server);
388
389 /* Query refused (usually by an ACL in the namserver) */
390 else if (strstr (input_buffer, "Query refused"))
391 die (STATE_CRITICAL, _("Query was refused by DNS server at %s\n"), dns_server);
392
393 /* No information (e.g. nameserver IP has two PTR records) */
394 else if (strstr (input_buffer, "No information"))
395 die (STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server);
396
397 /* Network is unreachable */
398 else if (strstr (input_buffer, "Network is unreachable"))
399 die (STATE_CRITICAL, _("Network is unreachable\n"));
400
401 /* Internal server failure */
402 else if (strstr (input_buffer, "Server failure"))
403 die (STATE_CRITICAL, _("DNS failure for %s\n"), dns_server);
404
405 /* Request error or the DNS lookup timed out */
406 else if (strstr (input_buffer, "Format error") ||
407 strstr (input_buffer, "Timed out"))
408 return STATE_WARNING;
409
410 return STATE_OK;
411 333
412} 334 const int nxdomain = strstr(input_buffer, "Non-existent") || strstr(input_buffer, "** server can't find") ||
335 strstr(input_buffer, "** Can't find") || strstr(input_buffer, "NXDOMAIN");
336 if (nxdomain)
337 *is_nxdomain = true;
338
339 /* the DNS lookup timed out */
340 if (strstr(input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) ||
341 strstr(input_buffer, _("Consider using the `dig' or `host' programs instead. Run nslookup with")) ||
342 strstr(input_buffer, _("the `-sil[ent]' option to prevent this message from appearing.")))
343 return STATE_OK;
344
345 /* DNS server is not running... */
346 else if (strstr(input_buffer, "No response from server"))
347 die(STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
348 else if (strstr(input_buffer, "no servers could be reached"))
349 die(STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
350
351 /* Host name is valid, but server doesn't have records... */
352 else if (strstr(input_buffer, "No records"))
353 die(STATE_CRITICAL, _("DNS %s has no records\n"), dns_server);
354
355 /* Connection was refused */
356 else if (strstr(input_buffer, "Connection refused") || strstr(input_buffer, "Couldn't find server") ||
357 strstr(input_buffer, "Refused") || (strstr(input_buffer, "** server can't find") && strstr(input_buffer, ": REFUSED")))
358 die(STATE_CRITICAL, _("Connection to DNS %s was refused\n"), dns_server);
359
360 /* Query refused (usually by an ACL in the namserver) */
361 else if (strstr(input_buffer, "Query refused"))
362 die(STATE_CRITICAL, _("Query was refused by DNS server at %s\n"), dns_server);
363
364 /* No information (e.g. nameserver IP has two PTR records) */
365 else if (strstr(input_buffer, "No information"))
366 die(STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server);
367
368 /* Network is unreachable */
369 else if (strstr(input_buffer, "Network is unreachable"))
370 die(STATE_CRITICAL, _("Network is unreachable\n"));
371
372 /* Internal server failure */
373 else if (strstr(input_buffer, "Server failure"))
374 die(STATE_CRITICAL, _("DNS failure for %s\n"), dns_server);
413 375
376 /* Request error or the DNS lookup timed out */
377 else if (strstr(input_buffer, "Format error") || strstr(input_buffer, "Timed out"))
378 return STATE_WARNING;
379
380 return STATE_OK;
381}
414 382
415/* process command-line arguments */ 383/* process command-line arguments */
416int 384int process_arguments(int argc, char **argv) {
417process_arguments (int argc, char **argv) 385 int c;
418{ 386 char *warning = NULL;
419 int c; 387 char *critical = NULL;
420 char *warning = NULL; 388
421 char *critical = NULL; 389 int opt_index = 0;
422 390 static struct option long_opts[] = {{"help", no_argument, 0, 'h'},
423 int opt_index = 0; 391 {"version", no_argument, 0, 'V'},
424 static struct option long_opts[] = { 392 {"verbose", no_argument, 0, 'v'},
425 {"help", no_argument, 0, 'h'}, 393 {"timeout", required_argument, 0, 't'},
426 {"version", no_argument, 0, 'V'}, 394 {"hostname", required_argument, 0, 'H'},
427 {"verbose", no_argument, 0, 'v'}, 395 {"server", required_argument, 0, 's'},
428 {"timeout", required_argument, 0, 't'}, 396 {"reverse-server", required_argument, 0, 'r'},
429 {"hostname", required_argument, 0, 'H'}, 397 {"expected-address", required_argument, 0, 'a'},
430 {"server", required_argument, 0, 's'}, 398 {"expect-nxdomain", no_argument, 0, 'n'},
431 {"reverse-server", required_argument, 0, 'r'}, 399 {"expect-authority", no_argument, 0, 'A'},
432 {"expected-address", required_argument, 0, 'a'}, 400 {"all", no_argument, 0, 'L'},
433 {"expect-nxdomain", no_argument, 0, 'n'}, 401 {"warning", required_argument, 0, 'w'},
434 {"expect-authority", no_argument, 0, 'A'}, 402 {"critical", required_argument, 0, 'c'},
435 {"all", no_argument, 0, 'L'}, 403 {0, 0, 0, 0}};
436 {"warning", required_argument, 0, 'w'}, 404
437 {"critical", required_argument, 0, 'c'}, 405 if (argc < 2)
438 {0, 0, 0, 0} 406 return ERROR;
439 }; 407
440 408 for (c = 1; c < argc; c++)
441 if (argc < 2) 409 if (strcmp("-to", argv[c]) == 0)
442 return ERROR; 410 strcpy(argv[c], "-t");
443 411
444 for (c = 1; c < argc; c++) 412 while (1) {
445 if (strcmp ("-to", argv[c]) == 0) 413 c = getopt_long(argc, argv, "hVvALnt:H:s:r:a:w:c:", long_opts, &opt_index);
446 strcpy (argv[c], "-t"); 414
447 415 if (c == -1 || c == EOF)
448 while (1) { 416 break;
449 c = getopt_long (argc, argv, "hVvALnt:H:s:r:a:w:c:", long_opts, &opt_index); 417
450 418 switch (c) {
451 if (c == -1 || c == EOF) 419 case 'h': /* help */
452 break; 420 print_help();
453 421 exit(STATE_UNKNOWN);
454 switch (c) { 422 case 'V': /* version */
455 case 'h': /* help */ 423 print_revision(progname, NP_VERSION);
456 print_help (); 424 exit(STATE_UNKNOWN);
457 exit (STATE_UNKNOWN); 425 case 'v': /* version */
458 case 'V': /* version */ 426 verbose = true;
459 print_revision (progname, NP_VERSION); 427 break;
460 exit (STATE_UNKNOWN); 428 case 't': /* timeout period */
461 case 'v': /* version */ 429 timeout_interval = atoi(optarg);
462 verbose = true; 430 break;
463 break; 431 case 'H': /* hostname */
464 case 't': /* timeout period */ 432 if (strlen(optarg) >= ADDRESS_LENGTH)
465 timeout_interval = atoi (optarg); 433 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
466 break; 434 strcpy(query_address, optarg);
467 case 'H': /* hostname */ 435 break;
468 if (strlen (optarg) >= ADDRESS_LENGTH) 436 case 's': /* server name */
469 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 437 /* TODO: this host_or_die check is probably unnecessary.
470 strcpy (query_address, optarg); 438 * Better to confirm nslookup response matches */
471 break; 439 host_or_die(optarg);
472 case 's': /* server name */ 440 if (strlen(optarg) >= ADDRESS_LENGTH)
473 /* TODO: this host_or_die check is probably unnecessary. 441 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
474 * Better to confirm nslookup response matches */ 442 strcpy(dns_server, optarg);
475 host_or_die(optarg); 443 break;
476 if (strlen (optarg) >= ADDRESS_LENGTH) 444 case 'r': /* reverse server name */
477 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 445 /* TODO: Is this host_or_die necessary? */
478 strcpy (dns_server, optarg); 446 host_or_die(optarg);
479 break; 447 if (strlen(optarg) >= ADDRESS_LENGTH)
480 case 'r': /* reverse server name */ 448 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
481 /* TODO: Is this host_or_die necessary? */ 449 strcpy(ptr_server, optarg);
482 host_or_die(optarg); 450 break;
483 if (strlen (optarg) >= ADDRESS_LENGTH) 451 case 'a': /* expected address */
484 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 452 if (strlen(optarg) >= ADDRESS_LENGTH)
485 strcpy (ptr_server, optarg); 453 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
486 break; 454 if (strchr(optarg, ',') != NULL) {
487 case 'a': /* expected address */ 455 char *comma = strchr(optarg, ',');
488 if (strlen (optarg) >= ADDRESS_LENGTH) 456 while (comma != NULL) {
489 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 457 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **));
490 if (strchr(optarg, ',') != NULL) { 458 expected_address[expected_address_cnt] = strndup(optarg, comma - optarg);
491 char *comma = strchr(optarg, ','); 459 expected_address_cnt++;
492 while (comma != NULL) { 460 optarg = comma + 1;
493 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**)); 461 comma = strchr(optarg, ',');
494 expected_address[expected_address_cnt] = strndup(optarg, comma - optarg); 462 }
495 expected_address_cnt++; 463 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **));
496 optarg = comma + 1; 464 expected_address[expected_address_cnt] = strdup(optarg);
497 comma = strchr(optarg, ','); 465 expected_address_cnt++;
466 } else {
467 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **));
468 expected_address[expected_address_cnt] = strdup(optarg);
469 expected_address_cnt++;
470 }
471 break;
472 case 'n': /* expect NXDOMAIN */
473 expect_nxdomain = true;
474 break;
475 case 'A': /* expect authority */
476 expect_authority = true;
477 break;
478 case 'L': /* all must match */
479 all_match = true;
480 break;
481 case 'w':
482 warning = optarg;
483 break;
484 case 'c':
485 critical = optarg;
486 break;
487 default: /* args not parsable */
488 usage5();
489 }
498 } 490 }
499 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
500 expected_address[expected_address_cnt] = strdup(optarg);
501 expected_address_cnt++;
502 } else {
503 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
504 expected_address[expected_address_cnt] = strdup(optarg);
505 expected_address_cnt++;
506 }
507 break;
508 case 'n': /* expect NXDOMAIN */
509 expect_nxdomain = true;
510 break;
511 case 'A': /* expect authority */
512 expect_authority = true;
513 break;
514 case 'L': /* all must match */
515 all_match = true;
516 break;
517 case 'w':
518 warning = optarg;
519 break;
520 case 'c':
521 critical = optarg;
522 break;
523 default: /* args not parsable */
524 usage5();
525 }
526 }
527
528 c = optind;
529 if (strlen(query_address)==0 && c<argc) {
530 if (strlen(argv[c])>=ADDRESS_LENGTH)
531 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
532 strcpy (query_address, argv[c++]);
533 }
534
535 if (strlen(dns_server)==0 && c<argc) {
536 /* TODO: See -s option */
537 host_or_die(argv[c]);
538 if (strlen(argv[c]) >= ADDRESS_LENGTH)
539 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
540 strcpy (dns_server, argv[c++]);
541 }
542
543 set_thresholds(&time_thresholds, warning, critical);
544
545 return validate_arguments ();
546}
547 491
492 c = optind;
493 if (strlen(query_address) == 0 && c < argc) {
494 if (strlen(argv[c]) >= ADDRESS_LENGTH)
495 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
496 strcpy(query_address, argv[c++]);
497 }
548 498
549int 499 if (strlen(dns_server) == 0 && c < argc) {
550validate_arguments () 500 /* TODO: See -s option */
551{ 501 host_or_die(argv[c]);
552 if (query_address[0] == 0) { 502 if (strlen(argv[c]) >= ADDRESS_LENGTH)
553 printf ("missing --host argument\n"); 503 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
554 return ERROR; 504 strcpy(dns_server, argv[c++]);
555 } 505 }
556 506
557 if (expected_address_cnt > 0 && expect_nxdomain) { 507 set_thresholds(&time_thresholds, warning, critical);
558 printf ("--expected-address and --expect-nxdomain cannot be combined\n");
559 return ERROR;
560 }
561 508
562 return OK; 509 return validate_arguments();
563} 510}
564 511
512int validate_arguments(void) {
513 if (query_address[0] == 0) {
514 printf("missing --host argument\n");
515 return ERROR;
516 }
517
518 if (expected_address_cnt > 0 && expect_nxdomain) {
519 printf("--expected-address and --expect-nxdomain cannot be combined\n");
520 return ERROR;
521 }
565 522
566void 523 return OK;
567print_help (void)
568{
569 print_revision (progname, NP_VERSION);
570
571 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
572 printf (COPYRIGHT, copyright, email);
573
574 printf ("%s\n", _("This plugin uses the nslookup program to obtain the IP address for the given host/domain query."));
575 printf ("%s\n", _("An optional DNS server to use may be specified."));
576 printf ("%s\n", _("If no DNS server is specified, the default server(s) specified in /etc/resolv.conf will be used."));
577
578 printf ("\n\n");
579
580 print_usage ();
581
582 printf (UT_HELP_VRSN);
583 printf (UT_EXTRA_OPTS);
584
585 printf (" -H, --hostname=HOST\n");
586 printf (" %s\n", _("The name or address you want to query"));
587 printf (" -s, --server=HOST\n");
588 printf (" %s\n", _("Optional DNS server you want to use for the lookup"));
589 printf (" -a, --expected-address=IP-ADDRESS|CIDR|HOST\n");
590 printf (" %s\n", _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end"));
591 printf (" %s\n", _("with a dot (.). This option can be repeated multiple times (Returns OK if any"));
592 printf (" %s\n", _("value matches)."));
593 printf (" -n, --expect-nxdomain\n");
594 printf (" %s\n", _("Expect the DNS server to return NXDOMAIN (i.e. the domain was not found)"));
595 printf (" %s\n", _("Cannot be used together with -a"));
596 printf (" -A, --expect-authority\n");
597 printf (" %s\n", _("Optionally expect the DNS server to be authoritative for the lookup"));
598 printf (" -w, --warning=seconds\n");
599 printf (" %s\n", _("Return warning if elapsed time exceeds value. Default off"));
600 printf (" -c, --critical=seconds\n");
601 printf (" %s\n", _("Return critical if elapsed time exceeds value. Default off"));
602 printf (" -L, --all\n");
603 printf (" %s\n", _("Return critical if the list of expected addresses does not match all addresses"));
604 printf (" %s\n", _("returned. Default off"));
605
606 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
607
608 printf (UT_SUPPORT);
609} 524}
610 525
526void print_help(void) {
527 print_revision(progname, NP_VERSION);
528
529 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
530 printf(COPYRIGHT, copyright, email);
531
532 printf("%s\n", _("This plugin uses the nslookup program to obtain the IP address for the given host/domain query."));
533 printf("%s\n", _("An optional DNS server to use may be specified."));
534 printf("%s\n", _("If no DNS server is specified, the default server(s) specified in /etc/resolv.conf will be used."));
535
536 printf("\n\n");
537
538 print_usage();
539
540 printf(UT_HELP_VRSN);
541 printf(UT_EXTRA_OPTS);
542
543 printf(" -H, --hostname=HOST\n");
544 printf(" %s\n", _("The name or address you want to query"));
545 printf(" -s, --server=HOST\n");
546 printf(" %s\n", _("Optional DNS server you want to use for the lookup"));
547 printf(" -a, --expected-address=IP-ADDRESS|CIDR|HOST\n");
548 printf(" %s\n", _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end"));
549 printf(" %s\n", _("with a dot (.). This option can be repeated multiple times (Returns OK if any"));
550 printf(" %s\n", _("value matches)."));
551 printf(" -n, --expect-nxdomain\n");
552 printf(" %s\n", _("Expect the DNS server to return NXDOMAIN (i.e. the domain was not found)"));
553 printf(" %s\n", _("Cannot be used together with -a"));
554 printf(" -A, --expect-authority\n");
555 printf(" %s\n", _("Optionally expect the DNS server to be authoritative for the lookup"));
556 printf(" -w, --warning=seconds\n");
557 printf(" %s\n", _("Return warning if elapsed time exceeds value. Default off"));
558 printf(" -c, --critical=seconds\n");
559 printf(" %s\n", _("Return critical if elapsed time exceeds value. Default off"));
560 printf(" -L, --all\n");
561 printf(" %s\n", _("Return critical if the list of expected addresses does not match all addresses"));
562 printf(" %s\n", _("returned. Default off"));
563
564 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
565
566 printf(UT_SUPPORT);
567}
611 568
612void 569void print_usage(void) {
613print_usage (void) 570 printf("%s\n", _("Usage:"));
614{ 571 printf("%s -H host [-s server] [-a expected-address] [-n] [-A] [-t timeout] [-w warn] [-c crit] [-L]\n", progname);
615 printf ("%s\n", _("Usage:"));
616 printf ("%s -H host [-s server] [-a expected-address] [-n] [-A] [-t timeout] [-w warn] [-c crit] [-L]\n", progname);
617} 572}
diff --git a/plugins/check_dummy.c b/plugins/check_dummy.c
index 212a1344..19f6c046 100644
--- a/plugins/check_dummy.c
+++ b/plugins/check_dummy.c
@@ -1,124 +1,111 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dummy plugin 3 * Monitoring check_dummy plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_dummy plugin 10 * This file contains the check_dummy plugin
11* 11 *
12* This plugin will simply return the state corresponding to the numeric value 12 * This plugin will simply return the state corresponding to the numeric value
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_dummy"; 31const char *progname = "check_dummy";
32const char *copyright = "1999-2007"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
36#include "utils.h" 36#include "utils.h"
37 37
38void print_help (void); 38static void print_help(void);
39void print_usage (void); 39void print_usage(void);
40 40
41 41int main(int argc, char **argv) {
42int 42 int result = STATE_UNKNOWN;
43main (int argc, char **argv) 43
44{ 44 setlocale(LC_ALL, "");
45 int result = STATE_UNKNOWN; 45 bindtextdomain(PACKAGE, LOCALEDIR);
46 46 textdomain(PACKAGE);
47 setlocale (LC_ALL, ""); 47
48 bindtextdomain (PACKAGE, LOCALEDIR); 48 if (argc < 2)
49 textdomain (PACKAGE); 49 usage4(_("Could not parse arguments"));
50 50 else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0) {
51 if (argc < 2) 51 print_revision(progname, NP_VERSION);
52 usage4 (_("Could not parse arguments")); 52 exit(STATE_UNKNOWN);
53 else if (strcmp (argv[1], "-V") == 0 || strcmp (argv[1], "--version") == 0) { 53 } else if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
54 print_revision (progname, NP_VERSION); 54 print_help();
55 exit (STATE_UNKNOWN); 55 exit(STATE_UNKNOWN);
56 } 56 } else if (!is_integer(argv[1]))
57 else if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) { 57 usage4(_("Arguments to check_dummy must be an integer"));
58 print_help (); 58 else
59 exit (STATE_UNKNOWN); 59 result = atoi(argv[1]);
60 } 60
61 else if (!is_integer (argv[1])) 61 switch (result) {
62 usage4 (_("Arguments to check_dummy must be an integer")); 62 case STATE_OK:
63 else 63 printf(_("OK"));
64 result = atoi (argv[1]); 64 break;
65 65 case STATE_WARNING:
66 switch (result) { 66 printf(_("WARNING"));
67 case STATE_OK: 67 break;
68 printf (_("OK")); 68 case STATE_CRITICAL:
69 break; 69 printf(_("CRITICAL"));
70 case STATE_WARNING: 70 break;
71 printf (_("WARNING")); 71 case STATE_UNKNOWN:
72 break; 72 printf(_("UNKNOWN"));
73 case STATE_CRITICAL: 73 break;
74 printf (_("CRITICAL")); 74 default:
75 break; 75 printf(_("UNKNOWN"));
76 case STATE_UNKNOWN: 76 printf(": ");
77 printf (_("UNKNOWN")); 77 printf(_("Status %d is not a supported error state\n"), result);
78 break; 78 return STATE_UNKNOWN;
79 default: 79 }
80 printf (_("UNKNOWN")); 80
81 printf (": "); 81 if (argc >= 3)
82 printf (_("Status %d is not a supported error state\n"), result); 82 printf(": %s", argv[2]);
83 return STATE_UNKNOWN; 83
84 } 84 printf("\n");
85 85
86 if (argc >= 3) 86 return result;
87 printf (": %s", argv[2]);
88
89 printf("\n");
90
91 return result;
92} 87}
93 88
89void print_help(void) {
90 print_revision(progname, NP_VERSION);
94 91
92 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
93 printf(COPYRIGHT, copyright, email);
95 94
96void 95 printf("%s\n", _("This plugin will simply return the state corresponding to the numeric value"));
97print_help (void)
98{
99 print_revision (progname, NP_VERSION);
100 96
101 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 97 printf("%s\n", _("of the <state> argument with optional text"));
102 printf (COPYRIGHT, copyright, email);
103 98
104 printf ("%s\n", _("This plugin will simply return the state corresponding to the numeric value")); 99 printf("\n\n");
105 100
106 printf ("%s\n", _("of the <state> argument with optional text")); 101 print_usage();
107 102
108 printf ("\n\n"); 103 printf(UT_HELP_VRSN);
109 104
110 print_usage (); 105 printf(UT_SUPPORT);
111
112 printf (UT_HELP_VRSN);
113
114 printf (UT_SUPPORT);
115} 106}
116 107
117 108void print_usage(void) {
118 109 printf("%s\n", _("Usage:"));
119void 110 printf(" %s <integer state> [optional text]\n", progname);
120print_usage (void)
121{
122 printf ("%s\n", _("Usage:"));
123 printf (" %s <integer state> [optional text]\n", progname);
124} 111}
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index 70d6f9fc..49235e28 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_fping plugin 3 * Monitoring check_fping plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_disk plugin 10 * This file contains the check_disk plugin
11* 11 *
12* This plugin will use the fping command to ping the specified host for a 12 * This plugin will use the fping command to ping the specified host for a
13* fast check 13 * fast check
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_fping"; 32const char *progname = "check_fping";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -40,488 +40,449 @@ const char *email = "devel@monitoring-plugins.org";
40#include <stdbool.h> 40#include <stdbool.h>
41 41
42enum { 42enum {
43 PACKET_COUNT = 1, 43 PACKET_COUNT = 1,
44 PACKET_SIZE = 56, 44 PACKET_SIZE = 56,
45 PL = 0, 45 PL = 0,
46 RTA = 1 46 RTA = 1
47}; 47};
48 48
49int textscan (char *buf); 49static int textscan(char *buf);
50int process_arguments (int, char **); 50static int process_arguments(int /*argc*/, char ** /*argv*/);
51int get_threshold (char *arg, char *rv[2]); 51static int get_threshold(char *arg, char *rv[2]);
52void print_help (void); 52static void print_help(void);
53void print_usage (void); 53void print_usage(void);
54 54
55char *server_name = NULL; 55static char *server_name = NULL;
56char *sourceip = NULL; 56static char *sourceip = NULL;
57char *sourceif = NULL; 57static char *sourceif = NULL;
58int packet_size = PACKET_SIZE; 58static int packet_size = PACKET_SIZE;
59int packet_count = PACKET_COUNT; 59static int packet_count = PACKET_COUNT;
60int target_timeout = 0; 60static int target_timeout = 0;
61int packet_interval = 0; 61static int packet_interval = 0;
62bool verbose = false; 62static bool verbose = false;
63int cpl; 63static int cpl;
64int wpl; 64static int wpl;
65double crta; 65static double crta;
66double wrta; 66static double wrta;
67bool cpl_p = false; 67static bool cpl_p = false;
68bool wpl_p = false; 68static bool wpl_p = false;
69bool alive_p = false; 69static bool alive_p = false;
70bool crta_p = false; 70static bool crta_p = false;
71bool wrta_p = false; 71static bool wrta_p = false;
72 72
73int 73int main(int argc, char **argv) {
74main (int argc, char **argv) 74 /* normally should be int result = STATE_UNKNOWN; */
75{ 75
76/* normally should be int result = STATE_UNKNOWN; */ 76 int status = STATE_UNKNOWN;
77 77 int result = 0;
78 int status = STATE_UNKNOWN; 78 char *fping_prog = NULL;
79 int result = 0; 79 char *server = NULL;
80 char *fping_prog = NULL; 80 char *command_line = NULL;
81 char *server = NULL; 81 char *input_buffer = NULL;
82 char *command_line = NULL; 82 char *option_string = "";
83 char *input_buffer = NULL; 83 input_buffer = malloc(MAX_INPUT_BUFFER);
84 char *option_string = ""; 84
85 input_buffer = malloc (MAX_INPUT_BUFFER); 85 setlocale(LC_ALL, "");
86 86 bindtextdomain(PACKAGE, LOCALEDIR);
87 setlocale (LC_ALL, ""); 87 textdomain(PACKAGE);
88 bindtextdomain (PACKAGE, LOCALEDIR); 88
89 textdomain (PACKAGE); 89 /* Parse extra opts if any */
90 90 argv = np_extra_opts(&argc, argv, progname);
91 /* Parse extra opts if any */ 91
92 argv=np_extra_opts (&argc, argv, progname); 92 if (process_arguments(argc, argv) == ERROR)
93 93 usage4(_("Could not parse arguments"));
94 if (process_arguments (argc, argv) == ERROR) 94
95 usage4 (_("Could not parse arguments")); 95 server = strscpy(server, server_name);
96 96
97 server = strscpy (server, server_name); 97 /* compose the command */
98 98 if (target_timeout)
99 /* compose the command */ 99 xasprintf(&option_string, "%s-t %d ", option_string, target_timeout);
100 if (target_timeout) 100 if (packet_interval)
101 xasprintf(&option_string, "%s-t %d ", option_string, target_timeout); 101 xasprintf(&option_string, "%s-p %d ", option_string, packet_interval);
102 if (packet_interval) 102 if (sourceip)
103 xasprintf(&option_string, "%s-p %d ", option_string, packet_interval); 103 xasprintf(&option_string, "%s-S %s ", option_string, sourceip);
104 if (sourceip) 104 if (sourceif)
105 xasprintf(&option_string, "%s-S %s ", option_string, sourceip); 105 xasprintf(&option_string, "%s-I %s ", option_string, sourceif);
106 if (sourceif)
107 xasprintf(&option_string, "%s-I %s ", option_string, sourceif);
108 106
109#ifdef PATH_TO_FPING6 107#ifdef PATH_TO_FPING6
110 if (address_family != AF_INET && is_inet6_addr(server)) 108 if (address_family != AF_INET && is_inet6_addr(server))
111 fping_prog = strdup(PATH_TO_FPING6); 109 fping_prog = strdup(PATH_TO_FPING6);
112 else 110 else
113 fping_prog = strdup(PATH_TO_FPING); 111 fping_prog = strdup(PATH_TO_FPING);
114#else 112#else
115 fping_prog = strdup(PATH_TO_FPING); 113 fping_prog = strdup(PATH_TO_FPING);
116#endif 114#endif
117 115
118 xasprintf (&command_line, "%s %s-b %d -c %d %s", fping_prog, 116 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, packet_size, packet_count, server);
119 option_string, packet_size, packet_count, server); 117
120 118 if (verbose)
121 if (verbose) 119 printf("%s\n", command_line);
122 printf ("%s\n", command_line); 120
123 121 /* run the command */
124 /* run the command */ 122 child_process = spopen(command_line);
125 child_process = spopen (command_line); 123 if (child_process == NULL) {
126 if (child_process == NULL) { 124 printf(_("Could not open pipe: %s\n"), command_line);
127 printf (_("Could not open pipe: %s\n"), command_line); 125 return STATE_UNKNOWN;
128 return STATE_UNKNOWN; 126 }
129 } 127
130 128 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
131 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 129 if (child_stderr == NULL) {
132 if (child_stderr == NULL) { 130 printf(_("Could not open stderr for %s\n"), command_line);
133 printf (_("Could not open stderr for %s\n"), command_line); 131 }
134 } 132
135 133 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
136 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 134 if (verbose)
137 if (verbose) 135 printf("%s", input_buffer);
138 printf ("%s", input_buffer); 136 status = max_state(status, textscan(input_buffer));
139 status = max_state (status, textscan (input_buffer)); 137 }
140 } 138
141 139 /* If we get anything on STDERR, at least set warning */
142 /* If we get anything on STDERR, at least set warning */ 140 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
143 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { 141 status = max_state(status, STATE_WARNING);
144 status = max_state (status, STATE_WARNING); 142 if (verbose)
145 if (verbose) 143 printf("%s", input_buffer);
146 printf ("%s", input_buffer); 144 status = max_state(status, textscan(input_buffer));
147 status = max_state (status, textscan (input_buffer)); 145 }
148 } 146 (void)fclose(child_stderr);
149 (void) fclose (child_stderr); 147
150 148 /* close the pipe */
151 /* close the pipe */ 149 result = spclose(child_process);
152 result = spclose (child_process); 150 if (result) {
153 if (result) { 151 /* need to use max_state not max */
154 /* need to use max_state not max */ 152 status = max_state(status, STATE_WARNING);
155 status = max_state (status, STATE_WARNING); 153 }
156 } 154
157 155 if (result > 1) {
158 if (result > 1 ) { 156 status = max_state(status, STATE_UNKNOWN);
159 status = max_state (status, STATE_UNKNOWN); 157 if (result == 2) {
160 if (result == 2) { 158 die(STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n"));
161 die (STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n")); 159 }
162 } 160 if (result == 3) {
163 if (result == 3) { 161 die(STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n"));
164 die (STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n")); 162 }
165 } 163 if (result == 4) {
166 if (result == 4) { 164 die(STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n"));
167 die (STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n")); 165 }
168 } 166 }
169 167
170 } 168 printf("FPING %s - %s\n", state_text(status), server_name);
171 169
172 printf ("FPING %s - %s\n", state_text (status), server_name); 170 return status;
173
174 return status;
175} 171}
176 172
177 173int textscan(char *buf) {
178int textscan (char *buf) { 174 char *rtastr = NULL;
179 char *rtastr = NULL; 175 char *losstr = NULL;
180 char *losstr = NULL; 176 char *xmtstr = NULL;
181 char *xmtstr = NULL; 177 double loss;
182 double loss; 178 double rta;
183 double rta; 179 double xmt;
184 double xmt; 180 int status = STATE_UNKNOWN;
185 int status = STATE_UNKNOWN; 181
186 182 /* stops testing after the first successful reply. */
187 /* stops testing after the first successful reply. */ 183 if (alive_p && strstr(buf, "avg, 0% loss)")) {
188 if (alive_p && strstr(buf, "avg, 0% loss)")) { 184 rtastr = strstr(buf, "ms (");
189 rtastr = strstr (buf, "ms ("); 185 rtastr = 1 + index(rtastr, '(');
190 rtastr = 1 + index(rtastr, '('); 186 rta = strtod(rtastr, NULL);
191 rta = strtod(rtastr, NULL); 187 loss = strtod("0", NULL);
192 loss=strtod("0",NULL); 188 die(STATE_OK, _("FPING %s - %s (rta=%f ms)|%s\n"), state_text(STATE_OK), server_name, rta,
193 die (STATE_OK, 189 /* No loss since we only waited for the first reply
194 _("FPING %s - %s (rta=%f ms)|%s\n"), 190 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */
195 state_text (STATE_OK), server_name,rta, 191 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0));
196 /* No loss since we only waited for the first reply 192 }
197 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */ 193
198 fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); 194 if (strstr(buf, "not found")) {
199 } 195 die(STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name);
200 196
201 if (strstr (buf, "not found")) { 197 } else if (strstr(buf, "is unreachable") || strstr(buf, "Unreachable")) {
202 die (STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name); 198 die(STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), "host");
203 199
204 } 200 } else if (strstr(buf, "Operation not permitted") || strstr(buf, "No such device")) {
205 else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) { 201 die(STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), "host");
206 die (STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), 202 } else if (strstr(buf, "is down")) {
207 "host"); 203 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
208 204
209 } 205 } else if (strstr(buf, "is alive")) {
210 else if (strstr (buf, "Operation not permitted") || strstr (buf, "No such device") ) { 206 status = STATE_OK;
211 die (STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), 207
212 "host"); 208 } else if (strstr(buf, "xmt/rcv/%loss") && strstr(buf, "min/avg/max")) {
213 } 209 losstr = strstr(buf, "=");
214 else if (strstr (buf, "is down")) { 210 losstr = 1 + strstr(losstr, "/");
215 die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 211 losstr = 1 + strstr(losstr, "/");
216 212 rtastr = strstr(buf, "min/avg/max");
217 } 213 rtastr = strstr(rtastr, "=");
218 else if (strstr (buf, "is alive")) { 214 rtastr = 1 + index(rtastr, '/');
219 status = STATE_OK; 215 loss = strtod(losstr, NULL);
220 216 rta = strtod(rtastr, NULL);
221 } 217 if (cpl_p && loss > cpl)
222 else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) { 218 status = STATE_CRITICAL;
223 losstr = strstr (buf, "="); 219 else if (crta_p && rta > crta)
224 losstr = 1 + strstr (losstr, "/"); 220 status = STATE_CRITICAL;
225 losstr = 1 + strstr (losstr, "/"); 221 else if (wpl_p && loss > wpl)
226 rtastr = strstr (buf, "min/avg/max"); 222 status = STATE_WARNING;
227 rtastr = strstr (rtastr, "="); 223 else if (wrta_p && rta > wrta)
228 rtastr = 1 + index (rtastr, '/'); 224 status = STATE_WARNING;
229 loss = strtod (losstr, NULL); 225 else
230 rta = strtod (rtastr, NULL); 226 status = STATE_OK;
231 if (cpl_p && loss > cpl) 227 die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), server_name, loss, rta,
232 status = STATE_CRITICAL; 228 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100),
233 else if (crta_p && rta > crta) 229 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0));
234 status = STATE_CRITICAL; 230
235 else if (wpl_p && loss > wpl) 231 } else if (strstr(buf, "xmt/rcv/%loss")) {
236 status = STATE_WARNING; 232 /* no min/max/avg if host was unreachable in fping v2.2.b1 */
237 else if (wrta_p && rta > wrta) 233 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */
238 status = STATE_WARNING; 234 losstr = strstr(buf, "=");
239 else 235 xmtstr = 1 + losstr;
240 status = STATE_OK; 236 xmt = strtod(xmtstr, NULL);
241 die (status, 237 if (xmt == 0)
242 _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), 238 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
243 state_text (status), server_name, loss, rta, 239 losstr = 1 + strstr(losstr, "/");
244 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), 240 losstr = 1 + strstr(losstr, "/");
245 fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); 241 loss = strtod(losstr, NULL);
246 242 if (atoi(losstr) == 100)
247 } 243 status = STATE_CRITICAL;
248 else if(strstr (buf, "xmt/rcv/%loss") ) { 244 else if (cpl_p && loss > cpl)
249 /* no min/max/avg if host was unreachable in fping v2.2.b1 */ 245 status = STATE_CRITICAL;
250 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */ 246 else if (wpl_p && loss > wpl)
251 losstr = strstr (buf, "="); 247 status = STATE_WARNING;
252 xmtstr = 1 + losstr; 248 else
253 xmt = strtod (xmtstr, NULL); 249 status = STATE_OK;
254 if(xmt == 0) 250 /* loss=%.0f%%;%d;%d;0;100 */
255 die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 251 die(status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), state_text(status), server_name, loss,
256 losstr = 1 + strstr (losstr, "/"); 252 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100));
257 losstr = 1 + strstr (losstr, "/"); 253
258 loss = strtod (losstr, NULL); 254 } else {
259 if (atoi(losstr) == 100) 255 status = max_state(status, STATE_WARNING);
260 status = STATE_CRITICAL; 256 }
261 else if (cpl_p && loss > cpl) 257
262 status = STATE_CRITICAL; 258 return status;
263 else if (wpl_p && loss > wpl)
264 status = STATE_WARNING;
265 else
266 status = STATE_OK;
267 /* loss=%.0f%%;%d;%d;0;100 */
268 die (status, _("FPING %s - %s (loss=%.0f%% )|%s\n"),
269 state_text (status), server_name, loss ,
270 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100));
271
272 }
273 else {
274 status = max_state (status, STATE_WARNING);
275 }
276
277 return status;
278} 259}
279 260
280
281
282/* process command-line arguments */ 261/* process command-line arguments */
283int 262int process_arguments(int argc, char **argv) {
284process_arguments (int argc, char **argv) 263 int c;
285{ 264 char *rv[2];
286 int c; 265
287 char *rv[2]; 266 int option = 0;
288 267 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
289 int option = 0; 268 {"sourceip", required_argument, 0, 'S'},
290 static struct option longopts[] = { 269 {"sourceif", required_argument, 0, 'I'},
291 {"hostname", required_argument, 0, 'H'}, 270 {"critical", required_argument, 0, 'c'},
292 {"sourceip", required_argument, 0, 'S'}, 271 {"warning", required_argument, 0, 'w'},
293 {"sourceif", required_argument, 0, 'I'}, 272 {"alive", no_argument, 0, 'a'},
294 {"critical", required_argument, 0, 'c'}, 273 {"bytes", required_argument, 0, 'b'},
295 {"warning", required_argument, 0, 'w'}, 274 {"number", required_argument, 0, 'n'},
296 {"alive", no_argument, 0, 'a'}, 275 {"target-timeout", required_argument, 0, 'T'},
297 {"bytes", required_argument, 0, 'b'}, 276 {"interval", required_argument, 0, 'i'},
298 {"number", required_argument, 0, 'n'}, 277 {"verbose", no_argument, 0, 'v'},
299 {"target-timeout", required_argument, 0, 'T'}, 278 {"version", no_argument, 0, 'V'},
300 {"interval", required_argument, 0, 'i'}, 279 {"help", no_argument, 0, 'h'},
301 {"verbose", no_argument, 0, 'v'}, 280 {"use-ipv4", no_argument, 0, '4'},
302 {"version", no_argument, 0, 'V'}, 281 {"use-ipv6", no_argument, 0, '6'},
303 {"help", no_argument, 0, 'h'}, 282 {0, 0, 0, 0}};
304 {"use-ipv4", no_argument, 0, '4'}, 283
305 {"use-ipv6", no_argument, 0, '6'}, 284 rv[PL] = NULL;
306 {0, 0, 0, 0} 285 rv[RTA] = NULL;
307 }; 286
308 287 if (argc < 2)
309 rv[PL] = NULL; 288 return ERROR;
310 rv[RTA] = NULL; 289
311 290 if (!is_option(argv[1])) {
312 if (argc < 2) 291 server_name = argv[1];
313 return ERROR; 292 argv[1] = argv[0];
314 293 argv = &argv[1];
315 if (!is_option (argv[1])) { 294 argc--;
316 server_name = argv[1]; 295 }
317 argv[1] = argv[0]; 296
318 argv = &argv[1]; 297 while (1) {
319 argc--; 298 c = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:46", longopts, &option);
320 } 299
321 300 if (c == -1 || c == EOF || c == 1)
322 while (1) { 301 break;
323 c = getopt_long (argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:46", longopts, &option); 302
324 303 switch (c) {
325 if (c == -1 || c == EOF || c == 1) 304 case '?': /* print short usage statement if args not parsable */
326 break; 305 usage5();
327 306 case 'a': /* host alive mode */
328 switch (c) { 307 alive_p = true;
329 case '?': /* print short usage statement if args not parsable */ 308 break;
330 usage5 (); 309 case 'h': /* help */
331 case 'a': /* host alive mode */ 310 print_help();
332 alive_p = true; 311 exit(STATE_UNKNOWN);
333 break; 312 case 'V': /* version */
334 case 'h': /* help */ 313 print_revision(progname, NP_VERSION);
335 print_help (); 314 exit(STATE_UNKNOWN);
336 exit (STATE_UNKNOWN); 315 case 'v': /* verbose mode */
337 case 'V': /* version */ 316 verbose = true;
338 print_revision (progname, NP_VERSION); 317 break;
339 exit (STATE_UNKNOWN); 318 case 'H': /* hostname */
340 case 'v': /* verbose mode */ 319 if (is_host(optarg) == false) {
341 verbose = true; 320 usage2(_("Invalid hostname/address"), optarg);
342 break; 321 }
343 case 'H': /* hostname */ 322 server_name = strscpy(server_name, optarg);
344 if (is_host (optarg) == false) { 323 break;
345 usage2 (_("Invalid hostname/address"), optarg); 324 case 'S': /* sourceip */
346 } 325 if (is_host(optarg) == false) {
347 server_name = strscpy (server_name, optarg); 326 usage2(_("Invalid hostname/address"), optarg);
348 break; 327 }
349 case 'S': /* sourceip */ 328 sourceip = strscpy(sourceip, optarg);
350 if (is_host (optarg) == false) { 329 break;
351 usage2 (_("Invalid hostname/address"), optarg); 330 case 'I': /* sourceip */
352 } 331 sourceif = strscpy(sourceif, optarg);
353 sourceip = strscpy (sourceip, optarg); 332 break;
354 break; 333 case '4': /* IPv4 only */
355 case 'I': /* sourceip */ 334 address_family = AF_INET;
356 sourceif = strscpy (sourceif, optarg);
357 break; 335 break;
358 case '4': /* IPv4 only */ 336 case '6': /* IPv6 only */
359 address_family = AF_INET;
360 break;
361 case '6': /* IPv6 only */
362#ifdef USE_IPV6 337#ifdef USE_IPV6
363 address_family = AF_INET6; 338 address_family = AF_INET6;
364#else 339#else
365 usage (_("IPv6 support not available\n")); 340 usage(_("IPv6 support not available\n"));
366#endif 341#endif
367 break; 342 break;
368 case 'c': 343 case 'c':
369 get_threshold (optarg, rv); 344 get_threshold(optarg, rv);
370 if (rv[RTA]) { 345 if (rv[RTA]) {
371 crta = strtod (rv[RTA], NULL); 346 crta = strtod(rv[RTA], NULL);
372 crta_p = true; 347 crta_p = true;
373 rv[RTA] = NULL; 348 rv[RTA] = NULL;
374 } 349 }
375 if (rv[PL]) { 350 if (rv[PL]) {
376 cpl = atoi (rv[PL]); 351 cpl = atoi(rv[PL]);
377 cpl_p = true; 352 cpl_p = true;
378 rv[PL] = NULL; 353 rv[PL] = NULL;
379 } 354 }
380 break; 355 break;
381 case 'w': 356 case 'w':
382 get_threshold (optarg, rv); 357 get_threshold(optarg, rv);
383 if (rv[RTA]) { 358 if (rv[RTA]) {
384 wrta = strtod (rv[RTA], NULL); 359 wrta = strtod(rv[RTA], NULL);
385 wrta_p = true; 360 wrta_p = true;
386 rv[RTA] = NULL; 361 rv[RTA] = NULL;
387 } 362 }
388 if (rv[PL]) { 363 if (rv[PL]) {
389 wpl = atoi (rv[PL]); 364 wpl = atoi(rv[PL]);
390 wpl_p = true; 365 wpl_p = true;
391 rv[PL] = NULL; 366 rv[PL] = NULL;
392 } 367 }
393 break; 368 break;
394 case 'b': /* bytes per packet */ 369 case 'b': /* bytes per packet */
395 if (is_intpos (optarg)) 370 if (is_intpos(optarg))
396 packet_size = atoi (optarg); 371 packet_size = atoi(optarg);
397 else 372 else
398 usage (_("Packet size must be a positive integer")); 373 usage(_("Packet size must be a positive integer"));
399 break; 374 break;
400 case 'n': /* number of packets */ 375 case 'n': /* number of packets */
401 if (is_intpos (optarg)) 376 if (is_intpos(optarg))
402 packet_count = atoi (optarg); 377 packet_count = atoi(optarg);
403 else 378 else
404 usage (_("Packet count must be a positive integer")); 379 usage(_("Packet count must be a positive integer"));
405 break; 380 break;
406 case 'T': /* timeout in msec */ 381 case 'T': /* timeout in msec */
407 if (is_intpos (optarg)) 382 if (is_intpos(optarg))
408 target_timeout = atoi (optarg); 383 target_timeout = atoi(optarg);
409 else 384 else
410 usage (_("Target timeout must be a positive integer")); 385 usage(_("Target timeout must be a positive integer"));
411 break; 386 break;
412 case 'i': /* interval in msec */ 387 case 'i': /* interval in msec */
413 if (is_intpos (optarg)) 388 if (is_intpos(optarg))
414 packet_interval = atoi (optarg); 389 packet_interval = atoi(optarg);
415 else 390 else
416 usage (_("Interval must be a positive integer")); 391 usage(_("Interval must be a positive integer"));
417 break; 392 break;
418 } 393 }
419 } 394 }
420
421 if (server_name == NULL)
422 usage4 (_("Hostname was not supplied"));
423
424 return OK;
425}
426 395
396 if (server_name == NULL)
397 usage4(_("Hostname was not supplied"));
427 398
428int 399 return OK;
429get_threshold (char *arg, char *rv[2])
430{
431 char *arg1 = NULL;
432 char *arg2 = NULL;
433
434 arg1 = strscpy (arg1, arg);
435 if (strpbrk (arg1, ",:"))
436 arg2 = 1 + strpbrk (arg1, ",:");
437
438 if (arg2) {
439 arg1[strcspn (arg1, ",:")] = 0;
440 if (strstr (arg1, "%") && strstr (arg2, "%"))
441 die (STATE_UNKNOWN,
442 _("%s: Only one threshold may be packet loss (%s)\n"), progname,
443 arg);
444 if (!strstr (arg1, "%") && !strstr (arg2, "%"))
445 die (STATE_UNKNOWN,
446 _("%s: Only one threshold must be packet loss (%s)\n"),
447 progname, arg);
448 }
449
450 if (arg2 && strstr (arg2, "%")) {
451 rv[PL] = arg2;
452 rv[RTA] = arg1;
453 }
454 else if (arg2) {
455 rv[PL] = arg1;
456 rv[RTA] = arg2;
457 }
458 else if (strstr (arg1, "%")) {
459 rv[PL] = arg1;
460 }
461 else {
462 rv[RTA] = arg1;
463 }
464
465 return OK;
466} 400}
467 401
402int get_threshold(char *arg, char *rv[2]) {
403 char *arg1 = NULL;
404 char *arg2 = NULL;
405
406 arg1 = strscpy(arg1, arg);
407 if (strpbrk(arg1, ",:"))
408 arg2 = 1 + strpbrk(arg1, ",:");
409
410 if (arg2) {
411 arg1[strcspn(arg1, ",:")] = 0;
412 if (strstr(arg1, "%") && strstr(arg2, "%"))
413 die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, arg);
414 if (!strstr(arg1, "%") && !strstr(arg2, "%"))
415 die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, arg);
416 }
417
418 if (arg2 && strstr(arg2, "%")) {
419 rv[PL] = arg2;
420 rv[RTA] = arg1;
421 } else if (arg2) {
422 rv[PL] = arg1;
423 rv[RTA] = arg2;
424 } else if (strstr(arg1, "%")) {
425 rv[PL] = arg1;
426 } else {
427 rv[RTA] = arg1;
428 }
429
430 return OK;
431}
468 432
469void print_help (void) { 433void print_help(void) {
470 434
471 print_revision (progname, NP_VERSION); 435 print_revision(progname, NP_VERSION);
472 436
473 printf ("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n"); 437 printf("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n");
474 printf (COPYRIGHT, copyright, email); 438 printf(COPYRIGHT, copyright, email);
475 439
476 printf ("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check")); 440 printf("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check"));
477 441
478 printf ("%s\n", _("Note that it is necessary to set the suid flag on fping.")); 442 printf("%s\n", _("Note that it is necessary to set the suid flag on fping."));
479 443
480 printf ("\n\n"); 444 printf("\n\n");
481 445
482 print_usage (); 446 print_usage();
483 447
484 printf (UT_HELP_VRSN); 448 printf(UT_HELP_VRSN);
485 printf (UT_EXTRA_OPTS); 449 printf(UT_EXTRA_OPTS);
486 450
487 printf (UT_IPv46); 451 printf(UT_IPv46);
488 452
489 printf (" %s\n", "-H, --hostname=HOST"); 453 printf(" %s\n", "-H, --hostname=HOST");
490 printf (" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)")); 454 printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)"));
491 printf (" %s\n", "-w, --warning=THRESHOLD"); 455 printf(" %s\n", "-w, --warning=THRESHOLD");
492 printf (" %s\n", _("warning threshold pair")); 456 printf(" %s\n", _("warning threshold pair"));
493 printf (" %s\n", "-c, --critical=THRESHOLD"); 457 printf(" %s\n", "-c, --critical=THRESHOLD");
494 printf (" %s\n", _("critical threshold pair")); 458 printf(" %s\n", _("critical threshold pair"));
495 printf (" %s\n", "-a, --alive"); 459 printf(" %s\n", "-a, --alive");
496 printf (" %s\n", _("Return OK after first successful reply")); 460 printf(" %s\n", _("Return OK after first successful reply"));
497 printf (" %s\n", "-b, --bytes=INTEGER"); 461 printf(" %s\n", "-b, --bytes=INTEGER");
498 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE); 462 printf(" %s (default: %d)\n", _("size of ICMP packet"), PACKET_SIZE);
499 printf (" %s\n", "-n, --number=INTEGER"); 463 printf(" %s\n", "-n, --number=INTEGER");
500 printf (" %s (default: %d)\n", _("number of ICMP packets to send"),PACKET_COUNT); 464 printf(" %s (default: %d)\n", _("number of ICMP packets to send"), PACKET_COUNT);
501 printf (" %s\n", "-T, --target-timeout=INTEGER"); 465 printf(" %s\n", "-T, --target-timeout=INTEGER");
502 printf (" %s (default: fping's default for -t)\n", _("Target timeout (ms)")); 466 printf(" %s (default: fping's default for -t)\n", _("Target timeout (ms)"));
503 printf (" %s\n", "-i, --interval=INTEGER"); 467 printf(" %s\n", "-i, --interval=INTEGER");
504 printf (" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets")); 468 printf(" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets"));
505 printf (" %s\n", "-S, --sourceip=HOST"); 469 printf(" %s\n", "-S, --sourceip=HOST");
506 printf (" %s\n", _("name or IP Address of sourceip")); 470 printf(" %s\n", _("name or IP Address of sourceip"));
507 printf (" %s\n", "-I, --sourceif=IF"); 471 printf(" %s\n", "-I, --sourceif=IF");
508 printf (" %s\n", _("source interface name")); 472 printf(" %s\n", _("source interface name"));
509 printf (UT_VERBOSE); 473 printf(UT_VERBOSE);
510 printf ("\n"); 474 printf("\n");
511 printf (" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)")); 475 printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));
512 printf (" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of")); 476 printf(" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of"));
513 printf (" %s\n", _("packet loss to trigger an alarm state.")); 477 printf(" %s\n", _("packet loss to trigger an alarm state."));
514 478
515 printf ("\n"); 479 printf("\n");
516 printf (" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6.")); 480 printf(" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6."));
517 481
518 printf (UT_SUPPORT); 482 printf(UT_SUPPORT);
519} 483}
520 484
521 485void print_usage(void) {
522void 486 printf("%s\n", _("Usage:"));
523print_usage (void) 487 printf(" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname);
524{
525 printf ("%s\n", _("Usage:"));
526 printf (" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname);
527} 488}
diff --git a/plugins/check_game.c b/plugins/check_game.c
index ca126973..619277e7 100644
--- a/plugins/check_game.c
+++ b/plugins/check_game.c
@@ -1,335 +1,308 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_game plugin 3 * Monitoring check_game plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2002-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_game plugin 10 * This file contains the check_game plugin
11* 11 *
12* This plugin tests game server connections with the specified host. 12 * This plugin tests game server connections with the specified host.
13* using the qstat program 13 * using the qstat program
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_game"; 32const char *progname = "check_game";
33const char *copyright = "2002-2007"; 33const char *copyright = "2002-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
37#include "utils.h" 37#include "utils.h"
38#include "runcmd.h" 38#include "runcmd.h"
39 39
40int process_arguments (int, char **); 40static int process_arguments(int /*argc*/, char ** /*argv*/);
41int validate_arguments (void); 41static int validate_arguments(void);
42void print_help (void); 42static void print_help(void);
43void print_usage (void); 43void print_usage(void);
44 44
45#define QSTAT_DATA_DELIMITER "," 45#define QSTAT_DATA_DELIMITER ","
46 46
47#define QSTAT_HOST_ERROR "ERROR" 47#define QSTAT_HOST_ERROR "ERROR"
48#define QSTAT_HOST_DOWN "DOWN" 48#define QSTAT_HOST_DOWN "DOWN"
49#define QSTAT_HOST_TIMEOUT "TIMEOUT" 49#define QSTAT_HOST_TIMEOUT "TIMEOUT"
50#define QSTAT_MAX_RETURN_ARGS 12 50#define QSTAT_MAX_RETURN_ARGS 12
51 51
52char *server_ip; 52static char *server_ip;
53char *game_type; 53static char *game_type;
54int port = 0; 54static int port = 0;
55 55
56bool verbose = false; 56static bool verbose = false;
57 57
58int qstat_game_players_max = -1; 58static int qstat_game_players_max = -1;
59int qstat_game_players = -1; 59static int qstat_game_players = -1;
60int qstat_game_field = -1; 60static int qstat_game_field = -1;
61int qstat_map_field = -1; 61static int qstat_map_field = -1;
62int qstat_ping_field = -1; 62static int qstat_ping_field = -1;
63 63
64 64int main(int argc, char **argv) {
65int 65 char *command_line;
66main (int argc, char **argv) 66 int result = STATE_UNKNOWN;
67{ 67 char *p;
68 char *command_line; 68 char *ret[QSTAT_MAX_RETURN_ARGS];
69 int result = STATE_UNKNOWN; 69 size_t i = 0;
70 char *p, *ret[QSTAT_MAX_RETURN_ARGS]; 70 output chld_out;
71 size_t i = 0; 71
72 output chld_out; 72 setlocale(LC_ALL, "");
73 73 bindtextdomain(PACKAGE, LOCALEDIR);
74 setlocale (LC_ALL, ""); 74 textdomain(PACKAGE);
75 bindtextdomain (PACKAGE, LOCALEDIR); 75
76 textdomain (PACKAGE); 76 /* Parse extra opts if any */
77 77 argv = np_extra_opts(&argc, argv, progname);
78 /* Parse extra opts if any */ 78
79 argv=np_extra_opts (&argc, argv, progname); 79 if (process_arguments(argc, argv) == ERROR)
80 80 usage_va(_("Could not parse arguments"));
81 if (process_arguments (argc, argv) == ERROR) 81
82 usage_va(_("Could not parse arguments")); 82 result = STATE_OK;
83 83
84 result = STATE_OK; 84 /* create the command line to execute */
85 85 xasprintf(&command_line, "%s -raw %s -%s %s", PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip);
86 /* create the command line to execute */ 86
87 xasprintf (&command_line, "%s -raw %s -%s %s", 87 if (port)
88 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip); 88 xasprintf(&command_line, "%s:%-d", command_line, port);
89 89
90 if (port) 90 if (verbose)
91 xasprintf (&command_line, "%s:%-d", command_line, port); 91 printf("%s\n", command_line);
92 92
93 if (verbose) 93 /* run the command. historically, this plugin ignores output on stderr,
94 printf ("%s\n", command_line); 94 * as well as return status of the qstat program */
95 95 (void)np_runcmd(command_line, &chld_out, NULL, 0);
96 /* run the command. historically, this plugin ignores output on stderr, 96
97 * as well as return status of the qstat program */ 97 /* sanity check */
98 (void)np_runcmd(command_line, &chld_out, NULL, 0); 98 /* was thinking about running qstat without any options, capturing the
99 99 -default line, parsing it & making an array of all know server types
100 /* sanity check */ 100 but thought this would be too much hassle considering this is a tool
101 /* was thinking about running qstat without any options, capturing the 101 for intelligent sysadmins (ha). Could put a static array of known
102 -default line, parsing it & making an array of all know server types 102 server types in a header file but then we'd be limiting ourselves
103 but thought this would be too much hassle considering this is a tool 103
104 for intelligent sysadmins (ha). Could put a static array of known 104 In the end, I figured I'd simply let an error occur & then trap it
105 server types in a header file but then we'd be limiting ourselves 105 */
106 106
107 In the end, I figured I'd simply let an error occur & then trap it 107 if (!strncmp(chld_out.line[0], "unknown option", 14)) {
108 */ 108 printf(_("CRITICAL - Host type parameter incorrect!\n"));
109 109 result = STATE_CRITICAL;
110 if (!strncmp (chld_out.line[0], "unknown option", 14)) { 110 return result;
111 printf (_("CRITICAL - Host type parameter incorrect!\n")); 111 }
112 result = STATE_CRITICAL; 112
113 return result; 113 p = (char *)strtok(chld_out.line[0], QSTAT_DATA_DELIMITER);
114 } 114 while (p != NULL) {
115 115 ret[i] = p;
116 p = (char *) strtok (chld_out.line[0], QSTAT_DATA_DELIMITER); 116 p = (char *)strtok(NULL, QSTAT_DATA_DELIMITER);
117 while (p != NULL) { 117 i++;
118 ret[i] = p; 118 if (i >= QSTAT_MAX_RETURN_ARGS)
119 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER); 119 break;
120 i++; 120 }
121 if (i >= QSTAT_MAX_RETURN_ARGS) 121
122 break; 122 if (strstr(ret[2], QSTAT_HOST_ERROR)) {
123 } 123 printf(_("CRITICAL - Host not found\n"));
124 124 result = STATE_CRITICAL;
125 if (strstr (ret[2], QSTAT_HOST_ERROR)) { 125 } else if (strstr(ret[2], QSTAT_HOST_DOWN)) {
126 printf (_("CRITICAL - Host not found\n")); 126 printf(_("CRITICAL - Game server down or unavailable\n"));
127 result = STATE_CRITICAL; 127 result = STATE_CRITICAL;
128 } 128 } else if (strstr(ret[2], QSTAT_HOST_TIMEOUT)) {
129 else if (strstr (ret[2], QSTAT_HOST_DOWN)) { 129 printf(_("CRITICAL - Game server timeout\n"));
130 printf (_("CRITICAL - Game server down or unavailable\n")); 130 result = STATE_CRITICAL;
131 result = STATE_CRITICAL; 131 } else {
132 } 132 printf("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", ret[qstat_game_players], ret[qstat_game_players_max], ret[qstat_game_field],
133 else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) { 133 ret[qstat_map_field], ret[qstat_ping_field],
134 printf (_("CRITICAL - Game server timeout\n")); 134 perfdata("players", atol(ret[qstat_game_players]), "", false, 0, false, 0, true, 0, true, atol(ret[qstat_game_players_max])),
135 result = STATE_CRITICAL; 135 fperfdata("ping", strtod(ret[qstat_ping_field], NULL), "", false, 0, false, 0, true, 0, false, 0));
136 } 136 }
137 else { 137
138 printf ("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", 138 return result;
139 ret[qstat_game_players],
140 ret[qstat_game_players_max],
141 ret[qstat_game_field],
142 ret[qstat_map_field],
143 ret[qstat_ping_field],
144 perfdata ("players", atol(ret[qstat_game_players]), "",
145 false, 0, false, 0,
146 true, 0, true, atol(ret[qstat_game_players_max])),
147 fperfdata ("ping", strtod(ret[qstat_ping_field], NULL), "",
148 false, 0, false, 0,
149 true, 0, false, 0));
150 }
151
152 return result;
153} 139}
154 140
155 141int process_arguments(int argc, char **argv) {
156int 142 int c;
157process_arguments (int argc, char **argv) 143
158{ 144 int opt_index = 0;
159 int c; 145 static struct option long_opts[] = {{"help", no_argument, 0, 'h'},
160 146 {"version", no_argument, 0, 'V'},
161 int opt_index = 0; 147 {"verbose", no_argument, 0, 'v'},
162 static struct option long_opts[] = { 148 {"timeout", required_argument, 0, 't'},
163 {"help", no_argument, 0, 'h'}, 149 {"hostname", required_argument, 0, 'H'},
164 {"version", no_argument, 0, 'V'}, 150 {"port", required_argument, 0, 'P'},
165 {"verbose", no_argument, 0, 'v'}, 151 {"game-type", required_argument, 0, 'G'},
166 {"timeout", required_argument, 0, 't'}, 152 {"map-field", required_argument, 0, 'm'},
167 {"hostname", required_argument, 0, 'H'}, 153 {"ping-field", required_argument, 0, 'p'},
168 {"port", required_argument, 0, 'P'}, 154 {"game-field", required_argument, 0, 'g'},
169 {"game-type", required_argument, 0, 'G'}, 155 {"players-field", required_argument, 0, 129},
170 {"map-field", required_argument, 0, 'm'}, 156 {"max-players-field", required_argument, 0, 130},
171 {"ping-field", required_argument, 0, 'p'}, 157 {0, 0, 0, 0}};
172 {"game-field", required_argument, 0, 'g'}, 158
173 {"players-field", required_argument, 0, 129}, 159 if (argc < 2)
174 {"max-players-field", required_argument, 0, 130}, 160 return ERROR;
175 {0, 0, 0, 0} 161
176 }; 162 for (c = 1; c < argc; c++) {
177 163 if (strcmp("-mf", argv[c]) == 0)
178 if (argc < 2) 164 strcpy(argv[c], "-m");
179 return ERROR; 165 else if (strcmp("-pf", argv[c]) == 0)
180 166 strcpy(argv[c], "-p");
181 for (c = 1; c < argc; c++) { 167 else if (strcmp("-gf", argv[c]) == 0)
182 if (strcmp ("-mf", argv[c]) == 0) 168 strcpy(argv[c], "-g");
183 strcpy (argv[c], "-m"); 169 }
184 else if (strcmp ("-pf", argv[c]) == 0) 170
185 strcpy (argv[c], "-p"); 171 while (1) {
186 else if (strcmp ("-gf", argv[c]) == 0) 172 c = getopt_long(argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
187 strcpy (argv[c], "-g"); 173
188 } 174 if (c == -1 || c == EOF)
189 175 break;
190 while (1) { 176
191 c = getopt_long (argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index); 177 switch (c) {
192 178 case 'h': /* help */
193 if (c == -1 || c == EOF) 179 print_help();
194 break; 180 exit(STATE_UNKNOWN);
195 181 case 'V': /* version */
196 switch (c) { 182 print_revision(progname, NP_VERSION);
197 case 'h': /* help */ 183 exit(STATE_UNKNOWN);
198 print_help (); 184 case 'v': /* version */
199 exit (STATE_UNKNOWN); 185 verbose = true;
200 case 'V': /* version */ 186 break;
201 print_revision (progname, NP_VERSION); 187 case 't': /* timeout period */
202 exit (STATE_UNKNOWN); 188 timeout_interval = atoi(optarg);
203 case 'v': /* version */ 189 break;
204 verbose = true; 190 case 'H': /* hostname */
205 break; 191 if (strlen(optarg) >= MAX_HOST_ADDRESS_LENGTH)
206 case 't': /* timeout period */ 192 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
207 timeout_interval = atoi (optarg); 193 server_ip = optarg;
208 break; 194 break;
209 case 'H': /* hostname */ 195 case 'P': /* port */
210 if (strlen (optarg) >= MAX_HOST_ADDRESS_LENGTH) 196 port = atoi(optarg);
211 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 197 break;
212 server_ip = optarg; 198 case 'G': /* hostname */
213 break; 199 if (strlen(optarg) >= MAX_INPUT_BUFFER)
214 case 'P': /* port */ 200 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
215 port = atoi (optarg); 201 game_type = optarg;
216 break; 202 break;
217 case 'G': /* hostname */ 203 case 'p': /* index of ping field */
218 if (strlen (optarg) >= MAX_INPUT_BUFFER) 204 qstat_ping_field = atoi(optarg);
219 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 205 if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
220 game_type = optarg; 206 return ERROR;
221 break; 207 break;
222 case 'p': /* index of ping field */ 208 case 'm': /* index on map field */
223 qstat_ping_field = atoi (optarg); 209 qstat_map_field = atoi(optarg);
224 if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS) 210 if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
225 return ERROR; 211 return ERROR;
226 break; 212 break;
227 case 'm': /* index on map field */ 213 case 'g': /* index of game field */
228 qstat_map_field = atoi (optarg); 214 qstat_game_field = atoi(optarg);
229 if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS) 215 if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
230 return ERROR; 216 return ERROR;
231 break; 217 break;
232 case 'g': /* index of game field */ 218 case 129: /* index of player count field */
233 qstat_game_field = atoi (optarg); 219 qstat_game_players = atoi(optarg);
234 if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS) 220 if (qstat_game_players_max == 0)
235 return ERROR; 221 qstat_game_players_max = qstat_game_players - 1;
236 break; 222 if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS)
237 case 129: /* index of player count field */ 223 return ERROR;
238 qstat_game_players = atoi (optarg); 224 break;
239 if (qstat_game_players_max == 0) 225 case 130: /* index of max players field */
240 qstat_game_players_max = qstat_game_players - 1; 226 qstat_game_players_max = atoi(optarg);
241 if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS) 227 if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS)
242 return ERROR; 228 return ERROR;
243 break; 229 break;
244 case 130: /* index of max players field */ 230 default: /* args not parsable */
245 qstat_game_players_max = atoi (optarg); 231 usage5();
246 if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS) 232 }
247 return ERROR; 233 }
248 break; 234
249 default: /* args not parsable */ 235 c = optind;
250 usage5(); 236 /* first option is the game type */
251 } 237 if (!game_type && c < argc)
252 } 238 game_type = strdup(argv[c++]);
253 239
254 c = optind; 240 /* Second option is the server name */
255 /* first option is the game type */ 241 if (!server_ip && c < argc)
256 if (!game_type && c<argc) 242 server_ip = strdup(argv[c++]);
257 game_type = strdup (argv[c++]); 243
258 244 return validate_arguments();
259 /* Second option is the server name */
260 if (!server_ip && c<argc)
261 server_ip = strdup (argv[c++]);
262
263 return validate_arguments ();
264} 245}
265 246
247int validate_arguments(void) {
248 if (qstat_game_players_max < 0)
249 qstat_game_players_max = 4;
266 250
267int 251 if (qstat_game_players < 0)
268validate_arguments (void) 252 qstat_game_players = 5;
269{
270 if (qstat_game_players_max < 0)
271 qstat_game_players_max = 4;
272 253
273 if (qstat_game_players < 0) 254 if (qstat_game_field < 0)
274 qstat_game_players = 5; 255 qstat_game_field = 2;
275 256
276 if (qstat_game_field < 0) 257 if (qstat_map_field < 0)
277 qstat_game_field = 2; 258 qstat_map_field = 3;
278 259
279 if (qstat_map_field < 0) 260 if (qstat_ping_field < 0)
280 qstat_map_field = 3; 261 qstat_ping_field = 5;
281 262
282 if (qstat_ping_field < 0) 263 return OK;
283 qstat_ping_field = 5;
284
285 return OK;
286} 264}
287 265
266void print_help(void) {
267 print_revision(progname, NP_VERSION);
288 268
289void 269 printf("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
290print_help (void) 270 printf(COPYRIGHT, copyright, email);
291{
292 print_revision (progname, NP_VERSION);
293
294 printf ("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
295 printf (COPYRIGHT, copyright, email);
296 271
297 printf (_("This plugin tests game server connections with the specified host.")); 272 printf(_("This plugin tests game server connections with the specified host."));
298 273
299 printf ("\n\n"); 274 printf("\n\n");
300 275
301 print_usage (); 276 print_usage();
302 277
303 printf (UT_HELP_VRSN); 278 printf(UT_HELP_VRSN);
304 printf (UT_EXTRA_OPTS); 279 printf(UT_EXTRA_OPTS);
305 280
306 printf (" %s\n", "-p"); 281 printf(" %s\n", "-p");
307 printf (" %s\n", _("Optional port of which to connect")); 282 printf(" %s\n", _("Optional port of which to connect"));
308 printf (" %s\n", "gf"); 283 printf(" %s\n", "gf");
309 printf (" %s\n", _("Field number in raw qstat output that contains game name")); 284 printf(" %s\n", _("Field number in raw qstat output that contains game name"));
310 printf (" %s\n", "-mf"); 285 printf(" %s\n", "-mf");
311 printf (" %s\n", _("Field number in raw qstat output that contains map name")); 286 printf(" %s\n", _("Field number in raw qstat output that contains map name"));
312 printf (" %s\n", "-pf"); 287 printf(" %s\n", "-pf");
313 printf (" %s\n", _("Field number in raw qstat output that contains ping time")); 288 printf(" %s\n", _("Field number in raw qstat output that contains ping time"));
314 289
315 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 290 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
316 291
317 printf ("\n"); 292 printf("\n");
318 printf ("%s\n", _("Notes:")); 293 printf("%s\n", _("Notes:"));
319 printf (" %s\n", _("This plugin uses the 'qstat' command, the popular game server status query tool.")); 294 printf(" %s\n", _("This plugin uses the 'qstat' command, the popular game server status query tool."));
320 printf (" %s\n", _("If you don't have the package installed, you will need to download it from")); 295 printf(" %s\n", _("If you don't have the package installed, you will need to download it from"));
321 printf (" %s\n", _("https://github.com/multiplay/qstat before you can use this plugin.")); 296 printf(" %s\n", _("https://github.com/multiplay/qstat before you can use this plugin."));
322 297
323 printf (UT_SUPPORT); 298 printf(UT_SUPPORT);
324} 299}
325 300
326 301void print_usage(void) {
327 302 printf("%s\n", _("Usage:"));
328void 303 printf(" %s [-hvV] [-P port] [-t timeout] [-g game_field] [-m map_field] [-p ping_field] [-G game-time] [-H hostname] <game> "
329print_usage (void) 304 "<ip_address>\n",
330{ 305 progname);
331 printf ("%s\n", _("Usage:"));
332 printf (" %s [-hvV] [-P port] [-t timeout] [-g game_field] [-m map_field] [-p ping_field] [-G game-time] [-H hostname] <game> <ip_address>\n", progname);
333} 306}
334 307
335/****************************************************************************** 308/******************************************************************************
diff --git a/plugins/check_hpjd.c b/plugins/check_hpjd.c
index c34bb082..b39bccff 100644
--- a/plugins/check_hpjd.c
+++ b/plugins/check_hpjd.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_hpjd plugin 3 * Monitoring check_hpjd plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_hpjd plugin 10 * This file contains the check_hpjd plugin
11* 11 *
12* This plugin tests the STATUS of an HP printer with a JetDirect card. 12 * This plugin tests the STATUS of an HP printer with a JetDirect card.
13* Net-SNMP must be installed on the computer running the plugin. 13 * Net-SNMP must be installed on the computer running the plugin.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_hpjd"; 32const char *progname = "check_hpjd";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -39,9 +39,7 @@ const char *email = "devel@monitoring-plugins.org";
39#include "netutils.h" 39#include "netutils.h"
40 40
41#define DEFAULT_COMMUNITY "public" 41#define DEFAULT_COMMUNITY "public"
42#define DEFAULT_PORT "161" 42#define DEFAULT_PORT "161"
43
44const char *option_summary = "-H host [-C community]\n";
45 43
46#define HPJD_LINE_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.1" 44#define HPJD_LINE_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.1"
47#define HPJD_PAPER_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.2" 45#define HPJD_PAPER_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.2"
@@ -56,22 +54,20 @@ const char *option_summary = "-H host [-C community]\n";
56#define HPJD_GD_PAPER_OUTPUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.19" 54#define HPJD_GD_PAPER_OUTPUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.19"
57#define HPJD_GD_STATUS_DISPLAY ".1.3.6.1.4.1.11.2.3.9.1.1.3" 55#define HPJD_GD_STATUS_DISPLAY ".1.3.6.1.4.1.11.2.3.9.1.1.3"
58 56
59#define ONLINE 0 57#define ONLINE 0
60#define OFFLINE 1 58#define OFFLINE 1
61 59
62int process_arguments (int, char **); 60static int process_arguments(int /*argc*/, char ** /*argv*/);
63int validate_arguments (void); 61static int validate_arguments(void);
64void print_help (void); 62static void print_help(void);
65void print_usage (void); 63void print_usage(void);
66 64
67char *community = NULL; 65static char *community = NULL;
68char *address = NULL; 66static char *address = NULL;
69unsigned int port = 0; 67static unsigned int port = 0;
70int check_paper_out = 1; 68static int check_paper_out = 1;
71 69
72int 70int main(int argc, char **argv) {
73main (int argc, char **argv)
74{
75 char command_line[1024]; 71 char command_line[1024];
76 int result = STATE_UNKNOWN; 72 int result = STATE_UNKNOWN;
77 int line; 73 int line;
@@ -94,116 +90,99 @@ main (int argc, char **argv)
94 90
95 errmsg = malloc(MAX_INPUT_BUFFER); 91 errmsg = malloc(MAX_INPUT_BUFFER);
96 92
97 setlocale (LC_ALL, ""); 93 setlocale(LC_ALL, "");
98 bindtextdomain (PACKAGE, LOCALEDIR); 94 bindtextdomain(PACKAGE, LOCALEDIR);
99 textdomain (PACKAGE); 95 textdomain(PACKAGE);
100 96
101 /* Parse extra opts if any */ 97 /* Parse extra opts if any */
102 argv=np_extra_opts (&argc, argv, progname); 98 argv = np_extra_opts(&argc, argv, progname);
103 99
104 if (process_arguments (argc, argv) == ERROR) 100 if (process_arguments(argc, argv) == ERROR)
105 usage4 (_("Could not parse arguments")); 101 usage4(_("Could not parse arguments"));
106 102
107 /* removed ' 2>1' at end of command 10/27/1999 - EG */ 103 /* removed ' 2>1' at end of command 10/27/1999 - EG */
108 /* create the query string */ 104 /* create the query string */
109 sprintf 105 sprintf(query_string, "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", HPJD_LINE_STATUS, HPJD_PAPER_STATUS,
110 (query_string, 106 HPJD_INTERVENTION_REQUIRED, HPJD_GD_PERIPHERAL_ERROR, HPJD_GD_PAPER_JAM, HPJD_GD_PAPER_OUT, HPJD_GD_TONER_LOW,
111 "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", 107 HPJD_GD_PAGE_PUNT, HPJD_GD_MEMORY_OUT, HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
112 HPJD_LINE_STATUS,
113 HPJD_PAPER_STATUS,
114 HPJD_INTERVENTION_REQUIRED,
115 HPJD_GD_PERIPHERAL_ERROR,
116 HPJD_GD_PAPER_JAM,
117 HPJD_GD_PAPER_OUT,
118 HPJD_GD_TONER_LOW,
119 HPJD_GD_PAGE_PUNT,
120 HPJD_GD_MEMORY_OUT,
121 HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
122 108
123 /* get the command to run */ 109 /* get the command to run */
124 sprintf (command_line, "%s -OQa -m : -v 1 -c %s %s:%u %s", 110 sprintf(command_line, "%s -OQa -m : -v 1 -c %s %s:%u %s", PATH_TO_SNMPGET, community, address, port, query_string);
125 PATH_TO_SNMPGET,
126 community,
127 address,
128 port,
129 query_string);
130 111
131 /* run the command */ 112 /* run the command */
132 child_process = spopen (command_line); 113 child_process = spopen(command_line);
133 if (child_process == NULL) { 114 if (child_process == NULL) {
134 printf (_("Could not open pipe: %s\n"), command_line); 115 printf(_("Could not open pipe: %s\n"), command_line);
135 return STATE_UNKNOWN; 116 return STATE_UNKNOWN;
136 } 117 }
137 118
138 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 119 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
139 if (child_stderr == NULL) { 120 if (child_stderr == NULL) {
140 printf (_("Could not open stderr for %s\n"), command_line); 121 printf(_("Could not open stderr for %s\n"), command_line);
141 } 122 }
142 123
143 result = STATE_OK; 124 result = STATE_OK;
144 125
145 line = 0; 126 line = 0;
146 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 127 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
147 128
148 /* strip the newline character from the end of the input */ 129 /* strip the newline character from the end of the input */
149 if (input_buffer[strlen (input_buffer) - 1] == '\n') 130 if (input_buffer[strlen(input_buffer) - 1] == '\n')
150 input_buffer[strlen (input_buffer) - 1] = 0; 131 input_buffer[strlen(input_buffer) - 1] = 0;
151 132
152 line++; 133 line++;
153 134
154 temp_buffer = strtok (input_buffer, "="); 135 temp_buffer = strtok(input_buffer, "=");
155 temp_buffer = strtok (NULL, "="); 136 temp_buffer = strtok(NULL, "=");
156 137
157 if (temp_buffer == NULL && line < 13) { 138 if (temp_buffer == NULL && line < 13) {
158 139
159 result = STATE_UNKNOWN; 140 result = STATE_UNKNOWN;
160 strcpy (errmsg, input_buffer); 141 strcpy(errmsg, input_buffer);
161 142
162 } else { 143 } else {
163 144
164 switch (line) { 145 switch (line) {
165 146
166 case 1: /* 1st line should contain the line status */ 147 case 1: /* 1st line should contain the line status */
167 line_status = atoi (temp_buffer); 148 line_status = atoi(temp_buffer);
168 break; 149 break;
169 case 2: /* 2nd line should contain the paper status */ 150 case 2: /* 2nd line should contain the paper status */
170 paper_status = atoi (temp_buffer); 151 paper_status = atoi(temp_buffer);
171 break; 152 break;
172 case 3: /* 3rd line should be intervention required */ 153 case 3: /* 3rd line should be intervention required */
173 intervention_required = atoi (temp_buffer); 154 intervention_required = atoi(temp_buffer);
174 break; 155 break;
175 case 4: /* 4th line should be peripheral error */ 156 case 4: /* 4th line should be peripheral error */
176 peripheral_error = atoi (temp_buffer); 157 peripheral_error = atoi(temp_buffer);
177 break; 158 break;
178 case 5: /* 5th line should contain the paper jam status */ 159 case 5: /* 5th line should contain the paper jam status */
179 paper_jam = atoi (temp_buffer); 160 paper_jam = atoi(temp_buffer);
180 break; 161 break;
181 case 6: /* 6th line should contain the paper out status */ 162 case 6: /* 6th line should contain the paper out status */
182 paper_out = atoi (temp_buffer); 163 paper_out = atoi(temp_buffer);
183 break; 164 break;
184 case 7: /* 7th line should contain the toner low status */ 165 case 7: /* 7th line should contain the toner low status */
185 toner_low = atoi (temp_buffer); 166 toner_low = atoi(temp_buffer);
186 break; 167 break;
187 case 8: /* did data come too slow for engine */ 168 case 8: /* did data come too slow for engine */
188 page_punt = atoi (temp_buffer); 169 page_punt = atoi(temp_buffer);
189 break; 170 break;
190 case 9: /* did we run out of memory */ 171 case 9: /* did we run out of memory */
191 memory_out = atoi (temp_buffer); 172 memory_out = atoi(temp_buffer);
192 break; 173 break;
193 case 10: /* is there a door open */ 174 case 10: /* is there a door open */
194 door_open = atoi (temp_buffer); 175 door_open = atoi(temp_buffer);
195 break; 176 break;
196 case 11: /* is output tray full */ 177 case 11: /* is output tray full */
197 paper_output = atoi (temp_buffer); 178 paper_output = atoi(temp_buffer);
198 break; 179 break;
199 case 12: /* display panel message */ 180 case 12: /* display panel message */
200 strcpy (display_message, temp_buffer + 1); 181 strcpy(display_message, temp_buffer + 1);
201 break; 182 break;
202 default: /* fold multiline message */ 183 default: /* fold multiline message */
203 strncat (display_message, input_buffer, 184 strncat(display_message, input_buffer, sizeof(display_message) - strlen(display_message) - 1);
204 sizeof (display_message) - strlen (display_message) - 1);
205 } 185 }
206
207 } 186 }
208 187
209 /* break out of the read loop if we encounter an error */ 188 /* break out of the read loop if we encounter an error */
@@ -212,29 +191,27 @@ main (int argc, char **argv)
212 } 191 }
213 192
214 /* WARNING if output found on stderr */ 193 /* WARNING if output found on stderr */
215 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { 194 if (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
216 result = max_state (result, STATE_WARNING); 195 result = max_state(result, STATE_WARNING);
217 /* remove CRLF */ 196 /* remove CRLF */
218 if (input_buffer[strlen (input_buffer) - 1] == '\n') 197 if (input_buffer[strlen(input_buffer) - 1] == '\n')
219 input_buffer[strlen (input_buffer) - 1] = 0; 198 input_buffer[strlen(input_buffer) - 1] = 0;
220 sprintf (errmsg, "%s", input_buffer ); 199 sprintf(errmsg, "%s", input_buffer);
221
222 } 200 }
223 201
224 /* close stderr */ 202 /* close stderr */
225 (void) fclose (child_stderr); 203 (void)fclose(child_stderr);
226 204
227 /* close the pipe */ 205 /* close the pipe */
228 if (spclose (child_process)) 206 if (spclose(child_process))
229 result = max_state (result, STATE_WARNING); 207 result = max_state(result, STATE_WARNING);
230 208
231 /* if there wasn't any output, display an error */ 209 /* if there wasn't any output, display an error */
232 if (line == 0) { 210 if (line == 0) {
233 211
234 /* might not be the problem, but most likely is. */ 212 /* might not be the problem, but most likely is. */
235 result = STATE_UNKNOWN ; 213 result = STATE_UNKNOWN;
236 xasprintf (&errmsg, "%s : Timeout from host %s\n", errmsg, address ); 214 xasprintf(&errmsg, "%s : Timeout from host %s\n", errmsg, address);
237
238 } 215 }
239 216
240 /* if we had no read errors, check the printer status results... */ 217 /* if we had no read errors, check the printer status results... */
@@ -242,201 +219,171 @@ main (int argc, char **argv)
242 219
243 if (paper_jam) { 220 if (paper_jam) {
244 result = STATE_WARNING; 221 result = STATE_WARNING;
245 strcpy (errmsg, _("Paper Jam")); 222 strcpy(errmsg, _("Paper Jam"));
246 } 223 } else if (paper_out) {
247 else if (paper_out) {
248 if (check_paper_out) 224 if (check_paper_out)
249 result = STATE_WARNING; 225 result = STATE_WARNING;
250 strcpy (errmsg, _("Out of Paper")); 226 strcpy(errmsg, _("Out of Paper"));
251 } 227 } else if (line_status == OFFLINE) {
252 else if (line_status == OFFLINE) { 228 if (strcmp(errmsg, "POWERSAVE ON") != 0) {
253 if (strcmp (errmsg, "POWERSAVE ON") != 0) {
254 result = STATE_WARNING; 229 result = STATE_WARNING;
255 strcpy (errmsg, _("Printer Offline")); 230 strcpy(errmsg, _("Printer Offline"));
256 } 231 }
257 } 232 } else if (peripheral_error) {
258 else if (peripheral_error) {
259 result = STATE_WARNING; 233 result = STATE_WARNING;
260 strcpy (errmsg, _("Peripheral Error")); 234 strcpy(errmsg, _("Peripheral Error"));
261 } 235 } else if (intervention_required) {
262 else if (intervention_required) {
263 result = STATE_WARNING; 236 result = STATE_WARNING;
264 strcpy (errmsg, _("Intervention Required")); 237 strcpy(errmsg, _("Intervention Required"));
265 } 238 } else if (toner_low) {
266 else if (toner_low) {
267 result = STATE_WARNING; 239 result = STATE_WARNING;
268 strcpy (errmsg, _("Toner Low")); 240 strcpy(errmsg, _("Toner Low"));
269 } 241 } else if (memory_out) {
270 else if (memory_out) {
271 result = STATE_WARNING; 242 result = STATE_WARNING;
272 strcpy (errmsg, _("Insufficient Memory")); 243 strcpy(errmsg, _("Insufficient Memory"));
273 } 244 } else if (door_open) {
274 else if (door_open) {
275 result = STATE_WARNING; 245 result = STATE_WARNING;
276 strcpy (errmsg, _("A Door is Open")); 246 strcpy(errmsg, _("A Door is Open"));
277 } 247 } else if (paper_output) {
278 else if (paper_output) {
279 result = STATE_WARNING; 248 result = STATE_WARNING;
280 strcpy (errmsg, _("Output Tray is Full")); 249 strcpy(errmsg, _("Output Tray is Full"));
281 } 250 } else if (page_punt) {
282 else if (page_punt) {
283 result = STATE_WARNING; 251 result = STATE_WARNING;
284 strcpy (errmsg, _("Data too Slow for Engine")); 252 strcpy(errmsg, _("Data too Slow for Engine"));
285 } 253 } else if (paper_status) {
286 else if (paper_status) {
287 result = STATE_WARNING; 254 result = STATE_WARNING;
288 strcpy (errmsg, _("Unknown Paper Error")); 255 strcpy(errmsg, _("Unknown Paper Error"));
289 } 256 }
290 } 257 }
291 258
292 if (result == STATE_OK) 259 if (result == STATE_OK)
293 printf (_("Printer ok - (%s)\n"), display_message); 260 printf(_("Printer ok - (%s)\n"), display_message);
294 261
295 else if (result == STATE_UNKNOWN) { 262 else if (result == STATE_UNKNOWN) {
296 263
297 printf ("%s\n", errmsg); 264 printf("%s\n", errmsg);
298 265
299 /* if printer could not be reached, escalate to critical */ 266 /* if printer could not be reached, escalate to critical */
300 if (strstr (errmsg, "Timeout")) 267 if (strstr(errmsg, "Timeout"))
301 result = STATE_CRITICAL; 268 result = STATE_CRITICAL;
302 } 269 }
303 270
304 else if (result == STATE_WARNING) 271 else if (result == STATE_WARNING)
305 printf ("%s (%s)\n", errmsg, display_message); 272 printf("%s (%s)\n", errmsg, display_message);
306 273
307 return result; 274 return result;
308} 275}
309 276
310
311/* process command-line arguments */ 277/* process command-line arguments */
312int 278int process_arguments(int argc, char **argv) {
313process_arguments (int argc, char **argv)
314{
315 int c; 279 int c;
316 280
317 int option = 0; 281 int option = 0;
318 static struct option longopts[] = { 282 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
319 {"hostname", required_argument, 0, 'H'}, 283 {"community", required_argument, 0, 'C'},
320 {"community", required_argument, 0, 'C'}, 284 /* {"critical", required_argument,0,'c'}, */
321/* {"critical", required_argument,0,'c'}, */ 285 /* {"warning", required_argument,0,'w'}, */
322/* {"warning", required_argument,0,'w'}, */ 286 {"port", required_argument, 0, 'p'},
323 {"port", required_argument,0,'p'}, 287 {"version", no_argument, 0, 'V'},
324 {"version", no_argument, 0, 'V'}, 288 {"help", no_argument, 0, 'h'},
325 {"help", no_argument, 0, 'h'}, 289 {0, 0, 0, 0}};
326 {0, 0, 0, 0}
327 };
328 290
329 if (argc < 2) 291 if (argc < 2)
330 return ERROR; 292 return ERROR;
331 293
332
333 while (1) { 294 while (1) {
334 c = getopt_long (argc, argv, "+hVH:C:p:D", longopts, &option); 295 c = getopt_long(argc, argv, "+hVH:C:p:D", longopts, &option);
335 296
336 if (c == -1 || c == EOF || c == 1) 297 if (c == -1 || c == EOF || c == 1)
337 break; 298 break;
338 299
339 switch (c) { 300 switch (c) {
340 case 'H': /* hostname */ 301 case 'H': /* hostname */
341 if (is_host (optarg)) { 302 if (is_host(optarg)) {
342 address = strscpy(address, optarg) ; 303 address = strscpy(address, optarg);
343 } 304 } else {
344 else { 305 usage2(_("Invalid hostname/address"), optarg);
345 usage2 (_("Invalid hostname/address"), optarg);
346 } 306 }
347 break; 307 break;
348 case 'C': /* community */ 308 case 'C': /* community */
349 community = strscpy (community, optarg); 309 community = strscpy(community, optarg);
350 break; 310 break;
351 case 'p': 311 case 'p':
352 if (!is_intpos(optarg)) 312 if (!is_intpos(optarg))
353 usage2 (_("Port must be a positive short integer"), optarg); 313 usage2(_("Port must be a positive short integer"), optarg);
354 else 314 else
355 port = atoi(optarg); 315 port = atoi(optarg);
356 break; 316 break;
357 case 'D': /* disable paper out check*/ 317 case 'D': /* disable paper out check*/
358 check_paper_out = 0; 318 check_paper_out = 0;
359 break; 319 break;
360 case 'V': /* version */ 320 case 'V': /* version */
361 print_revision (progname, NP_VERSION); 321 print_revision(progname, NP_VERSION);
362 exit (STATE_UNKNOWN); 322 exit(STATE_UNKNOWN);
363 case 'h': /* help */ 323 case 'h': /* help */
364 print_help (); 324 print_help();
365 exit (STATE_UNKNOWN); 325 exit(STATE_UNKNOWN);
366 case '?': /* help */ 326 case '?': /* help */
367 usage5 (); 327 usage5();
368 } 328 }
369 } 329 }
370 330
371 c = optind; 331 c = optind;
372 if (address == NULL) { 332 if (address == NULL) {
373 if (is_host (argv[c])) { 333 if (is_host(argv[c])) {
374 address = argv[c++]; 334 address = argv[c++];
375 } 335 } else {
376 else { 336 usage2(_("Invalid hostname/address"), argv[c]);
377 usage2 (_("Invalid hostname/address"), argv[c]);
378 } 337 }
379 } 338 }
380 339
381 if (community == NULL) { 340 if (community == NULL) {
382 if (argv[c] != NULL ) 341 if (argv[c] != NULL)
383 community = argv[c]; 342 community = argv[c];
384 else 343 else
385 community = strdup (DEFAULT_COMMUNITY); 344 community = strdup(DEFAULT_COMMUNITY);
386 } 345 }
387 346
388 if (port == 0) { 347 if (port == 0) {
389 port = atoi(DEFAULT_PORT); 348 port = atoi(DEFAULT_PORT);
390 } 349 }
391 350
392 return validate_arguments (); 351 return validate_arguments();
393}
394
395
396int
397validate_arguments (void)
398{
399 return OK;
400} 352}
401 353
354int validate_arguments(void) { return OK; }
402 355
403void 356void print_help(void) {
404print_help (void) 357 print_revision(progname, NP_VERSION);
405{
406 print_revision (progname, NP_VERSION);
407 358
408 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 359 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
409 printf (COPYRIGHT, copyright, email); 360 printf(COPYRIGHT, copyright, email);
410 361
411 printf ("%s\n", _("This plugin tests the STATUS of an HP printer with a JetDirect card.")); 362 printf("%s\n", _("This plugin tests the STATUS of an HP printer with a JetDirect card."));
412 printf ("%s\n", _("Net-snmp must be installed on the computer running the plugin.")); 363 printf("%s\n", _("Net-snmp must be installed on the computer running the plugin."));
413 364
414 printf ("\n\n"); 365 printf("\n\n");
415 366
416 print_usage (); 367 print_usage();
417 368
418 printf (UT_HELP_VRSN); 369 printf(UT_HELP_VRSN);
419 printf (UT_EXTRA_OPTS); 370 printf(UT_EXTRA_OPTS);
420 371
421 printf (" %s\n", "-C, --community=STRING"); 372 printf(" %s\n", "-C, --community=STRING");
422 printf (" %s", _("The SNMP community name ")); 373 printf(" %s", _("The SNMP community name "));
423 printf (_("(default=%s)"), DEFAULT_COMMUNITY); 374 printf(_("(default=%s)"), DEFAULT_COMMUNITY);
424 printf ("\n"); 375 printf("\n");
425 printf (" %s\n", "-p, --port=STRING"); 376 printf(" %s\n", "-p, --port=STRING");
426 printf (" %s", _("Specify the port to check ")); 377 printf(" %s", _("Specify the port to check "));
427 printf (_("(default=%s)"), DEFAULT_PORT); 378 printf(_("(default=%s)"), DEFAULT_PORT);
428 printf ("\n"); 379 printf("\n");
429 printf (" %s\n", "-D"); 380 printf(" %s\n", "-D");
430 printf (" %s", _("Disable paper check ")); 381 printf(" %s", _("Disable paper check "));
431 382
432 printf (UT_SUPPORT); 383 printf(UT_SUPPORT);
433} 384}
434 385
435 386void print_usage(void) {
436 387 printf("%s\n", _("Usage:"));
437void 388 printf("%s -H host [-C community] [-p port] [-D]\n", progname);
438print_usage (void)
439{
440 printf ("%s\n", _("Usage:"));
441 printf ("%s -H host [-C community] [-p port] [-D]\n", progname);
442} 389}
diff --git a/plugins/check_http.c b/plugins/check_http.c
index cdf768c9..97c0e39a 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -3,7 +3,7 @@
3* Monitoring check_http plugin 3* Monitoring check_http plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 1999-2013 Monitoring Plugins Development Team 6* Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -32,7 +32,7 @@
32*****************************************************************************/ 32*****************************************************************************/
33 33
34const char *progname = "check_http"; 34const char *progname = "check_http";
35const char *copyright = "1999-2022"; 35const char *copyright = "1999-2024";
36const char *email = "devel@monitoring-plugins.org"; 36const char *email = "devel@monitoring-plugins.org";
37 37
38// Do NOT sort those headers, it will break the build 38// Do NOT sort those headers, it will break the build
diff --git a/plugins/check_ide_smart.c b/plugins/check_ide_smart.c
index 3872e341..381dbd80 100644
--- a/plugins/check_ide_smart.c
+++ b/plugins/check_ide_smart.c
@@ -1,112 +1,105 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ide_smart plugin 3 * Monitoring check_ide_smart plugin
4* ide-smart 1.3 - IDE S.M.A.R.T. checking tool 4 * ide-smart 1.3 - IDE S.M.A.R.T. checking tool
5* 5 *
6* License: GPL 6 * License: GPL
7* Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org> 7 * Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>
8* 1998 Gadi Oxman <gadio@netvision.net.il> 8 * 1998 Gadi Oxman <gadio@netvision.net.il>
9* Copyright (c) 2000 Robert Dale <rdale@digital-mission.com> 9 * Copyright (c) 2000 Robert Dale <rdale@digital-mission.com>
10* Copyright (c) 2000-2007 Monitoring Plugins Development Team 10 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
11* 11 *
12* Description: 12 * Description:
13* 13 *
14* This file contains the check_ide_smart plugin 14 * This file contains the check_ide_smart plugin
15* 15 *
16* This plugin checks a local hard drive with the (Linux specific) SMART 16 * This plugin checks a local hard drive with the (Linux specific) SMART
17* interface 17 * interface
18* 18 *
19* 19 *
20* This program is free software: you can redistribute it and/or modify 20 * This program is free software: you can redistribute it and/or modify
21* it under the terms of the GNU General Public License as published by 21 * it under the terms of the GNU General Public License as published by
22* the Free Software Foundation, either version 3 of the License, or 22 * the Free Software Foundation, either version 3 of the License, or
23* (at your option) any later version. 23 * (at your option) any later version.
24* 24 *
25* This program is distributed in the hope that it will be useful, 25 * This program is distributed in the hope that it will be useful,
26* but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28* GNU General Public License for more details. 28 * GNU General Public License for more details.
29* 29 *
30* You should have received a copy of the GNU General Public License 30 * You should have received a copy of the GNU General Public License
31* along with this program. If not, see <http://www.gnu.org/licenses/>. 31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32* 32 *
33* 33 *
34*****************************************************************************/ 34 *****************************************************************************/
35 35
36const char *progname = "check_ide_smart"; 36const char *progname = "check_ide_smart";
37const char *copyright = "1998-2007"; 37const char *copyright = "1998-2024";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include "common.h" 40#include "common.h"
41#include "utils.h" 41#include "utils.h"
42 42
43void print_help (void); 43static void print_help(void);
44void print_usage (void); 44void print_usage(void);
45 45
46#include <sys/stat.h> 46#include <sys/stat.h>
47#include <sys/ioctl.h> 47#include <sys/ioctl.h>
48#include <fcntl.h> 48#include <fcntl.h>
49#ifdef __linux__ 49#ifdef __linux__
50#include <linux/hdreg.h> 50# include <linux/hdreg.h>
51#include <linux/types.h> 51# include <linux/types.h>
52 52
53#define OPEN_MODE O_RDONLY 53# define OPEN_MODE O_RDONLY
54#endif /* __linux__ */ 54#endif /* __linux__ */
55#ifdef __NetBSD__ 55#ifdef __NetBSD__
56#include <sys/device.h> 56# include <sys/device.h>
57#include <sys/param.h> 57# include <sys/param.h>
58#include <sys/sysctl.h> 58# include <sys/sysctl.h>
59#include <sys/videoio.h> /* for __u8 and friends */ 59# include <sys/videoio.h> /* for __u8 and friends */
60#include <sys/scsiio.h> 60# include <sys/scsiio.h>
61#include <sys/ataio.h> 61# include <sys/ataio.h>
62#include <dev/ata/atareg.h> 62# include <dev/ata/atareg.h>
63#include <dev/ic/wdcreg.h> 63# include <dev/ic/wdcreg.h>
64 64
65#define SMART_ENABLE WDSM_ENABLE_OPS 65# define SMART_ENABLE WDSM_ENABLE_OPS
66#define SMART_DISABLE WDSM_DISABLE_OPS 66# define SMART_DISABLE WDSM_DISABLE_OPS
67#define SMART_IMMEDIATE_OFFLINE WDSM_EXEC_OFFL_IMM 67# define SMART_IMMEDIATE_OFFLINE WDSM_EXEC_OFFL_IMM
68#define SMART_AUTO_OFFLINE 0xdb /* undefined in NetBSD headers */ 68# define SMART_AUTO_OFFLINE 0xdb /* undefined in NetBSD headers */
69 69
70#define OPEN_MODE O_RDWR 70# define OPEN_MODE O_RDWR
71#endif /* __NetBSD__ */ 71#endif /* __NetBSD__ */
72#include <errno.h> 72#include <errno.h>
73 73
74#define NR_ATTRIBUTES 30 74#define NR_ATTRIBUTES 30
75 75
76#define PREFAILURE 2 76#define PREFAILURE 2
77#define ADVISORY 1 77#define ADVISORY 1
78#define OPERATIONAL 0 78#define OPERATIONAL 0
79#define UNKNOWN -1 79#define UNKNOWN -1
80 80
81typedef struct threshold_s 81typedef struct threshold_s {
82{
83 __u8 id; 82 __u8 id;
84 __u8 threshold; 83 __u8 threshold;
85 __u8 reserved[10]; 84 __u8 reserved[10];
86} 85} __attribute__((packed)) threshold_t;
87__attribute__ ((packed)) threshold_t;
88 86
89typedef struct thresholds_s 87typedef struct thresholds_s {
90{
91 __u16 revision; 88 __u16 revision;
92 threshold_t thresholds[NR_ATTRIBUTES]; 89 threshold_t thresholds[NR_ATTRIBUTES];
93 __u8 reserved[18]; 90 __u8 reserved[18];
94 __u8 vendor[131]; 91 __u8 vendor[131];
95 __u8 checksum; 92 __u8 checksum;
96} 93} __attribute__((packed)) thresholds_t;
97__attribute__ ((packed)) thresholds_t;
98 94
99typedef struct value_s 95typedef struct value_s {
100{
101 __u8 id; 96 __u8 id;
102 __u16 status; 97 __u16 status;
103 __u8 value; 98 __u8 value;
104 __u8 vendor[8]; 99 __u8 vendor[8];
105} 100} __attribute__((packed)) value_t;
106__attribute__ ((packed)) value_t;
107 101
108typedef struct values_s 102typedef struct values_s {
109{
110 __u16 revision; 103 __u16 revision;
111 value_t values[NR_ATTRIBUTES]; 104 value_t values[NR_ATTRIBUTES];
112 __u8 offline_status; 105 __u8 offline_status;
@@ -118,90 +111,71 @@ typedef struct values_s
118 __u8 reserved[16]; 111 __u8 reserved[16];
119 __u8 vendor[125]; 112 __u8 vendor[125];
120 __u8 checksum; 113 __u8 checksum;
121} 114} __attribute__((packed)) values_t;
122__attribute__ ((packed)) values_t;
123 115
124struct 116struct {
125{
126 __u8 value; 117 __u8 value;
127 char *text; 118 char *text;
128} 119}
129 120
130offline_status_text[] = 121static offline_status_text[] = {{0x00, "NeverStarted"}, {0x02, "Completed"}, {0x04, "Suspended"},
131 { 122 {0x05, "Aborted"}, {0x06, "Failed"}, {0, 0}};
132 {0x00, "NeverStarted"}, 123
133 {0x02, "Completed"}, 124static struct {
134 {0x04, "Suspended"},
135 {0x05, "Aborted"},
136 {0x06, "Failed"},
137 {0, 0}
138 };
139
140struct
141{
142 __u8 value; 125 __u8 value;
143 char *text; 126 char *text;
144} 127} smart_command[] = {{SMART_ENABLE, "SMART_ENABLE"},
145 128 {SMART_DISABLE, "SMART_DISABLE"},
146smart_command[] = 129 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"},
147 { 130 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"}};
148 {SMART_ENABLE, "SMART_ENABLE"}, 131
149 {SMART_DISABLE, "SMART_DISABLE"}, 132/* Index to smart_command table, keep in order */
150 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"}, 133enum SmartCommand {
151 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"} 134 SMART_CMD_ENABLE,
152 }; 135 SMART_CMD_DISABLE,
153 136 SMART_CMD_IMMEDIATE_OFFLINE,
154 137 SMART_CMD_AUTO_OFFLINE
155/* Index to smart_command table, keep in order */ 138};
156enum SmartCommand 139
157 { SMART_CMD_ENABLE, 140static char *get_offline_text(int);
158 SMART_CMD_DISABLE, 141static int smart_read_values(int, values_t *);
159 SMART_CMD_IMMEDIATE_OFFLINE, 142static int nagios(values_t *, thresholds_t *);
160 SMART_CMD_AUTO_OFFLINE 143static void print_value(value_t *, threshold_t *);
161 }; 144static void print_values(values_t *, thresholds_t *);
162 145static int smart_cmd_simple(int, enum SmartCommand, __u8, bool);
163char *get_offline_text (int); 146static int smart_read_thresholds(int, thresholds_t *);
164int smart_read_values (int, values_t *); 147static bool verbose = false;
165int nagios (values_t *, thresholds_t *); 148
166void print_value (value_t *, threshold_t *); 149int main(int argc, char *argv[]) {
167void print_values (values_t *, thresholds_t *);
168int smart_cmd_simple (int, enum SmartCommand, __u8, bool);
169int smart_read_thresholds (int, thresholds_t *);
170bool verbose = false;
171
172int
173main (int argc, char *argv[])
174{
175 char *device = NULL; 150 char *device = NULL;
176 int o, longindex; 151 int o;
152 int longindex;
177 int retval = 0; 153 int retval = 0;
178 154
179 thresholds_t thresholds; 155 thresholds_t thresholds;
180 values_t values; 156 values_t values;
181 int fd; 157 int fd;
182 158
183 static struct option longopts[] = { 159 static struct option longopts[] = {{"device", required_argument, 0, 'd'},
184 {"device", required_argument, 0, 'd'}, 160 {"immediate", no_argument, 0, 'i'},
185 {"immediate", no_argument, 0, 'i'}, 161 {"quiet-check", no_argument, 0, 'q'},
186 {"quiet-check", no_argument, 0, 'q'}, 162 {"auto-on", no_argument, 0, '1'},
187 {"auto-on", no_argument, 0, '1'}, 163 {"auto-off", no_argument, 0, '0'},
188 {"auto-off", no_argument, 0, '0'}, 164 {"nagios", no_argument, 0, 'n'}, /* DEPRECATED, but we still accept it */
189 {"nagios", no_argument, 0, 'n'}, /* DEPRECATED, but we still accept it */ 165 {"help", no_argument, 0, 'h'},
190 {"help", no_argument, 0, 'h'}, 166 {"version", no_argument, 0, 'V'},
191 {"version", no_argument, 0, 'V'}, 167 {0, 0, 0, 0}};
192 {0, 0, 0, 0}
193 };
194 168
195 /* Parse extra opts if any */ 169 /* Parse extra opts if any */
196 argv=np_extra_opts (&argc, argv, progname); 170 argv = np_extra_opts(&argc, argv, progname);
197 171
198 setlocale (LC_ALL, ""); 172 setlocale(LC_ALL, "");
199 bindtextdomain (PACKAGE, LOCALEDIR); 173 bindtextdomain(PACKAGE, LOCALEDIR);
200 textdomain (PACKAGE); 174 textdomain(PACKAGE);
201 175
202 while (true) { 176 while (true) {
203 177
204 o = getopt_long (argc, argv, "+d:iq10nhVv", longopts, &longindex); 178 o = getopt_long(argc, argv, "+d:iq10nhVv", longopts, &longindex);
205 179
206 if (o == -1 || o == EOF || o == 1) 180 if (o == -1 || o == EOF || o == 1)
207 break; 181 break;
@@ -211,30 +185,30 @@ main (int argc, char *argv[])
211 device = optarg; 185 device = optarg;
212 break; 186 break;
213 case 'q': 187 case 'q':
214 fprintf (stderr, "%s\n", _("DEPRECATION WARNING: the -q switch (quiet output) is no longer \"quiet\".")); 188 fprintf(stderr, "%s\n", _("DEPRECATION WARNING: the -q switch (quiet output) is no longer \"quiet\"."));
215 fprintf (stderr, "%s\n", _("Nagios-compatible output is now always returned.")); 189 fprintf(stderr, "%s\n", _("Nagios-compatible output is now always returned."));
216 break; 190 break;
217 case 'i': 191 case 'i':
218 case '1': 192 case '1':
219 case '0': 193 case '0':
220 printf ("%s\n", _("SMART commands are broken and have been disabled (See Notes in --help).")); 194 printf("%s\n", _("SMART commands are broken and have been disabled (See Notes in --help)."));
221 return STATE_CRITICAL; 195 return STATE_CRITICAL;
222 break; 196 break;
223 case 'n': 197 case 'n':
224 fprintf (stderr, "%s\n", _("DEPRECATION WARNING: the -n switch (Nagios-compatible output) is now the")); 198 fprintf(stderr, "%s\n", _("DEPRECATION WARNING: the -n switch (Nagios-compatible output) is now the"));
225 fprintf (stderr, "%s\n", _("default and will be removed from future releases.")); 199 fprintf(stderr, "%s\n", _("default and will be removed from future releases."));
226 break; 200 break;
227 case 'v': /* verbose */ 201 case 'v': /* verbose */
228 verbose = true; 202 verbose = true;
229 break; 203 break;
230 case 'h': 204 case 'h':
231 print_help (); 205 print_help();
232 return STATE_UNKNOWN; 206 return STATE_UNKNOWN;
233 case 'V': 207 case 'V':
234 print_revision (progname, NP_VERSION); 208 print_revision(progname, NP_VERSION);
235 return STATE_UNKNOWN; 209 return STATE_UNKNOWN;
236 default: 210 default:
237 usage5 (); 211 usage5();
238 } 212 }
239 } 213 }
240 214
@@ -243,36 +217,33 @@ main (int argc, char *argv[])
243 } 217 }
244 218
245 if (!device) { 219 if (!device) {
246 print_help (); 220 print_help();
247 return STATE_UNKNOWN; 221 return STATE_UNKNOWN;
248 } 222 }
249 223
250 fd = open (device, OPEN_MODE); 224 fd = open(device, OPEN_MODE);
251 225
252 if (fd < 0) { 226 if (fd < 0) {
253 printf (_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror (errno)); 227 printf(_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror(errno));
254 return STATE_CRITICAL; 228 return STATE_CRITICAL;
255 } 229 }
256 230
257 if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, false)) { 231 if (smart_cmd_simple(fd, SMART_CMD_ENABLE, 0, false)) {
258 printf (_("CRITICAL - SMART_CMD_ENABLE\n")); 232 printf(_("CRITICAL - SMART_CMD_ENABLE\n"));
259 return STATE_CRITICAL; 233 return STATE_CRITICAL;
260 } 234 }
261 235
262 smart_read_values (fd, &values); 236 smart_read_values(fd, &values);
263 smart_read_thresholds (fd, &thresholds); 237 smart_read_thresholds(fd, &thresholds);
264 retval = nagios (&values, &thresholds); 238 retval = nagios(&values, &thresholds);
265 if (verbose) print_values (&values, &thresholds); 239 if (verbose)
240 print_values(&values, &thresholds);
266 241
267 close (fd); 242 close(fd);
268 return retval; 243 return retval;
269} 244}
270 245
271 246char *get_offline_text(int status) {
272
273char *
274get_offline_text (int status)
275{
276 int i; 247 int i;
277 for (i = 0; offline_status_text[i].text; i++) { 248 for (i = 0; offline_status_text[i].text; i++) {
278 if (offline_status_text[i].value == status) { 249 if (offline_status_text[i].value == status) {
@@ -282,11 +253,7 @@ get_offline_text (int status)
282 return "UNKNOWN"; 253 return "UNKNOWN";
283} 254}
284 255
285 256int smart_read_values(int fd, values_t *values) {
286
287int
288smart_read_values (int fd, values_t * values)
289{
290#ifdef __linux__ 257#ifdef __linux__
291 int e; 258 int e;
292 __u8 args[4 + 512]; 259 __u8 args[4 + 512];
@@ -294,12 +261,12 @@ smart_read_values (int fd, values_t * values)
294 args[1] = 0; 261 args[1] = 0;
295 args[2] = SMART_READ_VALUES; 262 args[2] = SMART_READ_VALUES;
296 args[3] = 1; 263 args[3] = 1;
297 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 264 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
298 e = errno; 265 e = errno;
299 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); 266 printf(_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror(errno));
300 return e; 267 return e;
301 } 268 }
302 memcpy (values, args + 4, 512); 269 memcpy(values, args + 4, 512);
303#endif /* __linux__ */ 270#endif /* __linux__ */
304#ifdef __NetBSD__ 271#ifdef __NetBSD__
305 struct atareq req; 272 struct atareq req;
@@ -323,7 +290,7 @@ smart_read_values (int fd, values_t * values)
323 290
324 if (errno != 0) { 291 if (errno != 0) {
325 int e = errno; 292 int e = errno;
326 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); 293 printf(_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror(errno));
327 return e; 294 return e;
328 } 295 }
329 296
@@ -332,13 +299,9 @@ smart_read_values (int fd, values_t * values)
332 return 0; 299 return 0;
333} 300}
334 301
335 302int nagios(values_t *p, thresholds_t *t) {
336 303 value_t *value = p->values;
337int 304 threshold_t *threshold = t->thresholds;
338nagios (values_t * p, thresholds_t * t)
339{
340 value_t * value = p->values;
341 threshold_t * threshold = t->thresholds;
342 int status = OPERATIONAL; 305 int status = OPERATIONAL;
343 int prefailure = 0; 306 int prefailure = 0;
344 int advisory = 0; 307 int advisory = 0;
@@ -353,13 +316,11 @@ nagios (values_t * p, thresholds_t * t)
353 if (value->status & 1) { 316 if (value->status & 1) {
354 status = PREFAILURE; 317 status = PREFAILURE;
355 ++prefailure; 318 ++prefailure;
356 } 319 } else {
357 else {
358 status = ADVISORY; 320 status = ADVISORY;
359 ++advisory; 321 ++advisory;
360 } 322 }
361 } 323 } else {
362 else {
363 ++passed; 324 ++passed;
364 } 325 }
365 ++total; 326 ++total;
@@ -369,81 +330,49 @@ nagios (values_t * p, thresholds_t * t)
369 } 330 }
370 switch (status) { 331 switch (status) {
371 case PREFAILURE: 332 case PREFAILURE:
372 printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), 333 printf(_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), prefailure, prefailure > 1 ? 's' : ' ', failed,
373 prefailure, 334 total);
374 prefailure > 1 ? 's' : ' ', 335 status = STATE_CRITICAL;
375 failed,
376 total);
377 status=STATE_CRITICAL;
378 break; 336 break;
379 case ADVISORY: 337 case ADVISORY:
380 printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), 338 printf(_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), advisory, advisory > 1 ? "ies" : "y", failed, total);
381 advisory, 339 status = STATE_WARNING;
382 advisory > 1 ? "ies" : "y",
383 failed,
384 total);
385 status=STATE_WARNING;
386 break; 340 break;
387 case OPERATIONAL: 341 case OPERATIONAL:
388 printf (_("OK - Operational (%d/%d tests passed)\n"), passed, total); 342 printf(_("OK - Operational (%d/%d tests passed)\n"), passed, total);
389 status=STATE_OK; 343 status = STATE_OK;
390 break; 344 break;
391 default: 345 default:
392 printf (_("ERROR - Status '%d' unknown. %d/%d tests passed\n"), status, 346 printf(_("ERROR - Status '%d' unknown. %d/%d tests passed\n"), status, passed, total);
393 passed, total);
394 status = STATE_UNKNOWN; 347 status = STATE_UNKNOWN;
395 break; 348 break;
396 } 349 }
397 return status; 350 return status;
398} 351}
399 352
400 353void print_value(value_t *p, threshold_t *t) {
401 354 printf("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n", p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
402void 355 p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold, p->value >= t->threshold ? "Passed" : "Failed");
403print_value (value_t * p, threshold_t * t)
404{
405 printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n",
406 p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
407 p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold,
408 p->value >= t->threshold ? "Passed" : "Failed");
409} 356}
410 357
411 358void print_values(values_t *p, thresholds_t *t) {
412 359 value_t *value = p->values;
413void 360 threshold_t *threshold = t->thresholds;
414print_values (values_t * p, thresholds_t * t)
415{
416 value_t * value = p->values;
417 threshold_t * threshold = t->thresholds;
418 int i; 361 int i;
419 for (i = 0; i < NR_ATTRIBUTES; i++) { 362 for (i = 0; i < NR_ATTRIBUTES; i++) {
420 if (value->id && threshold->id && value->id == threshold->id) { 363 if (value->id && threshold->id && value->id == threshold->id) {
421 print_value (value++, threshold++); 364 print_value(value++, threshold++);
422 } 365 }
423 } 366 }
424 printf 367 printf(_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), p->offline_status,
425 (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), 368 get_offline_text(p->offline_status & 0x7f), (p->offline_status & 0x80 ? "Yes" : "No"), p->offline_timeout / 60);
426 p->offline_status, 369 printf(_("OffLineCapability=%d {%s %s %s}\n"), p->offline_capability, p->offline_capability & 1 ? "Immediate" : "",
427 get_offline_text (p->offline_status & 0x7f), 370 p->offline_capability & 2 ? "Auto" : "", p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
428 (p->offline_status & 0x80 ? "Yes" : "No"), 371 printf(_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"), p->revision, p->checksum, p->smart_capability,
429 p->offline_timeout / 60); 372 p->smart_capability & 1 ? "SaveOnStandBy" : "", p->smart_capability & 2 ? "AutoSave" : "");
430 printf
431 (_("OffLineCapability=%d {%s %s %s}\n"),
432 p->offline_capability,
433 p->offline_capability & 1 ? "Immediate" : "",
434 p->offline_capability & 2 ? "Auto" : "",
435 p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
436 printf
437 (_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"),
438 p->revision,
439 p->checksum,
440 p->smart_capability,
441 p->smart_capability & 1 ? "SaveOnStandBy" : "",
442 p->smart_capability & 2 ? "AutoSave" : "");
443} 373}
444 374
445 375int smart_cmd_simple(int fd, enum SmartCommand command, __u8 val0, bool show_error) {
446int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_error) {
447 int e = STATE_UNKNOWN; 376 int e = STATE_UNKNOWN;
448#ifdef __linux__ 377#ifdef __linux__
449 __u8 args[4]; 378 __u8 args[4];
@@ -451,14 +380,14 @@ int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_er
451 args[1] = val0; 380 args[1] = val0;
452 args[2] = smart_command[command].value; 381 args[2] = smart_command[command].value;
453 args[3] = 0; 382 args[3] = 0;
454 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 383 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
455 e = STATE_CRITICAL; 384 e = STATE_CRITICAL;
456 if (show_error) 385 if (show_error)
457 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); 386 printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
458 } else { 387 } else {
459 e = STATE_OK; 388 e = STATE_OK;
460 if (show_error) 389 if (show_error)
461 printf (_("OK - Command sent (%s)\n"), smart_command[command].text); 390 printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
462 } 391 }
463 392
464#endif /* __linux__ */ 393#endif /* __linux__ */
@@ -483,35 +412,31 @@ int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_er
483 if (errno != 0) { 412 if (errno != 0) {
484 e = STATE_CRITICAL; 413 e = STATE_CRITICAL;
485 if (show_error) 414 if (show_error)
486 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); 415 printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
487 } else { 416 } else {
488 e = STATE_OK; 417 e = STATE_OK;
489 if (show_error) 418 if (show_error)
490 printf (_("OK - Command sent (%s)\n"), smart_command[command].text); 419 printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
491 } 420 }
492 421
493#endif /* __NetBSD__ */ 422#endif /* __NetBSD__ */
494 return e; 423 return e;
495} 424}
496 425
497 426int smart_read_thresholds(int fd, thresholds_t *thresholds) {
498
499int
500smart_read_thresholds (int fd, thresholds_t * thresholds)
501{
502#ifdef __linux__ 427#ifdef __linux__
503 int e; 428 int e;
504 __u8 args[4 + 512]; 429 __u8 args[4 + 512];
505 args[0] = WIN_SMART; 430 args[0] = WIN_SMART;
506 args[1] = 0; 431 args[1] = 0;
507 args[2] = SMART_READ_THRESHOLDS; 432 args[2] = SMART_READ_THRESHOLDS;
508 args[3] = 1; 433 args[3] = 1;
509 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 434 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
510 e = errno; 435 e = errno;
511 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); 436 printf(_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror(errno));
512 return e; 437 return e;
513 } 438 }
514 memcpy (thresholds, args + 4, 512); 439 memcpy(thresholds, args + 4, 512);
515#endif /* __linux__ */ 440#endif /* __linux__ */
516#ifdef __NetBSD__ 441#ifdef __NetBSD__
517 struct atareq req; 442 struct atareq req;
@@ -535,7 +460,7 @@ smart_read_thresholds (int fd, thresholds_t * thresholds)
535 460
536 if (errno != 0) { 461 if (errno != 0) {
537 int e = errno; 462 int e = errno;
538 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); 463 printf(_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror(errno));
539 return e; 464 return e;
540 } 465 }
541 466
@@ -544,45 +469,43 @@ smart_read_thresholds (int fd, thresholds_t * thresholds)
544 return 0; 469 return 0;
545} 470}
546 471
472void print_help(void) {
473 print_revision(progname, NP_VERSION);
547 474
548void 475 printf("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
549print_help (void) 476 printf("Plugin implementation - 1999 Robert Dale <rdale@digital-mission.com>\n");
550{ 477 printf(COPYRIGHT, copyright, email);
551 print_revision (progname, NP_VERSION);
552 478
553 printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n"); 479 printf(_("This plugin checks a local hard drive with the (Linux specific) SMART interface "
554 printf ("Plugin implementation - 1999 Robert Dale <rdale@digital-mission.com>\n"); 480 "[http://smartlinux.sourceforge.net/smart/index.php]."));
555 printf (COPYRIGHT, copyright, email);
556 481
557 printf (_("This plugin checks a local hard drive with the (Linux specific) SMART interface [http://smartlinux.sourceforge.net/smart/index.php].")); 482 printf("\n\n");
558 483
559 printf ("\n\n"); 484 print_usage();
560 485
561 print_usage (); 486 printf(UT_HELP_VRSN);
487 printf(UT_EXTRA_OPTS);
562 488
563 printf (UT_HELP_VRSN); 489 printf(" %s\n", "-d, --device=DEVICE");
564 printf (UT_EXTRA_OPTS); 490 printf(" %s\n", _("Select device DEVICE"));
491 printf(" %s\n", _("Note: if the device is specified without this option, any further option will"));
492 printf(" %s\n", _("be ignored."));
565 493
566 printf (" %s\n", "-d, --device=DEVICE"); 494 printf(UT_VERBOSE);
567 printf (" %s\n", _("Select device DEVICE"));
568 printf (" %s\n", _("Note: if the device is specified without this option, any further option will"));
569 printf (" %s\n", _("be ignored."));
570 495
571 printf (UT_VERBOSE); 496 printf("\n");
497 printf("%s\n", _("Notes:"));
498 printf(" %s\n", _("The SMART command modes (-i/--immediate, -0/--auto-off and -1/--auto-on) were"));
499 printf(" %s\n", _("broken in an underhand manner and have been disabled. You can use smartctl"));
500 printf(" %s\n", _("instead:"));
501 printf(" %s\n", _("-0/--auto-off: use \"smartctl --offlineauto=off\""));
502 printf(" %s\n", _("-1/--auto-on: use \"smartctl --offlineauto=on\""));
503 printf(" %s\n", _("-i/--immediate: use \"smartctl --test=offline\""));
572 504
573 printf ("\n"); 505 printf(UT_SUPPORT);
574 printf ("%s\n", _("Notes:"));
575 printf (" %s\n", _("The SMART command modes (-i/--immediate, -0/--auto-off and -1/--auto-on) were"));
576 printf (" %s\n", _("broken in an underhand manner and have been disabled. You can use smartctl"));
577 printf (" %s\n", _("instead:"));
578 printf (" %s\n", _("-0/--auto-off: use \"smartctl --offlineauto=off\""));
579 printf (" %s\n", _("-1/--auto-on: use \"smartctl --offlineauto=on\""));
580 printf (" %s\n", _("-i/--immediate: use \"smartctl --test=offline\""));
581
582 printf (UT_SUPPORT);
583} 506}
584 507
585 /* todo : add to the long nanual as example 508/* todo : add to the long nanual as example
586 * 509 *
587 * Run with: check_ide-smart --nagios [-d] <DRIVE> 510 * Run with: check_ide-smart --nagios [-d] <DRIVE>
588 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc 511 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
@@ -593,10 +516,7 @@ print_help (void)
593 * - Returns -1 not too often 516 * - Returns -1 not too often
594 */ 517 */
595 518
596 519void print_usage(void) {
597void 520 printf("%s\n", _("Usage:"));
598print_usage (void) 521 printf("%s [-d <device>] [-v]", progname);
599{
600 printf ("%s\n", _("Usage:"));
601 printf ("%s [-d <device>] [-v]", progname);
602} 522}
diff --git a/plugins/check_ldap.c b/plugins/check_ldap.c
index 868ffc1e..1c728292 100644
--- a/plugins/check_ldap.c
+++ b/plugins/check_ldap.c
@@ -3,7 +3,7 @@
3* Monitoring check_ldap plugin 3* Monitoring check_ldap plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2008 Monitoring Plugins Development Team 6* Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -28,7 +28,7 @@
28 28
29/* progname may be check_ldaps */ 29/* progname may be check_ldaps */
30char *progname = "check_ldap"; 30char *progname = "check_ldap";
31const char *copyright = "2000-2008"; 31const char *copyright = "2000-2024";
32const char *email = "devel@monitoring-plugins.org"; 32const char *email = "devel@monitoring-plugins.org";
33 33
34#include "common.h" 34#include "common.h"
diff --git a/plugins/check_mrtg.c b/plugins/check_mrtg.c
index 826b77e9..632e66fb 100644
--- a/plugins/check_mrtg.c
+++ b/plugins/check_mrtg.c
@@ -1,88 +1,79 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_mrtg plugin 3 * Monitoring check_mrtg plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_mrtg plugin 10 * This file contains the check_mrtg plugin
11* 11 *
12* This plugin will check either the average or maximum value of one of the 12 * This plugin will check either the average or maximum value of one of the
13* two variables recorded in an MRTG log file. 13 * two variables recorded in an MRTG log file.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_mrtg"; 32const char *progname = "check_mrtg";
33const char *copyright = "1999-2007"; 33const char *copyright = "1999-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
37#include "utils.h" 37#include "utils.h"
38 38
39int process_arguments (int, char **); 39static int process_arguments(int /*argc*/, char ** /*argv*/);
40int validate_arguments (void); 40static int validate_arguments(void);
41void print_help (void); 41static void print_help(void);
42void print_usage (void); 42void print_usage(void);
43 43
44char *log_file = NULL; 44static char *log_file = NULL;
45int expire_minutes = 0; 45static int expire_minutes = 0;
46bool use_average = true; 46static bool use_average = true;
47int variable_number = -1; 47static int variable_number = -1;
48unsigned long value_warning_threshold = 0L; 48static unsigned long value_warning_threshold = 0L;
49unsigned long value_critical_threshold = 0L; 49static unsigned long value_critical_threshold = 0L;
50char *label; 50static char *label;
51char *units; 51static char *units;
52 52
53int 53int main(int argc, char **argv) {
54main (int argc, char **argv) 54 setlocale(LC_ALL, "");
55{ 55 bindtextdomain(PACKAGE, LOCALEDIR);
56 int result = STATE_OK; 56 textdomain(PACKAGE);
57 FILE *fp;
58 int line;
59 char input_buffer[MAX_INPUT_BUFFER];
60 char *temp_buffer;
61 time_t current_time;
62 time_t timestamp = 0L;
63 unsigned long average_value_rate = 0L;
64 unsigned long maximum_value_rate = 0L;
65 unsigned long rate = 0L;
66
67 setlocale (LC_ALL, "");
68 bindtextdomain (PACKAGE, LOCALEDIR);
69 textdomain (PACKAGE);
70 57
71 /* Parse extra opts if any */ 58 /* Parse extra opts if any */
72 argv=np_extra_opts (&argc, argv, progname); 59 argv = np_extra_opts(&argc, argv, progname);
73 60
74 if (process_arguments (argc, argv) == ERROR) 61 if (process_arguments(argc, argv) == ERROR)
75 usage4 (_("Could not parse arguments\n")); 62 usage4(_("Could not parse arguments\n"));
76 63
77 /* open the MRTG log file for reading */ 64 /* open the MRTG log file for reading */
78 fp = fopen (log_file, "r"); 65 FILE *mtrg_log_file = fopen(log_file, "r");
79 if (fp == NULL) { 66 if (mtrg_log_file == NULL) {
80 printf (_("Unable to open MRTG log file\n")); 67 printf(_("Unable to open MRTG log file\n"));
81 return STATE_UNKNOWN; 68 return STATE_UNKNOWN;
82 } 69 }
83 70
84 line = 0; 71 time_t timestamp = 0L;
85 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) { 72 unsigned long average_value_rate = 0L;
73 unsigned long maximum_value_rate = 0L;
74 char input_buffer[MAX_INPUT_BUFFER];
75 int line = 0;
76 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, mtrg_log_file)) {
86 77
87 line++; 78 line++;
88 79
@@ -95,291 +86,260 @@ main (int argc, char **argv)
95 break; 86 break;
96 87
97 /* grab the timestamp */ 88 /* grab the timestamp */
98 temp_buffer = strtok (input_buffer, " "); 89 char *temp_buffer = strtok(input_buffer, " ");
99 timestamp = strtoul (temp_buffer, NULL, 10); 90 timestamp = strtoul(temp_buffer, NULL, 10);
100 91
101 /* grab the average value 1 rate */ 92 /* grab the average value 1 rate */
102 temp_buffer = strtok (NULL, " "); 93 temp_buffer = strtok(NULL, " ");
103 if (variable_number == 1) 94 if (variable_number == 1)
104 average_value_rate = strtoul (temp_buffer, NULL, 10); 95 average_value_rate = strtoul(temp_buffer, NULL, 10);
105 96
106 /* grab the average value 2 rate */ 97 /* grab the average value 2 rate */
107 temp_buffer = strtok (NULL, " "); 98 temp_buffer = strtok(NULL, " ");
108 if (variable_number == 2) 99 if (variable_number == 2)
109 average_value_rate = strtoul (temp_buffer, NULL, 10); 100 average_value_rate = strtoul(temp_buffer, NULL, 10);
110 101
111 /* grab the maximum value 1 rate */ 102 /* grab the maximum value 1 rate */
112 temp_buffer = strtok (NULL, " "); 103 temp_buffer = strtok(NULL, " ");
113 if (variable_number == 1) 104 if (variable_number == 1)
114 maximum_value_rate = strtoul (temp_buffer, NULL, 10); 105 maximum_value_rate = strtoul(temp_buffer, NULL, 10);
115 106
116 /* grab the maximum value 2 rate */ 107 /* grab the maximum value 2 rate */
117 temp_buffer = strtok (NULL, " "); 108 temp_buffer = strtok(NULL, " ");
118 if (variable_number == 2) 109 if (variable_number == 2)
119 maximum_value_rate = strtoul (temp_buffer, NULL, 10); 110 maximum_value_rate = strtoul(temp_buffer, NULL, 10);
120 } 111 }
121 112
122 /* close the log file */ 113 /* close the log file */
123 fclose (fp); 114 fclose(mtrg_log_file);
124 115
125 /* if we couldn't read enough data, return an unknown error */ 116 /* if we couldn't read enough data, return an unknown error */
126 if (line <= 2) { 117 if (line <= 2) {
127 printf (_("Unable to process MRTG log file\n")); 118 printf(_("Unable to process MRTG log file\n"));
128 return STATE_UNKNOWN; 119 return STATE_UNKNOWN;
129 } 120 }
130 121
131 /* make sure the MRTG data isn't too old */ 122 /* make sure the MRTG data isn't too old */
132 time (&current_time); 123 time_t current_time;
133 if (expire_minutes > 0 124 time(&current_time);
134 && (current_time - timestamp) > (expire_minutes * 60)) { 125 if (expire_minutes > 0 && (current_time - timestamp) > (expire_minutes * 60)) {
135 printf (_("MRTG data has expired (%d minutes old)\n"), 126 printf(_("MRTG data has expired (%d minutes old)\n"), (int)((current_time - timestamp) / 60));
136 (int) ((current_time - timestamp) / 60));
137 return STATE_WARNING; 127 return STATE_WARNING;
138 } 128 }
139 129
130 unsigned long rate = 0L;
140 /* else check the incoming/outgoing rates */ 131 /* else check the incoming/outgoing rates */
141 if (use_average) 132 if (use_average)
142 rate = average_value_rate; 133 rate = average_value_rate;
143 else 134 else
144 rate = maximum_value_rate; 135 rate = maximum_value_rate;
145 136
137 int result = STATE_OK;
146 if (rate > value_critical_threshold) 138 if (rate > value_critical_threshold)
147 result = STATE_CRITICAL; 139 result = STATE_CRITICAL;
148 else if (rate > value_warning_threshold) 140 else if (rate > value_warning_threshold)
149 result = STATE_WARNING; 141 result = STATE_WARNING;
150 142
151 printf("%s. %s = %lu %s|%s\n", 143 printf("%s. %s = %lu %s|%s\n", (use_average) ? _("Avg") : _("Max"), label, rate, units,
152 (use_average) ? _("Avg") : _("Max"), 144 perfdata(label, (long)rate, units, (int)value_warning_threshold, (long)value_warning_threshold, (int)value_critical_threshold,
153 label, rate, units, 145 (long)value_critical_threshold, 0, 0, 0, 0));
154 perfdata(label, (long) rate, units,
155 (int) value_warning_threshold, (long) value_warning_threshold,
156 (int) value_critical_threshold, (long) value_critical_threshold,
157 0, 0, 0, 0));
158 146
159 return result; 147 return result;
160} 148}
161 149
162
163
164/* process command-line arguments */ 150/* process command-line arguments */
165int 151int process_arguments(int argc, char **argv) {
166process_arguments (int argc, char **argv)
167{
168 int c;
169
170 int option = 0;
171 static struct option longopts[] = { 152 static struct option longopts[] = {
172 {"logfile", required_argument, 0, 'F'}, 153 {"logfile", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'}, {"aggregation", required_argument, 0, 'a'},
173 {"expires", required_argument, 0, 'e'}, 154 {"variable", required_argument, 0, 'v'}, {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'},
174 {"aggregation", required_argument, 0, 'a'}, 155 {"label", required_argument, 0, 'l'}, {"units", required_argument, 0, 'u'}, {"variable", required_argument, 0, 'v'},
175 {"variable", required_argument, 0, 'v'}, 156 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
176 {"critical", required_argument, 0, 'c'},
177 {"warning", required_argument, 0, 'w'},
178 {"label", required_argument, 0, 'l'},
179 {"units", required_argument, 0, 'u'},
180 {"variable", required_argument, 0, 'v'},
181 {"version", no_argument, 0, 'V'},
182 {"help", no_argument, 0, 'h'},
183 {0, 0, 0, 0}
184 };
185 157
186 if (argc < 2) 158 if (argc < 2)
187 return ERROR; 159 return ERROR;
188 160
189 for (c = 1; c < argc; c++) { 161 for (int i = 1; i < argc; i++) {
190 if (strcmp ("-to", argv[c]) == 0) 162 if (strcmp("-to", argv[i]) == 0)
191 strcpy (argv[c], "-t"); 163 strcpy(argv[i], "-t");
192 else if (strcmp ("-wt", argv[c]) == 0) 164 else if (strcmp("-wt", argv[i]) == 0)
193 strcpy (argv[c], "-w"); 165 strcpy(argv[i], "-w");
194 else if (strcmp ("-ct", argv[c]) == 0) 166 else if (strcmp("-ct", argv[i]) == 0)
195 strcpy (argv[c], "-c"); 167 strcpy(argv[i], "-c");
196 } 168 }
197 169
170 int option_char;
171 int option = 0;
198 while (1) { 172 while (1) {
199 c = getopt_long (argc, argv, "hVF:e:a:v:c:w:l:u:", longopts, 173 option_char = getopt_long(argc, argv, "hVF:e:a:v:c:w:l:u:", longopts, &option);
200 &option);
201 174
202 if (c == -1 || c == EOF) 175 if (option_char == -1 || option_char == EOF)
203 break; 176 break;
204 177
205 switch (c) { 178 switch (option_char) {
206 case 'F': /* input file */ 179 case 'F': /* input file */
207 log_file = optarg; 180 log_file = optarg;
208 break; 181 break;
209 case 'e': /* ups name */ 182 case 'e': /* ups name */
210 expire_minutes = atoi (optarg); 183 expire_minutes = atoi(optarg);
211 break; 184 break;
212 case 'a': /* port */ 185 case 'a': /* port */
213 if (!strcmp (optarg, "MAX")) 186 if (!strcmp(optarg, "MAX"))
214 use_average = false; 187 use_average = false;
215 else 188 else
216 use_average = true; 189 use_average = true;
217 break; 190 break;
218 case 'v': 191 case 'v':
219 variable_number = atoi (optarg); 192 variable_number = atoi(optarg);
220 if (variable_number < 1 || variable_number > 2) 193 if (variable_number < 1 || variable_number > 2)
221 usage4 (_("Invalid variable number")); 194 usage4(_("Invalid variable number"));
222 break; 195 break;
223 case 'w': /* critical time threshold */ 196 case 'w': /* critical time threshold */
224 value_warning_threshold = strtoul (optarg, NULL, 10); 197 value_warning_threshold = strtoul(optarg, NULL, 10);
225 break; 198 break;
226 case 'c': /* warning time threshold */ 199 case 'c': /* warning time threshold */
227 value_critical_threshold = strtoul (optarg, NULL, 10); 200 value_critical_threshold = strtoul(optarg, NULL, 10);
228 break; 201 break;
229 case 'l': /* label */ 202 case 'l': /* label */
230 label = optarg; 203 label = optarg;
231 break; 204 break;
232 case 'u': /* timeout */ 205 case 'u': /* timeout */
233 units = optarg; 206 units = optarg;
234 break; 207 break;
235 case 'V': /* version */ 208 case 'V': /* version */
236 print_revision (progname, NP_VERSION); 209 print_revision(progname, NP_VERSION);
237 exit (STATE_UNKNOWN); 210 exit(STATE_UNKNOWN);
238 case 'h': /* help */ 211 case 'h': /* help */
239 print_help (); 212 print_help();
240 exit (STATE_UNKNOWN); 213 exit(STATE_UNKNOWN);
241 case '?': /* help */ 214 case '?': /* help */
242 usage5 (); 215 usage5();
243 } 216 }
244 } 217 }
245 218
246 c = optind; 219 option_char = optind;
247 if (log_file == NULL && argc > c) { 220 if (log_file == NULL && argc > option_char) {
248 log_file = argv[c++]; 221 log_file = argv[option_char++];
249 } 222 }
250 223
251 if (expire_minutes <= 0 && argc > c) { 224 if (expire_minutes <= 0 && argc > option_char) {
252 if (is_intpos (argv[c])) 225 if (is_intpos(argv[option_char]))
253 expire_minutes = atoi (argv[c++]); 226 expire_minutes = atoi(argv[option_char++]);
254 else 227 else
255 die (STATE_UNKNOWN, 228 die(STATE_UNKNOWN, _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"), argv[option_char], progname);
256 _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"),
257 argv[c], progname);
258 } 229 }
259 230
260 if (argc > c && strcmp (argv[c], "MAX") == 0) { 231 if (argc > option_char && strcmp(argv[option_char], "MAX") == 0) {
261 use_average = false; 232 use_average = false;
262 c++; 233 option_char++;
263 } 234 } else if (argc > option_char && strcmp(argv[option_char], "AVG") == 0) {
264 else if (argc > c && strcmp (argv[c], "AVG") == 0) {
265 use_average = true; 235 use_average = true;
266 c++; 236 option_char++;
267 } 237 }
268 238
269 if (argc > c && variable_number == -1) { 239 if (argc > option_char && variable_number == -1) {
270 variable_number = atoi (argv[c++]); 240 variable_number = atoi(argv[option_char++]);
271 if (variable_number < 1 || variable_number > 2) { 241 if (variable_number < 1 || variable_number > 2) {
272 printf ("%s :", argv[c]); 242 printf("%s :", argv[option_char]);
273 usage (_("Invalid variable number\n")); 243 usage(_("Invalid variable number\n"));
274 } 244 }
275 } 245 }
276 246
277 if (argc > c && value_warning_threshold == 0) { 247 if (argc > option_char && value_warning_threshold == 0) {
278 value_warning_threshold = strtoul (argv[c++], NULL, 10); 248 value_warning_threshold = strtoul(argv[option_char++], NULL, 10);
279 } 249 }
280 250
281 if (argc > c && value_critical_threshold == 0) { 251 if (argc > option_char && value_critical_threshold == 0) {
282 value_critical_threshold = strtoul (argv[c++], NULL, 10); 252 value_critical_threshold = strtoul(argv[option_char++], NULL, 10);
283 } 253 }
284 254
285 if (argc > c && strlen (label) == 0) { 255 if (argc > option_char && strlen(label) == 0) {
286 label = argv[c++]; 256 label = argv[option_char++];
287 } 257 }
288 258
289 if (argc > c && strlen (units) == 0) { 259 if (argc > option_char && strlen(units) == 0) {
290 units = argv[c++]; 260 units = argv[option_char++];
291 } 261 }
292 262
293 return validate_arguments (); 263 return validate_arguments();
294} 264}
295 265
296int 266int validate_arguments(void) {
297validate_arguments (void)
298{
299 if (variable_number == -1) 267 if (variable_number == -1)
300 usage4 (_("You must supply the variable number")); 268 usage4(_("You must supply the variable number"));
301 269
302 if (label == NULL) 270 if (label == NULL)
303 label = strdup ("value"); 271 label = strdup("value");
304 272
305 if (units == NULL) 273 if (units == NULL)
306 units = strdup (""); 274 units = strdup("");
307 275
308 return OK; 276 return OK;
309} 277}
310 278
311 279void print_help(void) {
312 280 print_revision(progname, NP_VERSION);
313void 281
314print_help (void) 282 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
315{ 283 printf(COPYRIGHT, copyright, email);
316 print_revision (progname, NP_VERSION); 284
317 285 printf("%s\n", _("This plugin will check either the average or maximum value of one of the"));
318 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 286 printf("%s\n", _("two variables recorded in an MRTG log file."));
319 printf (COPYRIGHT, copyright, email); 287
320 288 printf("\n\n");
321 printf ("%s\n", _("This plugin will check either the average or maximum value of one of the")); 289
322 printf ("%s\n", _("two variables recorded in an MRTG log file.")); 290 print_usage();
323 291
324 printf ("\n\n"); 292 printf(UT_HELP_VRSN);
325 293 printf(UT_EXTRA_OPTS);
326 print_usage (); 294
327 295 printf(" %s\n", "-F, --logfile=FILE");
328 printf (UT_HELP_VRSN); 296 printf(" %s\n", _("The MRTG log file containing the data you want to monitor"));
329 printf (UT_EXTRA_OPTS); 297 printf(" %s\n", "-e, --expires=MINUTES");
330 298 printf(" %s\n", _("Minutes before MRTG data is considered to be too old"));
331 printf (" %s\n", "-F, --logfile=FILE"); 299 printf(" %s\n", "-a, --aggregation=AVG|MAX");
332 printf (" %s\n", _("The MRTG log file containing the data you want to monitor")); 300 printf(" %s\n", _("Should we check average or maximum values?"));
333 printf (" %s\n", "-e, --expires=MINUTES"); 301 printf(" %s\n", "-v, --variable=INTEGER");
334 printf (" %s\n", _("Minutes before MRTG data is considered to be too old")); 302 printf(" %s\n", _("Which variable set should we inspect? (1 or 2)"));
335 printf (" %s\n", "-a, --aggregation=AVG|MAX"); 303 printf(" %s\n", "-w, --warning=INTEGER");
336 printf (" %s\n", _("Should we check average or maximum values?")); 304 printf(" %s\n", _("Threshold value for data to result in WARNING status"));
337 printf (" %s\n", "-v, --variable=INTEGER"); 305 printf(" %s\n", "-c, --critical=INTEGER");
338 printf (" %s\n", _("Which variable set should we inspect? (1 or 2)")); 306 printf(" %s\n", _("Threshold value for data to result in CRITICAL status"));
339 printf (" %s\n", "-w, --warning=INTEGER"); 307 printf(" %s\n", "-l, --label=STRING");
340 printf (" %s\n", _("Threshold value for data to result in WARNING status")); 308 printf(" %s\n", _("Type label for data (Examples: Conns, \"Processor Load\", In, Out)"));
341 printf (" %s\n", "-c, --critical=INTEGER"); 309 printf(" %s\n", "-u, --units=STRING");
342 printf (" %s\n", _("Threshold value for data to result in CRITICAL status")); 310 printf(" %s\n", _("Option units label for data (Example: Packets/Sec, Errors/Sec,"));
343 printf (" %s\n", "-l, --label=STRING"); 311 printf(" %s\n", _("\"Bytes Per Second\", \"%% Utilization\")"));
344 printf (" %s\n", _("Type label for data (Examples: Conns, \"Processor Load\", In, Out)")); 312
345 printf (" %s\n", "-u, --units=STRING"); 313 printf("\n");
346 printf (" %s\n", _("Option units label for data (Example: Packets/Sec, Errors/Sec,")); 314 printf(" %s\n", _("If the value exceeds the <vwl> threshold, a WARNING status is returned. If"));
347 printf (" %s\n", _("\"Bytes Per Second\", \"%% Utilization\")")); 315 printf(" %s\n", _("the value exceeds the <vcl> threshold, a CRITICAL status is returned. If"));
348 316 printf(" %s\n", _("the data in the log file is older than <expire_minutes> old, a WARNING"));
349 printf ("\n"); 317 printf(" %s\n", _("status is returned and a warning message is printed."));
350 printf (" %s\n", _("If the value exceeds the <vwl> threshold, a WARNING status is returned. If")); 318
351 printf (" %s\n", _("the value exceeds the <vcl> threshold, a CRITICAL status is returned. If")); 319 printf("\n");
352 printf (" %s\n", _("the data in the log file is older than <expire_minutes> old, a WARNING")); 320 printf(" %s\n", _("This plugin is useful for monitoring MRTG data that does not correspond to"));
353 printf (" %s\n", _("status is returned and a warning message is printed.")); 321 printf(" %s\n", _("bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth)."));
354 322 printf(" %s\n", _("It can be used to monitor any kind of data that MRTG is monitoring - errors,"));
355 printf ("\n"); 323 printf(" %s\n", _("packets/sec, etc. I use MRTG in conjunction with the Novell NLM that allows"));
356 printf (" %s\n", _("This plugin is useful for monitoring MRTG data that does not correspond to")); 324 printf(" %s\n", _("me to track processor utilization, user connections, drive space, etc and"));
357 printf (" %s\n", _("bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).")); 325 printf(" %s\n\n", _("this plugin works well for monitoring that kind of data as well."));
358 printf (" %s\n", _("It can be used to monitor any kind of data that MRTG is monitoring - errors,")); 326
359 printf (" %s\n", _("packets/sec, etc. I use MRTG in conjunction with the Novell NLM that allows")); 327 printf("%s\n", _("Notes:"));
360 printf (" %s\n", _("me to track processor utilization, user connections, drive space, etc and")); 328 printf(" %s\n", _("- This plugin only monitors one of the two variables stored in the MRTG log"));
361 printf (" %s\n\n", _("this plugin works well for monitoring that kind of data as well.")); 329 printf(" %s\n", _("file. If you want to monitor both values you will have to define two"));
362 330 printf(" %s\n", _("commands with different values for the <variable> argument. Of course,"));
363 printf ("%s\n", _("Notes:")); 331 printf(" %s\n", _("you can always hack the code to make this plugin work for you..."));
364 printf (" %s\n", _("- This plugin only monitors one of the two variables stored in the MRTG log")); 332 printf(" %s\n", _("- MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from"));
365 printf (" %s\n", _("file. If you want to monitor both values you will have to define two")); 333 printf(" %s\n", "http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html");
366 printf (" %s\n", _("commands with different values for the <variable> argument. Of course,")); 334
367 printf (" %s\n", _("you can always hack the code to make this plugin work for you...")); 335 printf(UT_SUPPORT);
368 printf (" %s\n", _("- MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from"));
369 printf (" %s\n", "http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html");
370
371 printf (UT_SUPPORT);
372} 336}
373 337
374
375
376/* original command line: 338/* original command line:
377 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */ 339 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */
378 340
379void 341void print_usage(void) {
380print_usage (void) 342 printf("%s\n", _("Usage:"));
381{ 343 printf("%s -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n", progname);
382 printf ("%s\n", _("Usage:")); 344 printf("[-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]\n");
383 printf ("%s -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n",progname);
384 printf ("[-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]\n");
385} 345}
diff --git a/plugins/check_mrtgtraf.c b/plugins/check_mrtgtraf.c
index bd25d47d..e5a2e2ad 100644
--- a/plugins/check_mrtgtraf.c
+++ b/plugins/check_mrtgtraf.c
@@ -1,94 +1,77 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_mrtgtraf plugin 3 * Monitoring check_mrtgtraf plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_mtrgtraf plugin 10 * This file contains the check_mtrgtraf plugin
11* 11 *
12* This plugin will check the incoming/outgoing transfer rates of a router 12 * This plugin will check the incoming/outgoing transfer rates of a router
13* switch, etc recorded in an MRTG log. 13 * switch, etc recorded in an MRTG log.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32#include "common.h" 32#include "common.h"
33#include "utils.h" 33#include "utils.h"
34 34
35const char *progname = "check_mrtgtraf"; 35const char *progname = "check_mrtgtraf";
36const char *copyright = "1999-2007"; 36const char *copyright = "1999-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39int process_arguments (int, char **); 39static int process_arguments(int /*argc*/, char ** /*argv*/);
40int validate_arguments (void); 40static void print_help(void);
41void print_help(void);
42void print_usage(void); 41void print_usage(void);
43 42
44char *log_file = NULL; 43static char *log_file = NULL;
45int expire_minutes = -1; 44static int expire_minutes = -1;
46bool use_average = true; 45static bool use_average = true;
47unsigned long incoming_warning_threshold = 0L; 46static unsigned long incoming_warning_threshold = 0L;
48unsigned long incoming_critical_threshold = 0L; 47static unsigned long incoming_critical_threshold = 0L;
49unsigned long outgoing_warning_threshold = 0L; 48static unsigned long outgoing_warning_threshold = 0L;
50unsigned long outgoing_critical_threshold = 0L; 49static unsigned long outgoing_critical_threshold = 0L;
51 50
52 51int main(int argc, char **argv) {
53int 52 setlocale(LC_ALL, "");
54main (int argc, char **argv) 53 bindtextdomain(PACKAGE, LOCALEDIR);
55{ 54 textdomain(PACKAGE);
56 int result = STATE_OK;
57 FILE *fp;
58 int line;
59 char input_buffer[MAX_INPUT_BUFFER];
60 char *temp_buffer;
61 time_t current_time;
62 char *error_message;
63 time_t timestamp = 0L;
64 unsigned long average_incoming_rate = 0L;
65 unsigned long average_outgoing_rate = 0L;
66 unsigned long maximum_incoming_rate = 0L;
67 unsigned long maximum_outgoing_rate = 0L;
68 unsigned long incoming_rate = 0L;
69 unsigned long outgoing_rate = 0L;
70 double adjusted_incoming_rate = 0.0;
71 double adjusted_outgoing_rate = 0.0;
72 char incoming_speed_rating[8];
73 char outgoing_speed_rating[8];
74
75 setlocale (LC_ALL, "");
76 bindtextdomain (PACKAGE, LOCALEDIR);
77 textdomain (PACKAGE);
78 55
79 /* Parse extra opts if any */ 56 /* Parse extra opts if any */
80 argv=np_extra_opts (&argc, argv, progname); 57 argv = np_extra_opts(&argc, argv, progname);
81 58
82 if (process_arguments (argc, argv) == ERROR) 59 if (process_arguments(argc, argv) == ERROR)
83 usage4 (_("Could not parse arguments")); 60 usage4(_("Could not parse arguments"));
84 61
85 /* open the MRTG log file for reading */ 62 /* open the MRTG log file for reading */
86 fp = fopen (log_file, "r"); 63 FILE *mrtg_log_file_ptr = fopen(log_file, "r");
87 if (fp == NULL) 64 if (mrtg_log_file_ptr == NULL)
88 usage4 (_("Unable to open MRTG log file")); 65 usage4(_("Unable to open MRTG log file"));
89 66
90 line = 0; 67 time_t timestamp = 0L;
91 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) { 68 char input_buffer[MAX_INPUT_BUFFER];
69 unsigned long average_incoming_rate = 0L;
70 unsigned long average_outgoing_rate = 0L;
71 unsigned long maximum_incoming_rate = 0L;
72 unsigned long maximum_outgoing_rate = 0L;
73 int line = 0;
74 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, mrtg_log_file_ptr)) {
92 75
93 line++; 76 line++;
94 77
@@ -102,280 +85,254 @@ main (int argc, char **argv)
102 break; 85 break;
103 86
104 /* grab the timestamp */ 87 /* grab the timestamp */
105 temp_buffer = strtok (input_buffer, " "); 88 char *temp_buffer = strtok(input_buffer, " ");
106 timestamp = strtoul (temp_buffer, NULL, 10); 89 timestamp = strtoul(temp_buffer, NULL, 10);
107 90
108 /* grab the average incoming transfer rate */ 91 /* grab the average incoming transfer rate */
109 temp_buffer = strtok (NULL, " "); 92 temp_buffer = strtok(NULL, " ");
110 average_incoming_rate = strtoul (temp_buffer, NULL, 10); 93 average_incoming_rate = strtoul(temp_buffer, NULL, 10);
111 94
112 /* grab the average outgoing transfer rate */ 95 /* grab the average outgoing transfer rate */
113 temp_buffer = strtok (NULL, " "); 96 temp_buffer = strtok(NULL, " ");
114 average_outgoing_rate = strtoul (temp_buffer, NULL, 10); 97 average_outgoing_rate = strtoul(temp_buffer, NULL, 10);
115 98
116 /* grab the maximum incoming transfer rate */ 99 /* grab the maximum incoming transfer rate */
117 temp_buffer = strtok (NULL, " "); 100 temp_buffer = strtok(NULL, " ");
118 maximum_incoming_rate = strtoul (temp_buffer, NULL, 10); 101 maximum_incoming_rate = strtoul(temp_buffer, NULL, 10);
119 102
120 /* grab the maximum outgoing transfer rate */ 103 /* grab the maximum outgoing transfer rate */
121 temp_buffer = strtok (NULL, " "); 104 temp_buffer = strtok(NULL, " ");
122 maximum_outgoing_rate = strtoul (temp_buffer, NULL, 10); 105 maximum_outgoing_rate = strtoul(temp_buffer, NULL, 10);
123 } 106 }
124 107
125 /* close the log file */ 108 /* close the log file */
126 fclose (fp); 109 fclose(mrtg_log_file_ptr);
127 110
128 /* if we couldn't read enough data, return an unknown error */ 111 /* if we couldn't read enough data, return an unknown error */
129 if (line <= 2) 112 if (line <= 2)
130 usage4 (_("Unable to process MRTG log file")); 113 usage4(_("Unable to process MRTG log file"));
131 114
132 /* make sure the MRTG data isn't too old */ 115 /* make sure the MRTG data isn't too old */
133 time (&current_time); 116 time_t current_time;
134 if ((expire_minutes > 0) && 117 time(&current_time);
135 (current_time - timestamp) > (expire_minutes * 60)) 118 if ((expire_minutes > 0) && (current_time - timestamp) > (expire_minutes * 60))
136 die (STATE_WARNING, _("MRTG data has expired (%d minutes old)\n"), 119 die(STATE_WARNING, _("MRTG data has expired (%d minutes old)\n"), (int)((current_time - timestamp) / 60));
137 (int) ((current_time - timestamp) / 60));
138 120
121 unsigned long incoming_rate = 0L;
122 unsigned long outgoing_rate = 0L;
139 /* else check the incoming/outgoing rates */ 123 /* else check the incoming/outgoing rates */
140 if (use_average) { 124 if (use_average) {
141 incoming_rate = average_incoming_rate; 125 incoming_rate = average_incoming_rate;
142 outgoing_rate = average_outgoing_rate; 126 outgoing_rate = average_outgoing_rate;
143 } 127 } else {
144 else {
145 incoming_rate = maximum_incoming_rate; 128 incoming_rate = maximum_incoming_rate;
146 outgoing_rate = maximum_outgoing_rate; 129 outgoing_rate = maximum_outgoing_rate;
147 } 130 }
148 131
132 double adjusted_incoming_rate = 0.0;
133 char incoming_speed_rating[8];
149 /* report incoming traffic in Bytes/sec */ 134 /* report incoming traffic in Bytes/sec */
150 if (incoming_rate < 1024) { 135 if (incoming_rate < 1024) {
151 strcpy (incoming_speed_rating, "B"); 136 strcpy(incoming_speed_rating, "B");
152 adjusted_incoming_rate = (double) incoming_rate; 137 adjusted_incoming_rate = (double)incoming_rate;
153 } 138 }
154 139
155 /* report incoming traffic in KBytes/sec */ 140 /* report incoming traffic in KBytes/sec */
156 else if (incoming_rate < (1024 * 1024)) { 141 else if (incoming_rate < (1024 * 1024)) {
157 strcpy (incoming_speed_rating, "KB"); 142 strcpy(incoming_speed_rating, "KB");
158 adjusted_incoming_rate = (double) (incoming_rate / 1024.0); 143 adjusted_incoming_rate = (double)(incoming_rate / 1024.0);
159 } 144 }
160 145
161 /* report incoming traffic in MBytes/sec */ 146 /* report incoming traffic in MBytes/sec */
162 else { 147 else {
163 strcpy (incoming_speed_rating, "MB"); 148 strcpy(incoming_speed_rating, "MB");
164 adjusted_incoming_rate = (double) (incoming_rate / 1024.0 / 1024.0); 149 adjusted_incoming_rate = (double)(incoming_rate / 1024.0 / 1024.0);
165 } 150 }
166 151
152 double adjusted_outgoing_rate = 0.0;
153 char outgoing_speed_rating[8];
167 /* report outgoing traffic in Bytes/sec */ 154 /* report outgoing traffic in Bytes/sec */
168 if (outgoing_rate < 1024) { 155 if (outgoing_rate < 1024) {
169 strcpy (outgoing_speed_rating, "B"); 156 strcpy(outgoing_speed_rating, "B");
170 adjusted_outgoing_rate = (double) outgoing_rate; 157 adjusted_outgoing_rate = (double)outgoing_rate;
171 } 158 }
172 159
173 /* report outgoing traffic in KBytes/sec */ 160 /* report outgoing traffic in KBytes/sec */
174 else if (outgoing_rate < (1024 * 1024)) { 161 else if (outgoing_rate < (1024 * 1024)) {
175 strcpy (outgoing_speed_rating, "KB"); 162 strcpy(outgoing_speed_rating, "KB");
176 adjusted_outgoing_rate = (double) (outgoing_rate / 1024.0); 163 adjusted_outgoing_rate = (double)(outgoing_rate / 1024.0);
177 } 164 }
178 165
179 /* report outgoing traffic in MBytes/sec */ 166 /* report outgoing traffic in MBytes/sec */
180 else { 167 else {
181 strcpy (outgoing_speed_rating, "MB"); 168 strcpy(outgoing_speed_rating, "MB");
182 adjusted_outgoing_rate = (double) (outgoing_rate / 1024.0 / 1024.0); 169 adjusted_outgoing_rate = (double)(outgoing_rate / 1024.0 / 1024.0);
183 } 170 }
184 171
185 if (incoming_rate > incoming_critical_threshold 172 int result = STATE_OK;
186 || outgoing_rate > outgoing_critical_threshold) { 173 if (incoming_rate > incoming_critical_threshold || outgoing_rate > outgoing_critical_threshold) {
187 result = STATE_CRITICAL; 174 result = STATE_CRITICAL;
188 } 175 } else if (incoming_rate > incoming_warning_threshold || outgoing_rate > outgoing_warning_threshold) {
189 else if (incoming_rate > incoming_warning_threshold
190 || outgoing_rate > outgoing_warning_threshold) {
191 result = STATE_WARNING; 176 result = STATE_WARNING;
192 } 177 }
193 178
194 xasprintf (&error_message, _("%s. In = %0.1f %s/s, %s. Out = %0.1f %s/s|%s %s\n"), 179 char *error_message;
195 (use_average) ? _("Avg") : _("Max"), adjusted_incoming_rate, 180 xasprintf(&error_message, _("%s. In = %0.1f %s/s, %s. Out = %0.1f %s/s|%s %s\n"), (use_average) ? _("Avg") : _("Max"),
196 incoming_speed_rating, (use_average) ? _("Avg") : _("Max"), 181 adjusted_incoming_rate, incoming_speed_rating, (use_average) ? _("Avg") : _("Max"), adjusted_outgoing_rate,
197 adjusted_outgoing_rate, outgoing_speed_rating, 182 outgoing_speed_rating,
198 fperfdata("in", adjusted_incoming_rate, incoming_speed_rating, 183 fperfdata("in", adjusted_incoming_rate, incoming_speed_rating, (int)incoming_warning_threshold, incoming_warning_threshold,
199 (int)incoming_warning_threshold, incoming_warning_threshold, 184 (int)incoming_critical_threshold, incoming_critical_threshold, true, 0, false, 0),
200 (int)incoming_critical_threshold, incoming_critical_threshold, 185 fperfdata("out", adjusted_outgoing_rate, outgoing_speed_rating, (int)outgoing_warning_threshold, outgoing_warning_threshold,
201 true, 0, false, 0), 186 (int)outgoing_critical_threshold, outgoing_critical_threshold, true, 0, false, 0));
202 fperfdata("out", adjusted_outgoing_rate, outgoing_speed_rating, 187
203 (int)outgoing_warning_threshold, outgoing_warning_threshold, 188 printf(_("Traffic %s - %s\n"), state_text(result), error_message);
204 (int)outgoing_critical_threshold, outgoing_critical_threshold,
205 true, 0, false, 0));
206
207 printf (_("Traffic %s - %s\n"), state_text(result), error_message);
208 189
209 return result; 190 return result;
210} 191}
211 192
212
213
214/* process command-line arguments */ 193/* process command-line arguments */
215int 194int process_arguments(int argc, char **argv) {
216process_arguments (int argc, char **argv) 195 static struct option longopts[] = {{"filename", required_argument, 0, 'F'},
217{ 196 {"expires", required_argument, 0, 'e'},
218 int c; 197 {"aggregation", required_argument, 0, 'a'},
219 198 {"critical", required_argument, 0, 'c'},
220 int option = 0; 199 {"warning", required_argument, 0, 'w'},
221 static struct option longopts[] = { 200 {"version", no_argument, 0, 'V'},
222 {"filename", required_argument, 0, 'F'}, 201 {"help", no_argument, 0, 'h'},
223 {"expires", required_argument, 0, 'e'}, 202 {0, 0, 0, 0}};
224 {"aggregation", required_argument, 0, 'a'},
225 {"critical", required_argument, 0, 'c'},
226 {"warning", required_argument, 0, 'w'},
227 {"version", no_argument, 0, 'V'},
228 {"help", no_argument, 0, 'h'},
229 {0, 0, 0, 0}
230 };
231 203
232 if (argc < 2) 204 if (argc < 2)
233 return ERROR; 205 return ERROR;
234 206
235 for (c = 1; c < argc; c++) { 207 for (int i = 1; i < argc; i++) {
236 if (strcmp ("-to", argv[c]) == 0) 208 if (strcmp("-to", argv[i]) == 0)
237 strcpy (argv[c], "-t"); 209 strcpy(argv[i], "-t");
238 else if (strcmp ("-wt", argv[c]) == 0) 210 else if (strcmp("-wt", argv[i]) == 0)
239 strcpy (argv[c], "-w"); 211 strcpy(argv[i], "-w");
240 else if (strcmp ("-ct", argv[c]) == 0) 212 else if (strcmp("-ct", argv[i]) == 0)
241 strcpy (argv[c], "-c"); 213 strcpy(argv[i], "-c");
242 } 214 }
243 215
216 int option_char;
217 int option = 0;
244 while (1) { 218 while (1) {
245 c = getopt_long (argc, argv, "hVF:e:a:c:w:", longopts, &option); 219 option_char = getopt_long(argc, argv, "hVF:e:a:c:w:", longopts, &option);
246 220
247 if (c == -1 || c == EOF) 221 if (option_char == -1 || option_char == EOF)
248 break; 222 break;
249 223
250 switch (c) { 224 switch (option_char) {
251 case 'F': /* input file */ 225 case 'F': /* input file */
252 log_file = optarg; 226 log_file = optarg;
253 break; 227 break;
254 case 'e': /* expiration time */ 228 case 'e': /* expiration time */
255 expire_minutes = atoi (optarg); 229 expire_minutes = atoi(optarg);
256 break; 230 break;
257 case 'a': /* aggregation (AVE or MAX) */ 231 case 'a': /* aggregation (AVE or MAX) */
258 if (!strcmp (optarg, "MAX")) 232 if (!strcmp(optarg, "MAX"))
259 use_average = false; 233 use_average = false;
260 else 234 else
261 use_average = true; 235 use_average = true;
262 break; 236 break;
263 case 'c': /* warning threshold */ 237 case 'c': /* warning threshold */
264 sscanf (optarg, "%lu,%lu", &incoming_critical_threshold, 238 sscanf(optarg, "%lu,%lu", &incoming_critical_threshold, &outgoing_critical_threshold);
265 &outgoing_critical_threshold);
266 break; 239 break;
267 case 'w': /* critical threshold */ 240 case 'w': /* critical threshold */
268 sscanf (optarg, "%lu,%lu", &incoming_warning_threshold, 241 sscanf(optarg, "%lu,%lu", &incoming_warning_threshold, &outgoing_warning_threshold);
269 &outgoing_warning_threshold);
270 break; 242 break;
271 case 'V': /* version */ 243 case 'V': /* version */
272 print_revision (progname, NP_VERSION); 244 print_revision(progname, NP_VERSION);
273 exit (STATE_UNKNOWN); 245 exit(STATE_UNKNOWN);
274 case 'h': /* help */ 246 case 'h': /* help */
275 print_help (); 247 print_help();
276 exit (STATE_UNKNOWN); 248 exit(STATE_UNKNOWN);
277 case '?': /* help */ 249 case '?': /* help */
278 usage5 (); 250 usage5();
279 } 251 }
280 } 252 }
281 253
282 c = optind; 254 option_char = optind;
283 if (argc > c && log_file == NULL) { 255 if (argc > option_char && log_file == NULL) {
284 log_file = argv[c++]; 256 log_file = argv[option_char++];
285 } 257 }
286 258
287 if (argc > c && expire_minutes == -1) { 259 if (argc > option_char && expire_minutes == -1) {
288 expire_minutes = atoi (argv[c++]); 260 expire_minutes = atoi(argv[option_char++]);
289 } 261 }
290 262
291 if (argc > c && strcmp (argv[c], "MAX") == 0) { 263 if (argc > option_char && strcmp(argv[option_char], "MAX") == 0) {
292 use_average = false; 264 use_average = false;
293 c++; 265 option_char++;
294 } 266 } else if (argc > option_char && strcmp(argv[option_char], "AVG") == 0) {
295 else if (argc > c && strcmp (argv[c], "AVG") == 0) {
296 use_average = true; 267 use_average = true;
297 c++; 268 option_char++;
298 } 269 }
299 270
300 if (argc > c && incoming_warning_threshold == 0) { 271 if (argc > option_char && incoming_warning_threshold == 0) {
301 incoming_warning_threshold = strtoul (argv[c++], NULL, 10); 272 incoming_warning_threshold = strtoul(argv[option_char++], NULL, 10);
302 } 273 }
303 274
304 if (argc > c && incoming_critical_threshold == 0) { 275 if (argc > option_char && incoming_critical_threshold == 0) {
305 incoming_critical_threshold = strtoul (argv[c++], NULL, 10); 276 incoming_critical_threshold = strtoul(argv[option_char++], NULL, 10);
306 } 277 }
307 278
308 if (argc > c && outgoing_warning_threshold == 0) { 279 if (argc > option_char && outgoing_warning_threshold == 0) {
309 outgoing_warning_threshold = strtoul (argv[c++], NULL, 10); 280 outgoing_warning_threshold = strtoul(argv[option_char++], NULL, 10);
310 }
311
312 if (argc > c && outgoing_critical_threshold == 0) {
313 outgoing_critical_threshold = strtoul (argv[c++], NULL, 10);
314 } 281 }
315 282
316 return validate_arguments (); 283 if (argc > option_char && outgoing_critical_threshold == 0) {
317} 284 outgoing_critical_threshold = strtoul(argv[option_char++], NULL, 10);
318 285 }
319 286
320int
321validate_arguments (void)
322{
323 return OK; 287 return OK;
324} 288}
325 289
326 290void print_help(void) {
327void 291 print_revision(progname, NP_VERSION);
328print_help (void) 292
329{ 293 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
330 print_revision (progname, NP_VERSION); 294 printf(COPYRIGHT, copyright, email);
331 295
332 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 296 printf("%s\n", _("This plugin will check the incoming/outgoing transfer rates of a router,"));
333 printf (COPYRIGHT, copyright, email); 297 printf("%s\n", _("switch, etc recorded in an MRTG log. If the newest log entry is older"));
334 298 printf("%s\n", _("than <expire_minutes>, a WARNING status is returned. If either the"));
335 printf ("%s\n", _("This plugin will check the incoming/outgoing transfer rates of a router,")); 299 printf("%s\n", _("incoming or outgoing rates exceed the <icl> or <ocl> thresholds (in"));
336 printf ("%s\n", _("switch, etc recorded in an MRTG log. If the newest log entry is older")); 300 printf("%s\n", _("Bytes/sec), a CRITICAL status results. If either of the rates exceed"));
337 printf ("%s\n", _("than <expire_minutes>, a WARNING status is returned. If either the")); 301 printf("%s\n", _("the <iwl> or <owl> thresholds (in Bytes/sec), a WARNING status results."));
338 printf ("%s\n", _("incoming or outgoing rates exceed the <icl> or <ocl> thresholds (in")); 302
339 printf ("%s\n", _("Bytes/sec), a CRITICAL status results. If either of the rates exceed")); 303 printf("\n\n");
340 printf ("%s\n", _("the <iwl> or <owl> thresholds (in Bytes/sec), a WARNING status results.")); 304
341 305 print_usage();
342 printf ("\n\n"); 306
343 307 printf(UT_HELP_VRSN);
344 print_usage (); 308 printf(UT_EXTRA_OPTS);
345 309
346 printf (UT_HELP_VRSN); 310 printf(" %s\n", "-F, --filename=STRING");
347 printf (UT_EXTRA_OPTS); 311 printf(" %s\n", _("File to read log from"));
348 312 printf(" %s\n", "-e, --expires=INTEGER");
349 printf (" %s\n", "-F, --filename=STRING"); 313 printf(" %s\n", _("Minutes after which log expires"));
350 printf (" %s\n", _("File to read log from")); 314 printf(" %s\n", "-a, --aggregation=(AVG|MAX)");
351 printf (" %s\n", "-e, --expires=INTEGER"); 315 printf(" %s\n", _("Test average or maximum"));
352 printf (" %s\n", _("Minutes after which log expires")); 316 printf(" %s\n", "-w, --warning");
353 printf (" %s\n", "-a, --aggregation=(AVG|MAX)"); 317 printf(" %s\n", _("Warning threshold pair <incoming>,<outgoing>"));
354 printf (" %s\n", _("Test average or maximum")); 318 printf(" %s\n", "-c, --critical");
355 printf (" %s\n", "-w, --warning"); 319 printf(" %s\n", _("Critical threshold pair <incoming>,<outgoing>"));
356 printf (" %s\n", _("Warning threshold pair <incoming>,<outgoing>")); 320
357 printf (" %s\n", "-c, --critical"); 321 printf("\n");
358 printf (" %s\n", _("Critical threshold pair <incoming>,<outgoing>")); 322 printf("%s\n", _("Notes:"));
359 323 printf(" %s\n", _("- MRTG stands for Multi Router Traffic Grapher. It can be downloaded from"));
360 printf ("\n"); 324 printf(" %s\n", " http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html");
361 printf ("%s\n", _("Notes:")); 325 printf(" %s\n", _("- While MRTG can monitor things other than traffic rates, this"));
362 printf (" %s\n", _("- MRTG stands for Multi Router Traffic Grapher. It can be downloaded from")); 326 printf(" %s\n", _(" plugin probably won't work with much else without modification."));
363 printf (" %s\n", " http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html"); 327 printf(" %s\n", _("- The calculated i/o rates are a little off from what MRTG actually"));
364 printf (" %s\n", _("- While MRTG can monitor things other than traffic rates, this")); 328 printf(" %s\n", _(" reports. I'm not sure why this is right now, but will look into it"));
365 printf (" %s\n", _(" plugin probably won't work with much else without modification.")); 329 printf(" %s\n", _(" for future enhancements of this plugin."));
366 printf (" %s\n", _("- The calculated i/o rates are a little off from what MRTG actually")); 330
367 printf (" %s\n", _(" reports. I'm not sure why this is right now, but will look into it")); 331 printf(UT_SUPPORT);
368 printf (" %s\n", _(" for future enhancements of this plugin."));
369
370 printf (UT_SUPPORT);
371} 332}
372 333
373 334void print_usage(void) {
374 335 printf(_("Usage"));
375void 336 printf(" %s -F <log_file> -a <AVG | MAX> -w <warning_pair>\n", progname);
376print_usage (void) 337 printf("-c <critical_pair> [-e expire_minutes]\n");
377{
378 printf (_("Usage"));
379 printf (" %s -F <log_file> -a <AVG | MAX> -w <warning_pair>\n",progname);
380 printf ("-c <critical_pair> [-e expire_minutes]\n");
381} 338}
diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c
index 6a7daf11..1f0b7099 100644
--- a/plugins/check_mysql.c
+++ b/plugins/check_mysql.c
@@ -5,7 +5,7 @@
5* License: GPL 5* License: GPL
6* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at) 6* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
7* Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net) 7* Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
8* Copyright (c) 1999-2011 Monitoring Plugins Development Team 8* Copyright (c) 1999-2024 Monitoring Plugins Development Team
9* 9*
10* Description: 10* Description:
11* 11*
@@ -31,7 +31,7 @@
31*****************************************************************************/ 31*****************************************************************************/
32 32
33const char *progname = "check_mysql"; 33const char *progname = "check_mysql";
34const char *copyright = "1999-2011"; 34const char *copyright = "1999-2024";
35const char *email = "devel@monitoring-plugins.org"; 35const char *email = "devel@monitoring-plugins.org";
36 36
37#define SLAVERESULTSIZE 96 37#define SLAVERESULTSIZE 96
@@ -59,8 +59,8 @@ bool ssl = false;
59char *opt_file = NULL; 59char *opt_file = NULL;
60char *opt_group = NULL; 60char *opt_group = NULL;
61unsigned int db_port = MYSQL_PORT; 61unsigned int db_port = MYSQL_PORT;
62int check_slave = 0, warn_sec = 0, crit_sec = 0; 62bool check_slave = false;
63int ignore_auth = 0; 63bool ignore_auth = false;
64int verbose = 0; 64int verbose = 0;
65 65
66static double warning_time = 0; 66static double warning_time = 0;
@@ -456,10 +456,10 @@ process_arguments (int argc, char **argv)
456 db_port = atoi (optarg); 456 db_port = atoi (optarg);
457 break; 457 break;
458 case 'S': 458 case 'S':
459 check_slave = 1; /* check-slave */ 459 check_slave = true; /* check-slave */
460 break; 460 break;
461 case 'n': 461 case 'n':
462 ignore_auth = 1; /* ignore-auth */ 462 ignore_auth = true; /* ignore-auth */
463 break; 463 break;
464 case 'w': 464 case 'w':
465 warning = optarg; 465 warning = optarg;
diff --git a/plugins/check_mysql_query.c b/plugins/check_mysql_query.c
index 842b7a2f..79b6e2f4 100644
--- a/plugins/check_mysql_query.c
+++ b/plugins/check_mysql_query.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_mysql_query plugin 3 * Monitoring check_mysql_query plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2006-2009 Monitoring Plugins Development Team 6 * Copyright (c) 2006-2024 Monitoring Plugins Development Team
7* Original code from check_mysql, copyright 1999 Didi Rieder 7 * Original code from check_mysql, copyright 1999 Didi Rieder
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_mysql_query plugin 11 * This file contains the check_mysql_query plugin
12* 12 *
13* This plugin is for running arbitrary SQL and checking the results 13 * This plugin is for running arbitrary SQL and checking the results
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_mysql_query"; 32const char *progname = "check_mysql_query";
33const char *copyright = "1999-2007"; 33const char *copyright = "1999-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -41,117 +41,109 @@ const char *email = "devel@monitoring-plugins.org";
41#include <mysql.h> 41#include <mysql.h>
42#include <errmsg.h> 42#include <errmsg.h>
43 43
44char *db_user = NULL; 44static char *db_user = NULL;
45char *db_host = NULL; 45static char *db_host = NULL;
46char *db_socket = NULL; 46static char *db_socket = NULL;
47char *db_pass = NULL; 47static char *db_pass = NULL;
48char *db = NULL; 48static char *db = NULL;
49char *opt_file = NULL; 49static char *opt_file = NULL;
50char *opt_group = NULL; 50static char *opt_group = NULL;
51unsigned int db_port = MYSQL_PORT; 51static unsigned int db_port = MYSQL_PORT;
52 52
53int process_arguments (int, char **); 53static int process_arguments(int /*argc*/, char ** /*argv*/);
54int validate_arguments (void); 54static int validate_arguments(void);
55void print_help (void); 55static void print_help(void);
56void print_usage (void); 56void print_usage(void);
57 57
58char *sql_query = NULL; 58static char *sql_query = NULL;
59int verbose = 0; 59static int verbose = 0;
60thresholds *my_thresholds = NULL; 60static thresholds *my_thresholds = NULL;
61 61
62 62int main(int argc, char **argv) {
63int 63 setlocale(LC_ALL, "");
64main (int argc, char **argv) 64 bindtextdomain(PACKAGE, LOCALEDIR);
65{ 65 textdomain(PACKAGE);
66
67 MYSQL mysql;
68 MYSQL_RES *res;
69 MYSQL_ROW row;
70
71 double value;
72 char *error = NULL;
73 int status;
74
75 setlocale (LC_ALL, "");
76 bindtextdomain (PACKAGE, LOCALEDIR);
77 textdomain (PACKAGE);
78 66
79 /* Parse extra opts if any */ 67 /* Parse extra opts if any */
80 argv=np_extra_opts (&argc, argv, progname); 68 argv = np_extra_opts(&argc, argv, progname);
81 69
82 if (process_arguments (argc, argv) == ERROR) 70 if (process_arguments(argc, argv) == ERROR)
83 usage4 (_("Could not parse arguments")); 71 usage4(_("Could not parse arguments"));
84 72
73 MYSQL mysql;
85 /* initialize mysql */ 74 /* initialize mysql */
86 mysql_init (&mysql); 75 mysql_init(&mysql);
87 76
88 if (opt_file != NULL) 77 if (opt_file != NULL)
89 mysql_options(&mysql,MYSQL_READ_DEFAULT_FILE,opt_file); 78 mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, opt_file);
90 79
91 if (opt_group != NULL) 80 if (opt_group != NULL)
92 mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,opt_group); 81 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, opt_group);
93 else 82 else
94 mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"client"); 83 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client");
95 84
96 /* establish a connection to the server and error checking */ 85 /* establish a connection to the server and error checking */
97 if (!mysql_real_connect(&mysql,db_host,db_user,db_pass,db,db_port,db_socket,0)) { 86 if (!mysql_real_connect(&mysql, db_host, db_user, db_pass, db, db_port, db_socket, 0)) {
98 if (mysql_errno (&mysql) == CR_UNKNOWN_HOST) 87 if (mysql_errno(&mysql) == CR_UNKNOWN_HOST)
99 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 88 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
100 else if (mysql_errno (&mysql) == CR_VERSION_ERROR) 89 else if (mysql_errno(&mysql) == CR_VERSION_ERROR)
101 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 90 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
102 else if (mysql_errno (&mysql) == CR_OUT_OF_MEMORY) 91 else if (mysql_errno(&mysql) == CR_OUT_OF_MEMORY)
103 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 92 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
104 else if (mysql_errno (&mysql) == CR_IPSOCK_ERROR) 93 else if (mysql_errno(&mysql) == CR_IPSOCK_ERROR)
105 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 94 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
106 else if (mysql_errno (&mysql) == CR_SOCKET_CREATE_ERROR) 95 else if (mysql_errno(&mysql) == CR_SOCKET_CREATE_ERROR)
107 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 96 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
108 else 97 else
109 die (STATE_CRITICAL, "QUERY %s: %s\n", _("CRITICAL"), mysql_error (&mysql)); 98 die(STATE_CRITICAL, "QUERY %s: %s\n", _("CRITICAL"), mysql_error(&mysql));
110 } 99 }
111 100
112 if (mysql_query (&mysql, sql_query) != 0) { 101 char *error = NULL;
102 if (mysql_query(&mysql, sql_query) != 0) {
113 error = strdup(mysql_error(&mysql)); 103 error = strdup(mysql_error(&mysql));
114 mysql_close (&mysql); 104 mysql_close(&mysql);
115 die (STATE_CRITICAL, "QUERY %s: %s - %s\n", _("CRITICAL"), _("Error with query"), error); 105 die(STATE_CRITICAL, "QUERY %s: %s - %s\n", _("CRITICAL"), _("Error with query"), error);
116 } 106 }
117 107
108 MYSQL_RES *res;
118 /* store the result */ 109 /* store the result */
119 if ( (res = mysql_store_result (&mysql)) == NULL) { 110 if ((res = mysql_store_result(&mysql)) == NULL) {
120 error = strdup(mysql_error(&mysql)); 111 error = strdup(mysql_error(&mysql));
121 mysql_close (&mysql); 112 mysql_close(&mysql);
122 die (STATE_CRITICAL, "QUERY %s: Error with store_result - %s\n", _("CRITICAL"), error); 113 die(STATE_CRITICAL, "QUERY %s: Error with store_result - %s\n", _("CRITICAL"), error);
123 } 114 }
124 115
125 /* Check there is some data */ 116 /* Check there is some data */
126 if (mysql_num_rows(res) == 0) { 117 if (mysql_num_rows(res) == 0) {
127 mysql_close(&mysql); 118 mysql_close(&mysql);
128 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), _("No rows returned")); 119 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), _("No rows returned"));
129 } 120 }
130 121
122 MYSQL_ROW row;
131 /* fetch the first row */ 123 /* fetch the first row */
132 if ( (row = mysql_fetch_row (res)) == NULL) { 124 if ((row = mysql_fetch_row(res)) == NULL) {
133 error = strdup(mysql_error(&mysql)); 125 error = strdup(mysql_error(&mysql));
134 mysql_free_result (res); 126 mysql_free_result(res);
135 mysql_close (&mysql); 127 mysql_close(&mysql);
136 die (STATE_CRITICAL, "QUERY %s: Fetch row error - %s\n", _("CRITICAL"), error); 128 die(STATE_CRITICAL, "QUERY %s: Fetch row error - %s\n", _("CRITICAL"), error);
137 } 129 }
138 130
139 if (! is_numeric(row[0])) { 131 if (!is_numeric(row[0])) {
140 die (STATE_CRITICAL, "QUERY %s: %s - '%s'\n", _("CRITICAL"), _("Is not a numeric"), row[0]); 132 die(STATE_CRITICAL, "QUERY %s: %s - '%s'\n", _("CRITICAL"), _("Is not a numeric"), row[0]);
141 } 133 }
142 134
143 value = strtod(row[0], NULL); 135 double value = strtod(row[0], NULL);
144 136
145 /* free the result */ 137 /* free the result */
146 mysql_free_result (res); 138 mysql_free_result(res);
147 139
148 /* close the connection */ 140 /* close the connection */
149 mysql_close (&mysql); 141 mysql_close(&mysql);
150 142
151 if (verbose >= 3) 143 if (verbose >= 3)
152 printf("mysql result: %f\n", value); 144 printf("mysql result: %f\n", value);
153 145
154 status = get_status(value, my_thresholds); 146 int status = get_status(value, my_thresholds);
155 147
156 if (status == STATE_OK) { 148 if (status == STATE_OK) {
157 printf("QUERY %s: ", _("OK")); 149 printf("QUERY %s: ", _("OK"));
@@ -161,73 +153,54 @@ main (int argc, char **argv)
161 printf("QUERY %s: ", _("CRITICAL")); 153 printf("QUERY %s: ", _("CRITICAL"));
162 } 154 }
163 printf(_("'%s' returned %f | %s"), sql_query, value, 155 printf(_("'%s' returned %f | %s"), sql_query, value,
164 fperfdata("result", value, "", 156 fperfdata("result", value, "", my_thresholds->warning ? true : false, my_thresholds->warning ? my_thresholds->warning->end : 0,
165 my_thresholds->warning?true:false, my_thresholds->warning?my_thresholds->warning->end:0, 157 my_thresholds->critical ? true : false, my_thresholds->critical ? my_thresholds->critical->end : 0, false, 0, false,
166 my_thresholds->critical?true:false, my_thresholds->critical?my_thresholds->critical->end:0, 158 0));
167 false, 0,
168 false, 0)
169 );
170 printf("\n"); 159 printf("\n");
171 160
172 return status; 161 return status;
173} 162}
174 163
175
176/* process command-line arguments */ 164/* process command-line arguments */
177int 165int process_arguments(int argc, char **argv) {
178process_arguments (int argc, char **argv)
179{
180 int c;
181 char *warning = NULL;
182 char *critical = NULL;
183
184 int option = 0;
185 static struct option longopts[] = { 166 static struct option longopts[] = {
186 {"hostname", required_argument, 0, 'H'}, 167 {"hostname", required_argument, 0, 'H'}, {"socket", required_argument, 0, 's'}, {"database", required_argument, 0, 'd'},
187 {"socket", required_argument, 0, 's'}, 168 {"username", required_argument, 0, 'u'}, {"password", required_argument, 0, 'p'}, {"file", required_argument, 0, 'f'},
188 {"database", required_argument, 0, 'd'}, 169 {"group", required_argument, 0, 'g'}, {"port", required_argument, 0, 'P'}, {"verbose", no_argument, 0, 'v'},
189 {"username", required_argument, 0, 'u'}, 170 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"query", required_argument, 0, 'q'},
190 {"password", required_argument, 0, 'p'}, 171 {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {0, 0, 0, 0}};
191 {"file", required_argument, 0, 'f'},
192 {"group", required_argument, 0, 'g'},
193 {"port", required_argument, 0, 'P'},
194 {"verbose", no_argument, 0, 'v'},
195 {"version", no_argument, 0, 'V'},
196 {"help", no_argument, 0, 'h'},
197 {"query", required_argument, 0, 'q'},
198 {"warning", required_argument, 0, 'w'},
199 {"critical", required_argument, 0, 'c'},
200 {0, 0, 0, 0}
201 };
202 172
203 if (argc < 1) 173 if (argc < 1)
204 return ERROR; 174 return ERROR;
205 175
206 while (1) { 176 char *warning = NULL;
207 c = getopt_long (argc, argv, "hvVP:p:u:d:H:s:q:w:c:f:g:", longopts, &option); 177 char *critical = NULL;
178
179 while (true) {
180 int option = 0;
181 int option_char = getopt_long(argc, argv, "hvVP:p:u:d:H:s:q:w:c:f:g:", longopts, &option);
208 182
209 if (c == -1 || c == EOF) 183 if (option_char == -1 || option_char == EOF)
210 break; 184 break;
211 185
212 switch (c) { 186 switch (option_char) {
213 case 'H': /* hostname */ 187 case 'H': /* hostname */
214 if (is_host (optarg)) { 188 if (is_host(optarg)) {
215 db_host = optarg; 189 db_host = optarg;
216 } 190 } else {
217 else { 191 usage2(_("Invalid hostname/address"), optarg);
218 usage2 (_("Invalid hostname/address"), optarg);
219 } 192 }
220 break; 193 break;
221 case 's': /* socket */ 194 case 's': /* socket */
222 db_socket = optarg; 195 db_socket = optarg;
223 break; 196 break;
224 case 'd': /* database */ 197 case 'd': /* database */
225 db = optarg; 198 db = optarg;
226 break; 199 break;
227 case 'u': /* username */ 200 case 'u': /* username */
228 db_user = optarg; 201 db_user = optarg;
229 break; 202 break;
230 case 'p': /* authentication information: password */ 203 case 'p': /* authentication information: password */
231 db_pass = strdup(optarg); 204 db_pass = strdup(optarg);
232 205
233 /* Delete the password from process list */ 206 /* Delete the password from process list */
@@ -236,24 +209,24 @@ process_arguments (int argc, char **argv)
236 optarg++; 209 optarg++;
237 } 210 }
238 break; 211 break;
239 case 'f': /* client options file */ 212 case 'f': /* client options file */
240 opt_file = optarg; 213 opt_file = optarg;
241 break; 214 break;
242 case 'g': /* client options group */ 215 case 'g': /* client options group */
243 opt_group = optarg; 216 opt_group = optarg;
244 break; 217 break;
245 case 'P': /* critical time threshold */ 218 case 'P': /* critical time threshold */
246 db_port = atoi (optarg); 219 db_port = atoi(optarg);
247 break; 220 break;
248 case 'v': 221 case 'v':
249 verbose++; 222 verbose++;
250 break; 223 break;
251 case 'V': /* version */ 224 case 'V': /* version */
252 print_revision (progname, NP_VERSION); 225 print_revision(progname, NP_VERSION);
253 exit (STATE_UNKNOWN); 226 exit(STATE_UNKNOWN);
254 case 'h': /* help */ 227 case 'h': /* help */
255 print_help (); 228 print_help();
256 exit (STATE_UNKNOWN); 229 exit(STATE_UNKNOWN);
257 case 'q': 230 case 'q':
258 xasprintf(&sql_query, "%s", optarg); 231 xasprintf(&sql_query, "%s", optarg);
259 break; 232 break;
@@ -263,22 +236,17 @@ process_arguments (int argc, char **argv)
263 case 'c': 236 case 'c':
264 critical = optarg; 237 critical = optarg;
265 break; 238 break;
266 case '?': /* help */ 239 case '?': /* help */
267 usage5 (); 240 usage5();
268 } 241 }
269 } 242 }
270 243
271 c = optind;
272
273 set_thresholds(&my_thresholds, warning, critical); 244 set_thresholds(&my_thresholds, warning, critical);
274 245
275 return validate_arguments (); 246 return validate_arguments();
276} 247}
277 248
278 249int validate_arguments(void) {
279int
280validate_arguments (void)
281{
282 if (sql_query == NULL) 250 if (sql_query == NULL)
283 usage("Must specify a SQL query to run"); 251 usage("Must specify a SQL query to run");
284 252
@@ -294,61 +262,55 @@ validate_arguments (void)
294 return OK; 262 return OK;
295} 263}
296 264
297 265void print_help(void) {
298void
299print_help (void)
300{
301 char *myport; 266 char *myport;
302 xasprintf (&myport, "%d", MYSQL_PORT); 267 xasprintf(&myport, "%d", MYSQL_PORT);
303 268
304 print_revision (progname, NP_VERSION); 269 print_revision(progname, NP_VERSION);
305 270
306 printf (_(COPYRIGHT), copyright, email); 271 printf(_(COPYRIGHT), copyright, email);
307 272
308 printf ("%s\n", _("This program checks a query result against threshold levels")); 273 printf("%s\n", _("This program checks a query result against threshold levels"));
309 274
310 printf ("\n\n"); 275 printf("\n\n");
311 276
312 print_usage (); 277 print_usage();
313 278
314 printf (UT_HELP_VRSN); 279 printf(UT_HELP_VRSN);
315 printf (UT_EXTRA_OPTS); 280 printf(UT_EXTRA_OPTS);
316 printf (" -q, --query=STRING\n"); 281 printf(" -q, --query=STRING\n");
317 printf (" %s\n", _("SQL query to run. Only first column in first row will be read")); 282 printf(" %s\n", _("SQL query to run. Only first column in first row will be read"));
318 printf (UT_WARN_CRIT_RANGE); 283 printf(UT_WARN_CRIT_RANGE);
319 printf (UT_HOST_PORT, 'P', myport); 284 printf(UT_HOST_PORT, 'P', myport);
320 printf (" %s\n", "-s, --socket=STRING"); 285 printf(" %s\n", "-s, --socket=STRING");
321 printf (" %s\n", _("Use the specified socket (has no effect if -H is used)")); 286 printf(" %s\n", _("Use the specified socket (has no effect if -H is used)"));
322 printf (" -d, --database=STRING\n"); 287 printf(" -d, --database=STRING\n");
323 printf (" %s\n", _("Database to check")); 288 printf(" %s\n", _("Database to check"));
324 printf (" %s\n", "-f, --file=STRING"); 289 printf(" %s\n", "-f, --file=STRING");
325 printf (" %s\n", _("Read from the specified client options file")); 290 printf(" %s\n", _("Read from the specified client options file"));
326 printf (" %s\n", "-g, --group=STRING"); 291 printf(" %s\n", "-g, --group=STRING");
327 printf (" %s\n", _("Use a client options group")); 292 printf(" %s\n", _("Use a client options group"));
328 printf (" -u, --username=STRING\n"); 293 printf(" -u, --username=STRING\n");
329 printf (" %s\n", _("Username to login with")); 294 printf(" %s\n", _("Username to login with"));
330 printf (" -p, --password=STRING\n"); 295 printf(" -p, --password=STRING\n");
331 printf (" %s\n", _("Password to login with")); 296 printf(" %s\n", _("Password to login with"));
332 printf (" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!")); 297 printf(" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!"));
333 printf (" %s\n", _("Your clear-text password could be visible as a process table entry")); 298 printf(" %s\n", _("Your clear-text password could be visible as a process table entry"));
334 299
335 printf ("\n"); 300 printf("\n");
336 printf (" %s\n", _("A query is required. The result from the query should be numeric.")); 301 printf(" %s\n", _("A query is required. The result from the query should be numeric."));
337 printf (" %s\n", _("For extra security, create a user with minimal access.")); 302 printf(" %s\n", _("For extra security, create a user with minimal access."));
338 303
339 printf ("\n"); 304 printf("\n");
340 printf ("%s\n", _("Notes:")); 305 printf("%s\n", _("Notes:"));
341 printf (" %s\n", _("You must specify -p with an empty string to force an empty password,")); 306 printf(" %s\n", _("You must specify -p with an empty string to force an empty password,"));
342 printf (" %s\n", _("overriding any my.cnf settings.")); 307 printf(" %s\n", _("overriding any my.cnf settings."));
343
344 printf (UT_SUPPORT);
345}
346 308
309 printf(UT_SUPPORT);
310}
347 311
348void 312void print_usage(void) {
349print_usage (void) 313 printf("%s\n", _("Usage:"));
350{ 314 printf(" %s -q SQL_query [-w warn] [-c crit] [-H host] [-P port] [-s socket]\n", progname);
351 printf ("%s\n", _("Usage:")); 315 printf(" [-d database] [-u user] [-p password] [-f optfile] [-g group]\n");
352 printf (" %s -q SQL_query [-w warn] [-c crit] [-H host] [-P port] [-s socket]\n",progname);
353 printf (" [-d database] [-u user] [-p password] [-f optfile] [-g group]\n");
354} 316}
diff --git a/plugins/check_nagios.c b/plugins/check_nagios.c
index 40d68f03..48629be3 100644
--- a/plugins/check_nagios.c
+++ b/plugins/check_nagios.c
@@ -1,58 +1,56 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_nagios plugin 3 * Monitoring check_nagios plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_nagios plugin 10 * This file contains the check_nagios plugin
11* 11 *
12* This plugin checks the status of the Nagios process on the local machine. 12 * This plugin checks the status of the Nagios process on the local machine.
13* The plugin will check to make sure the Nagios status log is no older than 13 * The plugin will check to make sure the Nagios status log is no older than
14* the number of minutes specified by the expires option. 14 * the number of minutes specified by the expires option.
15* It also checks the process table for a process matching the command 15 * It also checks the process table for a process matching the command
16* argument. 16 * argument.
17* 17 *
18* 18 *
19* This program is free software: you can redistribute it and/or modify 19 * This program is free software: you can redistribute it and/or modify
20* it under the terms of the GNU General Public License as published by 20 * it under the terms of the GNU General Public License as published by
21* the Free Software Foundation, either version 3 of the License, or 21 * the Free Software Foundation, either version 3 of the License, or
22* (at your option) any later version. 22 * (at your option) any later version.
23* 23 *
24* This program is distributed in the hope that it will be useful, 24 * This program is distributed in the hope that it will be useful,
25* but WITHOUT ANY WARRANTY; without even the implied warranty of 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27* GNU General Public License for more details. 27 * GNU General Public License for more details.
28* 28 *
29* You should have received a copy of the GNU General Public License 29 * You should have received a copy of the GNU General Public License
30* along with this program. If not, see <http://www.gnu.org/licenses/>. 30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31* 31 *
32* 32 *
33*****************************************************************************/ 33 *****************************************************************************/
34 34
35const char *progname = "check_nagios"; 35const char *progname = "check_nagios";
36const char *copyright = "1999-2007"; 36const char *copyright = "1999-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
40#include "runcmd.h" 40#include "runcmd.h"
41#include "utils.h" 41#include "utils.h"
42 42
43int process_arguments (int, char **); 43static int process_arguments(int /*argc*/, char ** /*argv*/);
44void print_help (void); 44static void print_help(void);
45void print_usage (void); 45void print_usage(void);
46 46
47char *status_log = NULL; 47static char *status_log = NULL;
48char *process_string = NULL; 48static char *process_string = NULL;
49int expire_minutes = 0; 49static int expire_minutes = 0;
50 50
51int verbose = 0; 51static int verbose = 0;
52 52
53int 53int main(int argc, char **argv) {
54main (int argc, char **argv)
55{
56 int result = STATE_UNKNOWN; 54 int result = STATE_UNKNOWN;
57 char input_buffer[MAX_INPUT_BUFFER]; 55 char input_buffer[MAX_INPUT_BUFFER];
58 unsigned long latest_entry_time = 0L; 56 unsigned long latest_entry_time = 0L;
@@ -73,253 +71,231 @@ main (int argc, char **argv)
73#endif /* PS_USES_PROCETIME */ 71#endif /* PS_USES_PROCETIME */
74 char procprog[MAX_INPUT_BUFFER]; 72 char procprog[MAX_INPUT_BUFFER];
75 char *procargs; 73 char *procargs;
76 int pos, cols; 74 int pos;
75 int cols;
77 int expected_cols = PS_COLS - 1; 76 int expected_cols = PS_COLS - 1;
78 const char *zombie = "Z"; 77 const char *zombie = "Z";
79 char *temp_string; 78 char *temp_string;
80 output chld_out, chld_err; 79 output chld_out;
80 output chld_err;
81 size_t i; 81 size_t i;
82 82
83 setlocale (LC_ALL, ""); 83 setlocale(LC_ALL, "");
84 bindtextdomain (PACKAGE, LOCALEDIR); 84 bindtextdomain(PACKAGE, LOCALEDIR);
85 textdomain (PACKAGE); 85 textdomain(PACKAGE);
86 86
87 /* Parse extra opts if any */ 87 /* Parse extra opts if any */
88 argv=np_extra_opts (&argc, argv, progname); 88 argv = np_extra_opts(&argc, argv, progname);
89 89
90 if (process_arguments (argc, argv) == ERROR) 90 if (process_arguments(argc, argv) == ERROR)
91 usage_va(_("Could not parse arguments")); 91 usage_va(_("Could not parse arguments"));
92 92
93 /* Set signal handling and alarm timeout */ 93 /* Set signal handling and alarm timeout */
94 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 94 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
95 usage_va(_("Cannot catch SIGALRM")); 95 usage_va(_("Cannot catch SIGALRM"));
96 } 96 }
97 97
98 /* handle timeouts gracefully... */ 98 /* handle timeouts gracefully... */
99 alarm (timeout_interval); 99 alarm(timeout_interval);
100 100
101 /* open the status log */ 101 /* open the status log */
102 fp = fopen (status_log, "r"); 102 fp = fopen(status_log, "r");
103 if (fp == NULL) { 103 if (fp == NULL) {
104 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!")); 104 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!"));
105 } 105 }
106 106
107 /* get the date/time of the last item updated in the log */ 107 /* get the date/time of the last item updated in the log */
108 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) { 108 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
109 if ((temp_ptr = strstr (input_buffer, "created=")) != NULL) { 109 if ((temp_ptr = strstr(input_buffer, "created=")) != NULL) {
110 temp_entry_time = strtoul (temp_ptr + 8, NULL, 10); 110 temp_entry_time = strtoul(temp_ptr + 8, NULL, 10);
111 latest_entry_time = temp_entry_time; 111 latest_entry_time = temp_entry_time;
112 break; 112 break;
113 } else if ((temp_ptr = strtok (input_buffer, "]")) != NULL) { 113 }
114 temp_entry_time = strtoul (temp_ptr + 1, NULL, 10); 114 if ((temp_ptr = strtok(input_buffer, "]")) != NULL) {
115 temp_entry_time = strtoul(temp_ptr + 1, NULL, 10);
115 if (temp_entry_time > latest_entry_time) 116 if (temp_entry_time > latest_entry_time)
116 latest_entry_time = temp_entry_time; 117 latest_entry_time = temp_entry_time;
117 } 118 }
118 } 119 }
119 fclose (fp); 120 fclose(fp);
120 121
121 if (verbose >= 2) 122 if (verbose >= 2)
122 printf("command: %s\n", PS_COMMAND); 123 printf("command: %s\n", PS_COMMAND);
123 124
124 /* run the command to check for the Nagios process.. */ 125 /* run the command to check for the Nagios process.. */
125 if((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0) 126 if ((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0)
126 result = STATE_WARNING; 127 result = STATE_WARNING;
127 128
128 /* count the number of matching Nagios processes... */ 129 /* count the number of matching Nagios processes... */
129 for(i = 0; i < chld_out.lines; i++) { 130 for (i = 0; i < chld_out.lines; i++) {
130 cols = sscanf (chld_out.line[i], PS_FORMAT, PS_VARLIST); 131 cols = sscanf(chld_out.line[i], PS_FORMAT, PS_VARLIST);
131 /* Zombie processes do not give a procprog command */ 132 /* Zombie processes do not give a procprog command */
132 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) { 133 if (cols == (expected_cols - 1) && strstr(procstat, zombie)) {
133 cols = expected_cols; 134 cols = expected_cols;
134 /* Set some value for procargs for the strip command further below 135 /* Set some value for procargs for the strip command further below
135 * Seen to be a problem on some Solaris 7 and 8 systems */ 136 * Seen to be a problem on some Solaris 7 and 8 systems */
136 chld_out.line[i][pos] = '\n'; 137 chld_out.line[i][pos] = '\n';
137 chld_out.line[i][pos+1] = 0x0; 138 chld_out.line[i][pos + 1] = 0x0;
138 } 139 }
139 if ( cols >= expected_cols ) { 140 if (cols >= expected_cols) {
140 xasprintf (&procargs, "%s", chld_out.line[i] + pos); 141 xasprintf(&procargs, "%s", chld_out.line[i] + pos);
141 strip (procargs); 142 strip(procargs);
142 143
143 /* Some ps return full pathname for command. This removes path */ 144 /* Some ps return full pathname for command. This removes path */
144 temp_string = strtok ((char *)procprog, "/"); 145 temp_string = strtok((char *)procprog, "/");
145 while (temp_string) { 146 while (temp_string) {
146 strcpy(procprog, temp_string); 147 strcpy(procprog, temp_string);
147 temp_string = strtok (NULL, "/"); 148 temp_string = strtok(NULL, "/");
148 } 149 }
149 150
150 /* May get empty procargs */ 151 /* May get empty procargs */
151 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs,"")) { 152 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs, "")) {
152 proc_entries++; 153 proc_entries++;
153 if (verbose >= 2) { 154 if (verbose >= 2) {
154 printf (_("Found process: %s %s\n"), procprog, procargs); 155 printf(_("Found process: %s %s\n"), procprog, procargs);
155 } 156 }
156 } 157 }
157 } 158 }
158 } 159 }
159 160
160 /* If we get anything on stderr, at least set warning */ 161 /* If we get anything on stderr, at least set warning */
161 if(chld_err.buflen) 162 if (chld_err.buflen)
162 result = max_state (result, STATE_WARNING); 163 result = max_state(result, STATE_WARNING);
163 164
164 /* reset the alarm handler */ 165 /* reset the alarm handler */
165 alarm (0); 166 alarm(0);
166 167
167 if (proc_entries == 0) { 168 if (proc_entries == 0) {
168 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Could not locate a running Nagios process!")); 169 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Could not locate a running Nagios process!"));
169 } 170 }
170 171
171 if (latest_entry_time == 0L) { 172 if (latest_entry_time == 0L) {
172 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time")); 173 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time"));
173 } 174 }
174 175
175 time (&current_time); 176 time(&current_time);
176 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) { 177 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) {
177 result = STATE_WARNING; 178 result = STATE_WARNING;
178 } else { 179 } else {
179 result = STATE_OK; 180 result = STATE_OK;
180 } 181 }
181 182
182 printf ("NAGIOS %s: ", (result == STATE_OK) ? _("OK") : _("WARNING")); 183 printf("NAGIOS %s: ", (result == STATE_OK) ? _("OK") : _("WARNING"));
183 printf (ngettext ("%d process", "%d processes", proc_entries), proc_entries); 184 printf(ngettext("%d process", "%d processes", proc_entries), proc_entries);
184 printf (", "); 185 printf(", ");
185 printf ( 186 printf(ngettext("status log updated %d second ago", "status log updated %d seconds ago", (int)(current_time - latest_entry_time)),
186 ngettext ("status log updated %d second ago", 187 (int)(current_time - latest_entry_time));
187 "status log updated %d seconds ago", 188 printf("\n");
188 (int) (current_time - latest_entry_time) ),
189 (int) (current_time - latest_entry_time) );
190 printf ("\n");
191 189
192 return result; 190 return result;
193} 191}
194 192
195
196
197/* process command-line arguments */ 193/* process command-line arguments */
198int 194int process_arguments(int argc, char **argv) {
199process_arguments (int argc, char **argv)
200{
201 int c; 195 int c;
202 196
203 int option = 0; 197 int option = 0;
204 static struct option longopts[] = { 198 static struct option longopts[] = {{"filename", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'},
205 {"filename", required_argument, 0, 'F'}, 199 {"command", required_argument, 0, 'C'}, {"timeout", optional_argument, 0, 't'},
206 {"expires", required_argument, 0, 'e'}, 200 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'},
207 {"command", required_argument, 0, 'C'}, 201 {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}};
208 {"timeout", optional_argument, 0, 't'},
209 {"version", no_argument, 0, 'V'},
210 {"help", no_argument, 0, 'h'},
211 {"verbose", no_argument, 0, 'v'},
212 {0, 0, 0, 0}
213 };
214 202
215 if (argc < 2) 203 if (argc < 2)
216 return ERROR; 204 return ERROR;
217 205
218 if (!is_option (argv[1])) { 206 if (!is_option(argv[1])) {
219 status_log = argv[1]; 207 status_log = argv[1];
220 if (is_intnonneg (argv[2])) 208 if (is_intnonneg(argv[2]))
221 expire_minutes = atoi (argv[2]); 209 expire_minutes = atoi(argv[2]);
222 else 210 else
223 die (STATE_UNKNOWN, 211 die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
224 _("Expiration time must be an integer (seconds)\n"));
225 process_string = argv[3]; 212 process_string = argv[3];
226 return OK; 213 return OK;
227 } 214 }
228 215
229 while (1) { 216 while (1) {
230 c = getopt_long (argc, argv, "+hVvF:C:e:t:", longopts, &option); 217 c = getopt_long(argc, argv, "+hVvF:C:e:t:", longopts, &option);
231 218
232 if (c == -1 || c == EOF || c == 1) 219 if (c == -1 || c == EOF || c == 1)
233 break; 220 break;
234 221
235 switch (c) { 222 switch (c) {
236 case 'h': /* help */ 223 case 'h': /* help */
237 print_help (); 224 print_help();
238 exit (STATE_UNKNOWN); 225 exit(STATE_UNKNOWN);
239 case 'V': /* version */ 226 case 'V': /* version */
240 print_revision (progname, NP_VERSION); 227 print_revision(progname, NP_VERSION);
241 exit (STATE_UNKNOWN); 228 exit(STATE_UNKNOWN);
242 case 'F': /* status log */ 229 case 'F': /* status log */
243 status_log = optarg; 230 status_log = optarg;
244 break; 231 break;
245 case 'C': /* command */ 232 case 'C': /* command */
246 process_string = optarg; 233 process_string = optarg;
247 break; 234 break;
248 case 'e': /* expiry time */ 235 case 'e': /* expiry time */
249 if (is_intnonneg (optarg)) 236 if (is_intnonneg(optarg))
250 expire_minutes = atoi (optarg); 237 expire_minutes = atoi(optarg);
251 else 238 else
252 die (STATE_UNKNOWN, 239 die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
253 _("Expiration time must be an integer (seconds)\n"));
254 break; 240 break;
255 case 't': /* timeout */ 241 case 't': /* timeout */
256 if (is_intnonneg (optarg)) 242 if (is_intnonneg(optarg))
257 timeout_interval = atoi (optarg); 243 timeout_interval = atoi(optarg);
258 else 244 else
259 die (STATE_UNKNOWN, 245 die(STATE_UNKNOWN, _("Timeout must be an integer (seconds)\n"));
260 _("Timeout must be an integer (seconds)\n"));
261 break; 246 break;
262 case 'v': 247 case 'v':
263 verbose++; 248 verbose++;
264 break; 249 break;
265 default: /* print short usage_va statement if args not parsable */ 250 default: /* print short usage_va statement if args not parsable */
266 usage5(); 251 usage5();
267 } 252 }
268 } 253 }
269 254
270
271 if (status_log == NULL) 255 if (status_log == NULL)
272 die (STATE_UNKNOWN, _("You must provide the status_log\n")); 256 die(STATE_UNKNOWN, _("You must provide the status_log\n"));
273 257
274 if (process_string == NULL) 258 if (process_string == NULL)
275 die (STATE_UNKNOWN, _("You must provide a process string\n")); 259 die(STATE_UNKNOWN, _("You must provide a process string\n"));
276 260
277 return OK; 261 return OK;
278} 262}
279 263
264void print_help(void) {
265 print_revision(progname, NP_VERSION);
280 266
267 printf(_(COPYRIGHT), copyright, email);
281 268
282void 269 printf("%s\n", _("This plugin checks the status of the Nagios process on the local machine"));
283print_help (void) 270 printf("%s\n", _("The plugin will check to make sure the Nagios status log is no older than"));
284{ 271 printf("%s\n", _("the number of minutes specified by the expires option."));
285 print_revision (progname, NP_VERSION); 272 printf("%s\n", _("It also checks the process table for a process matching the command argument."));
286 273
287 printf (_(COPYRIGHT), copyright, email); 274 printf("\n\n");
288 275
289 printf ("%s\n", _("This plugin checks the status of the Nagios process on the local machine")); 276 print_usage();
290 printf ("%s\n", _("The plugin will check to make sure the Nagios status log is no older than"));
291 printf ("%s\n", _("the number of minutes specified by the expires option."));
292 printf ("%s\n", _("It also checks the process table for a process matching the command argument."));
293 277
294 printf ("\n\n"); 278 printf(UT_HELP_VRSN);
279 printf(UT_EXTRA_OPTS);
295 280
296 print_usage (); 281 printf(" %s\n", "-F, --filename=FILE");
282 printf(" %s\n", _("Name of the log file to check"));
283 printf(" %s\n", "-e, --expires=INTEGER");
284 printf(" %s\n", _("Minutes aging after which logfile is considered stale"));
285 printf(" %s\n", "-C, --command=STRING");
286 printf(" %s\n", _("Substring to search for in process arguments"));
287 printf(" %s\n", "-t, --timeout=INTEGER");
288 printf(" %s\n", _("Timeout for the plugin in seconds"));
289 printf(UT_VERBOSE);
297 290
298 printf (UT_HELP_VRSN); 291 printf("\n");
299 printf (UT_EXTRA_OPTS); 292 printf("%s\n", _("Examples:"));
293 printf(" %s\n", "check_nagios -t 20 -e 5 -F /usr/local/nagios/var/status.log -C /usr/local/nagios/bin/nagios");
300 294
301 printf (" %s\n", "-F, --filename=FILE"); 295 printf(UT_SUPPORT);
302 printf (" %s\n", _("Name of the log file to check"));
303 printf (" %s\n", "-e, --expires=INTEGER");
304 printf (" %s\n", _("Minutes aging after which logfile is considered stale"));
305 printf (" %s\n", "-C, --command=STRING");
306 printf (" %s\n", _("Substring to search for in process arguments"));
307 printf (" %s\n", "-t, --timeout=INTEGER");
308 printf (" %s\n", _("Timeout for the plugin in seconds"));
309 printf (UT_VERBOSE);
310
311 printf ("\n");
312 printf ("%s\n", _("Examples:"));
313 printf (" %s\n", "check_nagios -t 20 -e 5 -F /usr/local/nagios/var/status.log -C /usr/local/nagios/bin/nagios");
314
315 printf (UT_SUPPORT);
316} 296}
317 297
318 298void print_usage(void) {
319 299 printf("%s\n", _("Usage:"));
320void 300 printf("%s -F <status log file> -t <timeout_seconds> -e <expire_minutes> -C <process_string>\n", progname);
321print_usage (void)
322{
323 printf ("%s\n", _("Usage:"));
324 printf ("%s -F <status log file> -t <timeout_seconds> -e <expire_minutes> -C <process_string>\n", progname);
325} 301}
diff --git a/plugins/check_nt.c b/plugins/check_nt.c
index 19c050de..413aad6b 100644
--- a/plugins/check_nt.c
+++ b/plugins/check_nt.c
@@ -1,39 +1,39 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_nt plugin 3 * Monitoring check_nt plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2002 Yves Rubin (rubiyz@yahoo.com) 6 * Copyright (c) 2000-2002 Yves Rubin (rubiyz@yahoo.com)
7* Copyright (c) 2003-2007 Monitoring Plugins Development Team 7 * Copyright (c) 2003-2024 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_nt plugin 11 * This file contains the check_nt plugin
12* 12 *
13* This plugin collects data from the NSClient service running on a 13 * This plugin collects data from the NSClient service running on a
14* Windows NT/2000/XP/2003 server. 14 * Windows NT/2000/XP/2003 server.
15* This plugin requires NSClient software to run on NT 15 * This plugin requires NSClient software to run on NT
16* (http://nsclient.ready2run.nl/) 16 * (http://nsclient.ready2run.nl/)
17* 17 *
18* 18 *
19* This program is free software: you can redistribute it and/or modify 19 * This program is free software: you can redistribute it and/or modify
20* it under the terms of the GNU General Public License as published by 20 * it under the terms of the GNU General Public License as published by
21* the Free Software Foundation, either version 3 of the License, or 21 * the Free Software Foundation, either version 3 of the License, or
22* (at your option) any later version. 22 * (at your option) any later version.
23* 23 *
24* This program is distributed in the hope that it will be useful, 24 * This program is distributed in the hope that it will be useful,
25* but WITHOUT ANY WARRANTY; without even the implied warranty of 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27* GNU General Public License for more details. 27 * GNU General Public License for more details.
28* 28 *
29* You should have received a copy of the GNU General Public License 29 * You should have received a copy of the GNU General Public License
30* along with this program. If not, see <http://www.gnu.org/licenses/>. 30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31* 31 *
32* 32 *
33*****************************************************************************/ 33 *****************************************************************************/
34 34
35const char *progname = "check_nt"; 35const char *progname = "check_nt";
36const char *copyright = "2000-2007"; 36const char *copyright = "2000-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
@@ -59,75 +59,75 @@ enum {
59 PORT = 1248 59 PORT = 1248
60}; 60};
61 61
62char *server_address=NULL; 62char *server_address = NULL;
63char *volume_name=NULL; 63char *volume_name = NULL;
64int server_port=PORT; 64int server_port = PORT;
65char *value_list=NULL; 65char *value_list = NULL;
66char *req_password=NULL; 66char *req_password = NULL;
67unsigned long lvalue_list[MAX_VALUE_LIST]; 67unsigned long lvalue_list[MAX_VALUE_LIST];
68unsigned long warning_value=0L; 68unsigned long warning_value = 0L;
69unsigned long critical_value=0L; 69unsigned long critical_value = 0L;
70bool check_warning_value=false; 70bool check_warning_value = false;
71bool check_critical_value=false; 71bool check_critical_value = false;
72enum checkvars vars_to_check = CHECK_NONE; 72enum checkvars vars_to_check = CHECK_NONE;
73bool show_all = false; 73bool show_all = false;
74 74
75char recv_buffer[MAX_INPUT_BUFFER]; 75char recv_buffer[MAX_INPUT_BUFFER];
76 76
77void fetch_data (const char* address, int port, const char* sendb); 77void fetch_data(const char *address, int port, const char *sendb);
78int process_arguments(int, char **); 78int process_arguments(int, char **);
79void preparelist(char *string); 79void preparelist(char *string);
80bool strtoularray(unsigned long *array, char *string, const char *delim); 80bool strtoularray(unsigned long *array, char *string, const char *delim);
81void print_help(void); 81void print_help(void);
82void print_usage(void); 82void print_usage(void);
83 83
84int main(int argc, char **argv){ 84int main(int argc, char **argv) {
85 85
86/* should be int result = STATE_UNKNOWN; */ 86 /* should be int result = STATE_UNKNOWN; */
87 87
88 int return_code = STATE_UNKNOWN; 88 int return_code = STATE_UNKNOWN;
89 char *send_buffer=NULL; 89 char *send_buffer = NULL;
90 char *output_message=NULL; 90 char *output_message = NULL;
91 char *perfdata=NULL; 91 char *perfdata = NULL;
92 char *temp_string=NULL; 92 char *temp_string = NULL;
93 char *temp_string_perf=NULL; 93 char *temp_string_perf = NULL;
94 char *description=NULL,*counter_unit = NULL; 94 char *description = NULL, *counter_unit = NULL;
95 char *minval = NULL, *maxval = NULL, *errcvt = NULL; 95 char *minval = NULL, *maxval = NULL, *errcvt = NULL;
96 char *fds=NULL, *tds=NULL; 96 char *fds = NULL, *tds = NULL;
97 char *numstr; 97 char *numstr;
98 98
99 double total_disk_space=0; 99 double total_disk_space = 0;
100 double free_disk_space=0; 100 double free_disk_space = 0;
101 double percent_used_space=0; 101 double percent_used_space = 0;
102 double warning_used_space=0; 102 double warning_used_space = 0;
103 double critical_used_space=0; 103 double critical_used_space = 0;
104 double mem_commitLimit=0; 104 double mem_commitLimit = 0;
105 double mem_commitByte=0; 105 double mem_commitByte = 0;
106 double fminval = 0, fmaxval = 0; 106 double fminval = 0, fmaxval = 0;
107 unsigned long utilization; 107 unsigned long utilization;
108 unsigned long uptime; 108 unsigned long uptime;
109 unsigned long age_in_minutes; 109 unsigned long age_in_minutes;
110 double counter_value = 0.0; 110 double counter_value = 0.0;
111 int offset=0; 111 int offset = 0;
112 int updays=0; 112 int updays = 0;
113 int uphours=0; 113 int uphours = 0;
114 int upminutes=0; 114 int upminutes = 0;
115 115
116 bool isPercent = false; 116 bool isPercent = false;
117 bool allRight = false; 117 bool allRight = false;
118 118
119 setlocale (LC_ALL, ""); 119 setlocale(LC_ALL, "");
120 bindtextdomain (PACKAGE, LOCALEDIR); 120 bindtextdomain(PACKAGE, LOCALEDIR);
121 textdomain (PACKAGE); 121 textdomain(PACKAGE);
122 122
123 /* Parse extra opts if any */ 123 /* Parse extra opts if any */
124 argv=np_extra_opts (&argc, argv, progname); 124 argv = np_extra_opts(&argc, argv, progname);
125 125
126 if(process_arguments(argc,argv) == ERROR) 126 if (process_arguments(argc, argv) == ERROR)
127 usage4 (_("Could not parse arguments")); 127 usage4(_("Could not parse arguments"));
128 128
129 /* initialize alarm signal handling */ 129 /* initialize alarm signal handling */
130 signal(SIGALRM,socket_timeout_alarm_handler); 130 signal(SIGALRM, socket_timeout_alarm_handler);
131 131
132 /* set socket timeout */ 132 /* set socket timeout */
133 alarm(socket_timeout); 133 alarm(socket_timeout);
@@ -137,61 +137,58 @@ int main(int argc, char **argv){
137 case CHECK_CLIENTVERSION: 137 case CHECK_CLIENTVERSION:
138 138
139 xasprintf(&send_buffer, "%s&1", req_password); 139 xasprintf(&send_buffer, "%s&1", req_password);
140 fetch_data (server_address, server_port, send_buffer); 140 fetch_data(server_address, server_port, send_buffer);
141 if (value_list != NULL && strcmp(recv_buffer, value_list) != 0) { 141 if (value_list != NULL && strcmp(recv_buffer, value_list) != 0) {
142 xasprintf (&output_message, _("Wrong client version - running: %s, required: %s"), recv_buffer, value_list); 142 xasprintf(&output_message, _("Wrong client version - running: %s, required: %s"), recv_buffer, value_list);
143 return_code = STATE_WARNING; 143 return_code = STATE_WARNING;
144 } else { 144 } else {
145 xasprintf (&output_message, "%s", recv_buffer); 145 xasprintf(&output_message, "%s", recv_buffer);
146 return_code = STATE_OK; 146 return_code = STATE_OK;
147 } 147 }
148 break; 148 break;
149 149
150 case CHECK_CPULOAD: 150 case CHECK_CPULOAD:
151 151
152 if (value_list==NULL) 152 if (value_list == NULL)
153 output_message = strdup (_("missing -l parameters")); 153 output_message = strdup(_("missing -l parameters"));
154 else if (! strtoularray(lvalue_list,value_list,",")) 154 else if (!strtoularray(lvalue_list, value_list, ","))
155 output_message = strdup (_("wrong -l parameter.")); 155 output_message = strdup(_("wrong -l parameter."));
156 else { 156 else {
157 /* -l parameters is present with only integers */ 157 /* -l parameters is present with only integers */
158 return_code=STATE_OK; 158 return_code = STATE_OK;
159 temp_string = strdup (_("CPU Load")); 159 temp_string = strdup(_("CPU Load"));
160 temp_string_perf = strdup (" "); 160 temp_string_perf = strdup(" ");
161 161
162 /* loop until one of the parameters is wrong or not present */ 162 /* loop until one of the parameters is wrong or not present */
163 while (lvalue_list[0+offset]> (unsigned long)0 && 163 while (lvalue_list[0 + offset] > (unsigned long)0 && lvalue_list[0 + offset] <= (unsigned long)17280 &&
164 lvalue_list[0+offset]<=(unsigned long)17280 && 164 lvalue_list[1 + offset] > (unsigned long)0 && lvalue_list[1 + offset] <= (unsigned long)100 &&
165 lvalue_list[1+offset]> (unsigned long)0 && 165 lvalue_list[2 + offset] > (unsigned long)0 && lvalue_list[2 + offset] <= (unsigned long)100) {
166 lvalue_list[1+offset]<=(unsigned long)100 &&
167 lvalue_list[2+offset]> (unsigned long)0 &&
168 lvalue_list[2+offset]<=(unsigned long)100) {
169 166
170 /* Send request and retrieve data */ 167 /* Send request and retrieve data */
171 xasprintf(&send_buffer,"%s&2&%lu",req_password,lvalue_list[0+offset]); 168 xasprintf(&send_buffer, "%s&2&%lu", req_password, lvalue_list[0 + offset]);
172 fetch_data (server_address, server_port, send_buffer); 169 fetch_data(server_address, server_port, send_buffer);
173 170
174 utilization=strtoul(recv_buffer,NULL,10); 171 utilization = strtoul(recv_buffer, NULL, 10);
175 172
176 /* Check if any of the request is in a warning or critical state */ 173 /* Check if any of the request is in a warning or critical state */
177 if(utilization >= lvalue_list[2+offset]) 174 if (utilization >= lvalue_list[2 + offset])
178 return_code=STATE_CRITICAL; 175 return_code = STATE_CRITICAL;
179 else if(utilization >= lvalue_list[1+offset] && return_code<STATE_WARNING) 176 else if (utilization >= lvalue_list[1 + offset] && return_code < STATE_WARNING)
180 return_code=STATE_WARNING; 177 return_code = STATE_WARNING;
181 178
182 xasprintf(&output_message,_(" %lu%% (%lu min average)"), utilization, lvalue_list[0+offset]); 179 xasprintf(&output_message, _(" %lu%% (%lu min average)"), utilization, lvalue_list[0 + offset]);
183 xasprintf(&temp_string,"%s%s",temp_string,output_message); 180 xasprintf(&temp_string, "%s%s", temp_string, output_message);
184 xasprintf(&perfdata,_(" '%lu min avg Load'=%lu%%;%lu;%lu;0;100"), lvalue_list[0+offset], utilization, 181 xasprintf(&perfdata, _(" '%lu min avg Load'=%lu%%;%lu;%lu;0;100"), lvalue_list[0 + offset], utilization,
185 lvalue_list[1+offset], lvalue_list[2+offset]); 182 lvalue_list[1 + offset], lvalue_list[2 + offset]);
186 xasprintf(&temp_string_perf,"%s%s",temp_string_perf,perfdata); 183 xasprintf(&temp_string_perf, "%s%s", temp_string_perf, perfdata);
187 offset+=3; /* move across the array */ 184 offset += 3; /* move across the array */
188 } 185 }
189 186
190 if (strlen(temp_string)>10) { /* we had at least one loop */ 187 if (strlen(temp_string) > 10) { /* we had at least one loop */
191 output_message = strdup (temp_string); 188 output_message = strdup(temp_string);
192 perfdata = temp_string_perf; 189 perfdata = temp_string_perf;
193 } else 190 } else
194 output_message = strdup (_("not enough values for -l parameters")); 191 output_message = strdup(_("not enough values for -l parameters"));
195 } 192 }
196 break; 193 break;
197 194
@@ -200,16 +197,14 @@ int main(int argc, char **argv){
200 if (value_list == NULL) { 197 if (value_list == NULL) {
201 value_list = "minutes"; 198 value_list = "minutes";
202 } 199 }
203 if (strncmp(value_list, "seconds", strlen("seconds") + 1 ) && 200 if (strncmp(value_list, "seconds", strlen("seconds") + 1) && strncmp(value_list, "minutes", strlen("minutes") + 1) &&
204 strncmp(value_list, "minutes", strlen("minutes") + 1) && 201 strncmp(value_list, "hours", strlen("hours") + 1) && strncmp(value_list, "days", strlen("days") + 1)) {
205 strncmp(value_list, "hours", strlen("hours") + 1) &&
206 strncmp(value_list, "days", strlen("days") + 1)) {
207 202
208 output_message = strdup (_("wrong -l argument")); 203 output_message = strdup(_("wrong -l argument"));
209 } else { 204 } else {
210 xasprintf(&send_buffer, "%s&3", req_password); 205 xasprintf(&send_buffer, "%s&3", req_password);
211 fetch_data (server_address, server_port, send_buffer); 206 fetch_data(server_address, server_port, send_buffer);
212 uptime=strtoul(recv_buffer,NULL,10); 207 uptime = strtoul(recv_buffer, NULL, 10);
213 updays = uptime / 86400; 208 updays = uptime / 86400;
214 uphours = (uptime % 86400) / 3600; 209 uphours = (uptime % 86400) / 3600;
215 upminutes = ((uptime % 86400) % 3600) / 60; 210 upminutes = ((uptime % 86400) % 3600) / 60;
@@ -222,57 +217,58 @@ int main(int argc, char **argv){
222 uptime = uptime / 86400; 217 uptime = uptime / 86400;
223 /* else uptime in seconds, nothing to do */ 218 /* else uptime in seconds, nothing to do */
224 219
225 xasprintf(&output_message,_("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"),updays, uphours, upminutes, uptime); 220 xasprintf(&output_message, _("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"), updays, uphours, upminutes,
221 uptime);
226 222
227 if (check_critical_value && uptime <= critical_value) 223 if (check_critical_value && uptime <= critical_value)
228 return_code=STATE_CRITICAL; 224 return_code = STATE_CRITICAL;
229 else if (check_warning_value && uptime <= warning_value) 225 else if (check_warning_value && uptime <= warning_value)
230 return_code=STATE_WARNING; 226 return_code = STATE_WARNING;
231 else 227 else
232 return_code=STATE_OK; 228 return_code = STATE_OK;
233 } 229 }
234 break; 230 break;
235 231
236 case CHECK_USEDDISKSPACE: 232 case CHECK_USEDDISKSPACE:
237 233
238 if (value_list==NULL) 234 if (value_list == NULL)
239 output_message = strdup (_("missing -l parameters")); 235 output_message = strdup(_("missing -l parameters"));
240 else if (strlen(value_list)!=1) 236 else if (strlen(value_list) != 1)
241 output_message = strdup (_("wrong -l argument")); 237 output_message = strdup(_("wrong -l argument"));
242 else { 238 else {
243 xasprintf(&send_buffer,"%s&4&%s", req_password, value_list); 239 xasprintf(&send_buffer, "%s&4&%s", req_password, value_list);
244 fetch_data (server_address, server_port, send_buffer); 240 fetch_data(server_address, server_port, send_buffer);
245 fds=strtok(recv_buffer,"&"); 241 fds = strtok(recv_buffer, "&");
246 tds=strtok(NULL,"&"); 242 tds = strtok(NULL, "&");
247 if(fds!=NULL) 243 if (fds != NULL)
248 free_disk_space=atof(fds); 244 free_disk_space = atof(fds);
249 if(tds!=NULL) 245 if (tds != NULL)
250 total_disk_space=atof(tds); 246 total_disk_space = atof(tds);
251 247
252 if (total_disk_space>0 && free_disk_space>=0) { 248 if (total_disk_space > 0 && free_disk_space >= 0) {
253 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100; 249 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100;
254 warning_used_space = ((float)warning_value / 100) * total_disk_space; 250 warning_used_space = ((float)warning_value / 100) * total_disk_space;
255 critical_used_space = ((float)critical_value / 100) * total_disk_space; 251 critical_used_space = ((float)critical_value / 100) * total_disk_space;
256 252
257 xasprintf(&temp_string,_("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), 253 xasprintf(&temp_string, _("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), value_list,
258 value_list, total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, 254 total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, percent_used_space,
259 percent_used_space, free_disk_space / 1073741824, (free_disk_space / total_disk_space)*100); 255 free_disk_space / 1073741824, (free_disk_space / total_disk_space) * 100);
260 xasprintf(&temp_string_perf,_("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), value_list, 256 xasprintf(&temp_string_perf, _("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), value_list,
261 (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824, 257 (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824,
262 critical_used_space / 1073741824, total_disk_space / 1073741824); 258 critical_used_space / 1073741824, total_disk_space / 1073741824);
263 259
264 if(check_critical_value && percent_used_space >= critical_value) 260 if (check_critical_value && percent_used_space >= critical_value)
265 return_code=STATE_CRITICAL; 261 return_code = STATE_CRITICAL;
266 else if (check_warning_value && percent_used_space >= warning_value) 262 else if (check_warning_value && percent_used_space >= warning_value)
267 return_code=STATE_WARNING; 263 return_code = STATE_WARNING;
268 else 264 else
269 return_code=STATE_OK; 265 return_code = STATE_OK;
270 266
271 output_message = strdup (temp_string); 267 output_message = strdup(temp_string);
272 perfdata = temp_string_perf; 268 perfdata = temp_string_perf;
273 } else { 269 } else {
274 output_message = strdup (_("Free disk space : Invalid drive")); 270 output_message = strdup(_("Free disk space : Invalid drive"));
275 return_code=STATE_UNKNOWN; 271 return_code = STATE_UNKNOWN;
276 } 272 }
277 } 273 }
278 break; 274 break;
@@ -280,57 +276,56 @@ int main(int argc, char **argv){
280 case CHECK_SERVICESTATE: 276 case CHECK_SERVICESTATE:
281 case CHECK_PROCSTATE: 277 case CHECK_PROCSTATE:
282 278
283 if (value_list==NULL) 279 if (value_list == NULL)
284 output_message = strdup (_("No service/process specified")); 280 output_message = strdup(_("No service/process specified"));
285 else { 281 else {
286 preparelist(value_list); /* replace , between services with & to send the request */ 282 preparelist(value_list); /* replace , between services with & to send the request */
287 xasprintf(&send_buffer,"%s&%u&%s&%s", req_password,(vars_to_check==CHECK_SERVICESTATE)?5:6, 283 xasprintf(&send_buffer, "%s&%u&%s&%s", req_password, (vars_to_check == CHECK_SERVICESTATE) ? 5 : 6,
288 (show_all) ? "ShowAll" : "ShowFail",value_list); 284 (show_all) ? "ShowAll" : "ShowFail", value_list);
289 fetch_data (server_address, server_port, send_buffer); 285 fetch_data(server_address, server_port, send_buffer);
290 numstr = strtok(recv_buffer,"&"); 286 numstr = strtok(recv_buffer, "&");
291 if (numstr == NULL) 287 if (numstr == NULL)
292 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 288 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
293 return_code=atoi(numstr); 289 return_code = atoi(numstr);
294 temp_string=strtok(NULL,"&"); 290 temp_string = strtok(NULL, "&");
295 output_message = strdup (temp_string); 291 output_message = strdup(temp_string);
296 } 292 }
297 break; 293 break;
298 294
299 case CHECK_MEMUSE: 295 case CHECK_MEMUSE:
300 296
301 xasprintf(&send_buffer,"%s&7", req_password); 297 xasprintf(&send_buffer, "%s&7", req_password);
302 fetch_data (server_address, server_port, send_buffer); 298 fetch_data(server_address, server_port, send_buffer);
303 numstr = strtok(recv_buffer,"&"); 299 numstr = strtok(recv_buffer, "&");
304 if (numstr == NULL) 300 if (numstr == NULL)
305 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 301 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
306 mem_commitLimit=atof(numstr); 302 mem_commitLimit = atof(numstr);
307 numstr = strtok(NULL,"&"); 303 numstr = strtok(NULL, "&");
308 if (numstr == NULL) 304 if (numstr == NULL)
309 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 305 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
310 mem_commitByte=atof(numstr); 306 mem_commitByte = atof(numstr);
311 percent_used_space = (mem_commitByte / mem_commitLimit) * 100; 307 percent_used_space = (mem_commitByte / mem_commitLimit) * 100;
312 warning_used_space = ((float)warning_value / 100) * mem_commitLimit; 308 warning_used_space = ((float)warning_value / 100) * mem_commitLimit;
313 critical_used_space = ((float)critical_value / 100) * mem_commitLimit; 309 critical_used_space = ((float)critical_value / 100) * mem_commitLimit;
314 310
315 /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here, 311 /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here,
316 which equals RAM + Pagefiles. */ 312 which equals RAM + Pagefiles. */
317 xasprintf(&output_message,_("Memory usage: total:%.2f MB - used: %.2f MB (%.0f%%) - free: %.2f MB (%.0f%%)"), 313 xasprintf(&output_message, _("Memory usage: total:%.2f MB - used: %.2f MB (%.0f%%) - free: %.2f MB (%.0f%%)"),
318 mem_commitLimit / 1048567, mem_commitByte / 1048567, percent_used_space, 314 mem_commitLimit / 1048567, mem_commitByte / 1048567, percent_used_space, (mem_commitLimit - mem_commitByte) / 1048567,
319 (mem_commitLimit - mem_commitByte) / 1048567, (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100); 315 (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100);
320 xasprintf(&perfdata,_("'Memory usage'=%.2fMB;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567, 316 xasprintf(&perfdata, _("'Memory usage'=%.2fMB;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567, warning_used_space / 1048567,
321 warning_used_space / 1048567, critical_used_space / 1048567, mem_commitLimit / 1048567); 317 critical_used_space / 1048567, mem_commitLimit / 1048567);
322 318
323 return_code=STATE_OK; 319 return_code = STATE_OK;
324 if(check_critical_value && percent_used_space >= critical_value) 320 if (check_critical_value && percent_used_space >= critical_value)
325 return_code=STATE_CRITICAL; 321 return_code = STATE_CRITICAL;
326 else if (check_warning_value && percent_used_space >= warning_value) 322 else if (check_warning_value && percent_used_space >= warning_value)
327 return_code=STATE_WARNING; 323 return_code = STATE_WARNING;
328 324
329 break; 325 break;
330 326
331 case CHECK_COUNTER: 327 case CHECK_COUNTER:
332 328
333
334 /* 329 /*
335 CHECK_COUNTER has been modified to provide extensive perfdata information. 330 CHECK_COUNTER has been modified to provide extensive perfdata information.
336 In order to do this, some modifications have been done to the code 331 In order to do this, some modifications have been done to the code
@@ -353,311 +348,290 @@ int main(int argc, char **argv){
353 */ 348 */
354 349
355 if (value_list == NULL) 350 if (value_list == NULL)
356 output_message = strdup (_("No counter specified")); 351 output_message = strdup(_("No counter specified"));
357 else 352 else {
358 { 353 preparelist(value_list); /* replace , between services with & to send the request */
359 preparelist (value_list); /* replace , between services with & to send the request */ 354 isPercent = (strchr(value_list, '%') != NULL);
360 isPercent = (strchr (value_list, '%') != NULL); 355
361 356 strtok(value_list, "&"); /* burn the first parameters */
362 strtok (value_list, "&"); /* burn the first parameters */ 357 description = strtok(NULL, "&");
363 description = strtok (NULL, "&"); 358 counter_unit = strtok(NULL, "&");
364 counter_unit = strtok (NULL, "&"); 359 xasprintf(&send_buffer, "%s&8&%s", req_password, value_list);
365 xasprintf (&send_buffer, "%s&8&%s", req_password, value_list); 360 fetch_data(server_address, server_port, send_buffer);
366 fetch_data (server_address, server_port, send_buffer); 361 counter_value = atof(recv_buffer);
367 counter_value = atof (recv_buffer);
368 362
369 if (description == NULL) 363 if (description == NULL)
370 xasprintf (&output_message, "%.f", counter_value); 364 xasprintf(&output_message, "%.f", counter_value);
371 else if (isPercent) 365 else if (isPercent) {
372 { 366 counter_unit = strdup("%");
373 counter_unit = strdup ("%");
374 allRight = true; 367 allRight = true;
375 } 368 }
376 369
377 if ((counter_unit != NULL) && (!allRight)) 370 if ((counter_unit != NULL) && (!allRight)) {
378 { 371 minval = strtok(NULL, "&");
379 minval = strtok (NULL, "&"); 372 maxval = strtok(NULL, "&");
380 maxval = strtok (NULL, "&");
381 373
382 /* All parameters specified. Let's check the numbers */ 374 /* All parameters specified. Let's check the numbers */
383 375
384 fminval = (minval != NULL) ? strtod (minval, &errcvt) : -1; 376 fminval = (minval != NULL) ? strtod(minval, &errcvt) : -1;
385 fmaxval = (minval != NULL) ? strtod (maxval, &errcvt) : -1; 377 fmaxval = (minval != NULL) ? strtod(maxval, &errcvt) : -1;
386 378
387 if ((fminval == 0) && (minval == errcvt)) 379 if ((fminval == 0) && (minval == errcvt))
388 output_message = strdup (_("Minimum value contains non-numbers")); 380 output_message = strdup(_("Minimum value contains non-numbers"));
389 else 381 else {
390 {
391 if ((fmaxval == 0) && (maxval == errcvt)) 382 if ((fmaxval == 0) && (maxval == errcvt))
392 output_message = strdup (_("Maximum value contains non-numbers")); 383 output_message = strdup(_("Maximum value contains non-numbers"));
393 else 384 else
394 allRight = true; /* Everything is OK. */ 385 allRight = true; /* Everything is OK. */
395
396 } 386 }
397 } 387 } else if ((counter_unit == NULL) && (description != NULL))
398 else if ((counter_unit == NULL) && (description != NULL)) 388 output_message = strdup(_("No unit counter specified"));
399 output_message = strdup (_("No unit counter specified"));
400 389
401 if (allRight) 390 if (allRight) {
402 {
403 /* Let's format the output string, finally... */ 391 /* Let's format the output string, finally... */
404 if (strstr(description, "%") == NULL) { 392 if (strstr(description, "%") == NULL) {
405 xasprintf (&output_message, "%s = %.2f %s", description, counter_value, counter_unit); 393 xasprintf(&output_message, "%s = %.2f %s", description, counter_value, counter_unit);
406 } else { 394 } else {
407 /* has formatting, will segv if wrong */ 395 /* has formatting, will segv if wrong */
408 xasprintf (&output_message, description, counter_value); 396 xasprintf(&output_message, description, counter_value);
409 } 397 }
410 xasprintf (&output_message, "%s |", output_message); 398 xasprintf(&output_message, "%s |", output_message);
411 xasprintf (&output_message,"%s %s", output_message, 399 xasprintf(&output_message, "%s %s", output_message,
412 fperfdata (description, counter_value, 400 fperfdata(description, counter_value, counter_unit, 1, warning_value, 1, critical_value,
413 counter_unit, 1, warning_value, 1, critical_value, 401 (!(isPercent) && (minval != NULL)), fminval, (!(isPercent) && (minval != NULL)), fmaxval));
414 (!(isPercent) && (minval != NULL)), fminval,
415 (!(isPercent) && (minval != NULL)), fmaxval));
416 } 402 }
417 } 403 }
418 404
419 if (critical_value > warning_value) 405 if (critical_value > warning_value) { /* Normal thresholds */
420 { /* Normal thresholds */
421 if (check_critical_value && counter_value >= critical_value) 406 if (check_critical_value && counter_value >= critical_value)
422 return_code = STATE_CRITICAL; 407 return_code = STATE_CRITICAL;
423 else if (check_warning_value && counter_value >= warning_value) 408 else if (check_warning_value && counter_value >= warning_value)
424 return_code = STATE_WARNING; 409 return_code = STATE_WARNING;
425 else 410 else
426 return_code = STATE_OK; 411 return_code = STATE_OK;
427 } 412 } else { /* inverse thresholds */
428 else
429 { /* inverse thresholds */
430 return_code = STATE_OK; 413 return_code = STATE_OK;
431 if (check_critical_value && counter_value <= critical_value) 414 if (check_critical_value && counter_value <= critical_value)
432 return_code = STATE_CRITICAL; 415 return_code = STATE_CRITICAL;
433 else if (check_warning_value && counter_value <= warning_value) 416 else if (check_warning_value && counter_value <= warning_value)
434 return_code = STATE_WARNING; 417 return_code = STATE_WARNING;
435 } 418 }
436 break; 419 break;
437 420
438 case CHECK_FILEAGE: 421 case CHECK_FILEAGE:
439 422
440 if (value_list==NULL) 423 if (value_list == NULL)
441 output_message = strdup (_("No counter specified")); 424 output_message = strdup(_("No counter specified"));
442 else { 425 else {
443 preparelist(value_list); /* replace , between services with & to send the request */ 426 preparelist(value_list); /* replace , between services with & to send the request */
444 xasprintf(&send_buffer,"%s&9&%s", req_password,value_list); 427 xasprintf(&send_buffer, "%s&9&%s", req_password, value_list);
445 fetch_data (server_address, server_port, send_buffer); 428 fetch_data(server_address, server_port, send_buffer);
446 age_in_minutes = atoi(strtok(recv_buffer,"&")); 429 age_in_minutes = atoi(strtok(recv_buffer, "&"));
447 description = strtok(NULL,"&"); 430 description = strtok(NULL, "&");
448 output_message = strdup (description); 431 output_message = strdup(description);
449 432
450 if (critical_value > warning_value) { /* Normal thresholds */ 433 if (critical_value > warning_value) { /* Normal thresholds */
451 if(check_critical_value && age_in_minutes >= critical_value) 434 if (check_critical_value && age_in_minutes >= critical_value)
452 return_code=STATE_CRITICAL; 435 return_code = STATE_CRITICAL;
453 else if (check_warning_value && age_in_minutes >= warning_value) 436 else if (check_warning_value && age_in_minutes >= warning_value)
454 return_code=STATE_WARNING; 437 return_code = STATE_WARNING;
455 else 438 else
456 return_code=STATE_OK; 439 return_code = STATE_OK;
457 } 440 } else { /* inverse thresholds */
458 else { /* inverse thresholds */ 441 if (check_critical_value && age_in_minutes <= critical_value)
459 if(check_critical_value && age_in_minutes <= critical_value) 442 return_code = STATE_CRITICAL;
460 return_code=STATE_CRITICAL;
461 else if (check_warning_value && age_in_minutes <= warning_value) 443 else if (check_warning_value && age_in_minutes <= warning_value)
462 return_code=STATE_WARNING; 444 return_code = STATE_WARNING;
463 else 445 else
464 return_code=STATE_OK; 446 return_code = STATE_OK;
465 } 447 }
466 } 448 }
467 break; 449 break;
468 450
469 case CHECK_INSTANCES: 451 case CHECK_INSTANCES:
470 if (value_list==NULL) 452 if (value_list == NULL)
471 output_message = strdup (_("No counter specified")); 453 output_message = strdup(_("No counter specified"));
472 else { 454 else {
473 xasprintf(&send_buffer,"%s&10&%s", req_password,value_list); 455 xasprintf(&send_buffer, "%s&10&%s", req_password, value_list);
474 fetch_data (server_address, server_port, send_buffer); 456 fetch_data(server_address, server_port, send_buffer);
475 if (!strncmp(recv_buffer,"ERROR",5)) { 457 if (!strncmp(recv_buffer, "ERROR", 5)) {
476 printf("NSClient - %s\n",recv_buffer); 458 printf("NSClient - %s\n", recv_buffer);
477 exit(STATE_UNKNOWN); 459 exit(STATE_UNKNOWN);
478 } 460 }
479 xasprintf(&output_message,"%s",recv_buffer); 461 xasprintf(&output_message, "%s", recv_buffer);
480 return_code=STATE_OK; 462 return_code = STATE_OK;
481 } 463 }
482 break; 464 break;
483 465
484 case CHECK_NONE: 466 case CHECK_NONE:
485 default: 467 default:
486 usage4 (_("Please specify a variable to check")); 468 usage4(_("Please specify a variable to check"));
487 break; 469 break;
488
489 } 470 }
490 471
491 /* reset timeout */ 472 /* reset timeout */
492 alarm(0); 473 alarm(0);
493 474
494 if (perfdata==NULL) 475 if (perfdata == NULL)
495 printf("%s\n",output_message); 476 printf("%s\n", output_message);
496 else 477 else
497 printf("%s | %s\n",output_message,perfdata); 478 printf("%s | %s\n", output_message, perfdata);
498 return return_code; 479 return return_code;
499} 480}
500 481
501
502
503/* process command-line arguments */ 482/* process command-line arguments */
504int process_arguments(int argc, char **argv){ 483int process_arguments(int argc, char **argv) {
505 int c; 484 int c;
506 485
507 int option = 0; 486 int option = 0;
508 static struct option longopts[] = 487 static struct option longopts[] = {{"port", required_argument, 0, 'p'},
509 { 488 {"timeout", required_argument, 0, 't'},
510 {"port", required_argument,0,'p'}, 489 {"critical", required_argument, 0, 'c'},
511 {"timeout", required_argument,0,'t'}, 490 {"warning", required_argument, 0, 'w'},
512 {"critical", required_argument,0,'c'}, 491 {"variable", required_argument, 0, 'v'},
513 {"warning", required_argument,0,'w'}, 492 {"hostname", required_argument, 0, 'H'},
514 {"variable", required_argument,0,'v'}, 493 {"params", required_argument, 0, 'l'},
515 {"hostname", required_argument,0,'H'}, 494 {"secret", required_argument, 0, 's'},
516 {"params", required_argument,0,'l'}, 495 {"display", required_argument, 0, 'd'},
517 {"secret", required_argument,0,'s'}, 496 {"unknown-timeout", no_argument, 0, 'u'},
518 {"display", required_argument,0,'d'}, 497 {"version", no_argument, 0, 'V'},
519 {"unknown-timeout", no_argument, 0, 'u'}, 498 {"help", no_argument, 0, 'h'},
520 {"version", no_argument, 0,'V'}, 499 {0, 0, 0, 0}};
521 {"help", no_argument, 0,'h'},
522 {0,0,0,0}
523 };
524 500
525 /* no options were supplied */ 501 /* no options were supplied */
526 if(argc<2) return ERROR; 502 if (argc < 2)
503 return ERROR;
527 504
528 /* backwards compatibility */ 505 /* backwards compatibility */
529 if (! is_option(argv[1])) { 506 if (!is_option(argv[1])) {
530 server_address = strdup(argv[1]); 507 server_address = strdup(argv[1]);
531 argv[1]=argv[0]; 508 argv[1] = argv[0];
532 argv=&argv[1]; 509 argv = &argv[1];
533 argc--; 510 argc--;
534 } 511 }
535 512
536 for (c=1;c<argc;c++) { 513 for (c = 1; c < argc; c++) {
537 if(strcmp("-to",argv[c])==0) 514 if (strcmp("-to", argv[c]) == 0)
538 strcpy(argv[c],"-t"); 515 strcpy(argv[c], "-t");
539 else if (strcmp("-wv",argv[c])==0) 516 else if (strcmp("-wv", argv[c]) == 0)
540 strcpy(argv[c],"-w"); 517 strcpy(argv[c], "-w");
541 else if (strcmp("-cv",argv[c])==0) 518 else if (strcmp("-cv", argv[c]) == 0)
542 strcpy(argv[c],"-c"); 519 strcpy(argv[c], "-c");
543 } 520 }
544 521
545 while (1) { 522 while (1) {
546 c = getopt_long(argc,argv,"+hVH:t:c:w:p:v:l:s:d:u",longopts,&option); 523 c = getopt_long(argc, argv, "+hVH:t:c:w:p:v:l:s:d:u", longopts, &option);
547 524
548 if (c==-1||c==EOF||c==1) 525 if (c == -1 || c == EOF || c == 1)
549 break; 526 break;
550 527
551 switch (c) { 528 switch (c) {
552 case '?': /* print short usage statement if args not parsable */ 529 case '?': /* print short usage statement if args not parsable */
553 usage5 (); 530 usage5();
554 case 'h': /* help */ 531 case 'h': /* help */
555 print_help(); 532 print_help();
556 exit(STATE_UNKNOWN); 533 exit(STATE_UNKNOWN);
557 case 'V': /* version */ 534 case 'V': /* version */
558 print_revision(progname, NP_VERSION); 535 print_revision(progname, NP_VERSION);
559 exit(STATE_UNKNOWN); 536 exit(STATE_UNKNOWN);
560 case 'H': /* hostname */ 537 case 'H': /* hostname */
561 server_address = optarg; 538 server_address = optarg;
562 break; 539 break;
563 case 's': /* password */ 540 case 's': /* password */
564 req_password = optarg; 541 req_password = optarg;
565 break; 542 break;
566 case 'p': /* port */ 543 case 'p': /* port */
567 if (is_intnonneg(optarg)) 544 if (is_intnonneg(optarg))
568 server_port=atoi(optarg); 545 server_port = atoi(optarg);
569 else 546 else
570 die(STATE_UNKNOWN,_("Server port must be an integer\n")); 547 die(STATE_UNKNOWN, _("Server port must be an integer\n"));
571 break; 548 break;
572 case 'v': 549 case 'v':
573 if(strlen(optarg)<4) 550 if (strlen(optarg) < 4)
574 return ERROR; 551 return ERROR;
575 if(!strcmp(optarg,"CLIENTVERSION")) 552 if (!strcmp(optarg, "CLIENTVERSION"))
576 vars_to_check=CHECK_CLIENTVERSION; 553 vars_to_check = CHECK_CLIENTVERSION;
577 else if(!strcmp(optarg,"CPULOAD")) 554 else if (!strcmp(optarg, "CPULOAD"))
578 vars_to_check=CHECK_CPULOAD; 555 vars_to_check = CHECK_CPULOAD;
579 else if(!strcmp(optarg,"UPTIME")) 556 else if (!strcmp(optarg, "UPTIME"))
580 vars_to_check=CHECK_UPTIME; 557 vars_to_check = CHECK_UPTIME;
581 else if(!strcmp(optarg,"USEDDISKSPACE")) 558 else if (!strcmp(optarg, "USEDDISKSPACE"))
582 vars_to_check=CHECK_USEDDISKSPACE; 559 vars_to_check = CHECK_USEDDISKSPACE;
583 else if(!strcmp(optarg,"SERVICESTATE")) 560 else if (!strcmp(optarg, "SERVICESTATE"))
584 vars_to_check=CHECK_SERVICESTATE; 561 vars_to_check = CHECK_SERVICESTATE;
585 else if(!strcmp(optarg,"PROCSTATE")) 562 else if (!strcmp(optarg, "PROCSTATE"))
586 vars_to_check=CHECK_PROCSTATE; 563 vars_to_check = CHECK_PROCSTATE;
587 else if(!strcmp(optarg,"MEMUSE")) 564 else if (!strcmp(optarg, "MEMUSE"))
588 vars_to_check=CHECK_MEMUSE; 565 vars_to_check = CHECK_MEMUSE;
589 else if(!strcmp(optarg,"COUNTER")) 566 else if (!strcmp(optarg, "COUNTER"))
590 vars_to_check=CHECK_COUNTER; 567 vars_to_check = CHECK_COUNTER;
591 else if(!strcmp(optarg,"FILEAGE")) 568 else if (!strcmp(optarg, "FILEAGE"))
592 vars_to_check=CHECK_FILEAGE; 569 vars_to_check = CHECK_FILEAGE;
593 else if(!strcmp(optarg,"INSTANCES")) 570 else if (!strcmp(optarg, "INSTANCES"))
594 vars_to_check=CHECK_INSTANCES; 571 vars_to_check = CHECK_INSTANCES;
595 else 572 else
596 return ERROR; 573 return ERROR;
597 break; 574 break;
598 case 'l': /* value list */ 575 case 'l': /* value list */
599 value_list = optarg; 576 value_list = optarg;
600 break; 577 break;
601 case 'w': /* warning threshold */ 578 case 'w': /* warning threshold */
602 warning_value=strtoul(optarg,NULL,10); 579 warning_value = strtoul(optarg, NULL, 10);
603 check_warning_value=true; 580 check_warning_value = true;
604 break; 581 break;
605 case 'c': /* critical threshold */ 582 case 'c': /* critical threshold */
606 critical_value=strtoul(optarg,NULL,10); 583 critical_value = strtoul(optarg, NULL, 10);
607 check_critical_value=true; 584 check_critical_value = true;
608 break; 585 break;
609 case 'd': /* Display select for services */ 586 case 'd': /* Display select for services */
610 if (!strcmp(optarg,"SHOWALL")) 587 if (!strcmp(optarg, "SHOWALL"))
611 show_all = true; 588 show_all = true;
612 break; 589 break;
613 case 'u': 590 case 'u':
614 socket_timeout_state=STATE_UNKNOWN; 591 socket_timeout_state = STATE_UNKNOWN;
615 break; 592 break;
616 case 't': /* timeout */ 593 case 't': /* timeout */
617 socket_timeout=atoi(optarg); 594 socket_timeout = atoi(optarg);
618 if(socket_timeout<=0) 595 if (socket_timeout <= 0)
619 return ERROR; 596 return ERROR;
620 } 597 }
621
622 } 598 }
623 if (server_address == NULL) 599 if (server_address == NULL)
624 usage4 (_("You must provide a server address or host name")); 600 usage4(_("You must provide a server address or host name"));
625 601
626 if (vars_to_check==CHECK_NONE) 602 if (vars_to_check == CHECK_NONE)
627 return ERROR; 603 return ERROR;
628 604
629 if (req_password == NULL) 605 if (req_password == NULL)
630 req_password = strdup (_("None")); 606 req_password = strdup(_("None"));
631 607
632 return OK; 608 return OK;
633} 609}
634 610
635 611void fetch_data(const char *address, int port, const char *sendb) {
636
637void fetch_data (const char *address, int port, const char *sendb) {
638 int result; 612 int result;
639 613
640 result=process_tcp_request(address, port, sendb, recv_buffer,sizeof(recv_buffer)); 614 result = process_tcp_request(address, port, sendb, recv_buffer, sizeof(recv_buffer));
641 615
642 if(result!=STATE_OK) 616 if (result != STATE_OK)
643 die (result, _("could not fetch information from server\n")); 617 die(result, _("could not fetch information from server\n"));
644 618
645 if (!strncmp(recv_buffer,"ERROR",5)) 619 if (!strncmp(recv_buffer, "ERROR", 5))
646 die (STATE_UNKNOWN, "NSClient - %s\n",recv_buffer); 620 die(STATE_UNKNOWN, "NSClient - %s\n", recv_buffer);
647} 621}
648 622
649bool strtoularray(unsigned long *array, char *string, const char *delim) { 623bool strtoularray(unsigned long *array, char *string, const char *delim) {
650 /* split a <delim> delimited string into a long array */ 624 /* split a <delim> delimited string into a long array */
651 int idx=0; 625 int idx = 0;
652 char *t1; 626 char *t1;
653 627
654 for (idx=0;idx<MAX_VALUE_LIST;idx++) 628 for (idx = 0; idx < MAX_VALUE_LIST; idx++)
655 array[idx]=0; 629 array[idx] = 0;
656 630
657 idx=0; 631 idx = 0;
658 for(t1 = strtok(string,delim);t1 != NULL; t1 = strtok(NULL, delim)) { 632 for (t1 = strtok(string, delim); t1 != NULL; t1 = strtok(NULL, delim)) {
659 if (is_numeric(t1) && idx<MAX_VALUE_LIST) { 633 if (is_numeric(t1) && idx < MAX_VALUE_LIST) {
660 array[idx]=strtoul(t1,NULL,10); 634 array[idx] = strtoul(t1, NULL, 10);
661 idx++; 635 idx++;
662 } else 636 } else
663 return false; 637 return false;
@@ -671,131 +645,124 @@ void preparelist(char *string) {
671 645
672 for (i = 0; (size_t)i < strlen(string); i++) 646 for (i = 0; (size_t)i < strlen(string); i++)
673 if (string[i] == ',') { 647 if (string[i] == ',') {
674 string[i]='&'; 648 string[i] = '&';
675 } 649 }
676} 650}
677 651
678 652void print_help(void) {
679
680void print_help(void)
681{
682 print_revision(progname, NP_VERSION); 653 print_revision(progname, NP_VERSION);
683 654
684 printf ("Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n"); 655 printf("Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n");
685 printf (COPYRIGHT, copyright, email); 656 printf(COPYRIGHT, copyright, email);
686 657
687 printf ("%s\n", _("This plugin collects data from the NSClient service running on a")); 658 printf("%s\n", _("This plugin collects data from the NSClient service running on a"));
688 printf ("%s\n", _("Windows NT/2000/XP/2003 server.")); 659 printf("%s\n", _("Windows NT/2000/XP/2003 server."));
689 660
690 printf ("\n\n"); 661 printf("\n\n");
691 662
692 print_usage(); 663 print_usage();
693 664
694 printf (UT_HELP_VRSN); 665 printf(UT_HELP_VRSN);
695 printf (UT_EXTRA_OPTS); 666 printf(UT_EXTRA_OPTS);
696 667
697 printf ("%s\n", _("Options:")); 668 printf("%s\n", _("Options:"));
698 printf (" %s\n", "-H, --hostname=HOST"); 669 printf(" %s\n", "-H, --hostname=HOST");
699 printf (" %s\n", _("Name of the host to check")); 670 printf(" %s\n", _("Name of the host to check"));
700 printf (" %s\n", "-p, --port=INTEGER"); 671 printf(" %s\n", "-p, --port=INTEGER");
701 printf (" %s", _("Optional port number (default: ")); 672 printf(" %s", _("Optional port number (default: "));
702 printf ("%d)\n", PORT); 673 printf("%d)\n", PORT);
703 printf (" %s\n", "-s, --secret=<password>"); 674 printf(" %s\n", "-s, --secret=<password>");
704 printf (" %s\n", _("Password needed for the request")); 675 printf(" %s\n", _("Password needed for the request"));
705 printf (" %s\n", "-w, --warning=INTEGER"); 676 printf(" %s\n", "-w, --warning=INTEGER");
706 printf (" %s\n", _("Threshold which will result in a warning status")); 677 printf(" %s\n", _("Threshold which will result in a warning status"));
707 printf (" %s\n", "-c, --critical=INTEGER"); 678 printf(" %s\n", "-c, --critical=INTEGER");
708 printf (" %s\n", _("Threshold which will result in a critical status")); 679 printf(" %s\n", _("Threshold which will result in a critical status"));
709 printf (" %s\n", "-t, --timeout=INTEGER"); 680 printf(" %s\n", "-t, --timeout=INTEGER");
710 printf (" %s", _("Seconds before connection attempt times out (default: ")); 681 printf(" %s", _("Seconds before connection attempt times out (default: "));
711 printf (" %s\n", "-l, --params=<parameters>"); 682 printf(" %s\n", "-l, --params=<parameters>");
712 printf (" %s", _("Parameters passed to specified check (see below)")); 683 printf(" %s", _("Parameters passed to specified check (see below)"));
713 printf (" %s\n", "-d, --display={SHOWALL}"); 684 printf(" %s\n", "-d, --display={SHOWALL}");
714 printf (" %s", _("Display options (currently only SHOWALL works)")); 685 printf(" %s", _("Display options (currently only SHOWALL works)"));
715 printf (" %s\n", "-u, --unknown-timeout"); 686 printf(" %s\n", "-u, --unknown-timeout");
716 printf (" %s", _("Return UNKNOWN on timeouts")); 687 printf(" %s", _("Return UNKNOWN on timeouts"));
717 printf ("%d)\n", DEFAULT_SOCKET_TIMEOUT); 688 printf("%d)\n", DEFAULT_SOCKET_TIMEOUT);
718 printf (" %s\n", "-h, --help"); 689 printf(" %s\n", "-h, --help");
719 printf (" %s\n", _("Print this help screen")); 690 printf(" %s\n", _("Print this help screen"));
720 printf (" %s\n", "-V, --version"); 691 printf(" %s\n", "-V, --version");
721 printf (" %s\n", _("Print version information")); 692 printf(" %s\n", _("Print version information"));
722 printf (" %s\n", "-v, --variable=STRING"); 693 printf(" %s\n", "-v, --variable=STRING");
723 printf (" %s\n\n", _("Variable to check")); 694 printf(" %s\n\n", _("Variable to check"));
724 printf ("%s\n", _("Valid variables are:")); 695 printf("%s\n", _("Valid variables are:"));
725 printf (" %s", "CLIENTVERSION ="); 696 printf(" %s", "CLIENTVERSION =");
726 printf (" %s\n", _("Get the NSClient version")); 697 printf(" %s\n", _("Get the NSClient version"));
727 printf (" %s\n", _("If -l <version> is specified, will return warning if versions differ.")); 698 printf(" %s\n", _("If -l <version> is specified, will return warning if versions differ."));
728 printf (" %s\n", "CPULOAD ="); 699 printf(" %s\n", "CPULOAD =");
729 printf (" %s\n", _("Average CPU load on last x minutes.")); 700 printf(" %s\n", _("Average CPU load on last x minutes."));
730 printf (" %s\n", _("Request a -l parameter with the following syntax:")); 701 printf(" %s\n", _("Request a -l parameter with the following syntax:"));
731 printf (" %s\n", _("-l <minutes range>,<warning threshold>,<critical threshold>.")); 702 printf(" %s\n", _("-l <minutes range>,<warning threshold>,<critical threshold>."));
732 printf (" %s\n", _("<minute range> should be less than 24*60.")); 703 printf(" %s\n", _("<minute range> should be less than 24*60."));
733 printf (" %s\n", _("Thresholds are percentage and up to 10 requests can be done in one shot.")); 704 printf(" %s\n", _("Thresholds are percentage and up to 10 requests can be done in one shot."));
734 printf (" %s\n", "ie: -l 60,90,95,120,90,95"); 705 printf(" %s\n", "ie: -l 60,90,95,120,90,95");
735 printf (" %s\n", "UPTIME ="); 706 printf(" %s\n", "UPTIME =");
736 printf (" %s\n", _("Get the uptime of the machine.")); 707 printf(" %s\n", _("Get the uptime of the machine."));
737 printf (" %s\n", _("-l <unit> ")); 708 printf(" %s\n", _("-l <unit> "));
738 printf (" %s\n", _("<unit> = seconds, minutes, hours, or days. (default: minutes)")); 709 printf(" %s\n", _("<unit> = seconds, minutes, hours, or days. (default: minutes)"));
739 printf (" %s\n", _("Thresholds will use the unit specified above.")); 710 printf(" %s\n", _("Thresholds will use the unit specified above."));
740 printf (" %s\n", "USEDDISKSPACE ="); 711 printf(" %s\n", "USEDDISKSPACE =");
741 printf (" %s\n", _("Size and percentage of disk use.")); 712 printf(" %s\n", _("Size and percentage of disk use."));
742 printf (" %s\n", _("Request a -l parameter containing the drive letter only.")); 713 printf(" %s\n", _("Request a -l parameter containing the drive letter only."));
743 printf (" %s\n", _("Warning and critical thresholds can be specified with -w and -c.")); 714 printf(" %s\n", _("Warning and critical thresholds can be specified with -w and -c."));
744 printf (" %s\n", "MEMUSE ="); 715 printf(" %s\n", "MEMUSE =");
745 printf (" %s\n", _("Memory use.")); 716 printf(" %s\n", _("Memory use."));
746 printf (" %s\n", _("Warning and critical thresholds can be specified with -w and -c.")); 717 printf(" %s\n", _("Warning and critical thresholds can be specified with -w and -c."));
747 printf (" %s\n", "SERVICESTATE ="); 718 printf(" %s\n", "SERVICESTATE =");
748 printf (" %s\n", _("Check the state of one or several services.")); 719 printf(" %s\n", _("Check the state of one or several services."));
749 printf (" %s\n", _("Request a -l parameters with the following syntax:")); 720 printf(" %s\n", _("Request a -l parameters with the following syntax:"));
750 printf (" %s\n", _("-l <service1>,<service2>,<service3>,...")); 721 printf(" %s\n", _("-l <service1>,<service2>,<service3>,..."));
751 printf (" %s\n", _("You can specify -d SHOWALL in case you want to see working services")); 722 printf(" %s\n", _("You can specify -d SHOWALL in case you want to see working services"));
752 printf (" %s\n", _("in the returned string.")); 723 printf(" %s\n", _("in the returned string."));
753 printf (" %s\n", "PROCSTATE ="); 724 printf(" %s\n", "PROCSTATE =");
754 printf (" %s\n", _("Check if one or several process are running.")); 725 printf(" %s\n", _("Check if one or several process are running."));
755 printf (" %s\n", _("Same syntax as SERVICESTATE.")); 726 printf(" %s\n", _("Same syntax as SERVICESTATE."));
756 printf (" %s\n", "COUNTER ="); 727 printf(" %s\n", "COUNTER =");
757 printf (" %s\n", _("Check any performance counter of Windows NT/2000.")); 728 printf(" %s\n", _("Check any performance counter of Windows NT/2000."));
758 printf (" %s\n", _("Request a -l parameters with the following syntax:")); 729 printf(" %s\n", _("Request a -l parameters with the following syntax:"));
759 printf (" %s\n", _("-l \"\\\\<performance object>\\\\counter\",\"<description>")); 730 printf(" %s\n", _("-l \"\\\\<performance object>\\\\counter\",\"<description>"));
760 printf (" %s\n", _("The <description> parameter is optional and is given to a printf ")); 731 printf(" %s\n", _("The <description> parameter is optional and is given to a printf "));
761 printf (" %s\n", _("output command which requires a float parameter.")); 732 printf(" %s\n", _("output command which requires a float parameter."));
762 printf (" %s\n", _("If <description> does not include \"%%\", it is used as a label.")); 733 printf(" %s\n", _("If <description> does not include \"%%\", it is used as a label."));
763 printf (" %s\n", _("Some examples:")); 734 printf(" %s\n", _("Some examples:"));
764 printf (" %s\n", "\"Paging file usage is %%.2f %%%%\""); 735 printf(" %s\n", "\"Paging file usage is %%.2f %%%%\"");
765 printf (" %s\n", "\"%%.f %%%% paging file used.\""); 736 printf(" %s\n", "\"%%.f %%%% paging file used.\"");
766 printf (" %s\n", "INSTANCES ="); 737 printf(" %s\n", "INSTANCES =");
767 printf (" %s\n", _("Check any performance counter object of Windows NT/2000.")); 738 printf(" %s\n", _("Check any performance counter object of Windows NT/2000."));
768 printf (" %s\n", _("Syntax: check_nt -H <hostname> -p <port> -v INSTANCES -l <counter object>")); 739 printf(" %s\n", _("Syntax: check_nt -H <hostname> -p <port> -v INSTANCES -l <counter object>"));
769 printf (" %s\n", _("<counter object> is a Windows Perfmon Counter object (eg. Process),")); 740 printf(" %s\n", _("<counter object> is a Windows Perfmon Counter object (eg. Process),"));
770 printf (" %s\n", _("if it is two words, it should be enclosed in quotes")); 741 printf(" %s\n", _("if it is two words, it should be enclosed in quotes"));
771 printf (" %s\n", _("The returned results will be a comma-separated list of instances on ")); 742 printf(" %s\n", _("The returned results will be a comma-separated list of instances on "));
772 printf (" %s\n", _(" the selected computer for that object.")); 743 printf(" %s\n", _(" the selected computer for that object."));
773 printf (" %s\n", _("The purpose of this is to be run from command line to determine what instances")); 744 printf(" %s\n", _("The purpose of this is to be run from command line to determine what instances"));
774 printf (" %s\n", _(" are available for monitoring without having to log onto the Windows server")); 745 printf(" %s\n", _(" are available for monitoring without having to log onto the Windows server"));
775 printf (" %s\n", _(" to run Perfmon directly.")); 746 printf(" %s\n", _(" to run Perfmon directly."));
776 printf (" %s\n", _("It can also be used in scripts that automatically create the monitoring service")); 747 printf(" %s\n", _("It can also be used in scripts that automatically create the monitoring service"));
777 printf (" %s\n", _(" configuration files.")); 748 printf(" %s\n", _(" configuration files."));
778 printf (" %s\n", _("Some examples:")); 749 printf(" %s\n", _("Some examples:"));
779 printf (" %s\n\n", _("check_nt -H 192.168.1.1 -p 1248 -v INSTANCES -l Process")); 750 printf(" %s\n\n", _("check_nt -H 192.168.1.1 -p 1248 -v INSTANCES -l Process"));
780 751
781 printf ("%s\n", _("Notes:")); 752 printf("%s\n", _("Notes:"));
782 printf (" %s\n", _("- The NSClient service should be running on the server to get any information")); 753 printf(" %s\n", _("- The NSClient service should be running on the server to get any information"));
783 printf (" %s\n", "(http://nsclient.ready2run.nl)."); 754 printf(" %s\n", "(http://nsclient.ready2run.nl).");
784 printf (" %s\n", _("- Critical thresholds should be lower than warning thresholds")); 755 printf(" %s\n", _("- Critical thresholds should be lower than warning thresholds"));
785 printf (" %s\n", _("- Default port 1248 is sometimes in use by other services. The error")); 756 printf(" %s\n", _("- Default port 1248 is sometimes in use by other services. The error"));
786 printf (" %s\n", _("output when this happens contains \"Cannot map xxxxx to protocol number\".")); 757 printf(" %s\n", _("output when this happens contains \"Cannot map xxxxx to protocol number\"."));
787 printf (" %s\n", _("One fix for this is to change the port to something else on check_nt ")); 758 printf(" %s\n", _("One fix for this is to change the port to something else on check_nt "));
788 printf (" %s\n", _("and on the client service it\'s connecting to.")); 759 printf(" %s\n", _("and on the client service it\'s connecting to."));
789 760
790 printf (UT_SUPPORT); 761 printf(UT_SUPPORT);
791} 762}
792 763
793 764void print_usage(void) {
794 765 printf("%s\n", _("Usage:"));
795void print_usage(void) 766 printf("%s -H host -v variable [-p port] [-w warning] [-c critical]\n", progname);
796{ 767 printf("[-l params] [-d SHOWALL] [-u] [-t timeout]\n");
797 printf ("%s\n", _("Usage:"));
798 printf ("%s -H host -v variable [-p port] [-w warning] [-c critical]\n",progname);
799 printf ("[-l params] [-d SHOWALL] [-u] [-t timeout]\n");
800} 768}
801
diff --git a/plugins/check_ntp.c b/plugins/check_ntp.c
index 61b2d699..55a49460 100644
--- a/plugins/check_ntp.c
+++ b/plugins/check_ntp.c
@@ -4,7 +4,7 @@
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2006 Sean Finney <seanius@seanius.net> 6* Copyright (c) 2006 Sean Finney <seanius@seanius.net>
7* Copyright (c) 2006-2008 Monitoring Plugins Development Team 7* Copyright (c) 2006-2024 Monitoring Plugins Development Team
8* 8*
9* Description: 9* Description:
10* 10*
@@ -31,7 +31,7 @@
31*****************************************************************************/ 31*****************************************************************************/
32 32
33const char *progname = "check_ntp"; 33const char *progname = "check_ntp";
34const char *copyright = "2006-2008"; 34const char *copyright = "2006-2024";
35const char *email = "devel@monitoring-plugins.org"; 35const char *email = "devel@monitoring-plugins.org";
36 36
37#include "common.h" 37#include "common.h"
diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c
index 464a9e10..f99e5032 100644
--- a/plugins/check_ntp_peer.c
+++ b/plugins/check_ntp_peer.c
@@ -1,88 +1,88 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ntp_peer plugin 3 * Monitoring check_ntp_peer plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2006 Sean Finney <seanius@seanius.net> 6 * Copyright (c) 2006 Sean Finney <seanius@seanius.net>
7* Copyright (c) 2006-2008 Monitoring Plugins Development Team 7 * Copyright (c) 2006-2024 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_ntp_peer plugin 11 * This file contains the check_ntp_peer plugin
12* 12 *
13* This plugin checks an NTP server independent of any commandline 13 * This plugin checks an NTP server independent of any commandline
14* programs or external libraries. 14 * programs or external libraries.
15* 15 *
16* Use this plugin to check the health of an NTP server. It supports 16 * Use this plugin to check the health of an NTP server. It supports
17* checking the offset with the sync peer, the jitter and stratum. This 17 * checking the offset with the sync peer, the jitter and stratum. This
18* plugin will not check the clock offset between the local host and NTP 18 * plugin will not check the clock offset between the local host and NTP
19* server; please use check_ntp_time for that purpose. 19 * server; please use check_ntp_time for that purpose.
20* 20 *
21* 21 *
22* This program is free software: you can redistribute it and/or modify 22 * This program is free software: you can redistribute it and/or modify
23* it under the terms of the GNU General Public License as published by 23 * it under the terms of the GNU General Public License as published by
24* the Free Software Foundation, either version 3 of the License, or 24 * the Free Software Foundation, either version 3 of the License, or
25* (at your option) any later version. 25 * (at your option) any later version.
26* 26 *
27* This program is distributed in the hope that it will be useful, 27 * This program is distributed in the hope that it will be useful,
28* but WITHOUT ANY WARRANTY; without even the implied warranty of 28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30* GNU General Public License for more details. 30 * GNU General Public License for more details.
31* 31 *
32* You should have received a copy of the GNU General Public License 32 * You should have received a copy of the GNU General Public License
33* along with this program. If not, see <http://www.gnu.org/licenses/>. 33 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34* 34 *
35* 35 *
36*****************************************************************************/ 36 *****************************************************************************/
37 37
38const char *progname = "check_ntp_peer"; 38const char *progname = "check_ntp_peer";
39const char *copyright = "2006-2008"; 39const char *copyright = "2006-2024";
40const char *email = "devel@monitoring-plugins.org"; 40const char *email = "devel@monitoring-plugins.org";
41 41
42#include "common.h" 42#include "common.h"
43#include "netutils.h" 43#include "netutils.h"
44#include "utils.h" 44#include "utils.h"
45 45
46static char *server_address=NULL; 46static char *server_address = NULL;
47static int port=123; 47static int port = 123;
48static int verbose=0; 48static int verbose = 0;
49static bool quiet = false; 49static bool quiet = false;
50static char *owarn="60"; 50static char *owarn = "60";
51static char *ocrit="120"; 51static char *ocrit = "120";
52static bool do_stratum = false; 52static bool do_stratum = false;
53static char *swarn="-1:16"; 53static char *swarn = "-1:16";
54static char *scrit="-1:16"; 54static char *scrit = "-1:16";
55static bool do_jitter = false; 55static bool do_jitter = false;
56static char *jwarn="-1:5000"; 56static char *jwarn = "-1:5000";
57static char *jcrit="-1:10000"; 57static char *jcrit = "-1:10000";
58static bool do_truechimers = false; 58static bool do_truechimers = false;
59static char *twarn="0:"; 59static char *twarn = "0:";
60static char *tcrit="0:"; 60static char *tcrit = "0:";
61static bool syncsource_found = false; 61static bool syncsource_found = false;
62static bool li_alarm = false; 62static bool li_alarm = false;
63 63
64int process_arguments (int, char **); 64static int process_arguments(int /*argc*/, char ** /*argv*/);
65thresholds *offset_thresholds = NULL; 65static thresholds *offset_thresholds = NULL;
66thresholds *jitter_thresholds = NULL; 66static thresholds *jitter_thresholds = NULL;
67thresholds *stratum_thresholds = NULL; 67static thresholds *stratum_thresholds = NULL;
68thresholds *truechimer_thresholds = NULL; 68static thresholds *truechimer_thresholds = NULL;
69void print_help (void); 69static void print_help(void);
70void print_usage (void); 70void print_usage(void);
71 71
72/* max size of control message data */ 72/* max size of control message data */
73#define MAX_CM_SIZE 468 73#define MAX_CM_SIZE 468
74 74
75/* this structure holds everything in an ntp control message as per rfc1305 */ 75/* this structure holds everything in an ntp control message as per rfc1305 */
76typedef struct { 76typedef struct {
77 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ 77 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */
78 uint8_t op; /* R,E,M bits and Opcode */ 78 uint8_t op; /* R,E,M bits and Opcode */
79 uint16_t seq; /* Packet sequence */ 79 uint16_t seq; /* Packet sequence */
80 uint16_t status; /* Clock status */ 80 uint16_t status; /* Clock status */
81 uint16_t assoc; /* Association */ 81 uint16_t assoc; /* Association */
82 uint16_t offset; /* Similar to TCP sequence # */ 82 uint16_t offset; /* Similar to TCP sequence # */
83 uint16_t count; /* # bytes of data */ 83 uint16_t count; /* # bytes of data */
84 char data[MAX_CM_SIZE]; /* ASCII data of the request */ 84 char data[MAX_CM_SIZE]; /* ASCII data of the request */
85 /* NB: not necessarily NULL terminated! */ 85 /* NB: not necessarily NULL terminated! */
86} ntp_control_message; 86} ntp_control_message;
87 87
88/* this is an association/status-word pair found in control packet responses */ 88/* this is an association/status-word pair found in control packet responses */
@@ -93,82 +93,96 @@ typedef struct {
93 93
94/* bits 1,2 are the leap indicator */ 94/* bits 1,2 are the leap indicator */
95#define LI_MASK 0xc0 95#define LI_MASK 0xc0
96#define LI(x) ((x&LI_MASK)>>6) 96#define LI(x) ((x & LI_MASK) >> 6)
97#define LI_SET(x,y) do{ x |= ((y<<6)&LI_MASK); }while(0) 97#define LI_SET(x, y) \
98 do { \
99 x |= ((y << 6) & LI_MASK); \
100 } while (0)
98/* and these are the values of the leap indicator */ 101/* and these are the values of the leap indicator */
99#define LI_NOWARNING 0x00 102#define LI_NOWARNING 0x00
100#define LI_EXTRASEC 0x01 103#define LI_EXTRASEC 0x01
101#define LI_MISSINGSEC 0x02 104#define LI_MISSINGSEC 0x02
102#define LI_ALARM 0x03 105#define LI_ALARM 0x03
103/* bits 3,4,5 are the ntp version */ 106/* bits 3,4,5 are the ntp version */
104#define VN_MASK 0x38 107#define VN_MASK 0x38
105#define VN(x) ((x&VN_MASK)>>3) 108#define VN(x) ((x & VN_MASK) >> 3)
106#define VN_SET(x,y) do{ x |= ((y<<3)&VN_MASK); }while(0) 109#define VN_SET(x, y) \
110 do { \
111 x |= ((y << 3) & VN_MASK); \
112 } while (0)
107#define VN_RESERVED 0x02 113#define VN_RESERVED 0x02
108/* bits 6,7,8 are the ntp mode */ 114/* bits 6,7,8 are the ntp mode */
109#define MODE_MASK 0x07 115#define MODE_MASK 0x07
110#define MODE(x) (x&MODE_MASK) 116#define MODE(x) (x & MODE_MASK)
111#define MODE_SET(x,y) do{ x |= (y&MODE_MASK); }while(0) 117#define MODE_SET(x, y) \
118 do { \
119 x |= (y & MODE_MASK); \
120 } while (0)
112/* here are some values */ 121/* here are some values */
113#define MODE_CLIENT 0x03 122#define MODE_CLIENT 0x03
114#define MODE_CONTROLMSG 0x06 123#define MODE_CONTROLMSG 0x06
115/* In control message, bits 8-10 are R,E,M bits */ 124/* In control message, bits 8-10 are R,E,M bits */
116#define REM_MASK 0xe0 125#define REM_MASK 0xe0
117#define REM_RESP 0x80 126#define REM_RESP 0x80
118#define REM_ERROR 0x40 127#define REM_ERROR 0x40
119#define REM_MORE 0x20 128#define REM_MORE 0x20
120/* In control message, bits 11 - 15 are opcode */ 129/* In control message, bits 11 - 15 are opcode */
121#define OP_MASK 0x1f 130#define OP_MASK 0x1f
122#define OP_SET(x,y) do{ x |= (y&OP_MASK); }while(0) 131#define OP_SET(x, y) \
132 do { \
133 x |= (y & OP_MASK); \
134 } while (0)
123#define OP_READSTAT 0x01 135#define OP_READSTAT 0x01
124#define OP_READVAR 0x02 136#define OP_READVAR 0x02
125/* In peer status bytes, bits 6,7,8 determine clock selection status */ 137/* In peer status bytes, bits 6,7,8 determine clock selection status */
126#define PEER_SEL(x) ((ntohs(x)>>8)&0x07) 138#define PEER_SEL(x) ((ntohs(x) >> 8) & 0x07)
127#define PEER_TRUECHIMER 0x02 139#define PEER_TRUECHIMER 0x02
128#define PEER_INCLUDED 0x04 140#define PEER_INCLUDED 0x04
129#define PEER_SYNCSOURCE 0x06 141#define PEER_SYNCSOURCE 0x06
130 142
131/* NTP control message header is 12 bytes, plus any data in the data 143/* NTP control message header is 12 bytes, plus any data in the data
132 * field, plus null padding to the nearest 32-bit boundary per rfc. 144 * field, plus null padding to the nearest 32-bit boundary per rfc.
133 */ 145 */
134#define SIZEOF_NTPCM(m) (12+ntohs(m.count)+((ntohs(m.count)%4)?4-(ntohs(m.count)%4):0)) 146#define SIZEOF_NTPCM(m) (12 + ntohs(m.count) + ((ntohs(m.count) % 4) ? 4 - (ntohs(m.count) % 4) : 0))
135 147
136/* finally, a little helper or two for debugging: */ 148/* finally, a little helper or two for debugging: */
137#define DBG(x) do{if(verbose>1){ x; }}while(0); 149#define DBG(x) \
138#define PRINTSOCKADDR(x) \ 150 do { \
139 do{ \ 151 if (verbose > 1) { \
140 printf("%u.%u.%u.%u", (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff);\ 152 x; \
141 }while(0); 153 } \
142 154 } while (0);
143void print_ntp_control_message(const ntp_control_message *p){ 155#define PRINTSOCKADDR(x) \
144 int i=0, numpeers=0; 156 do { \
145 const ntp_assoc_status_pair *peer=NULL; 157 printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \
146 158 } while (0);
159
160void print_ntp_control_message(const ntp_control_message *p) {
147 printf("control packet contents:\n"); 161 printf("control packet contents:\n");
148 printf("\tflags: 0x%.2x , 0x%.2x\n", p->flags, p->op); 162 printf("\tflags: 0x%.2x , 0x%.2x\n", p->flags, p->op);
149 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags&LI_MASK); 163 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags & LI_MASK);
150 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags&VN_MASK); 164 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags & VN_MASK);
151 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags&MODE_MASK); 165 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags & MODE_MASK);
152 printf("\t response=%d (0x%.2x)\n", (p->op&REM_RESP)>0, p->op&REM_RESP); 166 printf("\t response=%d (0x%.2x)\n", (p->op & REM_RESP) > 0, p->op & REM_RESP);
153 printf("\t more=%d (0x%.2x)\n", (p->op&REM_MORE)>0, p->op&REM_MORE); 167 printf("\t more=%d (0x%.2x)\n", (p->op & REM_MORE) > 0, p->op & REM_MORE);
154 printf("\t error=%d (0x%.2x)\n", (p->op&REM_ERROR)>0, p->op&REM_ERROR); 168 printf("\t error=%d (0x%.2x)\n", (p->op & REM_ERROR) > 0, p->op & REM_ERROR);
155 printf("\t op=%d (0x%.2x)\n", p->op&OP_MASK, p->op&OP_MASK); 169 printf("\t op=%d (0x%.2x)\n", p->op & OP_MASK, p->op & OP_MASK);
156 printf("\tsequence: %d (0x%.2x)\n", ntohs(p->seq), ntohs(p->seq)); 170 printf("\tsequence: %d (0x%.2x)\n", ntohs(p->seq), ntohs(p->seq));
157 printf("\tstatus: %d (0x%.2x)\n", ntohs(p->status), ntohs(p->status)); 171 printf("\tstatus: %d (0x%.2x)\n", ntohs(p->status), ntohs(p->status));
158 printf("\tassoc: %d (0x%.2x)\n", ntohs(p->assoc), ntohs(p->assoc)); 172 printf("\tassoc: %d (0x%.2x)\n", ntohs(p->assoc), ntohs(p->assoc));
159 printf("\toffset: %d (0x%.2x)\n", ntohs(p->offset), ntohs(p->offset)); 173 printf("\toffset: %d (0x%.2x)\n", ntohs(p->offset), ntohs(p->offset));
160 printf("\tcount: %d (0x%.2x)\n", ntohs(p->count), ntohs(p->count)); 174 printf("\tcount: %d (0x%.2x)\n", ntohs(p->count), ntohs(p->count));
161 numpeers=ntohs(p->count)/(sizeof(ntp_assoc_status_pair)); 175
162 if(p->op&REM_RESP && p->op&OP_READSTAT){ 176 int numpeers = ntohs(p->count) / (sizeof(ntp_assoc_status_pair));
163 peer=(ntp_assoc_status_pair*)p->data; 177 if (p->op & REM_RESP && p->op & OP_READSTAT) {
164 for(i=0;i<numpeers;i++){ 178 const ntp_assoc_status_pair *peer = (ntp_assoc_status_pair *)p->data;
165 printf("\tpeer id %.2x status %.2x", 179 for (int i = 0; i < numpeers; i++) {
166 ntohs(peer[i].assoc), ntohs(peer[i].status)); 180 printf("\tpeer id %.2x status %.2x", ntohs(peer[i].assoc), ntohs(peer[i].status));
167 if(PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE){ 181 if (PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE) {
168 printf(" <-- current sync source"); 182 printf(" <-- current sync source");
169 } else if(PEER_SEL(peer[i].status) >= PEER_INCLUDED){ 183 } else if (PEER_SEL(peer[i].status) >= PEER_INCLUDED) {
170 printf(" <-- current sync candidate"); 184 printf(" <-- current sync candidate");
171 } else if(PEER_SEL(peer[i].status) >= PEER_TRUECHIMER){ 185 } else if (PEER_SEL(peer[i].status) >= PEER_TRUECHIMER) {
172 printf(" <-- outlyer, but truechimer"); 186 printf(" <-- outlyer, but truechimer");
173 } 187 }
174 printf("\n"); 188 printf("\n");
@@ -176,8 +190,7 @@ void print_ntp_control_message(const ntp_control_message *p){
176 } 190 }
177} 191}
178 192
179void 193void setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq) {
180setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){
181 memset(p, 0, sizeof(ntp_control_message)); 194 memset(p, 0, sizeof(ntp_control_message));
182 LI_SET(p->flags, LI_NOWARNING); 195 LI_SET(p->flags, LI_NOWARNING);
183 VN_SET(p->flags, VN_RESERVED); 196 VN_SET(p->flags, VN_RESERVED);
@@ -198,19 +211,7 @@ setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){
198 * status is pretty much useless as syncsource_found is a global variable 211 * status is pretty much useless as syncsource_found is a global variable
199 * used later in main to check is the server was synchronized. It works 212 * used later in main to check is the server was synchronized. It works
200 * so I left it alone */ 213 * so I left it alone */
201int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum, int *num_truechimers){ 214int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum, int *num_truechimers) {
202 int conn=-1, i, npeers=0, num_candidates=0;
203 double tmp_offset = 0;
204 int min_peer_sel=PEER_INCLUDED;
205 int peers_size=0, peer_offset=0;
206 int status;
207 ntp_assoc_status_pair *peers=NULL;
208 ntp_control_message req;
209 const char *getvar = "stratum,offset,jitter";
210 char *data, *value, *nptr;
211 void *tmp;
212
213 status = STATE_OK;
214 *offset_result = STATE_UNKNOWN; 215 *offset_result = STATE_UNKNOWN;
215 *jitter = *stratum = -1; 216 *jitter = *stratum = -1;
216 *num_truechimers = 0; 217 *num_truechimers = 0;
@@ -231,11 +232,20 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
231 * 4) Extract the offset, jitter and stratum value from the data[] 232 * 4) Extract the offset, jitter and stratum value from the data[]
232 * (it's ASCII) 233 * (it's ASCII)
233 */ 234 */
235 int min_peer_sel = PEER_INCLUDED;
236 int num_candidates = 0;
237 void *tmp;
238 ntp_assoc_status_pair *peers = NULL;
239 int peer_offset = 0;
240 int peers_size = 0;
241 int npeers = 0;
242 int conn = -1;
234 my_udp_connect(server_address, port, &conn); 243 my_udp_connect(server_address, port, &conn);
235 244
236 /* keep sending requests until the server stops setting the 245 /* keep sending requests until the server stops setting the
237 * REM_MORE bit, though usually this is only 1 packet. */ 246 * REM_MORE bit, though usually this is only 1 packet. */
238 do{ 247 ntp_control_message req;
248 do {
239 setup_control_request(&req, OP_READSTAT, 1); 249 setup_control_request(&req, OP_READSTAT, 1);
240 DBG(printf("sending READSTAT request")); 250 DBG(printf("sending READSTAT request"));
241 write(conn, &req, SIZEOF_NTPCM(req)); 251 write(conn, &req, SIZEOF_NTPCM(req));
@@ -243,63 +253,73 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
243 253
244 do { 254 do {
245 /* Attempt to read the largest size packet possible */ 255 /* Attempt to read the largest size packet possible */
246 req.count=htons(MAX_CM_SIZE); 256 req.count = htons(MAX_CM_SIZE);
247 DBG(printf("receiving READSTAT response")) 257 DBG(printf("receiving READSTAT response"))
248 if(read(conn, &req, SIZEOF_NTPCM(req)) == -1) 258 if (read(conn, &req, SIZEOF_NTPCM(req)) == -1)
249 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); 259 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n");
250 DBG(print_ntp_control_message(&req)); 260 DBG(print_ntp_control_message(&req));
251 /* discard obviously invalid packets */ 261 /* discard obviously invalid packets */
252 if (ntohs(req.count) > MAX_CM_SIZE) 262 if (ntohs(req.count) > MAX_CM_SIZE)
253 die(STATE_CRITICAL, "NTP CRITICAL: Invalid packet received from NTP server\n"); 263 die(STATE_CRITICAL, "NTP CRITICAL: Invalid packet received from NTP server\n");
254 } while (!(req.op&OP_READSTAT && ntohs(req.seq) == 1)); 264 } while (!(req.op & OP_READSTAT && ntohs(req.seq) == 1));
255 265
256 if (LI(req.flags) == LI_ALARM) li_alarm = true; 266 if (LI(req.flags) == LI_ALARM)
267 li_alarm = true;
257 /* Each peer identifier is 4 bytes in the data section, which 268 /* Each peer identifier is 4 bytes in the data section, which
258 * we represent as a ntp_assoc_status_pair datatype. 269 * we represent as a ntp_assoc_status_pair datatype.
259 */ 270 */
260 peers_size+=ntohs(req.count); 271 peers_size += ntohs(req.count);
261 if((tmp=realloc(peers, peers_size)) == NULL) 272 if ((tmp = realloc(peers, peers_size)) == NULL)
262 free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n"); 273 free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n");
263 peers=tmp; 274 peers = tmp;
264 memcpy((void*)((ptrdiff_t)peers+peer_offset), (void*)req.data, ntohs(req.count)); 275 memcpy((void *)((ptrdiff_t)peers + peer_offset), (void *)req.data, ntohs(req.count));
265 npeers=peers_size/sizeof(ntp_assoc_status_pair); 276 npeers = peers_size / sizeof(ntp_assoc_status_pair);
266 peer_offset+=ntohs(req.count); 277 peer_offset += ntohs(req.count);
267 } while(req.op&REM_MORE); 278 } while (req.op & REM_MORE);
268 279
269 /* first, let's find out if we have a sync source, or if there are 280 /* first, let's find out if we have a sync source, or if there are
270 * at least some candidates. In the latter case we'll issue 281 * at least some candidates. In the latter case we'll issue
271 * a warning but go ahead with the check on them. */ 282 * a warning but go ahead with the check on them. */
272 for (i = 0; i < npeers; i++){ 283 for (int i = 0; i < npeers; i++) {
273 if(PEER_SEL(peers[i].status) >= PEER_TRUECHIMER){ 284 if (PEER_SEL(peers[i].status) >= PEER_TRUECHIMER) {
274 (*num_truechimers)++; 285 (*num_truechimers)++;
275 if(PEER_SEL(peers[i].status) >= PEER_INCLUDED){ 286 if (PEER_SEL(peers[i].status) >= PEER_INCLUDED) {
276 num_candidates++; 287 num_candidates++;
277 if(PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE){ 288 if (PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE) {
278 syncsource_found = true; 289 syncsource_found = true;
279 min_peer_sel=PEER_SYNCSOURCE; 290 min_peer_sel = PEER_SYNCSOURCE;
280 } 291 }
281 } 292 }
282 } 293 }
283 } 294 }
284 if(verbose) printf("%d candidate peers available\n", num_candidates); 295
285 if(verbose && syncsource_found) printf("synchronization source found\n"); 296 if (verbose)
286 if(! syncsource_found){ 297 printf("%d candidate peers available\n", num_candidates);
298 if (verbose && syncsource_found)
299 printf("synchronization source found\n");
300
301 int status = STATE_OK;
302 if (!syncsource_found) {
287 status = STATE_WARNING; 303 status = STATE_WARNING;
288 if(verbose) printf("warning: no synchronization source found\n"); 304 if (verbose)
305 printf("warning: no synchronization source found\n");
289 } 306 }
290 if(li_alarm){ 307 if (li_alarm) {
291 status = STATE_WARNING; 308 status = STATE_WARNING;
292 if(verbose) printf("warning: LI_ALARM bit is set\n"); 309 if (verbose)
310 printf("warning: LI_ALARM bit is set\n");
293 } 311 }
294 312
295 313 const char *getvar = "stratum,offset,jitter";
296 for (i = 0; i < npeers; i++){ 314 char *data;
315 for (int i = 0; i < npeers; i++) {
297 /* Only query this server if it is the current sync source */ 316 /* Only query this server if it is the current sync source */
298 /* If there's no sync.peer, query all candidates and use the best one */ 317 /* If there's no sync.peer, query all candidates and use the best one */
299 if (PEER_SEL(peers[i].status) >= min_peer_sel){ 318 if (PEER_SEL(peers[i].status) >= min_peer_sel) {
300 if(verbose) printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc)); 319 if (verbose)
320 printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc));
301 xasprintf(&data, ""); 321 xasprintf(&data, "");
302 do{ 322 do {
303 setup_control_request(&req, OP_READVAR, 2); 323 setup_control_request(&req, OP_READVAR, 2);
304 req.assoc = peers[i].assoc; 324 req.assoc = peers[i].assoc;
305 /* Putting the wanted variable names in the request 325 /* Putting the wanted variable names in the request
@@ -309,7 +329,7 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
309 */ 329 */
310 /* Older servers doesn't know what jitter is, so if we get an 330 /* Older servers doesn't know what jitter is, so if we get an
311 * error on the first pass we redo it with "dispersion" */ 331 * error on the first pass we redo it with "dispersion" */
312 strncpy(req.data, getvar, MAX_CM_SIZE-1); 332 strncpy(req.data, getvar, MAX_CM_SIZE - 1);
313 req.count = htons(strlen(getvar)); 333 req.count = htons(strlen(getvar));
314 DBG(printf("sending READVAR request...\n")); 334 DBG(printf("sending READVAR request...\n"));
315 write(conn, &req, SIZEOF_NTPCM(req)); 335 write(conn, &req, SIZEOF_NTPCM(req));
@@ -320,44 +340,53 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
320 DBG(printf("receiving READVAR response...\n")); 340 DBG(printf("receiving READVAR response...\n"));
321 read(conn, &req, SIZEOF_NTPCM(req)); 341 read(conn, &req, SIZEOF_NTPCM(req));
322 DBG(print_ntp_control_message(&req)); 342 DBG(print_ntp_control_message(&req));
323 } while (!(req.op&OP_READVAR && ntohs(req.seq) == 2)); 343 } while (!(req.op & OP_READVAR && ntohs(req.seq) == 2));
324 344
325 if(!(req.op&REM_ERROR)) 345 if (!(req.op & REM_ERROR))
326 xasprintf(&data, "%s%s", data, req.data); 346 xasprintf(&data, "%s%s", data, req.data);
327 } while(req.op&REM_MORE); 347 } while (req.op & REM_MORE);
328 348
329 if(req.op&REM_ERROR) { 349 if (req.op & REM_ERROR) {
330 if(strstr(getvar, "jitter")) { 350 if (strstr(getvar, "jitter")) {
331 if(verbose) printf("The command failed. This is usually caused by servers refusing the 'jitter'\nvariable. Restarting with 'dispersion'...\n"); 351 if (verbose)
352 printf("The command failed. This is usually caused by servers refusing the 'jitter'\nvariable. Restarting with "
353 "'dispersion'...\n");
332 getvar = "stratum,offset,dispersion"; 354 getvar = "stratum,offset,dispersion";
333 i--; 355 i--;
334 continue; 356 continue;
335 } else if(strlen(getvar)) { 357 }
336 if(verbose) printf("Server didn't like dispersion either; will retrieve everything\n"); 358 if (strlen(getvar)) {
359 if (verbose)
360 printf("Server didn't like dispersion either; will retrieve everything\n");
337 getvar = ""; 361 getvar = "";
338 i--; 362 i--;
339 continue; 363 continue;
340 } 364 }
341 } 365 }
342 366
343 if(verbose > 1) 367 if (verbose > 1)
344 printf("Server responded: >>>%s<<<\n", data); 368 printf("Server responded: >>>%s<<<\n", data);
345 369
370 double tmp_offset = 0;
371 char *value;
372 char *nptr;
346 /* get the offset */ 373 /* get the offset */
347 if(verbose) 374 if (verbose)
348 printf("parsing offset from peer %.2x: ", ntohs(peers[i].assoc)); 375 printf("parsing offset from peer %.2x: ", ntohs(peers[i].assoc));
349 376
350 value = np_extract_ntpvar(data, "offset"); 377 value = np_extract_ntpvar(data, "offset");
351 nptr=NULL; 378 nptr = NULL;
352 /* Convert the value if we have one */ 379 /* Convert the value if we have one */
353 if(value != NULL) 380 if (value != NULL)
354 tmp_offset = strtod(value, &nptr) / 1000; 381 tmp_offset = strtod(value, &nptr) / 1000;
355 /* If value is null or no conversion was performed */ 382 /* If value is null or no conversion was performed */
356 if(value == NULL || value==nptr) { 383 if (value == NULL || value == nptr) {
357 if(verbose) printf("error: unable to read server offset response.\n"); 384 if (verbose)
385 printf("error: unable to read server offset response.\n");
358 } else { 386 } else {
359 if(verbose) printf("%.10g\n", tmp_offset); 387 if (verbose)
360 if(*offset_result == STATE_UNKNOWN || fabs(tmp_offset) < fabs(*offset)) { 388 printf("%.10g\n", tmp_offset);
389 if (*offset_result == STATE_UNKNOWN || fabs(tmp_offset) < fabs(*offset)) {
361 *offset = tmp_offset; 390 *offset = tmp_offset;
362 *offset_result = STATE_OK; 391 *offset_result = STATE_OK;
363 } else { 392 } else {
@@ -366,85 +395,75 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
366 } 395 }
367 } 396 }
368 397
369 if(do_jitter) { 398 if (do_jitter) {
370 /* get the jitter */ 399 /* get the jitter */
371 if(verbose) { 400 if (verbose) {
372 printf("parsing %s from peer %.2x: ", strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter", ntohs(peers[i].assoc)); 401 printf("parsing %s from peer %.2x: ", strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter",
402 ntohs(peers[i].assoc));
373 } 403 }
374 value = np_extract_ntpvar(data, strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter"); 404 value = np_extract_ntpvar(data, strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter");
375 nptr=NULL; 405 nptr = NULL;
376 /* Convert the value if we have one */ 406 /* Convert the value if we have one */
377 if(value != NULL) 407 if (value != NULL)
378 *jitter = strtod(value, &nptr); 408 *jitter = strtod(value, &nptr);
379 /* If value is null or no conversion was performed */ 409 /* If value is null or no conversion was performed */
380 if(value == NULL || value==nptr) { 410 if (value == NULL || value == nptr) {
381 if(verbose) printf("error: unable to read server jitter/dispersion response.\n"); 411 if (verbose)
412 printf("error: unable to read server jitter/dispersion response.\n");
382 *jitter = -1; 413 *jitter = -1;
383 } else if(verbose) { 414 } else if (verbose) {
384 printf("%.10g\n", *jitter); 415 printf("%.10g\n", *jitter);
385 } 416 }
386 } 417 }
387 418
388 if(do_stratum) { 419 if (do_stratum) {
389 /* get the stratum */ 420 /* get the stratum */
390 if(verbose) { 421 if (verbose) {
391 printf("parsing stratum from peer %.2x: ", ntohs(peers[i].assoc)); 422 printf("parsing stratum from peer %.2x: ", ntohs(peers[i].assoc));
392 } 423 }
393 value = np_extract_ntpvar(data, "stratum"); 424 value = np_extract_ntpvar(data, "stratum");
394 nptr=NULL; 425 nptr = NULL;
395 /* Convert the value if we have one */ 426 /* Convert the value if we have one */
396 if(value != NULL) 427 if (value != NULL)
397 *stratum = strtol(value, &nptr, 10); 428 *stratum = strtol(value, &nptr, 10);
398 if(value == NULL || value==nptr) { 429 if (value == NULL || value == nptr) {
399 if(verbose) printf("error: unable to read server stratum response.\n"); 430 if (verbose)
431 printf("error: unable to read server stratum response.\n");
400 *stratum = -1; 432 *stratum = -1;
401 } else { 433 } else {
402 if(verbose) printf("%i\n", *stratum); 434 if (verbose)
435 printf("%i\n", *stratum);
403 } 436 }
404 } 437 }
405 } /* if (PEER_SEL(peers[i].status) >= min_peer_sel) */ 438 } /* if (PEER_SEL(peers[i].status) >= min_peer_sel) */
406 } /* for (i = 0; i < npeers; i++) */ 439 } /* for (i = 0; i < npeers; i++) */
407 440
408 close(conn); 441 close(conn);
409 if(peers!=NULL) free(peers); 442 if (peers != NULL)
443 free(peers);
410 444
411 return status; 445 return status;
412} 446}
413 447
414int process_arguments(int argc, char **argv){ 448int process_arguments(int argc, char **argv) {
415 int c;
416 int option=0;
417 static struct option longopts[] = { 449 static struct option longopts[] = {
418 {"version", no_argument, 0, 'V'}, 450 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'},
419 {"help", no_argument, 0, 'h'}, 451 {"use-ipv4", no_argument, 0, '4'}, {"use-ipv6", no_argument, 0, '6'}, {"quiet", no_argument, 0, 'q'},
420 {"verbose", no_argument, 0, 'v'}, 452 {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {"swarn", required_argument, 0, 'W'},
421 {"use-ipv4", no_argument, 0, '4'}, 453 {"scrit", required_argument, 0, 'C'}, {"jwarn", required_argument, 0, 'j'}, {"jcrit", required_argument, 0, 'k'},
422 {"use-ipv6", no_argument, 0, '6'}, 454 {"twarn", required_argument, 0, 'm'}, {"tcrit", required_argument, 0, 'n'}, {"timeout", required_argument, 0, 't'},
423 {"quiet", no_argument, 0, 'q'}, 455 {"hostname", required_argument, 0, 'H'}, {"port", required_argument, 0, 'p'}, {0, 0, 0, 0}};
424 {"warning", required_argument, 0, 'w'},
425 {"critical", required_argument, 0, 'c'},
426 {"swarn", required_argument, 0, 'W'},
427 {"scrit", required_argument, 0, 'C'},
428 {"jwarn", required_argument, 0, 'j'},
429 {"jcrit", required_argument, 0, 'k'},
430 {"twarn", required_argument, 0, 'm'},
431 {"tcrit", required_argument, 0, 'n'},
432 {"timeout", required_argument, 0, 't'},
433 {"hostname", required_argument, 0, 'H'},
434 {"port", required_argument, 0, 'p'},
435 {0, 0, 0, 0}
436 };
437
438 456
439 if (argc < 2) 457 if (argc < 2)
440 usage ("\n"); 458 usage("\n");
441 459
442 while (true) { 460 while (true) {
443 c = getopt_long (argc, argv, "Vhv46qw:c:W:C:j:k:m:n:t:H:p:", longopts, &option); 461 int option = 0;
444 if (c == -1 || c == EOF || c == 1) 462 int option_char = getopt_long(argc, argv, "Vhv46qw:c:W:C:j:k:m:n:t:H:p:", longopts, &option);
463 if (option_char == -1 || option_char == EOF || option_char == 1)
445 break; 464 break;
446 465
447 switch (c) { 466 switch (option_char) {
448 case 'h': 467 case 'h':
449 print_help(); 468 print_help();
450 exit(STATE_UNKNOWN); 469 exit(STATE_UNKNOWN);
@@ -490,15 +509,15 @@ int process_arguments(int argc, char **argv){
490 tcrit = optarg; 509 tcrit = optarg;
491 break; 510 break;
492 case 'H': 511 case 'H':
493 if(!is_host(optarg)) 512 if (!is_host(optarg))
494 usage2(_("Invalid hostname/address"), optarg); 513 usage2(_("Invalid hostname/address"), optarg);
495 server_address = strdup(optarg); 514 server_address = strdup(optarg);
496 break; 515 break;
497 case 'p': 516 case 'p':
498 port=atoi(optarg); 517 port = atoi(optarg);
499 break; 518 break;
500 case 't': 519 case 't':
501 socket_timeout=atoi(optarg); 520 socket_timeout = atoi(optarg);
502 break; 521 break;
503 case '4': 522 case '4':
504 address_family = AF_INET; 523 address_family = AF_INET;
@@ -507,69 +526,53 @@ int process_arguments(int argc, char **argv){
507#ifdef USE_IPV6 526#ifdef USE_IPV6
508 address_family = AF_INET6; 527 address_family = AF_INET6;
509#else 528#else
510 usage4 (_("IPv6 support not available")); 529 usage4(_("IPv6 support not available"));
511#endif 530#endif
512 break; 531 break;
513 case '?': 532 case '?':
514 /* print short usage statement if args not parsable */ 533 /* print short usage statement if args not parsable */
515 usage5 (); 534 usage5();
516 break; 535 break;
517 } 536 }
518 } 537 }
519 538
520 if(server_address == NULL){ 539 if (server_address == NULL) {
521 usage4(_("Hostname was not supplied")); 540 usage4(_("Hostname was not supplied"));
522 } 541 }
523 542
524 return 0; 543 return 0;
525} 544}
526 545
527char *perfd_offset (double offset) 546char *perfd_offset(double offset) {
528{ 547 return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false,
529 return fperfdata ("offset", offset, "s", 548 0);
530 true, offset_thresholds->warning->end,
531 true, offset_thresholds->critical->end,
532 false, 0, false, 0);
533} 549}
534 550
535char *perfd_jitter (double jitter) 551char *perfd_jitter(double jitter) {
536{ 552 return fperfdata("jitter", jitter, "", do_jitter, jitter_thresholds->warning->end, do_jitter, jitter_thresholds->critical->end, true, 0,
537 return fperfdata ("jitter", jitter, "", 553 false, 0);
538 do_jitter, jitter_thresholds->warning->end,
539 do_jitter, jitter_thresholds->critical->end,
540 true, 0, false, 0);
541} 554}
542 555
543char *perfd_stratum (int stratum) 556char *perfd_stratum(int stratum) {
544{ 557 return perfdata("stratum", stratum, "", do_stratum, (int)stratum_thresholds->warning->end, do_stratum,
545 return perfdata ("stratum", stratum, "", 558 (int)stratum_thresholds->critical->end, true, 0, true, 16);
546 do_stratum, (int)stratum_thresholds->warning->end,
547 do_stratum, (int)stratum_thresholds->critical->end,
548 true, 0, true, 16);
549} 559}
550 560
551char *perfd_truechimers (int num_truechimers) 561char *perfd_truechimers(int num_truechimers) {
552{ 562 return perfdata("truechimers", num_truechimers, "", do_truechimers, (int)truechimer_thresholds->warning->end, do_truechimers,
553 return perfdata ("truechimers", num_truechimers, "", 563 (int)truechimer_thresholds->critical->end, true, 0, false, 0);
554 do_truechimers, (int)truechimer_thresholds->warning->end,
555 do_truechimers, (int)truechimer_thresholds->critical->end,
556 true, 0, false, 0);
557} 564}
558 565
559int main(int argc, char *argv[]){ 566int main(int argc, char *argv[]) {
560 int result, offset_result, stratum, num_truechimers; 567 setlocale(LC_ALL, "");
561 double offset=0, jitter=0; 568 bindtextdomain(PACKAGE, LOCALEDIR);
562 char *result_line, *perfdata_line; 569 textdomain(PACKAGE);
563
564 setlocale (LC_ALL, "");
565 bindtextdomain (PACKAGE, LOCALEDIR);
566 textdomain (PACKAGE);
567 570
568 /* Parse extra opts if any */ 571 /* Parse extra opts if any */
569 argv=np_extra_opts (&argc, argv, progname); 572 argv = np_extra_opts(&argc, argv, progname);
570 573
571 if (process_arguments (argc, argv) == ERROR) 574 if (process_arguments(argc, argv) == ERROR)
572 usage4 (_("Could not parse arguments")); 575 usage4(_("Could not parse arguments"));
573 576
574 set_thresholds(&offset_thresholds, owarn, ocrit); 577 set_thresholds(&offset_thresholds, owarn, ocrit);
575 set_thresholds(&jitter_thresholds, jwarn, jcrit); 578 set_thresholds(&jitter_thresholds, jwarn, jcrit);
@@ -577,15 +580,20 @@ int main(int argc, char *argv[]){
577 set_thresholds(&truechimer_thresholds, twarn, tcrit); 580 set_thresholds(&truechimer_thresholds, twarn, tcrit);
578 581
579 /* initialize alarm signal handling */ 582 /* initialize alarm signal handling */
580 signal (SIGALRM, socket_timeout_alarm_handler); 583 signal(SIGALRM, socket_timeout_alarm_handler);
581 584
582 /* set socket timeout */ 585 /* set socket timeout */
583 alarm (socket_timeout); 586 alarm(socket_timeout);
584 587
588 int offset_result;
589 int stratum;
590 int num_truechimers;
591 double offset = 0;
592 double jitter = 0;
585 /* This returns either OK or WARNING (See comment preceding ntp_request) */ 593 /* This returns either OK or WARNING (See comment preceding ntp_request) */
586 result = ntp_request(&offset, &offset_result, &jitter, &stratum, &num_truechimers); 594 int result = ntp_request(&offset, &offset_result, &jitter, &stratum, &num_truechimers);
587 595
588 if(offset_result == STATE_UNKNOWN) { 596 if (offset_result == STATE_UNKNOWN) {
589 /* if there's no sync peer (this overrides ntp_request output): */ 597 /* if there's no sync peer (this overrides ntp_request output): */
590 result = (quiet ? STATE_UNKNOWN : STATE_CRITICAL); 598 result = (quiet ? STATE_UNKNOWN : STATE_CRITICAL);
591 } else { 599 } else {
@@ -597,50 +605,49 @@ int main(int argc, char *argv[]){
597 605
598 int oresult = result; 606 int oresult = result;
599 607
600
601 int tresult = STATE_UNKNOWN; 608 int tresult = STATE_UNKNOWN;
602 609
603 if(do_truechimers) { 610 if (do_truechimers) {
604 tresult = get_status(num_truechimers, truechimer_thresholds); 611 tresult = get_status(num_truechimers, truechimer_thresholds);
605 result = max_state_alt(result, tresult); 612 result = max_state_alt(result, tresult);
606 } 613 }
607 614
608
609 int sresult = STATE_UNKNOWN; 615 int sresult = STATE_UNKNOWN;
610 616
611 if(do_stratum) { 617 if (do_stratum) {
612 sresult = get_status(stratum, stratum_thresholds); 618 sresult = get_status(stratum, stratum_thresholds);
613 result = max_state_alt(result, sresult); 619 result = max_state_alt(result, sresult);
614 } 620 }
615 621
616
617 int jresult = STATE_UNKNOWN; 622 int jresult = STATE_UNKNOWN;
618 623
619 if(do_jitter) { 624 if (do_jitter) {
620 jresult = get_status(jitter, jitter_thresholds); 625 jresult = get_status(jitter, jitter_thresholds);
621 result = max_state_alt(result, jresult); 626 result = max_state_alt(result, jresult);
622 } 627 }
623 628
629 char *result_line;
624 switch (result) { 630 switch (result) {
625 case STATE_CRITICAL : 631 case STATE_CRITICAL:
626 xasprintf(&result_line, _("NTP CRITICAL:")); 632 xasprintf(&result_line, _("NTP CRITICAL:"));
627 break; 633 break;
628 case STATE_WARNING : 634 case STATE_WARNING:
629 xasprintf(&result_line, _("NTP WARNING:")); 635 xasprintf(&result_line, _("NTP WARNING:"));
630 break; 636 break;
631 case STATE_OK : 637 case STATE_OK:
632 xasprintf(&result_line, _("NTP OK:")); 638 xasprintf(&result_line, _("NTP OK:"));
633 break; 639 break;
634 default : 640 default:
635 xasprintf(&result_line, _("NTP UNKNOWN:")); 641 xasprintf(&result_line, _("NTP UNKNOWN:"));
636 break; 642 break;
637 } 643 }
638 if(!syncsource_found) 644 if (!syncsource_found)
639 xasprintf(&result_line, "%s %s,", result_line, _("Server not synchronized")); 645 xasprintf(&result_line, "%s %s,", result_line, _("Server not synchronized"));
640 else if(li_alarm) 646 else if (li_alarm)
641 xasprintf(&result_line, "%s %s,", result_line, _("Server has the LI_ALARM bit set")); 647 xasprintf(&result_line, "%s %s,", result_line, _("Server has the LI_ALARM bit set"));
642 648
643 if(offset_result == STATE_UNKNOWN){ 649 char *perfdata_line;
650 if (offset_result == STATE_UNKNOWN) {
644 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); 651 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown"));
645 xasprintf(&perfdata_line, ""); 652 xasprintf(&perfdata_line, "");
646 } else if (oresult == STATE_WARNING) { 653 } else if (oresult == STATE_WARNING) {
@@ -649,9 +656,9 @@ int main(int argc, char *argv[]){
649 xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"), offset); 656 xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"), offset);
650 } else { 657 } else {
651 xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset); 658 xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset);
652 } 659 }
653 xasprintf(&perfdata_line, "%s", perfd_offset(offset)); 660 xasprintf(&perfdata_line, "%s", perfd_offset(offset));
654 661
655 if (do_jitter) { 662 if (do_jitter) {
656 if (jresult == STATE_WARNING) { 663 if (jresult == STATE_WARNING) {
657 xasprintf(&result_line, "%s, jitter=%f (WARNING)", result_line, jitter); 664 xasprintf(&result_line, "%s, jitter=%f (WARNING)", result_line, jitter);
@@ -684,45 +691,46 @@ int main(int argc, char *argv[]){
684 } 691 }
685 printf("%s|%s\n", result_line, perfdata_line); 692 printf("%s|%s\n", result_line, perfdata_line);
686 693
687 if(server_address!=NULL) free(server_address); 694 if (server_address != NULL)
695 free(server_address);
688 return result; 696 return result;
689} 697}
690 698
691void print_help(void){ 699void print_help(void) {
692 print_revision(progname, NP_VERSION); 700 print_revision(progname, NP_VERSION);
693 701
694 printf ("Copyright (c) 2006 Sean Finney\n"); 702 printf("Copyright (c) 2006 Sean Finney\n");
695 printf (COPYRIGHT, copyright, email); 703 printf(COPYRIGHT, copyright, email);
696 704
697 printf ("%s\n", _("This plugin checks the selected ntp server")); 705 printf("%s\n", _("This plugin checks the selected ntp server"));
698 706
699 printf ("\n\n"); 707 printf("\n\n");
700 708
701 print_usage(); 709 print_usage();
702 printf (UT_HELP_VRSN); 710 printf(UT_HELP_VRSN);
703 printf (UT_EXTRA_OPTS); 711 printf(UT_EXTRA_OPTS);
704 printf (UT_IPv46); 712 printf(UT_IPv46);
705 printf (UT_HOST_PORT, 'p', "123"); 713 printf(UT_HOST_PORT, 'p', "123");
706 printf (" %s\n", "-q, --quiet"); 714 printf(" %s\n", "-q, --quiet");
707 printf (" %s\n", _("Returns UNKNOWN instead of CRITICAL or WARNING if server isn't synchronized")); 715 printf(" %s\n", _("Returns UNKNOWN instead of CRITICAL or WARNING if server isn't synchronized"));
708 printf (" %s\n", "-w, --warning=THRESHOLD"); 716 printf(" %s\n", "-w, --warning=THRESHOLD");
709 printf (" %s\n", _("Offset to result in warning status (seconds)")); 717 printf(" %s\n", _("Offset to result in warning status (seconds)"));
710 printf (" %s\n", "-c, --critical=THRESHOLD"); 718 printf(" %s\n", "-c, --critical=THRESHOLD");
711 printf (" %s\n", _("Offset to result in critical status (seconds)")); 719 printf(" %s\n", _("Offset to result in critical status (seconds)"));
712 printf (" %s\n", "-W, --swarn=THRESHOLD"); 720 printf(" %s\n", "-W, --swarn=THRESHOLD");
713 printf (" %s\n", _("Warning threshold for stratum of server's synchronization peer")); 721 printf(" %s\n", _("Warning threshold for stratum of server's synchronization peer"));
714 printf (" %s\n", "-C, --scrit=THRESHOLD"); 722 printf(" %s\n", "-C, --scrit=THRESHOLD");
715 printf (" %s\n", _("Critical threshold for stratum of server's synchronization peer")); 723 printf(" %s\n", _("Critical threshold for stratum of server's synchronization peer"));
716 printf (" %s\n", "-j, --jwarn=THRESHOLD"); 724 printf(" %s\n", "-j, --jwarn=THRESHOLD");
717 printf (" %s\n", _("Warning threshold for jitter")); 725 printf(" %s\n", _("Warning threshold for jitter"));
718 printf (" %s\n", "-k, --jcrit=THRESHOLD"); 726 printf(" %s\n", "-k, --jcrit=THRESHOLD");
719 printf (" %s\n", _("Critical threshold for jitter")); 727 printf(" %s\n", _("Critical threshold for jitter"));
720 printf (" %s\n", "-m, --twarn=THRESHOLD"); 728 printf(" %s\n", "-m, --twarn=THRESHOLD");
721 printf (" %s\n", _("Warning threshold for number of usable time sources (\"truechimers\")")); 729 printf(" %s\n", _("Warning threshold for number of usable time sources (\"truechimers\")"));
722 printf (" %s\n", "-n, --tcrit=THRESHOLD"); 730 printf(" %s\n", "-n, --tcrit=THRESHOLD");
723 printf (" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")")); 731 printf(" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")"));
724 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 732 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
725 printf (UT_VERBOSE); 733 printf(UT_VERBOSE);
726 734
727 printf("\n"); 735 printf("\n");
728 printf("%s\n", _("This plugin checks an NTP server independent of any commandline")); 736 printf("%s\n", _("This plugin checks an NTP server independent of any commandline"));
@@ -751,13 +759,11 @@ void print_help(void){
751 printf(" %s\n", _("Check only stratum:")); 759 printf(" %s\n", _("Check only stratum:"));
752 printf(" %s\n", ("./check_ntp_peer -H ntpserv -W 4 -C 6")); 760 printf(" %s\n", ("./check_ntp_peer -H ntpserv -W 4 -C 6"));
753 761
754 printf (UT_SUPPORT); 762 printf(UT_SUPPORT);
755} 763}
756 764
757void 765void print_usage(void) {
758print_usage(void) 766 printf("%s\n", _("Usage:"));
759{
760 printf ("%s\n", _("Usage:"));
761 printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-W <warn>] [-C <crit>]\n", progname); 767 printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-W <warn>] [-C <crit>]\n", progname);
762 printf(" [-j <warn>] [-k <crit>] [-v verbose]\n"); 768 printf(" [-j <warn>] [-k <crit>] [-v verbose]\n");
763} 769}
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c
index b2e16556..703b69df 100644
--- a/plugins/check_ntp_time.c
+++ b/plugins/check_ntp_time.c
@@ -1,63 +1,63 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ntp_time plugin 3 * Monitoring check_ntp_time plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2006 Sean Finney <seanius@seanius.net> 6 * Copyright (c) 2006 Sean Finney <seanius@seanius.net>
7* Copyright (c) 2006-2008 Monitoring Plugins Development Team 7 * Copyright (c) 2006-2024 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_ntp_time plugin 11 * This file contains the check_ntp_time plugin
12* 12 *
13* This plugin checks the clock offset between the local host and a 13 * This plugin checks the clock offset between the local host and a
14* remote NTP server. It is independent of any commandline programs or 14 * remote NTP server. It is independent of any commandline programs or
15* external libraries. 15 * external libraries.
16* 16 *
17* If you'd rather want to monitor an NTP server, please use 17 * If you'd rather want to monitor an NTP server, please use
18* check_ntp_peer. 18 * check_ntp_peer.
19* 19 *
20* 20 *
21* This program is free software: you can redistribute it and/or modify 21 * This program is free software: you can redistribute it and/or modify
22* it under the terms of the GNU General Public License as published by 22 * it under the terms of the GNU General Public License as published by
23* the Free Software Foundation, either version 3 of the License, or 23 * the Free Software Foundation, either version 3 of the License, or
24* (at your option) any later version. 24 * (at your option) any later version.
25* 25 *
26* This program is distributed in the hope that it will be useful, 26 * This program is distributed in the hope that it will be useful,
27* but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29* GNU General Public License for more details. 29 * GNU General Public License for more details.
30* 30 *
31* You should have received a copy of the GNU General Public License 31 * You should have received a copy of the GNU General Public License
32* along with this program. If not, see <http://www.gnu.org/licenses/>. 32 * along with this program. If not, see <http://www.gnu.org/licenses/>.
33* 33 *
34* 34 *
35*****************************************************************************/ 35 *****************************************************************************/
36 36
37const char *progname = "check_ntp_time"; 37const char *progname = "check_ntp_time";
38const char *copyright = "2006-2008"; 38const char *copyright = "2006-2024";
39const char *email = "devel@monitoring-plugins.org"; 39const char *email = "devel@monitoring-plugins.org";
40 40
41#include "common.h" 41#include "common.h"
42#include "netutils.h" 42#include "netutils.h"
43#include "utils.h" 43#include "utils.h"
44 44
45static char *server_address=NULL; 45static char *server_address = NULL;
46static char *port="123"; 46static char *port = "123";
47static int verbose=0; 47static int verbose = 0;
48static bool quiet = false; 48static bool quiet = false;
49static char *owarn="60"; 49static char *owarn = "60";
50static char *ocrit="120"; 50static char *ocrit = "120";
51static int time_offset=0; 51static int time_offset = 0;
52 52
53int process_arguments (int, char **); 53static int process_arguments(int, char **);
54thresholds *offset_thresholds = NULL; 54static thresholds *offset_thresholds = NULL;
55void print_help (void); 55static void print_help(void);
56void print_usage (void); 56void print_usage(void);
57 57
58/* number of times to perform each request to get a good average. */ 58/* number of times to perform each request to get a good average. */
59#ifndef AVG_NUM 59#ifndef AVG_NUM
60#define AVG_NUM 4 60# define AVG_NUM 4
61#endif 61#endif
62 62
63/* max size of control message data */ 63/* max size of control message data */
@@ -65,17 +65,17 @@ void print_usage (void);
65 65
66/* this structure holds everything in an ntp request/response as per rfc1305 */ 66/* this structure holds everything in an ntp request/response as per rfc1305 */
67typedef struct { 67typedef struct {
68 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ 68 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */
69 uint8_t stratum; /* clock stratum */ 69 uint8_t stratum; /* clock stratum */
70 int8_t poll; /* polling interval */ 70 int8_t poll; /* polling interval */
71 int8_t precision; /* precision of the local clock */ 71 int8_t precision; /* precision of the local clock */
72 int32_t rtdelay; /* total rt delay, as a fixed point num. see macros */ 72 int32_t rtdelay; /* total rt delay, as a fixed point num. see macros */
73 uint32_t rtdisp; /* like above, but for max err to primary src */ 73 uint32_t rtdisp; /* like above, but for max err to primary src */
74 uint32_t refid; /* ref clock identifier */ 74 uint32_t refid; /* ref clock identifier */
75 uint64_t refts; /* reference timestamp. local time local clock */ 75 uint64_t refts; /* reference timestamp. local time local clock */
76 uint64_t origts; /* time at which request departed client */ 76 uint64_t origts; /* time at which request departed client */
77 uint64_t rxts; /* time at which request arrived at server */ 77 uint64_t rxts; /* time at which request arrived at server */
78 uint64_t txts; /* time at which request departed server */ 78 uint64_t txts; /* time at which request departed server */
79} ntp_message; 79} ntp_message;
80 80
81/* this structure holds data about results from querying offset from a peer */ 81/* this structure holds data about results from querying offset from a peer */
@@ -86,43 +86,55 @@ typedef struct {
86 double rtdelay; /* converted from the ntp_message */ 86 double rtdelay; /* converted from the ntp_message */
87 double rtdisp; /* converted from the ntp_message */ 87 double rtdisp; /* converted from the ntp_message */
88 double offset[AVG_NUM]; /* offsets from each response */ 88 double offset[AVG_NUM]; /* offsets from each response */
89 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ 89 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */
90} ntp_server_results; 90} ntp_server_results;
91 91
92/* bits 1,2 are the leap indicator */ 92/* bits 1,2 are the leap indicator */
93#define LI_MASK 0xc0 93#define LI_MASK 0xc0
94#define LI(x) ((x&LI_MASK)>>6) 94#define LI(x) ((x & LI_MASK) >> 6)
95#define LI_SET(x,y) do{ x |= ((y<<6)&LI_MASK); }while(0) 95#define LI_SET(x, y) \
96 do { \
97 x |= ((y << 6) & LI_MASK); \
98 } while (0)
96/* and these are the values of the leap indicator */ 99/* and these are the values of the leap indicator */
97#define LI_NOWARNING 0x00 100#define LI_NOWARNING 0x00
98#define LI_EXTRASEC 0x01 101#define LI_EXTRASEC 0x01
99#define LI_MISSINGSEC 0x02 102#define LI_MISSINGSEC 0x02
100#define LI_ALARM 0x03 103#define LI_ALARM 0x03
101/* bits 3,4,5 are the ntp version */ 104/* bits 3,4,5 are the ntp version */
102#define VN_MASK 0x38 105#define VN_MASK 0x38
103#define VN(x) ((x&VN_MASK)>>3) 106#define VN(x) ((x & VN_MASK) >> 3)
104#define VN_SET(x,y) do{ x |= ((y<<3)&VN_MASK); }while(0) 107#define VN_SET(x, y) \
108 do { \
109 x |= ((y << 3) & VN_MASK); \
110 } while (0)
105#define VN_RESERVED 0x02 111#define VN_RESERVED 0x02
106/* bits 6,7,8 are the ntp mode */ 112/* bits 6,7,8 are the ntp mode */
107#define MODE_MASK 0x07 113#define MODE_MASK 0x07
108#define MODE(x) (x&MODE_MASK) 114#define MODE(x) (x & MODE_MASK)
109#define MODE_SET(x,y) do{ x |= (y&MODE_MASK); }while(0) 115#define MODE_SET(x, y) \
116 do { \
117 x |= (y & MODE_MASK); \
118 } while (0)
110/* here are some values */ 119/* here are some values */
111#define MODE_CLIENT 0x03 120#define MODE_CLIENT 0x03
112#define MODE_CONTROLMSG 0x06 121#define MODE_CONTROLMSG 0x06
113/* In control message, bits 8-10 are R,E,M bits */ 122/* In control message, bits 8-10 are R,E,M bits */
114#define REM_MASK 0xe0 123#define REM_MASK 0xe0
115#define REM_RESP 0x80 124#define REM_RESP 0x80
116#define REM_ERROR 0x40 125#define REM_ERROR 0x40
117#define REM_MORE 0x20 126#define REM_MORE 0x20
118/* In control message, bits 11 - 15 are opcode */ 127/* In control message, bits 11 - 15 are opcode */
119#define OP_MASK 0x1f 128#define OP_MASK 0x1f
120#define OP_SET(x,y) do{ x |= (y&OP_MASK); }while(0) 129#define OP_SET(x, y) \
130 do { \
131 x |= (y & OP_MASK); \
132 } while (0)
121#define OP_READSTAT 0x01 133#define OP_READSTAT 0x01
122#define OP_READVAR 0x02 134#define OP_READVAR 0x02
123/* In peer status bytes, bits 6,7,8 determine clock selection status */ 135/* In peer status bytes, bits 6,7,8 determine clock selection status */
124#define PEER_SEL(x) ((ntohs(x)>>8)&0x07) 136#define PEER_SEL(x) ((ntohs(x) >> 8) & 0x07)
125#define PEER_INCLUDED 0x04 137#define PEER_INCLUDED 0x04
126#define PEER_SYNCSOURCE 0x06 138#define PEER_SYNCSOURCE 0x06
127 139
128/** 140/**
@@ -136,82 +148,91 @@ typedef struct {
136 148
137/* macros to access the left/right 16 bits of a 32-bit ntp "fixed point" 149/* macros to access the left/right 16 bits of a 32-bit ntp "fixed point"
138 number. note that these can be used as lvalues too */ 150 number. note that these can be used as lvalues too */
139#define L16(x) (((uint16_t*)&x)[0]) 151#define L16(x) (((uint16_t *)&x)[0])
140#define R16(x) (((uint16_t*)&x)[1]) 152#define R16(x) (((uint16_t *)&x)[1])
141/* macros to access the left/right 32 bits of a 64-bit ntp "fixed point" 153/* macros to access the left/right 32 bits of a 64-bit ntp "fixed point"
142 number. these too can be used as lvalues */ 154 number. these too can be used as lvalues */
143#define L32(x) (((uint32_t*)&x)[0]) 155#define L32(x) (((uint32_t *)&x)[0])
144#define R32(x) (((uint32_t*)&x)[1]) 156#define R32(x) (((uint32_t *)&x)[1])
145 157
146/* ntp wants seconds since 1/1/00, epoch is 1/1/70. this is the difference */ 158/* ntp wants seconds since 1/1/00, epoch is 1/1/70. this is the difference */
147#define EPOCHDIFF 0x83aa7e80UL 159#define EPOCHDIFF 0x83aa7e80UL
148 160
149/* extract a 32-bit ntp fixed point number into a double */ 161/* extract a 32-bit ntp fixed point number into a double */
150#define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x))/65536.0) 162#define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x)) / 65536.0)
151 163
152/* likewise for a 64-bit ntp fp number */ 164/* likewise for a 64-bit ntp fp number */
153#define NTP64asDOUBLE(n) (double)(((uint64_t)n)?\ 165#define NTP64asDOUBLE(n) \
154 (ntohl(L32(n))-EPOCHDIFF) + \ 166 (double)(((uint64_t)n) ? (ntohl(L32(n)) - EPOCHDIFF) + (.00000001 * (0.5 + (double)(ntohl(R32(n)) / 42.94967296))) : 0)
155 (.00000001*(0.5+(double)(ntohl(R32(n))/42.94967296))):\
156 0)
157 167
158/* convert a struct timeval to a double */ 168/* convert a struct timeval to a double */
159#define TVasDOUBLE(x) (double)(x.tv_sec+(0.000001*x.tv_usec)) 169#define TVasDOUBLE(x) (double)(x.tv_sec + (0.000001 * x.tv_usec))
160 170
161/* convert an ntp 64-bit fp number to a struct timeval */ 171/* convert an ntp 64-bit fp number to a struct timeval */
162#define NTP64toTV(n,t) \ 172#define NTP64toTV(n, t) \
163 do{ if(!n) t.tv_sec = t.tv_usec = 0; \ 173 do { \
164 else { \ 174 if (!n) \
165 t.tv_sec=ntohl(L32(n))-EPOCHDIFF; \ 175 t.tv_sec = t.tv_usec = 0; \
166 t.tv_usec=(int)(0.5+(double)(ntohl(R32(n))/4294.967296)); \ 176 else { \
167 } \ 177 t.tv_sec = ntohl(L32(n)) - EPOCHDIFF; \
168 }while(0) 178 t.tv_usec = (int)(0.5 + (double)(ntohl(R32(n)) / 4294.967296)); \
179 } \
180 } while (0)
169 181
170/* convert a struct timeval to an ntp 64-bit fp number */ 182/* convert a struct timeval to an ntp 64-bit fp number */
171#define TVtoNTP64(t,n) \ 183#define TVtoNTP64(t, n) \
172 do{ if(!t.tv_usec && !t.tv_sec) n=0x0UL; \ 184 do { \
173 else { \ 185 if (!t.tv_usec && !t.tv_sec) \
174 L32(n)=htonl(t.tv_sec + EPOCHDIFF); \ 186 n = 0x0UL; \
175 R32(n)=htonl((uint64_t)((4294.967296*t.tv_usec)+.5)); \ 187 else { \
176 } \ 188 L32(n) = htonl(t.tv_sec + EPOCHDIFF); \
177 } while(0) 189 R32(n) = htonl((uint64_t)((4294.967296 * t.tv_usec) + .5)); \
190 } \
191 } while (0)
178 192
179/* NTP control message header is 12 bytes, plus any data in the data 193/* NTP control message header is 12 bytes, plus any data in the data
180 * field, plus null padding to the nearest 32-bit boundary per rfc. 194 * field, plus null padding to the nearest 32-bit boundary per rfc.
181 */ 195 */
182#define SIZEOF_NTPCM(m) (12+ntohs(m.count)+((m.count)?4-(ntohs(m.count)%4):0)) 196#define SIZEOF_NTPCM(m) (12 + ntohs(m.count) + ((m.count) ? 4 - (ntohs(m.count) % 4) : 0))
183 197
184/* finally, a little helper or two for debugging: */ 198/* finally, a little helper or two for debugging: */
185#define DBG(x) do{if(verbose>1){ x; }}while(0); 199#define DBG(x) \
186#define PRINTSOCKADDR(x) \ 200 do { \
187 do{ \ 201 if (verbose > 1) { \
188 printf("%u.%u.%u.%u", (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff);\ 202 x; \
189 }while(0); 203 } \
204 } while (0);
205#define PRINTSOCKADDR(x) \
206 do { \
207 printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \
208 } while (0);
190 209
191/* calculate the offset of the local clock */ 210/* calculate the offset of the local clock */
192static inline double calc_offset(const ntp_message *m, const struct timeval *t){ 211static inline double calc_offset(const ntp_message *m, const struct timeval *t) {
193 double client_tx, peer_rx, peer_tx, client_rx; 212 double client_tx = NTP64asDOUBLE(m->origts);
194 client_tx = NTP64asDOUBLE(m->origts); 213 double peer_rx = NTP64asDOUBLE(m->rxts);
195 peer_rx = NTP64asDOUBLE(m->rxts); 214 double peer_tx = NTP64asDOUBLE(m->txts);
196 peer_tx = NTP64asDOUBLE(m->txts); 215 double client_rx = TVasDOUBLE((*t));
197 client_rx=TVasDOUBLE((*t)); 216 return (.5 * ((peer_tx - client_rx) + (peer_rx - client_tx)));
198 return (.5*((peer_tx-client_rx)+(peer_rx-client_tx)));
199} 217}
200 218
201/* print out a ntp packet in human readable/debuggable format */ 219/* print out a ntp packet in human readable/debuggable format */
202void print_ntp_message(const ntp_message *p){ 220void print_ntp_message(const ntp_message *p) {
203 struct timeval ref, orig, rx, tx; 221 struct timeval ref;
222 struct timeval orig;
223 struct timeval rx;
224 struct timeval tx;
204 225
205 NTP64toTV(p->refts,ref); 226 NTP64toTV(p->refts, ref);
206 NTP64toTV(p->origts,orig); 227 NTP64toTV(p->origts, orig);
207 NTP64toTV(p->rxts,rx); 228 NTP64toTV(p->rxts, rx);
208 NTP64toTV(p->txts,tx); 229 NTP64toTV(p->txts, tx);
209 230
210 printf("packet contents:\n"); 231 printf("packet contents:\n");
211 printf("\tflags: 0x%.2x\n", p->flags); 232 printf("\tflags: 0x%.2x\n", p->flags);
212 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags&LI_MASK); 233 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags & LI_MASK);
213 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags&VN_MASK); 234 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags & VN_MASK);
214 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags&MODE_MASK); 235 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags & MODE_MASK);
215 printf("\tstratum = %d\n", p->stratum); 236 printf("\tstratum = %d\n", p->stratum);
216 printf("\tpoll = %g\n", pow(2, p->poll)); 237 printf("\tpoll = %g\n", pow(2, p->poll));
217 printf("\tprecision = %g\n", pow(2, p->precision)); 238 printf("\tprecision = %g\n", pow(2, p->precision));
@@ -224,41 +245,42 @@ void print_ntp_message(const ntp_message *p){
224 printf("\ttxts = %-.16g\n", NTP64asDOUBLE(p->txts)); 245 printf("\ttxts = %-.16g\n", NTP64asDOUBLE(p->txts));
225} 246}
226 247
227void setup_request(ntp_message *p){ 248void setup_request(ntp_message *p) {
228 struct timeval t;
229
230 memset(p, 0, sizeof(ntp_message)); 249 memset(p, 0, sizeof(ntp_message));
231 LI_SET(p->flags, LI_ALARM); 250 LI_SET(p->flags, LI_ALARM);
232 VN_SET(p->flags, 4); 251 VN_SET(p->flags, 4);
233 MODE_SET(p->flags, MODE_CLIENT); 252 MODE_SET(p->flags, MODE_CLIENT);
234 p->poll=4; 253 p->poll = 4;
235 p->precision=(int8_t)0xfa; 254 p->precision = (int8_t)0xfa;
236 L16(p->rtdelay)=htons(1); 255 L16(p->rtdelay) = htons(1);
237 L16(p->rtdisp)=htons(1); 256 L16(p->rtdisp) = htons(1);
238 257
258 struct timeval t;
239 gettimeofday(&t, NULL); 259 gettimeofday(&t, NULL);
240 TVtoNTP64(t,p->txts); 260 TVtoNTP64(t, p->txts);
241} 261}
242 262
243/* select the "best" server from a list of servers, and return its index. 263/* select the "best" server from a list of servers, and return its index.
244 * this is done by filtering servers based on stratum, dispersion, and 264 * this is done by filtering servers based on stratum, dispersion, and
245 * finally round-trip delay. */ 265 * finally round-trip delay. */
246int best_offset_server(const ntp_server_results *slist, int nservers){ 266int best_offset_server(const ntp_server_results *slist, int nservers) {
247 int cserver=0, best_server=-1; 267 int best_server = -1;
248 268
249 /* for each server */ 269 /* for each server */
250 for(cserver=0; cserver<nservers; cserver++){ 270 for (int cserver = 0; cserver < nservers; cserver++) {
251 /* We don't want any servers that fails these tests */ 271 /* We don't want any servers that fails these tests */
252 /* Sort out servers that didn't respond or responede with a 0 stratum; 272 /* Sort out servers that didn't respond or responede with a 0 stratum;
253 * stratum 0 is for reference clocks so no NTP server should ever report 273 * stratum 0 is for reference clocks so no NTP server should ever report
254 * a stratum 0 */ 274 * a stratum 0 */
255 if ( slist[cserver].stratum == 0){ 275 if (slist[cserver].stratum == 0) {
256 if (verbose) printf("discarding peer %d: stratum=%d\n", cserver, slist[cserver].stratum); 276 if (verbose)
277 printf("discarding peer %d: stratum=%d\n", cserver, slist[cserver].stratum);
257 continue; 278 continue;
258 } 279 }
259 /* Sort out servers with error flags */ 280 /* Sort out servers with error flags */
260 if ( LI(slist[cserver].flags) == LI_ALARM ){ 281 if (LI(slist[cserver].flags) == LI_ALARM) {
261 if (verbose) printf("discarding peer %d: flags=%d\n", cserver, LI(slist[cserver].flags)); 282 if (verbose)
283 printf("discarding peer %d: flags=%d\n", cserver, LI(slist[cserver].flags));
262 continue; 284 continue;
263 } 285 }
264 286
@@ -272,13 +294,13 @@ int best_offset_server(const ntp_server_results *slist, int nservers){
272 /* compare the server to the best one we've seen so far */ 294 /* compare the server to the best one we've seen so far */
273 /* does it have an equal or better stratum? */ 295 /* does it have an equal or better stratum? */
274 DBG(printf("comparing peer %d with peer %d\n", cserver, best_server)); 296 DBG(printf("comparing peer %d with peer %d\n", cserver, best_server));
275 if(slist[cserver].stratum <= slist[best_server].stratum){ 297 if (slist[cserver].stratum <= slist[best_server].stratum) {
276 DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server)); 298 DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server));
277 /* does it have an equal or better dispersion? */ 299 /* does it have an equal or better dispersion? */
278 if(slist[cserver].rtdisp <= slist[best_server].rtdisp){ 300 if (slist[cserver].rtdisp <= slist[best_server].rtdisp) {
279 DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server)); 301 DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server));
280 /* does it have a better rtdelay? */ 302 /* does it have a better rtdelay? */
281 if(slist[cserver].rtdelay < slist[best_server].rtdelay){ 303 if (slist[cserver].rtdelay < slist[best_server].rtdelay) {
282 DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server)); 304 DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server));
283 best_server = cserver; 305 best_server = cserver;
284 DBG(printf("peer %d is now our best candidate\n", best_server)); 306 DBG(printf("peer %d is now our best candidate\n", best_server));
@@ -287,13 +309,12 @@ int best_offset_server(const ntp_server_results *slist, int nservers){
287 } 309 }
288 } 310 }
289 311
290 if(best_server >= 0) { 312 if (best_server >= 0) {
291 DBG(printf("best server selected: peer %d\n", best_server)); 313 DBG(printf("best server selected: peer %d\n", best_server));
292 return best_server; 314 return best_server;
293 } else {
294 DBG(printf("no peers meeting synchronization criteria :(\n"));
295 return -1;
296 } 315 }
316 DBG(printf("no peers meeting synchronization criteria :(\n"));
317 return -1;
297} 318}
298 319
299/* do everything we need to get the total average offset 320/* do everything we need to get the total average offset
@@ -301,178 +322,190 @@ int best_offset_server(const ntp_server_results *slist, int nservers){
301 * we don't waste time sitting around waiting for single packets. 322 * we don't waste time sitting around waiting for single packets.
302 * - we also "manually" handle resolving host names and connecting, because 323 * - we also "manually" handle resolving host names and connecting, because
303 * we have to do it in a way that our lazy macros don't handle currently :( */ 324 * we have to do it in a way that our lazy macros don't handle currently :( */
304double offset_request(const char *host, int *status){ 325double offset_request(const char *host, int *status) {
305 int i=0, j=0, ga_result=0, num_hosts=0, *socklist=NULL, respnum=0;
306 int servers_completed=0, one_read=0, servers_readable=0, best_index=-1;
307 time_t now_time=0, start_ts=0;
308 ntp_message *req=NULL;
309 double avg_offset=0.;
310 struct timeval recv_time;
311 struct addrinfo *ai=NULL, *ai_tmp=NULL, hints;
312 struct pollfd *ufds=NULL;
313 ntp_server_results *servers=NULL;
314
315 /* setup hints to only return results from getaddrinfo that we'd like */ 326 /* setup hints to only return results from getaddrinfo that we'd like */
327 struct addrinfo hints;
316 memset(&hints, 0, sizeof(struct addrinfo)); 328 memset(&hints, 0, sizeof(struct addrinfo));
317 hints.ai_family = address_family; 329 hints.ai_family = address_family;
318 hints.ai_protocol = IPPROTO_UDP; 330 hints.ai_protocol = IPPROTO_UDP;
319 hints.ai_socktype = SOCK_DGRAM; 331 hints.ai_socktype = SOCK_DGRAM;
320 332
321 /* fill in ai with the list of hosts resolved by the host name */ 333 /* fill in ai with the list of hosts resolved by the host name */
322 ga_result = getaddrinfo(host, port, &hints, &ai); 334 struct addrinfo *ai = NULL;
323 if(ga_result!=0){ 335 int ga_result = getaddrinfo(host, port, &hints, &ai);
324 die(STATE_UNKNOWN, "error getting address for %s: %s\n", 336 if (ga_result != 0) {
325 host, gai_strerror(ga_result)); 337 die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result));
326 } 338 }
327 339
328 /* count the number of returned hosts, and allocate stuff accordingly */ 340 /* count the number of returned hosts, and allocate stuff accordingly */
329 for(ai_tmp=ai; ai_tmp!=NULL; ai_tmp=ai_tmp->ai_next){ num_hosts++; } 341 int num_hosts = 0;
330 req=(ntp_message*)malloc(sizeof(ntp_message)*num_hosts); 342 for (struct addrinfo *ai_tmp = ai; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) {
331 if(req==NULL) die(STATE_UNKNOWN, "can not allocate ntp message array"); 343 num_hosts++;
332 socklist=(int*)malloc(sizeof(int)*num_hosts); 344 }
333 if(socklist==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); 345
334 ufds=(struct pollfd*)malloc(sizeof(struct pollfd)*num_hosts); 346 ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts);
335 if(ufds==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); 347
336 servers=(ntp_server_results*)malloc(sizeof(ntp_server_results)*num_hosts); 348 if (req == NULL)
337 if(servers==NULL) die(STATE_UNKNOWN, "can not allocate server array"); 349 die(STATE_UNKNOWN, "can not allocate ntp message array");
338 memset(servers, 0, sizeof(ntp_server_results)*num_hosts); 350 int *socklist = (int *)malloc(sizeof(int) * num_hosts);
351
352 if (socklist == NULL)
353 die(STATE_UNKNOWN, "can not allocate socket array");
354
355 struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_hosts);
356 if (ufds == NULL)
357 die(STATE_UNKNOWN, "can not allocate socket array");
358
359 ntp_server_results *servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts);
360 if (servers == NULL)
361 die(STATE_UNKNOWN, "can not allocate server array");
362 memset(servers, 0, sizeof(ntp_server_results) * num_hosts);
339 DBG(printf("Found %d peers to check\n", num_hosts)); 363 DBG(printf("Found %d peers to check\n", num_hosts));
340 364
341 /* setup each socket for writing, and the corresponding struct pollfd */ 365 /* setup each socket for writing, and the corresponding struct pollfd */
342 ai_tmp=ai; 366 struct addrinfo *ai_tmp = ai;
343 for(i=0;ai_tmp;i++){ 367 for (int i = 0; ai_tmp; i++) {
344 socklist[i]=socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); 368 socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP);
345 if(socklist[i] == -1) { 369 if (socklist[i] == -1) {
346 perror(NULL); 370 perror(NULL);
347 die(STATE_UNKNOWN, "can not create new socket"); 371 die(STATE_UNKNOWN, "can not create new socket");
348 } 372 }
349 if(connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)){ 373 if (connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)) {
350 /* don't die here, because it is enough if there is one server 374 /* don't die here, because it is enough if there is one server
351 answering in time. This also would break for dual ipv4/6 stacked 375 answering in time. This also would break for dual ipv4/6 stacked
352 ntp servers when the client only supports on of them. 376 ntp servers when the client only supports on of them.
353 */ 377 */
354 DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno))); 378 DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno)));
355 } else { 379 } else {
356 ufds[i].fd=socklist[i]; 380 ufds[i].fd = socklist[i];
357 ufds[i].events=POLLIN; 381 ufds[i].events = POLLIN;
358 ufds[i].revents=0; 382 ufds[i].revents = 0;
359 } 383 }
360 ai_tmp = ai_tmp->ai_next; 384 ai_tmp = ai_tmp->ai_next;
361 } 385 }
362 386
363 /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds 387 /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds
364 * have passed in order to ensure post-processing and jitter time. */ 388 * have passed in order to ensure post-processing and jitter time. */
365 now_time=start_ts=time(NULL); 389 time_t start_ts = 0;
366 while(servers_completed<num_hosts && now_time-start_ts <= socket_timeout/2){ 390 time_t now_time = 0;
391 now_time = start_ts = time(NULL);
392 int servers_completed = 0;
393 bool one_read = false;
394 while (servers_completed < num_hosts && now_time - start_ts <= socket_timeout / 2) {
367 /* loop through each server and find each one which hasn't 395 /* loop through each server and find each one which hasn't
368 * been touched in the past second or so and is still lacking 396 * been touched in the past second or so and is still lacking
369 * some responses. For each of these servers, send a new request, 397 * some responses. For each of these servers, send a new request,
370 * and update the "waiting" timestamp with the current time. */ 398 * and update the "waiting" timestamp with the current time. */
371 now_time=time(NULL); 399 now_time = time(NULL);
372 400
373 for(i=0; i<num_hosts; i++){ 401 for (int i = 0; i < num_hosts; i++) {
374 if(servers[i].waiting<now_time && servers[i].num_responses<AVG_NUM){ 402 if (servers[i].waiting < now_time && servers[i].num_responses < AVG_NUM) {
375 if(verbose && servers[i].waiting != 0) printf("re-"); 403 if (verbose && servers[i].waiting != 0)
376 if(verbose) printf("sending request to peer %d\n", i); 404 printf("re-");
405 if (verbose)
406 printf("sending request to peer %d\n", i);
377 setup_request(&req[i]); 407 setup_request(&req[i]);
378 write(socklist[i], &req[i], sizeof(ntp_message)); 408 write(socklist[i], &req[i], sizeof(ntp_message));
379 servers[i].waiting=now_time; 409 servers[i].waiting = now_time;
380 break; 410 break;
381 } 411 }
382 } 412 }
383 413
384 /* quickly poll for any sockets with pending data */ 414 /* quickly poll for any sockets with pending data */
385 servers_readable=poll(ufds, num_hosts, 100); 415 int servers_readable = poll(ufds, num_hosts, 100);
386 if(servers_readable==-1){ 416 if (servers_readable == -1) {
387 perror("polling ntp sockets"); 417 perror("polling ntp sockets");
388 die(STATE_UNKNOWN, "communication errors"); 418 die(STATE_UNKNOWN, "communication errors");
389 } 419 }
390 420
391 /* read from any sockets with pending data */ 421 /* read from any sockets with pending data */
392 for(i=0; servers_readable && i<num_hosts; i++){ 422 for (int i = 0; servers_readable && i < num_hosts; i++) {
393 if(ufds[i].revents&POLLIN && servers[i].num_responses < AVG_NUM){ 423 if (ufds[i].revents & POLLIN && servers[i].num_responses < AVG_NUM) {
394 if(verbose) { 424 if (verbose) {
395 printf("response from peer %d: ", i); 425 printf("response from peer %d: ", i);
396 } 426 }
397 427
398 read(ufds[i].fd, &req[i], sizeof(ntp_message)); 428 read(ufds[i].fd, &req[i], sizeof(ntp_message));
429
430 struct timeval recv_time;
399 gettimeofday(&recv_time, NULL); 431 gettimeofday(&recv_time, NULL);
400 DBG(print_ntp_message(&req[i])); 432 DBG(print_ntp_message(&req[i]));
401 respnum=servers[i].num_responses++; 433 int respnum = servers[i].num_responses++;
402 servers[i].offset[respnum]=calc_offset(&req[i], &recv_time)+time_offset; 434 servers[i].offset[respnum] = calc_offset(&req[i], &recv_time) + time_offset;
403 if(verbose) { 435 if (verbose) {
404 printf("offset %.10g\n", servers[i].offset[respnum]); 436 printf("offset %.10g\n", servers[i].offset[respnum]);
405 } 437 }
406 servers[i].stratum=req[i].stratum; 438 servers[i].stratum = req[i].stratum;
407 servers[i].rtdisp=NTP32asDOUBLE(req[i].rtdisp); 439 servers[i].rtdisp = NTP32asDOUBLE(req[i].rtdisp);
408 servers[i].rtdelay=NTP32asDOUBLE(req[i].rtdelay); 440 servers[i].rtdelay = NTP32asDOUBLE(req[i].rtdelay);
409 servers[i].waiting=0; 441 servers[i].waiting = 0;
410 servers[i].flags=req[i].flags; 442 servers[i].flags = req[i].flags;
411 servers_readable--; 443 servers_readable--;
412 one_read = 1; 444 one_read = true;
413 if(servers[i].num_responses==AVG_NUM) servers_completed++; 445 if (servers[i].num_responses == AVG_NUM)
446 servers_completed++;
414 } 447 }
415 } 448 }
416 /* lather, rinse, repeat. */ 449 /* lather, rinse, repeat. */
417 } 450 }
418 451
419 if (one_read == 0) { 452 if (one_read == false) {
420 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); 453 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n");
421 } 454 }
422 455
423 /* now, pick the best server from the list */ 456 /* now, pick the best server from the list */
424 best_index=best_offset_server(servers, num_hosts); 457 double avg_offset = 0.;
425 if(best_index < 0){ 458 int best_index = best_offset_server(servers, num_hosts);
426 *status=STATE_UNKNOWN; 459 if (best_index < 0) {
460 *status = STATE_UNKNOWN;
427 } else { 461 } else {
428 /* finally, calculate the average offset */ 462 /* finally, calculate the average offset */
429 for(i=0; i<servers[best_index].num_responses;i++){ 463 for (int i = 0; i < servers[best_index].num_responses; i++) {
430 avg_offset+=servers[best_index].offset[i]; 464 avg_offset += servers[best_index].offset[i];
431 } 465 }
432 avg_offset/=servers[best_index].num_responses; 466 avg_offset /= servers[best_index].num_responses;
433 } 467 }
434 468
435 /* cleanup */ 469 /* cleanup */
436 for(j=0; j<num_hosts; j++){ close(socklist[j]); } 470 for (int j = 0; j < num_hosts; j++) {
471 close(socklist[j]);
472 }
437 free(socklist); 473 free(socklist);
438 free(ufds); 474 free(ufds);
439 free(servers); 475 free(servers);
440 free(req); 476 free(req);
441 freeaddrinfo(ai); 477 freeaddrinfo(ai);
442 478
443 if(verbose) printf("overall average offset: %.10g\n", avg_offset); 479 if (verbose)
480 printf("overall average offset: %.10g\n", avg_offset);
444 return avg_offset; 481 return avg_offset;
445} 482}
446 483
447int process_arguments(int argc, char **argv){ 484int process_arguments(int argc, char **argv) {
448 int c; 485 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
449 int option=0; 486 {"help", no_argument, 0, 'h'},
450 static struct option longopts[] = { 487 {"verbose", no_argument, 0, 'v'},
451 {"version", no_argument, 0, 'V'}, 488 {"use-ipv4", no_argument, 0, '4'},
452 {"help", no_argument, 0, 'h'}, 489 {"use-ipv6", no_argument, 0, '6'},
453 {"verbose", no_argument, 0, 'v'}, 490 {"quiet", no_argument, 0, 'q'},
454 {"use-ipv4", no_argument, 0, '4'}, 491 {"time-offset", optional_argument, 0, 'o'},
455 {"use-ipv6", no_argument, 0, '6'}, 492 {"warning", required_argument, 0, 'w'},
456 {"quiet", no_argument, 0, 'q'}, 493 {"critical", required_argument, 0, 'c'},
457 {"time-offset", optional_argument, 0, 'o'}, 494 {"timeout", required_argument, 0, 't'},
458 {"warning", required_argument, 0, 'w'}, 495 {"hostname", required_argument, 0, 'H'},
459 {"critical", required_argument, 0, 'c'}, 496 {"port", required_argument, 0, 'p'},
460 {"timeout", required_argument, 0, 't'}, 497 {0, 0, 0, 0}};
461 {"hostname", required_argument, 0, 'H'},
462 {"port", required_argument, 0, 'p'},
463 {0, 0, 0, 0}
464 };
465
466 498
467 if (argc < 2) 499 if (argc < 2)
468 usage ("\n"); 500 usage("\n");
469 501
470 while (1) { 502 while (true) {
471 c = getopt_long (argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); 503 int option = 0;
472 if (c == -1 || c == EOF || c == 1) 504 int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option);
505 if (option_char == -1 || option_char == EOF || option_char == 1)
473 break; 506 break;
474 507
475 switch (c) { 508 switch (option_char) {
476 case 'h': 509 case 'h':
477 print_help(); 510 print_help();
478 exit(STATE_UNKNOWN); 511 exit(STATE_UNKNOWN);
@@ -494,7 +527,7 @@ int process_arguments(int argc, char **argv){
494 ocrit = optarg; 527 ocrit = optarg;
495 break; 528 break;
496 case 'H': 529 case 'H':
497 if(!is_host(optarg)) 530 if (!is_host(optarg))
498 usage2(_("Invalid hostname/address"), optarg); 531 usage2(_("Invalid hostname/address"), optarg);
499 server_address = strdup(optarg); 532 server_address = strdup(optarg);
500 break; 533 break;
@@ -502,11 +535,11 @@ int process_arguments(int argc, char **argv){
502 port = strdup(optarg); 535 port = strdup(optarg);
503 break; 536 break;
504 case 't': 537 case 't':
505 socket_timeout=atoi(optarg); 538 socket_timeout = atoi(optarg);
506 break; 539 break;
507 case 'o': 540 case 'o':
508 time_offset=atoi(optarg); 541 time_offset = atoi(optarg);
509 break; 542 break;
510 case '4': 543 case '4':
511 address_family = AF_INET; 544 address_family = AF_INET;
512 break; 545 break;
@@ -514,77 +547,74 @@ int process_arguments(int argc, char **argv){
514#ifdef USE_IPV6 547#ifdef USE_IPV6
515 address_family = AF_INET6; 548 address_family = AF_INET6;
516#else 549#else
517 usage4 (_("IPv6 support not available")); 550 usage4(_("IPv6 support not available"));
518#endif 551#endif
519 break; 552 break;
520 case '?': 553 case '?':
521 /* print short usage statement if args not parsable */ 554 /* print short usage statement if args not parsable */
522 usage5 (); 555 usage5();
523 break; 556 break;
524 } 557 }
525 } 558 }
526 559
527 if(server_address == NULL){ 560 if (server_address == NULL) {
528 usage4(_("Hostname was not supplied")); 561 usage4(_("Hostname was not supplied"));
529 } 562 }
530 563
531 return 0; 564 return 0;
532} 565}
533 566
534char *perfd_offset (double offset) { 567char *perfd_offset(double offset) {
535 return fperfdata ("offset", offset, "s", 568 return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false,
536 true, offset_thresholds->warning->end, 569 0);
537 true, offset_thresholds->critical->end,
538 false, 0, false, 0);
539} 570}
540 571
541int main(int argc, char *argv[]){ 572int main(int argc, char *argv[]) {
542 int result, offset_result; 573 setlocale(LC_ALL, "");
543 double offset=0; 574 bindtextdomain(PACKAGE, LOCALEDIR);
544 char *result_line, *perfdata_line; 575 textdomain(PACKAGE);
545
546 setlocale (LC_ALL, "");
547 bindtextdomain (PACKAGE, LOCALEDIR);
548 textdomain (PACKAGE);
549
550 result = offset_result = STATE_OK;
551 576
552 /* Parse extra opts if any */ 577 /* Parse extra opts if any */
553 argv=np_extra_opts (&argc, argv, progname); 578 argv = np_extra_opts(&argc, argv, progname);
554 579
555 if (process_arguments (argc, argv) == ERROR) 580 if (process_arguments(argc, argv) == ERROR)
556 usage4 (_("Could not parse arguments")); 581 usage4(_("Could not parse arguments"));
557 582
558 set_thresholds(&offset_thresholds, owarn, ocrit); 583 set_thresholds(&offset_thresholds, owarn, ocrit);
559 584
560 /* initialize alarm signal handling */ 585 /* initialize alarm signal handling */
561 signal (SIGALRM, socket_timeout_alarm_handler); 586 signal(SIGALRM, socket_timeout_alarm_handler);
562 587
563 /* set socket timeout */ 588 /* set socket timeout */
564 alarm (socket_timeout); 589 alarm(socket_timeout);
565 590
566 offset = offset_request(server_address, &offset_result); 591 int offset_result = STATE_OK;
592 int result = STATE_OK;
593 double offset = offset_request(server_address, &offset_result);
567 if (offset_result == STATE_UNKNOWN) { 594 if (offset_result == STATE_UNKNOWN) {
568 result = ( (!quiet) ? STATE_UNKNOWN : STATE_CRITICAL); 595 result = ((!quiet) ? STATE_UNKNOWN : STATE_CRITICAL);
569 } else { 596 } else {
570 result = get_status(fabs(offset), offset_thresholds); 597 result = get_status(fabs(offset), offset_thresholds);
571 } 598 }
572 599
600 char *result_line;
573 switch (result) { 601 switch (result) {
574 case STATE_CRITICAL : 602 case STATE_CRITICAL:
575 xasprintf(&result_line, _("NTP CRITICAL:")); 603 xasprintf(&result_line, _("NTP CRITICAL:"));
576 break; 604 break;
577 case STATE_WARNING : 605 case STATE_WARNING:
578 xasprintf(&result_line, _("NTP WARNING:")); 606 xasprintf(&result_line, _("NTP WARNING:"));
579 break; 607 break;
580 case STATE_OK : 608 case STATE_OK:
581 xasprintf(&result_line, _("NTP OK:")); 609 xasprintf(&result_line, _("NTP OK:"));
582 break; 610 break;
583 default : 611 default:
584 xasprintf(&result_line, _("NTP UNKNOWN:")); 612 xasprintf(&result_line, _("NTP UNKNOWN:"));
585 break; 613 break;
586 } 614 }
587 if(offset_result == STATE_UNKNOWN){ 615
616 char *perfdata_line;
617 if (offset_result == STATE_UNKNOWN) {
588 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); 618 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown"));
589 xasprintf(&perfdata_line, ""); 619 xasprintf(&perfdata_line, "");
590 } else { 620 } else {
@@ -593,35 +623,36 @@ int main(int argc, char *argv[]){
593 } 623 }
594 printf("%s|%s\n", result_line, perfdata_line); 624 printf("%s|%s\n", result_line, perfdata_line);
595 625
596 if(server_address!=NULL) free(server_address); 626 if (server_address != NULL)
627 free(server_address);
597 return result; 628 return result;
598} 629}
599 630
600void print_help(void){ 631void print_help(void) {
601 print_revision(progname, NP_VERSION); 632 print_revision(progname, NP_VERSION);
602 633
603 printf ("Copyright (c) 2006 Sean Finney\n"); 634 printf("Copyright (c) 2006 Sean Finney\n");
604 printf (COPYRIGHT, copyright, email); 635 printf(COPYRIGHT, copyright, email);
605 636
606 printf ("%s\n", _("This plugin checks the clock offset with the ntp server")); 637 printf("%s\n", _("This plugin checks the clock offset with the ntp server"));
607 638
608 printf ("\n\n"); 639 printf("\n\n");
609 640
610 print_usage(); 641 print_usage();
611 printf (UT_HELP_VRSN); 642 printf(UT_HELP_VRSN);
612 printf (UT_EXTRA_OPTS); 643 printf(UT_EXTRA_OPTS);
613 printf (UT_IPv46); 644 printf(UT_IPv46);
614 printf (UT_HOST_PORT, 'p', "123"); 645 printf(UT_HOST_PORT, 'p', "123");
615 printf (" %s\n", "-q, --quiet"); 646 printf(" %s\n", "-q, --quiet");
616 printf (" %s\n", _("Returns UNKNOWN instead of CRITICAL if offset cannot be found")); 647 printf(" %s\n", _("Returns UNKNOWN instead of CRITICAL if offset cannot be found"));
617 printf (" %s\n", "-w, --warning=THRESHOLD"); 648 printf(" %s\n", "-w, --warning=THRESHOLD");
618 printf (" %s\n", _("Offset to result in warning status (seconds)")); 649 printf(" %s\n", _("Offset to result in warning status (seconds)"));
619 printf (" %s\n", "-c, --critical=THRESHOLD"); 650 printf(" %s\n", "-c, --critical=THRESHOLD");
620 printf (" %s\n", _("Offset to result in critical status (seconds)")); 651 printf(" %s\n", _("Offset to result in critical status (seconds)"));
621 printf (" %s\n", "-o, --time_offset=INTEGER"); 652 printf(" %s\n", "-o, --time_offset=INTEGER");
622 printf (" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); 653 printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)"));
623 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 654 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
624 printf (UT_VERBOSE); 655 printf(UT_VERBOSE);
625 656
626 printf("\n"); 657 printf("\n");
627 printf("%s\n", _("This plugin checks the clock offset between the local host and a")); 658 printf("%s\n", _("This plugin checks the clock offset between the local host and a"));
@@ -641,13 +672,10 @@ void print_help(void){
641 printf("%s\n", _("Examples:")); 672 printf("%s\n", _("Examples:"));
642 printf(" %s\n", ("./check_ntp_time -H ntpserv -w 0.5 -c 1")); 673 printf(" %s\n", ("./check_ntp_time -H ntpserv -w 0.5 -c 1"));
643 674
644 printf (UT_SUPPORT); 675 printf(UT_SUPPORT);
645} 676}
646 677
647void 678void print_usage(void) {
648print_usage(void) 679 printf("%s\n", _("Usage:"));
649{
650 printf ("%s\n", _("Usage:"));
651 printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-v verbose] [-o <time offset>]\n", progname); 680 printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-v verbose] [-o <time offset>]\n", progname);
652} 681}
653
diff --git a/plugins/check_nwstat.c b/plugins/check_nwstat.c
index 10c493b6..3af63603 100644
--- a/plugins/check_nwstat.c
+++ b/plugins/check_nwstat.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_nwstat plugin 3 * Monitoring check_nwstat plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_nwstat plugin 10 * This file contains the check_nwstat plugin
11* 11 *
12* This plugin attempts to contact the MRTGEXT NLM running on a 12 * This plugin attempts to contact the MRTGEXT NLM running on a
13* Novell server to gather the requested system information. 13 * Novell server to gather the requested system information.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_nwstat"; 32const char *progname = "check_nwstat";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -44,10 +44,10 @@ enum checkvar {
44 LOAD15, /* check 15 minute CPU load */ 44 LOAD15, /* check 15 minute CPU load */
45 CONNS, /* check number of connections */ 45 CONNS, /* check number of connections */
46 VPF, /* check % free space on volume */ 46 VPF, /* check % free space on volume */
47 VMF, /* check MB free space on volume */ 47 VMF, /* check MB free space on volume */
48 VMU, /* check MB used space on volume */ 48 VMU, /* check MB used space on volume */
49 VPU, /* check % used space on volume */ 49 VPU, /* check % used space on volume */
50 VMP, /* check MB purgeable space on volume */ 50 VMP, /* check MB purgeable space on volume */
51 VKF, /* check KB free space on volume */ 51 VKF, /* check KB free space on volume */
52 LTCH, /* check long-term cache hit percentage */ 52 LTCH, /* check long-term cache hit percentage */
53 CBUFF, /* check total cache buffers */ 53 CBUFF, /* check total cache buffers */
@@ -55,7 +55,7 @@ enum checkvar {
55 LRUM, /* check LRU sitting time in minutes */ 55 LRUM, /* check LRU sitting time in minutes */
56 DSDB, /* check to see if DS Database is open */ 56 DSDB, /* check to see if DS Database is open */
57 LOGINS, /* check to see if logins are enabled */ 57 LOGINS, /* check to see if logins are enabled */
58 NRMH, /* check to see NRM Health Status */ 58 NRMH, /* check to see NRM Health Status */
59 PUPRB, /* check % of used packet receive buffers */ 59 PUPRB, /* check % of used packet receive buffers */
60 UPRB, /* check used packet receive buffers */ 60 UPRB, /* check used packet receive buffers */
61 SAPENTRIES, /* check SAP entries */ 61 SAPENTRIES, /* check SAP entries */
@@ -73,8 +73,8 @@ enum checkvar {
73 DSVER, /* check NDS version */ 73 DSVER, /* check NDS version */
74 UPTIME, /* check server uptime */ 74 UPTIME, /* check server uptime */
75 NLM, /* check NLM loaded */ 75 NLM, /* check NLM loaded */
76 NRMP, /* check NRM Process Values */ 76 NRMP, /* check NRM Process Values */
77 NRMM, /* check NRM Memory Values */ 77 NRMM, /* check NRM Memory Values */
78 NRMS, /* check NRM Values */ 78 NRMS, /* check NRM Values */
79 NSS1, /* check Statistics from _Admin:Manage_NSS\GeneralStats.xml */ 79 NSS1, /* check Statistics from _Admin:Manage_NSS\GeneralStats.xml */
80 NSS2, /* check Statistics from _Admin:Manage_NSS\BufferCache.xml */ 80 NSS2, /* check Statistics from _Admin:Manage_NSS\BufferCache.xml */
@@ -89,1652 +89,1439 @@ enum {
89 PORT = 9999 89 PORT = 9999
90}; 90};
91 91
92char *server_address=NULL; 92char *server_address = NULL;
93char *volume_name=NULL; 93char *volume_name = NULL;
94char *nlm_name=NULL; 94char *nlm_name = NULL;
95char *nrmp_name=NULL; 95char *nrmp_name = NULL;
96char *nrmm_name=NULL; 96char *nrmm_name = NULL;
97char *nrms_name=NULL; 97char *nrms_name = NULL;
98char *nss1_name=NULL; 98char *nss1_name = NULL;
99char *nss2_name=NULL; 99char *nss2_name = NULL;
100char *nss3_name=NULL; 100char *nss3_name = NULL;
101char *nss4_name=NULL; 101char *nss4_name = NULL;
102char *nss5_name=NULL; 102char *nss5_name = NULL;
103char *nss6_name=NULL; 103char *nss6_name = NULL;
104char *nss7_name=NULL; 104char *nss7_name = NULL;
105int server_port=PORT; 105int server_port = PORT;
106unsigned long warning_value=0L; 106unsigned long warning_value = 0L;
107unsigned long critical_value=0L; 107unsigned long critical_value = 0L;
108bool check_warning_value = false; 108bool check_warning_value = false;
109bool check_critical_value = false; 109bool check_critical_value = false;
110bool check_netware_version = false; 110bool check_netware_version = false;
111enum checkvar vars_to_check = NONE; 111enum checkvar vars_to_check = NONE;
112int sap_number=-1; 112int sap_number = -1;
113 113
114int process_arguments(int, char **); 114int process_arguments(int, char **);
115void print_help(void); 115void print_help(void);
116void print_usage(void); 116void print_usage(void);
117 117
118 118int main(int argc, char **argv) {
119
120int
121main(int argc, char **argv) {
122 int result = STATE_UNKNOWN; 119 int result = STATE_UNKNOWN;
123 int sd; 120 int sd;
124 char *send_buffer=NULL; 121 char *send_buffer = NULL;
125 char recv_buffer[MAX_INPUT_BUFFER]; 122 char recv_buffer[MAX_INPUT_BUFFER];
126 char *output_message=NULL; 123 char *output_message = NULL;
127 char *temp_buffer=NULL; 124 char *temp_buffer = NULL;
128 char *netware_version=NULL; 125 char *netware_version = NULL;
129 126
130 int time_sync_status=0; 127 int time_sync_status = 0;
131 int nrm_health_status=0; 128 int nrm_health_status = 0;
132 unsigned long total_cache_buffers=0; 129 unsigned long total_cache_buffers = 0;
133 unsigned long dirty_cache_buffers=0; 130 unsigned long dirty_cache_buffers = 0;
134 unsigned long open_files=0; 131 unsigned long open_files = 0;
135 unsigned long abended_threads=0; 132 unsigned long abended_threads = 0;
136 unsigned long max_service_processes=0; 133 unsigned long max_service_processes = 0;
137 unsigned long current_service_processes=0; 134 unsigned long current_service_processes = 0;
138 unsigned long free_disk_space=0L; 135 unsigned long free_disk_space = 0L;
139 unsigned long nrmp_value=0L; 136 unsigned long nrmp_value = 0L;
140 unsigned long nrmm_value=0L; 137 unsigned long nrmm_value = 0L;
141 unsigned long nrms_value=0L; 138 unsigned long nrms_value = 0L;
142 unsigned long nss1_value=0L; 139 unsigned long nss1_value = 0L;
143 unsigned long nss2_value=0L; 140 unsigned long nss2_value = 0L;
144 unsigned long nss3_value=0L; 141 unsigned long nss3_value = 0L;
145 unsigned long nss4_value=0L; 142 unsigned long nss4_value = 0L;
146 unsigned long nss5_value=0L; 143 unsigned long nss5_value = 0L;
147 unsigned long nss6_value=0L; 144 unsigned long nss6_value = 0L;
148 unsigned long nss7_value=0L; 145 unsigned long nss7_value = 0L;
149 unsigned long total_disk_space=0L; 146 unsigned long total_disk_space = 0L;
150 unsigned long used_disk_space=0L; 147 unsigned long used_disk_space = 0L;
151 unsigned long percent_used_disk_space=0L; 148 unsigned long percent_used_disk_space = 0L;
152 unsigned long purgeable_disk_space=0L; 149 unsigned long purgeable_disk_space = 0L;
153 unsigned long non_purgeable_disk_space=0L; 150 unsigned long non_purgeable_disk_space = 0L;
154 unsigned long percent_free_space=0; 151 unsigned long percent_free_space = 0;
155 unsigned long percent_purgeable_space=0; 152 unsigned long percent_purgeable_space = 0;
156 unsigned long percent_non_purgeable_space=0; 153 unsigned long percent_non_purgeable_space = 0;
157 unsigned long current_connections=0L; 154 unsigned long current_connections = 0L;
158 unsigned long utilization=0L; 155 unsigned long utilization = 0L;
159 unsigned long cache_hits=0; 156 unsigned long cache_hits = 0;
160 unsigned long cache_buffers=0L; 157 unsigned long cache_buffers = 0L;
161 unsigned long lru_time=0L; 158 unsigned long lru_time = 0L;
162 unsigned long max_packet_receive_buffers=0; 159 unsigned long max_packet_receive_buffers = 0;
163 unsigned long used_packet_receive_buffers=0; 160 unsigned long used_packet_receive_buffers = 0;
164 unsigned long percent_used_packet_receive_buffers=0L; 161 unsigned long percent_used_packet_receive_buffers = 0L;
165 unsigned long sap_entries=0; 162 unsigned long sap_entries = 0;
166 char uptime[MAX_INPUT_BUFFER]; 163 char uptime[MAX_INPUT_BUFFER];
167 164
168 setlocale (LC_ALL, ""); 165 setlocale(LC_ALL, "");
169 bindtextdomain (PACKAGE, LOCALEDIR); 166 bindtextdomain(PACKAGE, LOCALEDIR);
170 textdomain (PACKAGE); 167 textdomain(PACKAGE);
171 168
172 /* Parse extra opts if any */ 169 /* Parse extra opts if any */
173 argv=np_extra_opts(&argc, argv, progname); 170 argv = np_extra_opts(&argc, argv, progname);
174 171
175 if (process_arguments(argc,argv) == ERROR) 172 if (process_arguments(argc, argv) == ERROR)
176 usage4 (_("Could not parse arguments")); 173 usage4(_("Could not parse arguments"));
177 174
178 /* initialize alarm signal handling */ 175 /* initialize alarm signal handling */
179 signal(SIGALRM,socket_timeout_alarm_handler); 176 signal(SIGALRM, socket_timeout_alarm_handler);
180 177
181 /* set socket timeout */ 178 /* set socket timeout */
182 alarm(socket_timeout); 179 alarm(socket_timeout);
183 180
184 /* open connection */ 181 /* open connection */
185 my_tcp_connect (server_address, server_port, &sd); 182 my_tcp_connect(server_address, server_port, &sd);
186 183
187 /* get OS version string */ 184 /* get OS version string */
188 if (check_netware_version) { 185 if (check_netware_version) {
189 send_buffer = strdup ("S19\r\n"); 186 send_buffer = strdup("S19\r\n");
190 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 187 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
191 if (result!=STATE_OK) 188 if (result != STATE_OK)
192 return result; 189 return result;
193 if (!strcmp(recv_buffer,"-1\n")) 190 if (!strcmp(recv_buffer, "-1\n"))
194 netware_version = strdup(""); 191 netware_version = strdup("");
195 else { 192 else {
196 recv_buffer[strlen(recv_buffer)-1]=0; 193 recv_buffer[strlen(recv_buffer) - 1] = 0;
197 xasprintf (&netware_version,_("NetWare %s: "),recv_buffer); 194 xasprintf(&netware_version, _("NetWare %s: "), recv_buffer);
198 } 195 }
199 } else 196 } else
200 netware_version = strdup(""); 197 netware_version = strdup("");
201 198
202
203 /* check CPU load */ 199 /* check CPU load */
204 if (vars_to_check==LOAD1 || vars_to_check==LOAD5 || vars_to_check==LOAD15) { 200 if (vars_to_check == LOAD1 || vars_to_check == LOAD5 || vars_to_check == LOAD15) {
205 201
206 switch(vars_to_check) { 202 switch (vars_to_check) {
207 case LOAD1: 203 case LOAD1:
208 temp_buffer = strdup ("1"); 204 temp_buffer = strdup("1");
209 break; 205 break;
210 case LOAD5: 206 case LOAD5:
211 temp_buffer = strdup ("5"); 207 temp_buffer = strdup("5");
212 break; 208 break;
213 default: 209 default:
214 temp_buffer = strdup ("15"); 210 temp_buffer = strdup("15");
215 break; 211 break;
216 } 212 }
217 213
218 close(sd); 214 close(sd);
219 my_tcp_connect (server_address, server_port, &sd); 215 my_tcp_connect(server_address, server_port, &sd);
220 216
221 xasprintf (&send_buffer,"UTIL%s\r\n",temp_buffer); 217 xasprintf(&send_buffer, "UTIL%s\r\n", temp_buffer);
222 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 218 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
223 if (result!=STATE_OK) 219 if (result != STATE_OK)
224 return result; 220 return result;
225 utilization=strtoul(recv_buffer,NULL,10); 221 utilization = strtoul(recv_buffer, NULL, 10);
226 222
227 close(sd); 223 close(sd);
228 my_tcp_connect (server_address, server_port, &sd); 224 my_tcp_connect(server_address, server_port, &sd);
229 225
230 send_buffer = strdup ("UPTIME\r\n"); 226 send_buffer = strdup("UPTIME\r\n");
231 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 227 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
232 if (result!=STATE_OK) 228 if (result != STATE_OK)
233 return result; 229 return result;
234 recv_buffer[strlen(recv_buffer)-1]=0; 230 recv_buffer[strlen(recv_buffer) - 1] = 0;
235 sprintf(uptime,_("Up %s,"),recv_buffer); 231 sprintf(uptime, _("Up %s,"), recv_buffer);
236 232
237 if (check_critical_value && utilization >= critical_value) 233 if (check_critical_value && utilization >= critical_value)
238 result=STATE_CRITICAL; 234 result = STATE_CRITICAL;
239 else if (check_warning_value && utilization >= warning_value) 235 else if (check_warning_value && utilization >= warning_value)
240 result=STATE_WARNING; 236 result = STATE_WARNING;
241 237
242 xasprintf (&output_message, 238 xasprintf(&output_message, _("Load %s - %s %s-min load average = %lu%%|load%s=%lu;%lu;%lu;0;100"), state_text(result), uptime,
243 _("Load %s - %s %s-min load average = %lu%%|load%s=%lu;%lu;%lu;0;100"), 239 temp_buffer, utilization, temp_buffer, utilization, warning_value, critical_value);
244 state_text(result),
245 uptime,
246 temp_buffer,
247 utilization,
248 temp_buffer,
249 utilization,
250 warning_value,
251 critical_value);
252 240
253 /* check number of user connections */ 241 /* check number of user connections */
254 } else if (vars_to_check==CONNS) { 242 } else if (vars_to_check == CONNS) {
255 243
256 close(sd); 244 close(sd);
257 my_tcp_connect (server_address, server_port, &sd); 245 my_tcp_connect(server_address, server_port, &sd);
258 246
259 send_buffer = strdup ("CONNECT\r\n"); 247 send_buffer = strdup("CONNECT\r\n");
260 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 248 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
261 if (result!=STATE_OK) 249 if (result != STATE_OK)
262 return result; 250 return result;
263 current_connections=strtoul(recv_buffer,NULL,10); 251 current_connections = strtoul(recv_buffer, NULL, 10);
264 252
265 if (check_critical_value && current_connections >= critical_value) 253 if (check_critical_value && current_connections >= critical_value)
266 result=STATE_CRITICAL; 254 result = STATE_CRITICAL;
267 else if (check_warning_value && current_connections >= warning_value) 255 else if (check_warning_value && current_connections >= warning_value)
268 result=STATE_WARNING; 256 result = STATE_WARNING;
269 257
270 xasprintf (&output_message, 258 xasprintf(&output_message, _("Conns %s - %lu current connections|Conns=%lu;%lu;%lu;;"), state_text(result), current_connections,
271 _("Conns %s - %lu current connections|Conns=%lu;%lu;%lu;;"), 259 current_connections, warning_value, critical_value);
272 state_text(result),
273 current_connections,
274 current_connections,
275 warning_value,
276 critical_value);
277 260
278 /* check % long term cache hits */ 261 /* check % long term cache hits */
279 } else if (vars_to_check==LTCH) { 262 } else if (vars_to_check == LTCH) {
280 263
281 close(sd); 264 close(sd);
282 my_tcp_connect (server_address, server_port, &sd); 265 my_tcp_connect(server_address, server_port, &sd);
283 266
284 send_buffer = strdup ("S1\r\n"); 267 send_buffer = strdup("S1\r\n");
285 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 268 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
286 if (result!=STATE_OK) 269 if (result != STATE_OK)
287 return result; 270 return result;
288 cache_hits=atoi(recv_buffer); 271 cache_hits = atoi(recv_buffer);
289 272
290 if (check_critical_value && cache_hits <= critical_value) 273 if (check_critical_value && cache_hits <= critical_value)
291 result=STATE_CRITICAL; 274 result = STATE_CRITICAL;
292 else if (check_warning_value && cache_hits <= warning_value) 275 else if (check_warning_value && cache_hits <= warning_value)
293 result=STATE_WARNING; 276 result = STATE_WARNING;
294 277
295 xasprintf (&output_message, 278 xasprintf(&output_message, _("%s: Long term cache hits = %lu%%"), state_text(result), cache_hits);
296 _("%s: Long term cache hits = %lu%%"),
297 state_text(result),
298 cache_hits);
299 279
300 /* check cache buffers */ 280 /* check cache buffers */
301 } else if (vars_to_check==CBUFF) { 281 } else if (vars_to_check == CBUFF) {
302 282
303 close(sd); 283 close(sd);
304 my_tcp_connect (server_address, server_port, &sd); 284 my_tcp_connect(server_address, server_port, &sd);
305 285
306 send_buffer = strdup ("S2\r\n"); 286 send_buffer = strdup("S2\r\n");
307 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 287 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
308 if (result!=STATE_OK) 288 if (result != STATE_OK)
309 return result; 289 return result;
310 cache_buffers=strtoul(recv_buffer,NULL,10); 290 cache_buffers = strtoul(recv_buffer, NULL, 10);
311 291
312 if (check_critical_value && cache_buffers <= critical_value) 292 if (check_critical_value && cache_buffers <= critical_value)
313 result=STATE_CRITICAL; 293 result = STATE_CRITICAL;
314 else if (check_warning_value && cache_buffers <= warning_value) 294 else if (check_warning_value && cache_buffers <= warning_value)
315 result=STATE_WARNING; 295 result = STATE_WARNING;
316 296
317 xasprintf (&output_message, 297 xasprintf(&output_message, _("%s: Total cache buffers = %lu|Cachebuffers=%lu;%lu;%lu;;"), state_text(result), cache_buffers,
318 _("%s: Total cache buffers = %lu|Cachebuffers=%lu;%lu;%lu;;"), 298 cache_buffers, warning_value, critical_value);
319 state_text(result),
320 cache_buffers,
321 cache_buffers,
322 warning_value,
323 critical_value);
324 299
325 /* check dirty cache buffers */ 300 /* check dirty cache buffers */
326 } else if (vars_to_check==CDBUFF) { 301 } else if (vars_to_check == CDBUFF) {
327 302
328 close(sd); 303 close(sd);
329 my_tcp_connect (server_address, server_port, &sd); 304 my_tcp_connect(server_address, server_port, &sd);
330 305
331 send_buffer = strdup ("S3\r\n"); 306 send_buffer = strdup("S3\r\n");
332 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 307 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
333 if (result!=STATE_OK) 308 if (result != STATE_OK)
334 return result; 309 return result;
335 cache_buffers=strtoul(recv_buffer,NULL,10); 310 cache_buffers = strtoul(recv_buffer, NULL, 10);
336 311
337 if (check_critical_value && cache_buffers >= critical_value) 312 if (check_critical_value && cache_buffers >= critical_value)
338 result=STATE_CRITICAL; 313 result = STATE_CRITICAL;
339 else if (check_warning_value && cache_buffers >= warning_value) 314 else if (check_warning_value && cache_buffers >= warning_value)
340 result=STATE_WARNING; 315 result = STATE_WARNING;
341 316
342 xasprintf (&output_message, 317 xasprintf(&output_message, _("%s: Dirty cache buffers = %lu|Dirty-Cache-Buffers=%lu;%lu;%lu;;"), state_text(result), cache_buffers,
343 _("%s: Dirty cache buffers = %lu|Dirty-Cache-Buffers=%lu;%lu;%lu;;"), 318 cache_buffers, warning_value, critical_value);
344 state_text(result),
345 cache_buffers,
346 cache_buffers,
347 warning_value,
348 critical_value);
349 319
350 /* check LRU sitting time in minutes */ 320 /* check LRU sitting time in minutes */
351 } else if (vars_to_check==LRUM) { 321 } else if (vars_to_check == LRUM) {
352 322
353 close(sd); 323 close(sd);
354 my_tcp_connect (server_address, server_port, &sd); 324 my_tcp_connect(server_address, server_port, &sd);
355 325
356 send_buffer = strdup ("S5\r\n"); 326 send_buffer = strdup("S5\r\n");
357 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 327 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
358 if (result!=STATE_OK) 328 if (result != STATE_OK)
359 return result; 329 return result;
360 lru_time=strtoul(recv_buffer,NULL,10); 330 lru_time = strtoul(recv_buffer, NULL, 10);
361 331
362 if (check_critical_value && lru_time <= critical_value) 332 if (check_critical_value && lru_time <= critical_value)
363 result=STATE_CRITICAL; 333 result = STATE_CRITICAL;
364 else if (check_warning_value && lru_time <= warning_value) 334 else if (check_warning_value && lru_time <= warning_value)
365 result=STATE_WARNING; 335 result = STATE_WARNING;
366
367 xasprintf (&output_message,
368 _("%s: LRU sitting time = %lu minutes"),
369 state_text(result),
370 lru_time);
371 336
337 xasprintf(&output_message, _("%s: LRU sitting time = %lu minutes"), state_text(result), lru_time);
372 338
373 /* check KB free space on volume */ 339 /* check KB free space on volume */
374 } else if (vars_to_check==VKF) { 340 } else if (vars_to_check == VKF) {
375 341
376 close(sd); 342 close(sd);
377 my_tcp_connect (server_address, server_port, &sd); 343 my_tcp_connect(server_address, server_port, &sd);
378 344
379 xasprintf (&send_buffer,"VKF%s\r\n",volume_name); 345 xasprintf(&send_buffer, "VKF%s\r\n", volume_name);
380 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 346 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
381 if (result!=STATE_OK) 347 if (result != STATE_OK)
382 return result; 348 return result;
383 349
384 if (!strcmp(recv_buffer,"-1\n")) { 350 if (!strcmp(recv_buffer, "-1\n")) {
385 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 351 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
386 result=STATE_CRITICAL; 352 result = STATE_CRITICAL;
387 } else { 353 } else {
388 free_disk_space=strtoul(recv_buffer,NULL,10); 354 free_disk_space = strtoul(recv_buffer, NULL, 10);
389 if (check_critical_value && free_disk_space <= critical_value) 355 if (check_critical_value && free_disk_space <= critical_value)
390 result=STATE_CRITICAL; 356 result = STATE_CRITICAL;
391 else if (check_warning_value && free_disk_space <= warning_value) 357 else if (check_warning_value && free_disk_space <= warning_value)
392 result=STATE_WARNING; 358 result = STATE_WARNING;
393 xasprintf (&output_message, 359 xasprintf(&output_message, _("%s%lu KB free on volume %s|KBFree%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
394 _("%s%lu KB free on volume %s|KBFree%s=%lu;%lu;%lu;;"), 360 free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
395 (result==STATE_OK)?"":_("Only "),
396 free_disk_space,
397 volume_name,
398 volume_name,
399 free_disk_space,
400 warning_value,
401 critical_value);
402 } 361 }
403 362
404 /* check MB free space on volume */ 363 /* check MB free space on volume */
405 } else if (vars_to_check==VMF) { 364 } else if (vars_to_check == VMF) {
406 365
407 xasprintf (&send_buffer,"VMF%s\r\n",volume_name); 366 xasprintf(&send_buffer, "VMF%s\r\n", volume_name);
408 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 367 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
409 if (result!=STATE_OK) 368 if (result != STATE_OK)
410 return result; 369 return result;
411 370
412 if (!strcmp(recv_buffer,"-1\n")) { 371 if (!strcmp(recv_buffer, "-1\n")) {
413 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 372 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
414 result=STATE_CRITICAL; 373 result = STATE_CRITICAL;
415 } else { 374 } else {
416 free_disk_space=strtoul(recv_buffer,NULL,10); 375 free_disk_space = strtoul(recv_buffer, NULL, 10);
417 if (check_critical_value && free_disk_space <= critical_value) 376 if (check_critical_value && free_disk_space <= critical_value)
418 result=STATE_CRITICAL; 377 result = STATE_CRITICAL;
419 else if (check_warning_value && free_disk_space <= warning_value) 378 else if (check_warning_value && free_disk_space <= warning_value)
420 result=STATE_WARNING; 379 result = STATE_WARNING;
421 xasprintf (&output_message, 380 xasprintf(&output_message, _("%s%lu MB free on volume %s|MBFree%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
422 _("%s%lu MB free on volume %s|MBFree%s=%lu;%lu;%lu;;"), 381 free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
423 (result==STATE_OK)?"":_("Only "),
424 free_disk_space,
425 volume_name,
426 volume_name,
427 free_disk_space,
428 warning_value,
429 critical_value);
430 } 382 }
431 /* check MB used space on volume */ 383 /* check MB used space on volume */
432 } else if (vars_to_check==VMU) { 384 } else if (vars_to_check == VMU) {
433 385
434 xasprintf (&send_buffer,"VMU%s\r\n",volume_name); 386 xasprintf(&send_buffer, "VMU%s\r\n", volume_name);
435 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 387 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
436 if (result!=STATE_OK) 388 if (result != STATE_OK)
437 return result; 389 return result;
438 390
439 if (!strcmp(recv_buffer,"-1\n")) { 391 if (!strcmp(recv_buffer, "-1\n")) {
440 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 392 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
441 result=STATE_CRITICAL; 393 result = STATE_CRITICAL;
442 } else { 394 } else {
443 free_disk_space=strtoul(recv_buffer,NULL,10); 395 free_disk_space = strtoul(recv_buffer, NULL, 10);
444 if (check_critical_value && free_disk_space <= critical_value) 396 if (check_critical_value && free_disk_space <= critical_value)
445 result=STATE_CRITICAL; 397 result = STATE_CRITICAL;
446 else if (check_warning_value && free_disk_space <= warning_value) 398 else if (check_warning_value && free_disk_space <= warning_value)
447 result=STATE_WARNING; 399 result = STATE_WARNING;
448 xasprintf (&output_message, 400 xasprintf(&output_message, _("%s%lu MB used on volume %s|MBUsed%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
449 _("%s%lu MB used on volume %s|MBUsed%s=%lu;%lu;%lu;;"), 401 free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
450 (result==STATE_OK)?"":_("Only "),
451 free_disk_space,
452 volume_name,
453 volume_name,
454 free_disk_space,
455 warning_value,
456 critical_value);
457 } 402 }
458 /* check % used space on volume */ 403 /* check % used space on volume */
459 } else if (vars_to_check==VPU) { 404 } else if (vars_to_check == VPU) {
460 close(sd); 405 close(sd);
461 my_tcp_connect (server_address, server_port, &sd); 406 my_tcp_connect(server_address, server_port, &sd);
462 407
463 asprintf (&send_buffer,"VMU%s\r\n",volume_name); 408 asprintf(&send_buffer, "VMU%s\r\n", volume_name);
464 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 409 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
465 410
466 if (result!=STATE_OK) 411 if (result != STATE_OK)
467 return result; 412 return result;
468 413
469 if (!strcmp(recv_buffer,"-1\n")) { 414 if (!strcmp(recv_buffer, "-1\n")) {
470 asprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 415 asprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
471 result=STATE_CRITICAL; 416 result = STATE_CRITICAL;
472 417
473 } else { 418 } else {
474 used_disk_space=strtoul(recv_buffer,NULL,10); 419 used_disk_space = strtoul(recv_buffer, NULL, 10);
475 close(sd); 420 close(sd);
476 my_tcp_connect (server_address, server_port, &sd); 421 my_tcp_connect(server_address, server_port, &sd);
477 /* get total volume in MB */ 422 /* get total volume in MB */
478 asprintf (&send_buffer,"VMS%s\r\n",volume_name); 423 asprintf(&send_buffer, "VMS%s\r\n", volume_name);
479 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 424 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
480 if (result!=STATE_OK) 425 if (result != STATE_OK)
481 return result; 426 return result;
482 total_disk_space=strtoul(recv_buffer,NULL,10); 427 total_disk_space = strtoul(recv_buffer, NULL, 10);
483 /* calculate percent used on volume */ 428 /* calculate percent used on volume */
484 percent_used_disk_space=(unsigned long)(((double)used_disk_space/(double)total_disk_space)*100.0); 429 percent_used_disk_space = (unsigned long)(((double)used_disk_space / (double)total_disk_space) * 100.0);
485 430
486 if (check_critical_value && percent_used_disk_space >= critical_value) 431 if (check_critical_value && percent_used_disk_space >= critical_value)
487 result=STATE_CRITICAL; 432 result = STATE_CRITICAL;
488 else if (check_warning_value && percent_used_disk_space >= warning_value) 433 else if (check_warning_value && percent_used_disk_space >= warning_value)
489 result=STATE_WARNING; 434 result = STATE_WARNING;
490 435
491 asprintf (&output_message,_("%lu MB (%lu%%) used on volume %s - total %lu MB|Used space in percent on %s=%lu;%lu;%lu;0;100"), 436 asprintf(&output_message, _("%lu MB (%lu%%) used on volume %s - total %lu MB|Used space in percent on %s=%lu;%lu;%lu;0;100"),
492 used_disk_space, 437 used_disk_space, percent_used_disk_space, volume_name, total_disk_space, volume_name, percent_used_disk_space,
493 percent_used_disk_space, 438 warning_value, critical_value);
494 volume_name,
495 total_disk_space,
496 volume_name,
497 percent_used_disk_space,
498 warning_value,
499 critical_value
500 );
501 } 439 }
502 440
503 /* check % free space on volume */ 441 /* check % free space on volume */
504 } else if (vars_to_check==VPF) { 442 } else if (vars_to_check == VPF) {
505 443
506 close(sd); 444 close(sd);
507 my_tcp_connect (server_address, server_port, &sd); 445 my_tcp_connect(server_address, server_port, &sd);
508 446
509 xasprintf (&send_buffer,"VKF%s\r\n",volume_name); 447 xasprintf(&send_buffer, "VKF%s\r\n", volume_name);
510 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 448 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
511 if (result!=STATE_OK) 449 if (result != STATE_OK)
512 return result; 450 return result;
513 451
514 if (!strcmp(recv_buffer,"-1\n")) { 452 if (!strcmp(recv_buffer, "-1\n")) {
515 453
516 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 454 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
517 result=STATE_CRITICAL; 455 result = STATE_CRITICAL;
518 456
519 } else { 457 } else {
520 458
521 free_disk_space=strtoul(recv_buffer,NULL,10); 459 free_disk_space = strtoul(recv_buffer, NULL, 10);
522 460
523 close(sd); 461 close(sd);
524 my_tcp_connect (server_address, server_port, &sd); 462 my_tcp_connect(server_address, server_port, &sd);
525 463
526 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 464 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
527 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 465 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
528 if (result!=STATE_OK) 466 if (result != STATE_OK)
529 return result; 467 return result;
530 total_disk_space=strtoul(recv_buffer,NULL,10); 468 total_disk_space = strtoul(recv_buffer, NULL, 10);
531 469
532 percent_free_space=(unsigned long)(((double)free_disk_space/(double)total_disk_space)*100.0); 470 percent_free_space = (unsigned long)(((double)free_disk_space / (double)total_disk_space) * 100.0);
533 471
534 if (check_critical_value && percent_free_space <= critical_value) 472 if (check_critical_value && percent_free_space <= critical_value)
535 result=STATE_CRITICAL; 473 result = STATE_CRITICAL;
536 else if (check_warning_value && percent_free_space <= warning_value) 474 else if (check_warning_value && percent_free_space <= warning_value)
537 result=STATE_WARNING; 475 result = STATE_WARNING;
538 free_disk_space/=1024; 476 free_disk_space /= 1024;
539 total_disk_space/=1024; 477 total_disk_space /= 1024;
540 xasprintf (&output_message,_("%lu MB (%lu%%) free on volume %s - total %lu MB|FreeMB%s=%lu;%lu;%lu;0;100"), 478 xasprintf(&output_message, _("%lu MB (%lu%%) free on volume %s - total %lu MB|FreeMB%s=%lu;%lu;%lu;0;100"), free_disk_space,
541 free_disk_space, 479 percent_free_space, volume_name, total_disk_space, volume_name, percent_free_space, warning_value, critical_value);
542 percent_free_space,
543 volume_name,
544 total_disk_space,
545 volume_name,
546 percent_free_space,
547 warning_value,
548 critical_value
549 );
550 } 480 }
551 481
552 /* check to see if DS Database is open or closed */ 482 /* check to see if DS Database is open or closed */
553 } else if (vars_to_check==DSDB) { 483 } else if (vars_to_check == DSDB) {
554 484
555 close(sd); 485 close(sd);
556 my_tcp_connect (server_address, server_port, &sd); 486 my_tcp_connect(server_address, server_port, &sd);
557 487
558 send_buffer = strdup ("S11\r\n"); 488 send_buffer = strdup("S11\r\n");
559 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 489 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
560 if (result!=STATE_OK) 490 if (result != STATE_OK)
561 return result; 491 return result;
562 if (atoi(recv_buffer)==1) 492 if (atoi(recv_buffer) == 1)
563 result=STATE_OK; 493 result = STATE_OK;
564 else 494 else
565 result=STATE_WARNING; 495 result = STATE_WARNING;
566 496
567 close(sd); 497 close(sd);
568 my_tcp_connect (server_address, server_port, &sd); 498 my_tcp_connect(server_address, server_port, &sd);
569 499
570 send_buffer = strdup ("S13\r\n"); 500 send_buffer = strdup("S13\r\n");
571 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 501 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
572 temp_buffer=strtok(recv_buffer,"\r\n"); 502 temp_buffer = strtok(recv_buffer, "\r\n");
573 503
574 xasprintf (&output_message,_("Directory Services Database is %s (DS version %s)"),(result==STATE_OK)?"open":"closed",temp_buffer); 504 xasprintf(&output_message, _("Directory Services Database is %s (DS version %s)"), (result == STATE_OK) ? "open" : "closed",
505 temp_buffer);
575 506
576 /* check to see if logins are enabled */ 507 /* check to see if logins are enabled */
577 } else if (vars_to_check==LOGINS) { 508 } else if (vars_to_check == LOGINS) {
578 509
579 close(sd); 510 close(sd);
580 my_tcp_connect (server_address, server_port, &sd); 511 my_tcp_connect(server_address, server_port, &sd);
581 512
582 send_buffer = strdup ("S12\r\n"); 513 send_buffer = strdup("S12\r\n");
583 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 514 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
584 if (result!=STATE_OK) 515 if (result != STATE_OK)
585 return result; 516 return result;
586 if (atoi(recv_buffer)==1) 517 if (atoi(recv_buffer) == 1)
587 result=STATE_OK; 518 result = STATE_OK;
588 else 519 else
589 result=STATE_WARNING; 520 result = STATE_WARNING;
590
591 xasprintf (&output_message,_("Logins are %s"),(result==STATE_OK)?_("enabled"):_("disabled"));
592 521
522 xasprintf(&output_message, _("Logins are %s"), (result == STATE_OK) ? _("enabled") : _("disabled"));
593 523
594 /* check NRM Health Status Summary*/ 524 /* check NRM Health Status Summary*/
595 } else if (vars_to_check==NRMH) { 525 } else if (vars_to_check == NRMH) {
596 526
597 xasprintf (&send_buffer,"NRMH\r\n"); 527 xasprintf(&send_buffer, "NRMH\r\n");
598 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 528 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
599 if (result!=STATE_OK) 529 if (result != STATE_OK)
600 return result; 530 return result;
601 531
602 nrm_health_status=atoi(recv_buffer); 532 nrm_health_status = atoi(recv_buffer);
603 533
604 if (nrm_health_status==2) { 534 if (nrm_health_status == 2) {
605 result=STATE_OK; 535 result = STATE_OK;
606 xasprintf (&output_message,_("CRITICAL - NRM Status is bad!")); 536 xasprintf(&output_message, _("CRITICAL - NRM Status is bad!"));
607 } 537 } else {
608 else { 538 if (nrm_health_status == 1) {
609 if (nrm_health_status==1) { 539 result = STATE_WARNING;
610 result=STATE_WARNING; 540 xasprintf(&output_message, _("Warning - NRM Status is suspect!"));
611 xasprintf (&output_message,_("Warning - NRM Status is suspect!"));
612 } 541 }
613 542
614 xasprintf (&output_message,_("OK - NRM Status is good!")); 543 xasprintf(&output_message, _("OK - NRM Status is good!"));
615 } 544 }
616 545
617
618
619 /* check packet receive buffers */ 546 /* check packet receive buffers */
620 } else if (vars_to_check==UPRB || vars_to_check==PUPRB) { 547 } else if (vars_to_check == UPRB || vars_to_check == PUPRB) {
621 548
622 close(sd); 549 close(sd);
623 my_tcp_connect (server_address, server_port, &sd); 550 my_tcp_connect(server_address, server_port, &sd);
624 551
625 xasprintf (&send_buffer,"S15\r\n"); 552 xasprintf(&send_buffer, "S15\r\n");
626 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 553 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
627 if (result!=STATE_OK) 554 if (result != STATE_OK)
628 return result; 555 return result;
629 556
630 used_packet_receive_buffers=atoi(recv_buffer); 557 used_packet_receive_buffers = atoi(recv_buffer);
631 558
632 close(sd); 559 close(sd);
633 my_tcp_connect (server_address, server_port, &sd); 560 my_tcp_connect(server_address, server_port, &sd);
634 561
635 xasprintf (&send_buffer,"S16\r\n"); 562 xasprintf(&send_buffer, "S16\r\n");
636 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 563 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
637 if (result!=STATE_OK) 564 if (result != STATE_OK)
638 return result; 565 return result;
639 566
640 max_packet_receive_buffers=atoi(recv_buffer); 567 max_packet_receive_buffers = atoi(recv_buffer);
641 568
642 percent_used_packet_receive_buffers=(unsigned long)(((double)used_packet_receive_buffers/(double)max_packet_receive_buffers)*100.0); 569 percent_used_packet_receive_buffers =
570 (unsigned long)(((double)used_packet_receive_buffers / (double)max_packet_receive_buffers) * 100.0);
643 571
644 if (vars_to_check==UPRB) { 572 if (vars_to_check == UPRB) {
645 if (check_critical_value && used_packet_receive_buffers >= critical_value) 573 if (check_critical_value && used_packet_receive_buffers >= critical_value)
646 result=STATE_CRITICAL; 574 result = STATE_CRITICAL;
647 else if (check_warning_value && used_packet_receive_buffers >= warning_value) 575 else if (check_warning_value && used_packet_receive_buffers >= warning_value)
648 result=STATE_WARNING; 576 result = STATE_WARNING;
649 } else { 577 } else {
650 if (check_critical_value && percent_used_packet_receive_buffers >= critical_value) 578 if (check_critical_value && percent_used_packet_receive_buffers >= critical_value)
651 result=STATE_CRITICAL; 579 result = STATE_CRITICAL;
652 else if (check_warning_value && percent_used_packet_receive_buffers >= warning_value) 580 else if (check_warning_value && percent_used_packet_receive_buffers >= warning_value)
653 result=STATE_WARNING; 581 result = STATE_WARNING;
654 } 582 }
655 583
656 xasprintf (&output_message,_("%lu of %lu (%lu%%) packet receive buffers used"),used_packet_receive_buffers,max_packet_receive_buffers,percent_used_packet_receive_buffers); 584 xasprintf(&output_message, _("%lu of %lu (%lu%%) packet receive buffers used"), used_packet_receive_buffers,
585 max_packet_receive_buffers, percent_used_packet_receive_buffers);
657 586
658 /* check SAP table entries */ 587 /* check SAP table entries */
659 } else if (vars_to_check==SAPENTRIES) { 588 } else if (vars_to_check == SAPENTRIES) {
660 589
661 close(sd); 590 close(sd);
662 my_tcp_connect (server_address, server_port, &sd); 591 my_tcp_connect(server_address, server_port, &sd);
663 592
664 if (sap_number==-1) 593 if (sap_number == -1)
665 xasprintf (&send_buffer,"S9\r\n"); 594 xasprintf(&send_buffer, "S9\r\n");
666 else 595 else
667 xasprintf (&send_buffer,"S9.%d\r\n",sap_number); 596 xasprintf(&send_buffer, "S9.%d\r\n", sap_number);
668 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 597 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
669 if (result!=STATE_OK) 598 if (result != STATE_OK)
670 return result; 599 return result;
671 600
672 sap_entries=atoi(recv_buffer); 601 sap_entries = atoi(recv_buffer);
673 602
674 if (check_critical_value && sap_entries >= critical_value) 603 if (check_critical_value && sap_entries >= critical_value)
675 result=STATE_CRITICAL; 604 result = STATE_CRITICAL;
676 else if (check_warning_value && sap_entries >= warning_value) 605 else if (check_warning_value && sap_entries >= warning_value)
677 result=STATE_WARNING; 606 result = STATE_WARNING;
678 607
679 if (sap_number==-1) 608 if (sap_number == -1)
680 xasprintf (&output_message,_("%lu entries in SAP table"),sap_entries); 609 xasprintf(&output_message, _("%lu entries in SAP table"), sap_entries);
681 else 610 else
682 xasprintf (&output_message,_("%lu entries in SAP table for SAP type %d"),sap_entries,sap_number); 611 xasprintf(&output_message, _("%lu entries in SAP table for SAP type %d"), sap_entries, sap_number);
683 612
684 /* check KB purgeable space on volume */ 613 /* check KB purgeable space on volume */
685 } else if (vars_to_check==VKP) { 614 } else if (vars_to_check == VKP) {
686 615
687 close(sd); 616 close(sd);
688 my_tcp_connect (server_address, server_port, &sd); 617 my_tcp_connect(server_address, server_port, &sd);
689 618
690 xasprintf (&send_buffer,"VKP%s\r\n",volume_name); 619 xasprintf(&send_buffer, "VKP%s\r\n", volume_name);
691 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 620 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
692 if (result!=STATE_OK) 621 if (result != STATE_OK)
693 return result; 622 return result;
694 623
695 if (!strcmp(recv_buffer,"-1\n")) { 624 if (!strcmp(recv_buffer, "-1\n")) {
696 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 625 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
697 result=STATE_CRITICAL; 626 result = STATE_CRITICAL;
698 } else { 627 } else {
699 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 628 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
700 if (check_critical_value && purgeable_disk_space >= critical_value) 629 if (check_critical_value && purgeable_disk_space >= critical_value)
701 result=STATE_CRITICAL; 630 result = STATE_CRITICAL;
702 else if (check_warning_value && purgeable_disk_space >= warning_value) 631 else if (check_warning_value && purgeable_disk_space >= warning_value)
703 result=STATE_WARNING; 632 result = STATE_WARNING;
704 xasprintf (&output_message,_("%s%lu KB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), 633 xasprintf(&output_message, _("%s%lu KB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
705 (result==STATE_OK)?"":_("Only "), 634 purgeable_disk_space, volume_name, volume_name, purgeable_disk_space, warning_value, critical_value);
706 purgeable_disk_space,
707 volume_name,
708 volume_name,
709 purgeable_disk_space,
710 warning_value,
711 critical_value);
712 } 635 }
713 /* check MB purgeable space on volume */ 636 /* check MB purgeable space on volume */
714 } else if (vars_to_check==VMP) { 637 } else if (vars_to_check == VMP) {
715 638
716 xasprintf (&send_buffer,"VMP%s\r\n",volume_name); 639 xasprintf(&send_buffer, "VMP%s\r\n", volume_name);
717 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 640 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
718 if (result!=STATE_OK) 641 if (result != STATE_OK)
719 return result; 642 return result;
720 643
721 if (!strcmp(recv_buffer,"-1\n")) { 644 if (!strcmp(recv_buffer, "-1\n")) {
722 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 645 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
723 result=STATE_CRITICAL; 646 result = STATE_CRITICAL;
724 } else { 647 } else {
725 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 648 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
726 if (check_critical_value && purgeable_disk_space >= critical_value) 649 if (check_critical_value && purgeable_disk_space >= critical_value)
727 result=STATE_CRITICAL; 650 result = STATE_CRITICAL;
728 else if (check_warning_value && purgeable_disk_space >= warning_value) 651 else if (check_warning_value && purgeable_disk_space >= warning_value)
729 result=STATE_WARNING; 652 result = STATE_WARNING;
730 xasprintf (&output_message,_("%s%lu MB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), 653 xasprintf(&output_message, _("%s%lu MB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
731 (result==STATE_OK)?"":_("Only "), 654 purgeable_disk_space, volume_name, volume_name, purgeable_disk_space, warning_value, critical_value);
732 purgeable_disk_space,
733 volume_name,
734 volume_name,
735 purgeable_disk_space,
736 warning_value,
737 critical_value);
738 } 655 }
739 656
740 /* check % purgeable space on volume */ 657 /* check % purgeable space on volume */
741 } else if (vars_to_check==VPP) { 658 } else if (vars_to_check == VPP) {
742 659
743 close(sd); 660 close(sd);
744 my_tcp_connect (server_address, server_port, &sd); 661 my_tcp_connect(server_address, server_port, &sd);
745 662
746 xasprintf (&send_buffer,"VKP%s\r\n",volume_name); 663 xasprintf(&send_buffer, "VKP%s\r\n", volume_name);
747 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 664 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
748 if (result!=STATE_OK) 665 if (result != STATE_OK)
749 return result; 666 return result;
750 667
751 if (!strcmp(recv_buffer,"-1\n")) { 668 if (!strcmp(recv_buffer, "-1\n")) {
752 669
753 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 670 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
754 result=STATE_CRITICAL; 671 result = STATE_CRITICAL;
755 672
756 } else { 673 } else {
757 674
758 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 675 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
759 676
760 close(sd); 677 close(sd);
761 my_tcp_connect (server_address, server_port, &sd); 678 my_tcp_connect(server_address, server_port, &sd);
762 679
763 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 680 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
764 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 681 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
765 if (result!=STATE_OK) 682 if (result != STATE_OK)
766 return result; 683 return result;
767 total_disk_space=strtoul(recv_buffer,NULL,10); 684 total_disk_space = strtoul(recv_buffer, NULL, 10);
768 685
769 percent_purgeable_space=(unsigned long)(((double)purgeable_disk_space/(double)total_disk_space)*100.0); 686 percent_purgeable_space = (unsigned long)(((double)purgeable_disk_space / (double)total_disk_space) * 100.0);
770 687
771 if (check_critical_value && percent_purgeable_space >= critical_value) 688 if (check_critical_value && percent_purgeable_space >= critical_value)
772 result=STATE_CRITICAL; 689 result = STATE_CRITICAL;
773 else if (check_warning_value && percent_purgeable_space >= warning_value) 690 else if (check_warning_value && percent_purgeable_space >= warning_value)
774 result=STATE_WARNING; 691 result = STATE_WARNING;
775 purgeable_disk_space/=1024; 692 purgeable_disk_space /= 1024;
776 xasprintf (&output_message,_("%lu MB (%lu%%) purgeable on volume %s|Purgeable%s=%lu;%lu;%lu;0;100"), 693 xasprintf(&output_message, _("%lu MB (%lu%%) purgeable on volume %s|Purgeable%s=%lu;%lu;%lu;0;100"), purgeable_disk_space,
777 purgeable_disk_space, 694 percent_purgeable_space, volume_name, volume_name, percent_purgeable_space, warning_value, critical_value);
778 percent_purgeable_space,
779 volume_name,
780 volume_name,
781 percent_purgeable_space,
782 warning_value,
783 critical_value
784 );
785 } 695 }
786 696
787 /* check KB not yet purgeable space on volume */ 697 /* check KB not yet purgeable space on volume */
788 } else if (vars_to_check==VKNP) { 698 } else if (vars_to_check == VKNP) {
789 699
790 close(sd); 700 close(sd);
791 my_tcp_connect (server_address, server_port, &sd); 701 my_tcp_connect(server_address, server_port, &sd);
792 702
793 xasprintf (&send_buffer,"VKNP%s\r\n",volume_name); 703 xasprintf(&send_buffer, "VKNP%s\r\n", volume_name);
794 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 704 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
795 if (result!=STATE_OK) 705 if (result != STATE_OK)
796 return result; 706 return result;
797 707
798 if (!strcmp(recv_buffer,"-1\n")) { 708 if (!strcmp(recv_buffer, "-1\n")) {
799 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 709 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
800 result=STATE_CRITICAL; 710 result = STATE_CRITICAL;
801 } else { 711 } else {
802 non_purgeable_disk_space=strtoul(recv_buffer,NULL,10); 712 non_purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
803 if (check_critical_value && non_purgeable_disk_space >= critical_value) 713 if (check_critical_value && non_purgeable_disk_space >= critical_value)
804 result=STATE_CRITICAL; 714 result = STATE_CRITICAL;
805 else if (check_warning_value && non_purgeable_disk_space >= warning_value) 715 else if (check_warning_value && non_purgeable_disk_space >= warning_value)
806 result=STATE_WARNING; 716 result = STATE_WARNING;
807 xasprintf (&output_message,_("%s%lu KB not yet purgeable on volume %s"),(result==STATE_OK)?"":_("Only "),non_purgeable_disk_space,volume_name); 717 xasprintf(&output_message, _("%s%lu KB not yet purgeable on volume %s"), (result == STATE_OK) ? "" : _("Only "),
718 non_purgeable_disk_space, volume_name);
808 } 719 }
809 720
810 /* check % not yet purgeable space on volume */ 721 /* check % not yet purgeable space on volume */
811 } else if (vars_to_check==VPNP) { 722 } else if (vars_to_check == VPNP) {
812 723
813 close(sd); 724 close(sd);
814 my_tcp_connect (server_address, server_port, &sd); 725 my_tcp_connect(server_address, server_port, &sd);
815 726
816 xasprintf (&send_buffer,"VKNP%s\r\n",volume_name); 727 xasprintf(&send_buffer, "VKNP%s\r\n", volume_name);
817 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 728 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
818 if (result!=STATE_OK) 729 if (result != STATE_OK)
819 return result; 730 return result;
820 731
821 if (!strcmp(recv_buffer,"-1\n")) { 732 if (!strcmp(recv_buffer, "-1\n")) {
822 733
823 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 734 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
824 result=STATE_CRITICAL; 735 result = STATE_CRITICAL;
825 736
826 } else { 737 } else {
827 738
828 non_purgeable_disk_space=strtoul(recv_buffer,NULL,10); 739 non_purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
829 740
830 close(sd); 741 close(sd);
831 my_tcp_connect (server_address, server_port, &sd); 742 my_tcp_connect(server_address, server_port, &sd);
832 743
833 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 744 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
834 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 745 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
835 if (result!=STATE_OK) 746 if (result != STATE_OK)
836 return result; 747 return result;
837 total_disk_space=strtoul(recv_buffer,NULL,10); 748 total_disk_space = strtoul(recv_buffer, NULL, 10);
838 749
839 percent_non_purgeable_space=(unsigned long)(((double)non_purgeable_disk_space/(double)total_disk_space)*100.0); 750 percent_non_purgeable_space = (unsigned long)(((double)non_purgeable_disk_space / (double)total_disk_space) * 100.0);
840 751
841 if (check_critical_value && percent_non_purgeable_space >= critical_value) 752 if (check_critical_value && percent_non_purgeable_space >= critical_value)
842 result=STATE_CRITICAL; 753 result = STATE_CRITICAL;
843 else if (check_warning_value && percent_non_purgeable_space >= warning_value) 754 else if (check_warning_value && percent_non_purgeable_space >= warning_value)
844 result=STATE_WARNING; 755 result = STATE_WARNING;
845 purgeable_disk_space/=1024; 756 purgeable_disk_space /= 1024;
846 xasprintf (&output_message,_("%lu MB (%lu%%) not yet purgeable on volume %s"),non_purgeable_disk_space,percent_non_purgeable_space,volume_name); 757 xasprintf(&output_message, _("%lu MB (%lu%%) not yet purgeable on volume %s"), non_purgeable_disk_space,
758 percent_non_purgeable_space, volume_name);
847 } 759 }
848 760
849 /* check # of open files */ 761 /* check # of open files */
850 } else if (vars_to_check==OFILES) { 762 } else if (vars_to_check == OFILES) {
851 763
852 close(sd); 764 close(sd);
853 my_tcp_connect (server_address, server_port, &sd); 765 my_tcp_connect(server_address, server_port, &sd);
854 766
855 xasprintf (&send_buffer,"S18\r\n"); 767 xasprintf(&send_buffer, "S18\r\n");
856 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 768 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
857 if (result!=STATE_OK) 769 if (result != STATE_OK)
858 return result; 770 return result;
859 771
860 open_files=atoi(recv_buffer); 772 open_files = atoi(recv_buffer);
861 773
862 if (check_critical_value && open_files >= critical_value) 774 if (check_critical_value && open_files >= critical_value)
863 result=STATE_CRITICAL; 775 result = STATE_CRITICAL;
864 else if (check_warning_value && open_files >= warning_value) 776 else if (check_warning_value && open_files >= warning_value)
865 result=STATE_WARNING; 777 result = STATE_WARNING;
866
867 xasprintf (&output_message,_("%lu open files|Openfiles=%lu;%lu;%lu;0,0"),
868 open_files,
869 open_files,
870 warning_value,
871 critical_value);
872 778
779 xasprintf(&output_message, _("%lu open files|Openfiles=%lu;%lu;%lu;0,0"), open_files, open_files, warning_value, critical_value);
873 780
874 /* check # of abended threads (Netware > 5.x only) */ 781 /* check # of abended threads (Netware > 5.x only) */
875 } else if (vars_to_check==ABENDS) { 782 } else if (vars_to_check == ABENDS) {
876 783
877 close(sd); 784 close(sd);
878 my_tcp_connect (server_address, server_port, &sd); 785 my_tcp_connect(server_address, server_port, &sd);
879 786
880 xasprintf (&send_buffer,"S17\r\n"); 787 xasprintf(&send_buffer, "S17\r\n");
881 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 788 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
882 if (result!=STATE_OK) 789 if (result != STATE_OK)
883 return result; 790 return result;
884 791
885 abended_threads=atoi(recv_buffer); 792 abended_threads = atoi(recv_buffer);
886 793
887 if (check_critical_value && abended_threads >= critical_value) 794 if (check_critical_value && abended_threads >= critical_value)
888 result=STATE_CRITICAL; 795 result = STATE_CRITICAL;
889 else if (check_warning_value && abended_threads >= warning_value) 796 else if (check_warning_value && abended_threads >= warning_value)
890 result=STATE_WARNING; 797 result = STATE_WARNING;
891 798
892 xasprintf (&output_message,_("%lu abended threads|Abends=%lu;%lu;%lu;;"), 799 xasprintf(&output_message, _("%lu abended threads|Abends=%lu;%lu;%lu;;"), abended_threads, abended_threads, warning_value,
893 abended_threads, 800 critical_value);
894 abended_threads,
895 warning_value,
896 critical_value);
897 801
898 /* check # of current service processes (Netware 5.x only) */ 802 /* check # of current service processes (Netware 5.x only) */
899 } else if (vars_to_check==CSPROCS) { 803 } else if (vars_to_check == CSPROCS) {
900 804
901 close(sd); 805 close(sd);
902 my_tcp_connect (server_address, server_port, &sd); 806 my_tcp_connect(server_address, server_port, &sd);
903 807
904 xasprintf (&send_buffer,"S20\r\n"); 808 xasprintf(&send_buffer, "S20\r\n");
905 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 809 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
906 if (result!=STATE_OK) 810 if (result != STATE_OK)
907 return result; 811 return result;
908 812
909 max_service_processes=atoi(recv_buffer); 813 max_service_processes = atoi(recv_buffer);
910 814
911 close(sd); 815 close(sd);
912 my_tcp_connect (server_address, server_port, &sd); 816 my_tcp_connect(server_address, server_port, &sd);
913 817
914 xasprintf (&send_buffer,"S21\r\n"); 818 xasprintf(&send_buffer, "S21\r\n");
915 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 819 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
916 if (result!=STATE_OK) 820 if (result != STATE_OK)
917 return result; 821 return result;
918 822
919 current_service_processes=atoi(recv_buffer); 823 current_service_processes = atoi(recv_buffer);
920 824
921 if (check_critical_value && current_service_processes >= critical_value) 825 if (check_critical_value && current_service_processes >= critical_value)
922 result=STATE_CRITICAL; 826 result = STATE_CRITICAL;
923 else if (check_warning_value && current_service_processes >= warning_value) 827 else if (check_warning_value && current_service_processes >= warning_value)
924 result=STATE_WARNING; 828 result = STATE_WARNING;
925 829
926 xasprintf (&output_message, 830 xasprintf(&output_message, _("%lu current service processes (%lu max)|Processes=%lu;%lu;%lu;0;%lu"), current_service_processes,
927 _("%lu current service processes (%lu max)|Processes=%lu;%lu;%lu;0;%lu"), 831 max_service_processes, current_service_processes, warning_value, critical_value, max_service_processes);
928 current_service_processes,
929 max_service_processes,
930 current_service_processes,
931 warning_value,
932 critical_value,
933 max_service_processes);
934 832
935 /* check # Timesync Status */ 833 /* check # Timesync Status */
936 } else if (vars_to_check==TSYNC) { 834 } else if (vars_to_check == TSYNC) {
937 835
938 close(sd); 836 close(sd);
939 my_tcp_connect (server_address, server_port, &sd); 837 my_tcp_connect(server_address, server_port, &sd);
940 838
941 xasprintf (&send_buffer,"S22\r\n"); 839 xasprintf(&send_buffer, "S22\r\n");
942 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 840 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
943 if (result!=STATE_OK) 841 if (result != STATE_OK)
944 return result; 842 return result;
945 843
946 time_sync_status=atoi(recv_buffer); 844 time_sync_status = atoi(recv_buffer);
947 845
948 if (time_sync_status==0) { 846 if (time_sync_status == 0) {
949 result=STATE_CRITICAL; 847 result = STATE_CRITICAL;
950 xasprintf (&output_message,_("CRITICAL - Time not in sync with network!")); 848 xasprintf(&output_message, _("CRITICAL - Time not in sync with network!"));
951 } 849 } else {
952 else { 850 xasprintf(&output_message, _("OK - Time in sync with network!"));
953 xasprintf (&output_message,_("OK - Time in sync with network!"));
954 } 851 }
955 852
956
957
958
959
960 /* check LRU sitting time in secondss */ 853 /* check LRU sitting time in secondss */
961 } else if (vars_to_check==LRUS) { 854 } else if (vars_to_check == LRUS) {
962 855
963 close(sd); 856 close(sd);
964 my_tcp_connect (server_address, server_port, &sd); 857 my_tcp_connect(server_address, server_port, &sd);
965 858
966 send_buffer = strdup ("S4\r\n"); 859 send_buffer = strdup("S4\r\n");
967 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 860 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
968 if (result!=STATE_OK) 861 if (result != STATE_OK)
969 return result; 862 return result;
970 lru_time=strtoul(recv_buffer,NULL,10); 863 lru_time = strtoul(recv_buffer, NULL, 10);
971 864
972 if (check_critical_value && lru_time <= critical_value) 865 if (check_critical_value && lru_time <= critical_value)
973 result=STATE_CRITICAL; 866 result = STATE_CRITICAL;
974 else if (check_warning_value && lru_time <= warning_value) 867 else if (check_warning_value && lru_time <= warning_value)
975 result=STATE_WARNING; 868 result = STATE_WARNING;
976 xasprintf (&output_message,_("LRU sitting time = %lu seconds"),lru_time); 869 xasprintf(&output_message, _("LRU sitting time = %lu seconds"), lru_time);
977
978 870
979 /* check % dirty cacheobuffers as a percentage of the total*/ 871 /* check % dirty cacheobuffers as a percentage of the total*/
980 } else if (vars_to_check==DCB) { 872 } else if (vars_to_check == DCB) {
981 873
982 close(sd); 874 close(sd);
983 my_tcp_connect (server_address, server_port, &sd); 875 my_tcp_connect(server_address, server_port, &sd);
984 876
985 send_buffer = strdup ("S6\r\n"); 877 send_buffer = strdup("S6\r\n");
986 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 878 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
987 if (result!=STATE_OK) 879 if (result != STATE_OK)
988 return result; 880 return result;
989 dirty_cache_buffers=atoi(recv_buffer); 881 dirty_cache_buffers = atoi(recv_buffer);
990 882
991 if (check_critical_value && dirty_cache_buffers <= critical_value) 883 if (check_critical_value && dirty_cache_buffers <= critical_value)
992 result=STATE_CRITICAL; 884 result = STATE_CRITICAL;
993 else if (check_warning_value && dirty_cache_buffers <= warning_value) 885 else if (check_warning_value && dirty_cache_buffers <= warning_value)
994 result=STATE_WARNING; 886 result = STATE_WARNING;
995 xasprintf (&output_message,_("Dirty cache buffers = %lu%% of the total|DCB=%lu;%lu;%lu;0;100"), 887 xasprintf(&output_message, _("Dirty cache buffers = %lu%% of the total|DCB=%lu;%lu;%lu;0;100"), dirty_cache_buffers,
996 dirty_cache_buffers, 888 dirty_cache_buffers, warning_value, critical_value);
997 dirty_cache_buffers,
998 warning_value,
999 critical_value);
1000 889
1001 /* check % total cache buffers as a percentage of the original*/ 890 /* check % total cache buffers as a percentage of the original*/
1002 } else if (vars_to_check==TCB) { 891 } else if (vars_to_check == TCB) {
1003 892
1004 close(sd); 893 close(sd);
1005 my_tcp_connect (server_address, server_port, &sd); 894 my_tcp_connect(server_address, server_port, &sd);
1006 895
1007 send_buffer = strdup ("S7\r\n"); 896 send_buffer = strdup("S7\r\n");
1008 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 897 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1009 if (result!=STATE_OK) 898 if (result != STATE_OK)
1010 return result; 899 return result;
1011 total_cache_buffers=atoi(recv_buffer); 900 total_cache_buffers = atoi(recv_buffer);
1012 901
1013 if (check_critical_value && total_cache_buffers <= critical_value) 902 if (check_critical_value && total_cache_buffers <= critical_value)
1014 result=STATE_CRITICAL; 903 result = STATE_CRITICAL;
1015 else if (check_warning_value && total_cache_buffers <= warning_value) 904 else if (check_warning_value && total_cache_buffers <= warning_value)
1016 result=STATE_WARNING; 905 result = STATE_WARNING;
1017 xasprintf (&output_message,_("Total cache buffers = %lu%% of the original|TCB=%lu;%lu;%lu;0;100"), 906 xasprintf(&output_message, _("Total cache buffers = %lu%% of the original|TCB=%lu;%lu;%lu;0;100"), total_cache_buffers,
1018 total_cache_buffers, 907 total_cache_buffers, warning_value, critical_value);
1019 total_cache_buffers,
1020 warning_value,
1021 critical_value);
1022 908
1023 } else if (vars_to_check==DSVER) { 909 } else if (vars_to_check == DSVER) {
1024 910
1025 close(sd); 911 close(sd);
1026 my_tcp_connect (server_address, server_port, &sd); 912 my_tcp_connect(server_address, server_port, &sd);
1027 913
1028 xasprintf (&send_buffer,"S13\r\n"); 914 xasprintf(&send_buffer, "S13\r\n");
1029 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 915 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1030 if (result!=STATE_OK) 916 if (result != STATE_OK)
1031 return result; 917 return result;
1032 918
1033 recv_buffer[strlen(recv_buffer)-1]=0; 919 recv_buffer[strlen(recv_buffer) - 1] = 0;
1034 920
1035 xasprintf (&output_message,_("NDS Version %s"),recv_buffer); 921 xasprintf(&output_message, _("NDS Version %s"), recv_buffer);
1036 922
1037 } else if (vars_to_check==UPTIME) { 923 } else if (vars_to_check == UPTIME) {
1038 924
1039 close(sd); 925 close(sd);
1040 my_tcp_connect (server_address, server_port, &sd); 926 my_tcp_connect(server_address, server_port, &sd);
1041
1042 xasprintf (&send_buffer,"UPTIME\r\n");
1043 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer));
1044 if (result!=STATE_OK)
1045 return result;
1046 927
928 xasprintf(&send_buffer, "UPTIME\r\n");
929 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
930 if (result != STATE_OK)
931 return result;
1047 932
1048 recv_buffer[sizeof(recv_buffer)-1]=0; 933 recv_buffer[sizeof(recv_buffer) - 1] = 0;
1049 recv_buffer[strlen(recv_buffer)-1]=0; 934 recv_buffer[strlen(recv_buffer) - 1] = 0;
1050 935
1051 xasprintf (&output_message,_("Up %s"),recv_buffer); 936 xasprintf(&output_message, _("Up %s"), recv_buffer);
1052 937
1053 } else if (vars_to_check==NLM) { 938 } else if (vars_to_check == NLM) {
1054 939
1055 close(sd); 940 close(sd);
1056 my_tcp_connect (server_address, server_port, &sd); 941 my_tcp_connect(server_address, server_port, &sd);
1057 942
1058 xasprintf (&send_buffer,"S24:%s\r\n",nlm_name); 943 xasprintf(&send_buffer, "S24:%s\r\n", nlm_name);
1059 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 944 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1060 if (result!=STATE_OK) 945 if (result != STATE_OK)
1061 return result; 946 return result;
1062 947
1063 recv_buffer[strlen(recv_buffer)-1]=0; 948 recv_buffer[strlen(recv_buffer) - 1] = 0;
1064 if (strcmp(recv_buffer,"-1")) { 949 if (strcmp(recv_buffer, "-1")) {
1065 xasprintf (&output_message,_("Module %s version %s is loaded"),nlm_name,recv_buffer); 950 xasprintf(&output_message, _("Module %s version %s is loaded"), nlm_name, recv_buffer);
1066 } else { 951 } else {
1067 result=STATE_CRITICAL; 952 result = STATE_CRITICAL;
1068 xasprintf (&output_message,_("Module %s is not loaded"),nlm_name); 953 xasprintf(&output_message, _("Module %s is not loaded"), nlm_name);
1069 954 }
1070 } 955 } else if (vars_to_check == NRMP) {
1071 } else if (vars_to_check==NRMP) {
1072 956
1073 xasprintf (&send_buffer,"NRMP:%s\r\n",nrmp_name); 957 xasprintf(&send_buffer, "NRMP:%s\r\n", nrmp_name);
1074 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 958 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1075 if (result!=STATE_OK) 959 if (result != STATE_OK)
1076 return result; 960 return result;
1077 961
1078 if (!strcmp(recv_buffer,"-1\n")) { 962 if (!strcmp(recv_buffer, "-1\n")) {
1079 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrmp_name); 963 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrmp_name);
1080 result=STATE_CRITICAL; 964 result = STATE_CRITICAL;
1081 } else { 965 } else {
1082 nrmp_value=strtoul(recv_buffer,NULL,10); 966 nrmp_value = strtoul(recv_buffer, NULL, 10);
1083 if (check_critical_value && nrmp_value <= critical_value) 967 if (check_critical_value && nrmp_value <= critical_value)
1084 result=STATE_CRITICAL; 968 result = STATE_CRITICAL;
1085 else if (check_warning_value && nrmp_value <= warning_value) 969 else if (check_warning_value && nrmp_value <= warning_value)
1086 result=STATE_WARNING; 970 result = STATE_WARNING;
1087 xasprintf (&output_message, 971 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrmp_name, nrmp_value, nrmp_name, nrmp_value, warning_value,
1088 _("%s is %lu|%s=%lu;%lu;%lu;;"), 972 critical_value);
1089 nrmp_name,
1090 nrmp_value,
1091 nrmp_name,
1092 nrmp_value,
1093 warning_value,
1094 critical_value);
1095 } 973 }
1096 974
1097 } else if (vars_to_check==NRMM) { 975 } else if (vars_to_check == NRMM) {
1098 976
1099 xasprintf (&send_buffer,"NRMM:%s\r\n",nrmm_name); 977 xasprintf(&send_buffer, "NRMM:%s\r\n", nrmm_name);
1100 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 978 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1101 if (result!=STATE_OK) 979 if (result != STATE_OK)
1102 return result; 980 return result;
1103 981
1104 if (!strcmp(recv_buffer,"-1\n")) { 982 if (!strcmp(recv_buffer, "-1\n")) {
1105 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrmm_name); 983 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrmm_name);
1106 result=STATE_CRITICAL; 984 result = STATE_CRITICAL;
1107 } else { 985 } else {
1108 nrmm_value=strtoul(recv_buffer,NULL,10); 986 nrmm_value = strtoul(recv_buffer, NULL, 10);
1109 if (check_critical_value && nrmm_value <= critical_value) 987 if (check_critical_value && nrmm_value <= critical_value)
1110 result=STATE_CRITICAL; 988 result = STATE_CRITICAL;
1111 else if (check_warning_value && nrmm_value <= warning_value) 989 else if (check_warning_value && nrmm_value <= warning_value)
1112 result=STATE_WARNING; 990 result = STATE_WARNING;
1113 xasprintf (&output_message, 991 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrmm_name, nrmm_value, nrmm_name, nrmm_value, warning_value,
1114 _("%s is %lu|%s=%lu;%lu;%lu;;"), 992 critical_value);
1115 nrmm_name,
1116 nrmm_value,
1117 nrmm_name,
1118 nrmm_value,
1119 warning_value,
1120 critical_value);
1121 } 993 }
1122 994
1123 } else if (vars_to_check==NRMS) { 995 } else if (vars_to_check == NRMS) {
1124 996
1125 xasprintf (&send_buffer,"NRMS:%s\r\n",nrms_name); 997 xasprintf(&send_buffer, "NRMS:%s\r\n", nrms_name);
1126 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 998 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1127 if (result!=STATE_OK) 999 if (result != STATE_OK)
1128 return result; 1000 return result;
1129 1001
1130 if (!strcmp(recv_buffer,"-1\n")) { 1002 if (!strcmp(recv_buffer, "-1\n")) {
1131 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrms_name); 1003 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrms_name);
1132 result=STATE_CRITICAL; 1004 result = STATE_CRITICAL;
1133 } else { 1005 } else {
1134 nrms_value=strtoul(recv_buffer,NULL,10); 1006 nrms_value = strtoul(recv_buffer, NULL, 10);
1135 if (check_critical_value && nrms_value >= critical_value) 1007 if (check_critical_value && nrms_value >= critical_value)
1136 result=STATE_CRITICAL; 1008 result = STATE_CRITICAL;
1137 else if (check_warning_value && nrms_value >= warning_value) 1009 else if (check_warning_value && nrms_value >= warning_value)
1138 result=STATE_WARNING; 1010 result = STATE_WARNING;
1139 xasprintf (&output_message, 1011 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrms_name, nrms_value, nrms_name, nrms_value, warning_value,
1140 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1012 critical_value);
1141 nrms_name,
1142 nrms_value,
1143 nrms_name,
1144 nrms_value,
1145 warning_value,
1146 critical_value);
1147 } 1013 }
1148 1014
1149 } else if (vars_to_check==NSS1) { 1015 } else if (vars_to_check == NSS1) {
1150 1016
1151 xasprintf (&send_buffer,"NSS1:%s\r\n",nss1_name); 1017 xasprintf(&send_buffer, "NSS1:%s\r\n", nss1_name);
1152 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1018 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1153 if (result!=STATE_OK) 1019 if (result != STATE_OK)
1154 return result; 1020 return result;
1155 1021
1156 if (!strcmp(recv_buffer,"-1\n")) { 1022 if (!strcmp(recv_buffer, "-1\n")) {
1157 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss1_name); 1023 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss1_name);
1158 result=STATE_CRITICAL; 1024 result = STATE_CRITICAL;
1159 } else { 1025 } else {
1160 nss1_value=strtoul(recv_buffer,NULL,10); 1026 nss1_value = strtoul(recv_buffer, NULL, 10);
1161 if (check_critical_value && nss1_value >= critical_value) 1027 if (check_critical_value && nss1_value >= critical_value)
1162 result=STATE_CRITICAL; 1028 result = STATE_CRITICAL;
1163 else if (check_warning_value && nss1_value >= warning_value) 1029 else if (check_warning_value && nss1_value >= warning_value)
1164 result=STATE_WARNING; 1030 result = STATE_WARNING;
1165 xasprintf (&output_message, 1031 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss1_name, nss1_value, nss1_name, nss1_value, warning_value,
1166 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1032 critical_value);
1167 nss1_name,
1168 nss1_value,
1169 nss1_name,
1170 nss1_value,
1171 warning_value,
1172 critical_value);
1173 } 1033 }
1174 1034
1175 } else if (vars_to_check==NSS2) { 1035 } else if (vars_to_check == NSS2) {
1176 1036
1177 xasprintf (&send_buffer,"NSS2:%s\r\n",nss2_name); 1037 xasprintf(&send_buffer, "NSS2:%s\r\n", nss2_name);
1178 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1038 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1179 if (result!=STATE_OK) 1039 if (result != STATE_OK)
1180 return result; 1040 return result;
1181 1041
1182 if (!strcmp(recv_buffer,"-1\n")) { 1042 if (!strcmp(recv_buffer, "-1\n")) {
1183 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss2_name); 1043 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss2_name);
1184 result=STATE_CRITICAL; 1044 result = STATE_CRITICAL;
1185 } else { 1045 } else {
1186 nss2_value=strtoul(recv_buffer,NULL,10); 1046 nss2_value = strtoul(recv_buffer, NULL, 10);
1187 if (check_critical_value && nss2_value >= critical_value) 1047 if (check_critical_value && nss2_value >= critical_value)
1188 result=STATE_CRITICAL; 1048 result = STATE_CRITICAL;
1189 else if (check_warning_value && nss2_value >= warning_value) 1049 else if (check_warning_value && nss2_value >= warning_value)
1190 result=STATE_WARNING; 1050 result = STATE_WARNING;
1191 xasprintf (&output_message, 1051 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss2_name, nss2_value, nss2_name, nss2_value, warning_value,
1192 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1052 critical_value);
1193 nss2_name,
1194 nss2_value,
1195 nss2_name,
1196 nss2_value,
1197 warning_value,
1198 critical_value);
1199 } 1053 }
1200 1054
1201 } else if (vars_to_check==NSS3) { 1055 } else if (vars_to_check == NSS3) {
1202 1056
1203 xasprintf (&send_buffer,"NSS3:%s\r\n",nss3_name); 1057 xasprintf(&send_buffer, "NSS3:%s\r\n", nss3_name);
1204 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1058 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1205 if (result!=STATE_OK) 1059 if (result != STATE_OK)
1206 return result; 1060 return result;
1207 1061
1208 if (!strcmp(recv_buffer,"-1\n")) { 1062 if (!strcmp(recv_buffer, "-1\n")) {
1209 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss3_name); 1063 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss3_name);
1210 result=STATE_CRITICAL; 1064 result = STATE_CRITICAL;
1211 } else { 1065 } else {
1212 nss3_value=strtoul(recv_buffer,NULL,10); 1066 nss3_value = strtoul(recv_buffer, NULL, 10);
1213 if (check_critical_value && nss3_value >= critical_value) 1067 if (check_critical_value && nss3_value >= critical_value)
1214 result=STATE_CRITICAL; 1068 result = STATE_CRITICAL;
1215 else if (check_warning_value && nss3_value >= warning_value) 1069 else if (check_warning_value && nss3_value >= warning_value)
1216 result=STATE_WARNING; 1070 result = STATE_WARNING;
1217 xasprintf (&output_message, 1071 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss3_name, nss3_value, nss3_name, nss3_value, warning_value,
1218 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1072 critical_value);
1219 nss3_name,
1220 nss3_value,
1221 nss3_name,
1222 nss3_value,
1223 warning_value,
1224 critical_value);
1225 } 1073 }
1226 1074
1227 } else if (vars_to_check==NSS4) { 1075 } else if (vars_to_check == NSS4) {
1228 1076
1229 xasprintf (&send_buffer,"NSS4:%s\r\n",nss4_name); 1077 xasprintf(&send_buffer, "NSS4:%s\r\n", nss4_name);
1230 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1078 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1231 if (result!=STATE_OK) 1079 if (result != STATE_OK)
1232 return result; 1080 return result;
1233 1081
1234 if (!strcmp(recv_buffer,"-1\n")) { 1082 if (!strcmp(recv_buffer, "-1\n")) {
1235 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss4_name); 1083 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss4_name);
1236 result=STATE_CRITICAL; 1084 result = STATE_CRITICAL;
1237 } else { 1085 } else {
1238 nss4_value=strtoul(recv_buffer,NULL,10); 1086 nss4_value = strtoul(recv_buffer, NULL, 10);
1239 if (check_critical_value && nss4_value >= critical_value) 1087 if (check_critical_value && nss4_value >= critical_value)
1240 result=STATE_CRITICAL; 1088 result = STATE_CRITICAL;
1241 else if (check_warning_value && nss4_value >= warning_value) 1089 else if (check_warning_value && nss4_value >= warning_value)
1242 result=STATE_WARNING; 1090 result = STATE_WARNING;
1243 xasprintf (&output_message, 1091 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss4_name, nss4_value, nss4_name, nss4_value, warning_value,
1244 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1092 critical_value);
1245 nss4_name,
1246 nss4_value,
1247 nss4_name,
1248 nss4_value,
1249 warning_value,
1250 critical_value);
1251 } 1093 }
1252 1094
1253 } else if (vars_to_check==NSS5) { 1095 } else if (vars_to_check == NSS5) {
1254 1096
1255 xasprintf (&send_buffer,"NSS5:%s\r\n",nss5_name); 1097 xasprintf(&send_buffer, "NSS5:%s\r\n", nss5_name);
1256 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1098 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1257 if (result!=STATE_OK) 1099 if (result != STATE_OK)
1258 return result; 1100 return result;
1259 1101
1260 if (!strcmp(recv_buffer,"-1\n")) { 1102 if (!strcmp(recv_buffer, "-1\n")) {
1261 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss5_name); 1103 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss5_name);
1262 result=STATE_CRITICAL; 1104 result = STATE_CRITICAL;
1263 } else { 1105 } else {
1264 nss5_value=strtoul(recv_buffer,NULL,10); 1106 nss5_value = strtoul(recv_buffer, NULL, 10);
1265 if (check_critical_value && nss5_value >= critical_value) 1107 if (check_critical_value && nss5_value >= critical_value)
1266 result=STATE_CRITICAL; 1108 result = STATE_CRITICAL;
1267 else if (check_warning_value && nss5_value >= warning_value) 1109 else if (check_warning_value && nss5_value >= warning_value)
1268 result=STATE_WARNING; 1110 result = STATE_WARNING;
1269 xasprintf (&output_message, 1111 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss5_name, nss5_value, nss5_name, nss5_value, warning_value,
1270 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1112 critical_value);
1271 nss5_name,
1272 nss5_value,
1273 nss5_name,
1274 nss5_value,
1275 warning_value,
1276 critical_value);
1277 } 1113 }
1278 1114
1279 } else if (vars_to_check==NSS6) { 1115 } else if (vars_to_check == NSS6) {
1280 1116
1281 xasprintf (&send_buffer,"NSS6:%s\r\n",nss6_name); 1117 xasprintf(&send_buffer, "NSS6:%s\r\n", nss6_name);
1282 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1118 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1283 if (result!=STATE_OK) 1119 if (result != STATE_OK)
1284 return result; 1120 return result;
1285 1121
1286 if (!strcmp(recv_buffer,"-1\n")) { 1122 if (!strcmp(recv_buffer, "-1\n")) {
1287 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss6_name); 1123 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss6_name);
1288 result=STATE_CRITICAL; 1124 result = STATE_CRITICAL;
1289 } else { 1125 } else {
1290 nss6_value=strtoul(recv_buffer,NULL,10); 1126 nss6_value = strtoul(recv_buffer, NULL, 10);
1291 if (check_critical_value && nss6_value >= critical_value) 1127 if (check_critical_value && nss6_value >= critical_value)
1292 result=STATE_CRITICAL; 1128 result = STATE_CRITICAL;
1293 else if (check_warning_value && nss6_value >= warning_value) 1129 else if (check_warning_value && nss6_value >= warning_value)
1294 result=STATE_WARNING; 1130 result = STATE_WARNING;
1295 xasprintf (&output_message, 1131 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss6_name, nss6_value, nss6_name, nss6_value, warning_value,
1296 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1132 critical_value);
1297 nss6_name,
1298 nss6_value,
1299 nss6_name,
1300 nss6_value,
1301 warning_value,
1302 critical_value);
1303 } 1133 }
1304 1134
1305 } else if (vars_to_check==NSS7) { 1135 } else if (vars_to_check == NSS7) {
1306 1136
1307 xasprintf (&send_buffer,"NSS7:%s\r\n",nss7_name); 1137 xasprintf(&send_buffer, "NSS7:%s\r\n", nss7_name);
1308 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1138 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1309 if (result!=STATE_OK) 1139 if (result != STATE_OK)
1310 return result; 1140 return result;
1311 1141
1312 if (!strcmp(recv_buffer,"-1\n")) { 1142 if (!strcmp(recv_buffer, "-1\n")) {
1313 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss7_name); 1143 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss7_name);
1314 result=STATE_CRITICAL; 1144 result = STATE_CRITICAL;
1315 } else { 1145 } else {
1316 nss7_value=strtoul(recv_buffer,NULL,10); 1146 nss7_value = strtoul(recv_buffer, NULL, 10);
1317 if (check_critical_value && nss7_value >= critical_value) 1147 if (check_critical_value && nss7_value >= critical_value)
1318 result=STATE_CRITICAL; 1148 result = STATE_CRITICAL;
1319 else if (check_warning_value && nss7_value >= warning_value) 1149 else if (check_warning_value && nss7_value >= warning_value)
1320 result=STATE_WARNING; 1150 result = STATE_WARNING;
1321 xasprintf (&output_message, 1151 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss7_name, nss7_value, nss7_name, nss7_value, warning_value,
1322 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1152 critical_value);
1323 nss7_name,
1324 nss7_value,
1325 nss7_name,
1326 nss7_value,
1327 warning_value,
1328 critical_value);
1329 } 1153 }
1330 1154
1155 } else {
1331 1156
1332} 1157 output_message = strdup(_("Nothing to check!\n"));
1333 else { 1158 result = STATE_UNKNOWN;
1334
1335 output_message = strdup (_("Nothing to check!\n"));
1336 result=STATE_UNKNOWN;
1337
1338 } 1159 }
1339 1160
1340 close (sd); 1161 close(sd);
1341 1162
1342 /* reset timeout */ 1163 /* reset timeout */
1343 alarm(0); 1164 alarm(0);
1344 1165
1345 printf("%s%s\n",netware_version,output_message); 1166 printf("%s%s\n", netware_version, output_message);
1346 1167
1347 return result; 1168 return result;
1348} 1169}
1349 1170
1350
1351
1352/* process command-line arguments */ 1171/* process command-line arguments */
1353int process_arguments(int argc, char **argv) { 1172int process_arguments(int argc, char **argv) {
1354 int c; 1173 int c;
1355 1174
1356 int option = 0; 1175 int option = 0;
1357 static struct option longopts[] = 1176 static struct option longopts[] = {{"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'},
1358 { 1177 {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'},
1359 {"port", required_argument,0,'p'}, 1178 {"variable", required_argument, 0, 'v'}, {"hostname", required_argument, 0, 'H'},
1360 {"timeout", required_argument,0,'t'}, 1179 {"osversion", no_argument, 0, 'o'}, {"version", no_argument, 0, 'V'},
1361 {"critical", required_argument,0,'c'}, 1180 {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
1362 {"warning", required_argument,0,'w'},
1363 {"variable", required_argument,0,'v'},
1364 {"hostname", required_argument,0,'H'},
1365 {"osversion",no_argument, 0,'o'},
1366 {"version", no_argument, 0,'V'},
1367 {"help", no_argument, 0,'h'},
1368 {0,0,0,0}
1369 };
1370 1181
1371 /* no options were supplied */ 1182 /* no options were supplied */
1372 if (argc<2) return ERROR; 1183 if (argc < 2)
1184 return ERROR;
1373 1185
1374 /* backwards compatibility */ 1186 /* backwards compatibility */
1375 if (! is_option(argv[1])) { 1187 if (!is_option(argv[1])) {
1376 server_address=argv[1]; 1188 server_address = argv[1];
1377 argv[1]=argv[0]; 1189 argv[1] = argv[0];
1378 argv=&argv[1]; 1190 argv = &argv[1];
1379 argc--; 1191 argc--;
1380 } 1192 }
1381 1193
1382 for (c=1;c<argc;c++) { 1194 for (c = 1; c < argc; c++) {
1383 if (strcmp("-to",argv[c])==0) 1195 if (strcmp("-to", argv[c]) == 0)
1384 strcpy(argv[c],"-t"); 1196 strcpy(argv[c], "-t");
1385 else if (strcmp("-wv",argv[c])==0) 1197 else if (strcmp("-wv", argv[c]) == 0)
1386 strcpy(argv[c],"-w"); 1198 strcpy(argv[c], "-w");
1387 else if (strcmp("-cv",argv[c])==0) 1199 else if (strcmp("-cv", argv[c]) == 0)
1388 strcpy(argv[c],"-c"); 1200 strcpy(argv[c], "-c");
1389 } 1201 }
1390 1202
1391 while (1) { 1203 while (1) {
1392 c = getopt_long(argc,argv,"+hoVH:t:c:w:p:v:",longopts,&option); 1204 c = getopt_long(argc, argv, "+hoVH:t:c:w:p:v:", longopts, &option);
1393 1205
1394 if (c==-1||c==EOF||c==1) 1206 if (c == -1 || c == EOF || c == 1)
1395 break; 1207 break;
1396 1208
1397 switch (c) 1209 switch (c) {
1398 { 1210 case '?': /* print short usage statement if args not parsable */
1399 case '?': /* print short usage statement if args not parsable */ 1211 usage5();
1400 usage5 (); 1212 case 'h': /* help */
1401 case 'h': /* help */ 1213 print_help();
1402 print_help(); 1214 exit(STATE_UNKNOWN);
1403 exit(STATE_UNKNOWN); 1215 case 'V': /* version */
1404 case 'V': /* version */ 1216 print_revision(progname, NP_VERSION);
1405 print_revision(progname, NP_VERSION); 1217 exit(STATE_UNKNOWN);
1406 exit(STATE_UNKNOWN); 1218 case 'H': /* hostname */
1407 case 'H': /* hostname */ 1219 server_address = optarg;
1408 server_address=optarg; 1220 break;
1409 break; 1221 case 'o': /* display nos version */
1410 case 'o': /* display nos version */ 1222 check_netware_version = true;
1411 check_netware_version = true; 1223 break;
1412 break; 1224 case 'p': /* port */
1413 case 'p': /* port */ 1225 if (is_intnonneg(optarg))
1414 if (is_intnonneg(optarg)) 1226 server_port = atoi(optarg);
1415 server_port=atoi(optarg); 1227 else
1228 die(STATE_UNKNOWN, _("Server port an integer\n"));
1229 break;
1230 case 'v':
1231 if (strlen(optarg) < 3)
1232 return ERROR;
1233 if (!strcmp(optarg, "LOAD1"))
1234 vars_to_check = LOAD1;
1235 else if (!strcmp(optarg, "LOAD5"))
1236 vars_to_check = LOAD5;
1237 else if (!strcmp(optarg, "LOAD15"))
1238 vars_to_check = LOAD15;
1239 else if (!strcmp(optarg, "CONNS"))
1240 vars_to_check = CONNS;
1241 else if (!strcmp(optarg, "LTCH"))
1242 vars_to_check = LTCH;
1243 else if (!strcmp(optarg, "DCB"))
1244 vars_to_check = DCB;
1245 else if (!strcmp(optarg, "TCB"))
1246 vars_to_check = TCB;
1247 else if (!strcmp(optarg, "CBUFF"))
1248 vars_to_check = CBUFF;
1249 else if (!strcmp(optarg, "CDBUFF"))
1250 vars_to_check = CDBUFF;
1251 else if (!strcmp(optarg, "LRUM"))
1252 vars_to_check = LRUM;
1253 else if (!strcmp(optarg, "LRUS"))
1254 vars_to_check = LRUS;
1255 else if (strncmp(optarg, "VPF", 3) == 0) {
1256 vars_to_check = VPF;
1257 volume_name = strdup(optarg + 3);
1258 if (!strcmp(volume_name, ""))
1259 volume_name = strdup("SYS");
1260 } else if (strncmp(optarg, "VKF", 3) == 0) {
1261 vars_to_check = VKF;
1262 volume_name = strdup(optarg + 3);
1263 if (!strcmp(volume_name, ""))
1264 volume_name = strdup("SYS");
1265 } else if (strncmp(optarg, "VMF", 3) == 0) {
1266 vars_to_check = VMF;
1267 volume_name = strdup(optarg + 3);
1268 if (!strcmp(volume_name, ""))
1269 volume_name = strdup("SYS");
1270 } else if (!strcmp(optarg, "DSDB"))
1271 vars_to_check = DSDB;
1272 else if (!strcmp(optarg, "LOGINS"))
1273 vars_to_check = LOGINS;
1274 else if (!strcmp(optarg, "NRMH"))
1275 vars_to_check = NRMH;
1276 else if (!strcmp(optarg, "UPRB"))
1277 vars_to_check = UPRB;
1278 else if (!strcmp(optarg, "PUPRB"))
1279 vars_to_check = PUPRB;
1280 else if (!strncmp(optarg, "SAPENTRIES", 10)) {
1281 vars_to_check = SAPENTRIES;
1282 if (strlen(optarg) > 10)
1283 sap_number = atoi(optarg + 10);
1416 else 1284 else
1417 die(STATE_UNKNOWN,_("Server port an integer\n")); 1285 sap_number = -1;
1418 break; 1286 } else if (!strcmp(optarg, "OFILES"))
1419 case 'v': 1287 vars_to_check = OFILES;
1420 if (strlen(optarg)<3) 1288 else if (strncmp(optarg, "VKP", 3) == 0) {
1421 return ERROR; 1289 vars_to_check = VKP;
1422 if (!strcmp(optarg,"LOAD1")) 1290 volume_name = strdup(optarg + 3);
1423 vars_to_check=LOAD1; 1291 if (!strcmp(volume_name, ""))
1424 else if (!strcmp(optarg,"LOAD5")) 1292 volume_name = strdup("SYS");
1425 vars_to_check=LOAD5; 1293 } else if (strncmp(optarg, "VMP", 3) == 0) {
1426 else if (!strcmp(optarg,"LOAD15")) 1294 vars_to_check = VMP;
1427 vars_to_check=LOAD15; 1295 volume_name = strdup(optarg + 3);
1428 else if (!strcmp(optarg,"CONNS")) 1296 if (!strcmp(volume_name, ""))
1429 vars_to_check=CONNS; 1297 volume_name = strdup("SYS");
1430 else if (!strcmp(optarg,"LTCH")) 1298 } else if (strncmp(optarg, "VMU", 3) == 0) {
1431 vars_to_check=LTCH; 1299 vars_to_check = VMU;
1432 else if (!strcmp(optarg,"DCB")) 1300 volume_name = strdup(optarg + 3);
1433 vars_to_check=DCB; 1301 if (!strcmp(volume_name, ""))
1434 else if (!strcmp(optarg,"TCB")) 1302 volume_name = strdup("SYS");
1435 vars_to_check=TCB; 1303 } else if (strncmp(optarg, "VPU", 3) == 0) {
1436 else if (!strcmp(optarg,"CBUFF")) 1304 vars_to_check = VPU;
1437 vars_to_check=CBUFF; 1305 volume_name = strdup(optarg + 3);
1438 else if (!strcmp(optarg,"CDBUFF")) 1306 if (!strcmp(volume_name, ""))
1439 vars_to_check=CDBUFF; 1307 volume_name = strdup("SYS");
1440 else if (!strcmp(optarg,"LRUM")) 1308 } else if (strncmp(optarg, "VPP", 3) == 0) {
1441 vars_to_check=LRUM; 1309 vars_to_check = VPP;
1442 else if (!strcmp(optarg,"LRUS")) 1310 volume_name = strdup(optarg + 3);
1443 vars_to_check=LRUS; 1311 if (!strcmp(volume_name, ""))
1444 else if (strncmp(optarg,"VPF",3)==0) { 1312 volume_name = strdup("SYS");
1445 vars_to_check=VPF; 1313 } else if (strncmp(optarg, "VKNP", 4) == 0) {
1446 volume_name = strdup (optarg+3); 1314 vars_to_check = VKNP;
1447 if (!strcmp(volume_name,"")) 1315 volume_name = strdup(optarg + 4);
1448 volume_name = strdup ("SYS"); 1316 if (!strcmp(volume_name, ""))
1449 } 1317 volume_name = strdup("SYS");
1450 else if (strncmp(optarg,"VKF",3)==0) { 1318 } else if (strncmp(optarg, "VPNP", 4) == 0) {
1451 vars_to_check=VKF; 1319 vars_to_check = VPNP;
1452 volume_name = strdup (optarg+3); 1320 volume_name = strdup(optarg + 4);
1453 if (!strcmp(volume_name,"")) 1321 if (!strcmp(volume_name, ""))
1454 volume_name = strdup ("SYS"); 1322 volume_name = strdup("SYS");
1455 } 1323 } else if (!strcmp(optarg, "ABENDS"))
1456 else if (strncmp(optarg,"VMF",3)==0) { 1324 vars_to_check = ABENDS;
1457 vars_to_check=VMF; 1325 else if (!strcmp(optarg, "CSPROCS"))
1458 volume_name = strdup (optarg+3); 1326 vars_to_check = CSPROCS;
1459 if (!strcmp(volume_name,"")) 1327 else if (!strcmp(optarg, "TSYNC"))
1460 volume_name = strdup ("SYS"); 1328 vars_to_check = TSYNC;
1461 } 1329 else if (!strcmp(optarg, "DSVER"))
1462 else if (!strcmp(optarg,"DSDB")) 1330 vars_to_check = DSVER;
1463 vars_to_check=DSDB; 1331 else if (!strcmp(optarg, "UPTIME")) {
1464 else if (!strcmp(optarg,"LOGINS")) 1332 vars_to_check = UPTIME;
1465 vars_to_check=LOGINS; 1333 } else if (strncmp(optarg, "NLM:", 4) == 0) {
1466 else if (!strcmp(optarg,"NRMH")) 1334 vars_to_check = NLM;
1467 vars_to_check=NRMH; 1335 nlm_name = strdup(optarg + 4);
1468 else if (!strcmp(optarg,"UPRB")) 1336 } else if (strncmp(optarg, "NRMP", 4) == 0) {
1469 vars_to_check=UPRB; 1337 vars_to_check = NRMP;
1470 else if (!strcmp(optarg,"PUPRB")) 1338 nrmp_name = strdup(optarg + 4);
1471 vars_to_check=PUPRB; 1339 if (!strcmp(nrmp_name, ""))
1472 else if (!strncmp(optarg,"SAPENTRIES",10)) { 1340 nrmp_name = strdup("AVAILABLE_MEMORY");
1473 vars_to_check=SAPENTRIES; 1341 } else if (strncmp(optarg, "NRMM", 4) == 0) {
1474 if (strlen(optarg)>10) 1342 vars_to_check = NRMM;
1475 sap_number=atoi(optarg+10); 1343 nrmm_name = strdup(optarg + 4);
1476 else 1344 if (!strcmp(nrmm_name, ""))
1477 sap_number=-1; 1345 nrmm_name = strdup("AVAILABLE_CACHE_MEMORY");
1478 }
1479 else if (!strcmp(optarg,"OFILES"))
1480 vars_to_check=OFILES;
1481 else if (strncmp(optarg,"VKP",3)==0) {
1482 vars_to_check=VKP;
1483 volume_name = strdup (optarg+3);
1484 if (!strcmp(volume_name,""))
1485 volume_name = strdup ("SYS");
1486 }
1487 else if (strncmp(optarg,"VMP",3)==0) {
1488 vars_to_check=VMP;
1489 volume_name = strdup (optarg+3);
1490 if (!strcmp(volume_name,""))
1491 volume_name = strdup ("SYS");
1492 }
1493 else if (strncmp(optarg,"VMU",3)==0) {
1494 vars_to_check=VMU;
1495 volume_name = strdup (optarg+3);
1496 if (!strcmp(volume_name,""))
1497 volume_name = strdup ("SYS");
1498 }
1499 else if (strncmp(optarg,"VPU",3)==0) {
1500 vars_to_check=VPU;
1501 volume_name = strdup (optarg+3);
1502 if (!strcmp(volume_name,""))
1503 volume_name = strdup ("SYS");
1504 }
1505 else if (strncmp(optarg,"VPP",3)==0) {
1506 vars_to_check=VPP;
1507 volume_name = strdup (optarg+3);
1508 if (!strcmp(volume_name,""))
1509 volume_name = strdup ("SYS");
1510 }
1511 else if (strncmp(optarg,"VKNP",4)==0) {
1512 vars_to_check=VKNP;
1513 volume_name = strdup (optarg+4);
1514 if (!strcmp(volume_name,""))
1515 volume_name = strdup ("SYS");
1516 }
1517 else if (strncmp(optarg,"VPNP",4)==0) {
1518 vars_to_check=VPNP;
1519 volume_name = strdup (optarg+4);
1520 if (!strcmp(volume_name,""))
1521 volume_name = strdup("SYS");
1522 }
1523 else if (!strcmp(optarg,"ABENDS"))
1524 vars_to_check=ABENDS;
1525 else if (!strcmp(optarg,"CSPROCS"))
1526 vars_to_check=CSPROCS;
1527 else if (!strcmp(optarg,"TSYNC"))
1528 vars_to_check=TSYNC;
1529 else if (!strcmp(optarg,"DSVER"))
1530 vars_to_check=DSVER;
1531 else if (!strcmp(optarg,"UPTIME")) {
1532 vars_to_check=UPTIME;
1533 }
1534 else if (strncmp(optarg,"NLM:",4)==0) {
1535 vars_to_check=NLM;
1536 nlm_name=strdup (optarg+4);
1537 }
1538 else if (strncmp(optarg,"NRMP",4)==0) {
1539 vars_to_check=NRMP;
1540 nrmp_name = strdup (optarg+4);
1541 if (!strcmp(nrmp_name,""))
1542 nrmp_name = strdup ("AVAILABLE_MEMORY");
1543 }
1544 else if (strncmp(optarg,"NRMM",4)==0) {
1545 vars_to_check=NRMM;
1546 nrmm_name = strdup (optarg+4);
1547 if (!strcmp(nrmm_name,""))
1548 nrmm_name = strdup ("AVAILABLE_CACHE_MEMORY");
1549
1550 }
1551
1552 else if (strncmp(optarg,"NRMS",4)==0) {
1553 vars_to_check=NRMS;
1554 nrms_name = strdup (optarg+4);
1555 if (!strcmp(nrms_name,""))
1556 nrms_name = strdup ("USED_SWAP_SPACE");
1557
1558 }
1559
1560 else if (strncmp(optarg,"NSS1",4)==0) {
1561 vars_to_check=NSS1;
1562 nss1_name = strdup (optarg+4);
1563 if (!strcmp(nss1_name,""))
1564 nss1_name = strdup ("CURRENTBUFFERCACHESIZE");
1565
1566 }
1567
1568 else if (strncmp(optarg,"NSS2",4)==0) {
1569 vars_to_check=NSS2;
1570 nss2_name = strdup (optarg+4);
1571 if (!strcmp(nss2_name,""))
1572 nss2_name = strdup ("CACHEHITS");
1573
1574 }
1575
1576 else if (strncmp(optarg,"NSS3",4)==0) {
1577 vars_to_check=NSS3;
1578 nss3_name = strdup (optarg+4);
1579 if (!strcmp(nss3_name,""))
1580 nss3_name = strdup ("CACHEGITPERCENT");
1581
1582 }
1583
1584 else if (strncmp(optarg,"NSS4",4)==0) {
1585 vars_to_check=NSS4;
1586 nss4_name = strdup (optarg+4);
1587 if (!strcmp(nss4_name,""))
1588 nss4_name = strdup ("CURRENTOPENCOUNT");
1589
1590 }
1591
1592 else if (strncmp(optarg,"NSS5",4)==0) {
1593 vars_to_check=NSS5;
1594 nss5_name = strdup (optarg+4);
1595 if (!strcmp(nss5_name,""))
1596 nss5_name = strdup ("CACHEMISSES");
1597
1598 }
1599
1600
1601 else if (strncmp(optarg,"NSS6",4)==0) {
1602 vars_to_check=NSS6;
1603 nss6_name = strdup (optarg+4);
1604 if (!strcmp(nss6_name,""))
1605 nss6_name = strdup ("PENDINGWORKSCOUNT");
1606
1607 }
1608
1609
1610 else if (strncmp(optarg,"NSS7",4)==0) {
1611 vars_to_check=NSS7;
1612 nss7_name = strdup (optarg+4);
1613 if (!strcmp(nss7_name,""))
1614 nss7_name = strdup ("CACHESIZE");
1615
1616 }
1617 1346
1347 }
1348
1349 else if (strncmp(optarg, "NRMS", 4) == 0) {
1350 vars_to_check = NRMS;
1351 nrms_name = strdup(optarg + 4);
1352 if (!strcmp(nrms_name, ""))
1353 nrms_name = strdup("USED_SWAP_SPACE");
1618 1354
1619 else
1620 return ERROR;
1621 break;
1622 case 'w': /* warning threshold */
1623 warning_value=strtoul(optarg,NULL,10);
1624 check_warning_value = true;
1625 break;
1626 case 'c': /* critical threshold */
1627 critical_value=strtoul(optarg,NULL,10);
1628 check_critical_value = true;
1629 break;
1630 case 't': /* timeout */
1631 socket_timeout=atoi(optarg);
1632 if (socket_timeout<=0)
1633 return ERROR;
1634 } 1355 }
1635 1356
1357 else if (strncmp(optarg, "NSS1", 4) == 0) {
1358 vars_to_check = NSS1;
1359 nss1_name = strdup(optarg + 4);
1360 if (!strcmp(nss1_name, ""))
1361 nss1_name = strdup("CURRENTBUFFERCACHESIZE");
1362
1363 }
1364
1365 else if (strncmp(optarg, "NSS2", 4) == 0) {
1366 vars_to_check = NSS2;
1367 nss2_name = strdup(optarg + 4);
1368 if (!strcmp(nss2_name, ""))
1369 nss2_name = strdup("CACHEHITS");
1370
1371 }
1372
1373 else if (strncmp(optarg, "NSS3", 4) == 0) {
1374 vars_to_check = NSS3;
1375 nss3_name = strdup(optarg + 4);
1376 if (!strcmp(nss3_name, ""))
1377 nss3_name = strdup("CACHEGITPERCENT");
1378
1379 }
1380
1381 else if (strncmp(optarg, "NSS4", 4) == 0) {
1382 vars_to_check = NSS4;
1383 nss4_name = strdup(optarg + 4);
1384 if (!strcmp(nss4_name, ""))
1385 nss4_name = strdup("CURRENTOPENCOUNT");
1386
1387 }
1388
1389 else if (strncmp(optarg, "NSS5", 4) == 0) {
1390 vars_to_check = NSS5;
1391 nss5_name = strdup(optarg + 4);
1392 if (!strcmp(nss5_name, ""))
1393 nss5_name = strdup("CACHEMISSES");
1394
1395 }
1396
1397 else if (strncmp(optarg, "NSS6", 4) == 0) {
1398 vars_to_check = NSS6;
1399 nss6_name = strdup(optarg + 4);
1400 if (!strcmp(nss6_name, ""))
1401 nss6_name = strdup("PENDINGWORKSCOUNT");
1402
1403 }
1404
1405 else if (strncmp(optarg, "NSS7", 4) == 0) {
1406 vars_to_check = NSS7;
1407 nss7_name = strdup(optarg + 4);
1408 if (!strcmp(nss7_name, ""))
1409 nss7_name = strdup("CACHESIZE");
1410
1411 }
1412
1413 else
1414 return ERROR;
1415 break;
1416 case 'w': /* warning threshold */
1417 warning_value = strtoul(optarg, NULL, 10);
1418 check_warning_value = true;
1419 break;
1420 case 'c': /* critical threshold */
1421 critical_value = strtoul(optarg, NULL, 10);
1422 check_critical_value = true;
1423 break;
1424 case 't': /* timeout */
1425 socket_timeout = atoi(optarg);
1426 if (socket_timeout <= 0)
1427 return ERROR;
1428 }
1636 } 1429 }
1637 1430
1638 return OK; 1431 return OK;
1639} 1432}
1640 1433
1641 1434void print_help(void) {
1642
1643void print_help(void)
1644{
1645 char *myport; 1435 char *myport;
1646 xasprintf (&myport, "%d", PORT); 1436 xasprintf(&myport, "%d", PORT);
1647 1437
1648 print_revision (progname, NP_VERSION); 1438 print_revision(progname, NP_VERSION);
1649 1439
1650 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1440 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1651 printf (COPYRIGHT, copyright, email); 1441 printf(COPYRIGHT, copyright, email);
1652 1442
1653 printf ("%s\n", _("This plugin attempts to contact the MRTGEXT NLM running on a")); 1443 printf("%s\n", _("This plugin attempts to contact the MRTGEXT NLM running on a"));
1654 printf ("%s\n", _("Novell server to gather the requested system information.")); 1444 printf("%s\n", _("Novell server to gather the requested system information."));
1655 1445
1656 printf ("\n\n"); 1446 printf("\n\n");
1657 1447
1658 print_usage(); 1448 print_usage();
1659 1449
1660 printf (UT_HELP_VRSN); 1450 printf(UT_HELP_VRSN);
1661 printf (UT_EXTRA_OPTS); 1451 printf(UT_EXTRA_OPTS);
1662 1452
1663 printf (UT_HOST_PORT, 'p', myport); 1453 printf(UT_HOST_PORT, 'p', myport);
1664 1454
1665 printf (" %s\n", "-v, --variable=STRING"); 1455 printf(" %s\n", "-v, --variable=STRING");
1666 printf (" %s\n", _("Variable to check. Valid variables include:")); 1456 printf(" %s\n", _("Variable to check. Valid variables include:"));
1667 printf (" %s\n", _("LOAD1 = 1 minute average CPU load")); 1457 printf(" %s\n", _("LOAD1 = 1 minute average CPU load"));
1668 printf (" %s\n", _("LOAD5 = 5 minute average CPU load")); 1458 printf(" %s\n", _("LOAD5 = 5 minute average CPU load"));
1669 printf (" %s\n", _("LOAD15 = 15 minute average CPU load")); 1459 printf(" %s\n", _("LOAD15 = 15 minute average CPU load"));
1670 printf (" %s\n", _("CSPROCS = number of current service processes (NW 5.x only)")); 1460 printf(" %s\n", _("CSPROCS = number of current service processes (NW 5.x only)"));
1671 printf (" %s\n", _("ABENDS = number of abended threads (NW 5.x only)")); 1461 printf(" %s\n", _("ABENDS = number of abended threads (NW 5.x only)"));
1672 printf (" %s\n", _("UPTIME = server uptime")); 1462 printf(" %s\n", _("UPTIME = server uptime"));
1673 printf (" %s\n", _("LTCH = percent long term cache hits")); 1463 printf(" %s\n", _("LTCH = percent long term cache hits"));
1674 printf (" %s\n", _("CBUFF = current number of cache buffers")); 1464 printf(" %s\n", _("CBUFF = current number of cache buffers"));
1675 printf (" %s\n", _("CDBUFF = current number of dirty cache buffers")); 1465 printf(" %s\n", _("CDBUFF = current number of dirty cache buffers"));
1676 printf (" %s\n", _("DCB = dirty cache buffers as a percentage of the total")); 1466 printf(" %s\n", _("DCB = dirty cache buffers as a percentage of the total"));
1677 printf (" %s\n", _("TCB = dirty cache buffers as a percentage of the original")); 1467 printf(" %s\n", _("TCB = dirty cache buffers as a percentage of the original"));
1678 printf (" %s\n", _("OFILES = number of open files")); 1468 printf(" %s\n", _("OFILES = number of open files"));
1679 printf (" %s\n", _(" VMF<vol> = MB of free space on Volume <vol>")); 1469 printf(" %s\n", _(" VMF<vol> = MB of free space on Volume <vol>"));
1680 printf (" %s\n", _(" VMU<vol> = MB used space on Volume <vol>")); 1470 printf(" %s\n", _(" VMU<vol> = MB used space on Volume <vol>"));
1681 printf (" %s\n", _(" VPU<vol> = percent used space on Volume <vol>")); 1471 printf(" %s\n", _(" VPU<vol> = percent used space on Volume <vol>"));
1682 printf (" %s\n", _(" VMP<vol> = MB of purgeable space on Volume <vol>")); 1472 printf(" %s\n", _(" VMP<vol> = MB of purgeable space on Volume <vol>"));
1683 printf (" %s\n", _(" VPF<vol> = percent free space on volume <vol>")); 1473 printf(" %s\n", _(" VPF<vol> = percent free space on volume <vol>"));
1684 printf (" %s\n", _(" VKF<vol> = KB of free space on volume <vol>")); 1474 printf(" %s\n", _(" VKF<vol> = KB of free space on volume <vol>"));
1685 printf (" %s\n", _(" VPP<vol> = percent purgeable space on volume <vol>")); 1475 printf(" %s\n", _(" VPP<vol> = percent purgeable space on volume <vol>"));
1686 printf (" %s\n", _(" VKP<vol> = KB of purgeable space on volume <vol>")); 1476 printf(" %s\n", _(" VKP<vol> = KB of purgeable space on volume <vol>"));
1687 printf (" %s\n", _(" VPNP<vol> = percent not yet purgeable space on volume <vol>")); 1477 printf(" %s\n", _(" VPNP<vol> = percent not yet purgeable space on volume <vol>"));
1688 printf (" %s\n", _(" VKNP<vol> = KB of not yet purgeable space on volume <vol>")); 1478 printf(" %s\n", _(" VKNP<vol> = KB of not yet purgeable space on volume <vol>"));
1689 printf (" %s\n", _(" LRUM = LRU sitting time in minutes")); 1479 printf(" %s\n", _(" LRUM = LRU sitting time in minutes"));
1690 printf (" %s\n", _(" LRUS = LRU sitting time in seconds")); 1480 printf(" %s\n", _(" LRUS = LRU sitting time in seconds"));
1691 printf (" %s\n", _(" DSDB = check to see if DS Database is open")); 1481 printf(" %s\n", _(" DSDB = check to see if DS Database is open"));
1692 printf (" %s\n", _(" DSVER = NDS version")); 1482 printf(" %s\n", _(" DSVER = NDS version"));
1693 printf (" %s\n", _(" UPRB = used packet receive buffers")); 1483 printf(" %s\n", _(" UPRB = used packet receive buffers"));
1694 printf (" %s\n", _(" PUPRB = percent (of max) used packet receive buffers")); 1484 printf(" %s\n", _(" PUPRB = percent (of max) used packet receive buffers"));
1695 printf (" %s\n", _(" SAPENTRIES = number of entries in the SAP table")); 1485 printf(" %s\n", _(" SAPENTRIES = number of entries in the SAP table"));
1696 printf (" %s\n", _(" SAPENTRIES<n> = number of entries in the SAP table for SAP type <n>")); 1486 printf(" %s\n", _(" SAPENTRIES<n> = number of entries in the SAP table for SAP type <n>"));
1697 printf (" %s\n", _(" TSYNC = timesync status")); 1487 printf(" %s\n", _(" TSYNC = timesync status"));
1698 printf (" %s\n", _(" LOGINS = check to see if logins are enabled")); 1488 printf(" %s\n", _(" LOGINS = check to see if logins are enabled"));
1699 printf (" %s\n", _(" CONNS = number of currently licensed connections")); 1489 printf(" %s\n", _(" CONNS = number of currently licensed connections"));
1700 printf (" %s\n", _(" NRMH = NRM Summary Status")); 1490 printf(" %s\n", _(" NRMH = NRM Summary Status"));
1701 printf (" %s\n", _(" NRMP<stat> = Returns the current value for a NRM health item")); 1491 printf(" %s\n", _(" NRMP<stat> = Returns the current value for a NRM health item"));
1702 printf (" %s\n", _(" NRMM<stat> = Returns the current memory stats from NRM")); 1492 printf(" %s\n", _(" NRMM<stat> = Returns the current memory stats from NRM"));
1703 printf (" %s\n", _(" NRMS<stat> = Returns the current Swapfile stats from NRM")); 1493 printf(" %s\n", _(" NRMS<stat> = Returns the current Swapfile stats from NRM"));
1704 printf (" %s\n", _(" NSS1<stat> = Statistics from _Admin:Manage_NSS\\GeneralStats.xml")); 1494 printf(" %s\n", _(" NSS1<stat> = Statistics from _Admin:Manage_NSS\\GeneralStats.xml"));
1705 printf (" %s\n", _(" NSS3<stat> = Statistics from _Admin:Manage_NSS\\NameCache.xml")); 1495 printf(" %s\n", _(" NSS3<stat> = Statistics from _Admin:Manage_NSS\\NameCache.xml"));
1706 printf (" %s\n", _(" NSS4<stat> = Statistics from _Admin:Manage_NSS\\FileStats.xml")); 1496 printf(" %s\n", _(" NSS4<stat> = Statistics from _Admin:Manage_NSS\\FileStats.xml"));
1707 printf (" %s\n", _(" NSS5<stat> = Statistics from _Admin:Manage_NSS\\ObjectCache.xml")); 1497 printf(" %s\n", _(" NSS5<stat> = Statistics from _Admin:Manage_NSS\\ObjectCache.xml"));
1708 printf (" %s\n", _(" NSS6<stat> = Statistics from _Admin:Manage_NSS\\Thread.xml")); 1498 printf(" %s\n", _(" NSS6<stat> = Statistics from _Admin:Manage_NSS\\Thread.xml"));
1709 printf (" %s\n", _(" NSS7<stat> = Statistics from _Admin:Manage_NSS\\AuthorizationCache.xml")); 1499 printf(" %s\n", _(" NSS7<stat> = Statistics from _Admin:Manage_NSS\\AuthorizationCache.xml"));
1710 printf (" %s\n", _(" NLM:<nlm> = check if NLM is loaded and report version")); 1500 printf(" %s\n", _(" NLM:<nlm> = check if NLM is loaded and report version"));
1711 printf (" %s\n", _(" (e.g. NLM:TSANDS.NLM)")); 1501 printf(" %s\n", _(" (e.g. NLM:TSANDS.NLM)"));
1712 printf ("\n"); 1502 printf("\n");
1713 printf (" %s\n", "-w, --warning=INTEGER"); 1503 printf(" %s\n", "-w, --warning=INTEGER");
1714 printf (" %s\n", _("Threshold which will result in a warning status")); 1504 printf(" %s\n", _("Threshold which will result in a warning status"));
1715 printf (" %s\n", "-c, --critical=INTEGER"); 1505 printf(" %s\n", "-c, --critical=INTEGER");
1716 printf (" %s\n", _("Threshold which will result in a critical status")); 1506 printf(" %s\n", _("Threshold which will result in a critical status"));
1717 printf (" %s\n", "-o, --osversion"); 1507 printf(" %s\n", "-o, --osversion");
1718 printf (" %s\n", _("Include server version string in results")); 1508 printf(" %s\n", _("Include server version string in results"));
1719 1509
1720 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1510 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1721 1511
1722 printf ("\n"); 1512 printf("\n");
1723 printf ("%s\n", _("Notes:")); 1513 printf("%s\n", _("Notes:"));
1724 printf (" %s\n", _("- This plugin requires that the MRTGEXT.NLM file from James Drews' MRTG")); 1514 printf(" %s\n", _("- This plugin requires that the MRTGEXT.NLM file from James Drews' MRTG"));
1725 printf (" %s\n", _(" extension for NetWare be loaded on the Novell servers you wish to check.")); 1515 printf(" %s\n", _(" extension for NetWare be loaded on the Novell servers you wish to check."));
1726 printf (" %s\n", _(" (available from http://www.engr.wisc.edu/~drews/mrtg/)")); 1516 printf(" %s\n", _(" (available from http://www.engr.wisc.edu/~drews/mrtg/)"));
1727 printf (" %s\n", _("- Values for critical thresholds should be lower than warning thresholds")); 1517 printf(" %s\n", _("- Values for critical thresholds should be lower than warning thresholds"));
1728 printf (" %s\n", _(" when the following variables are checked: VPF, VKF, LTCH, CBUFF, DCB, ")); 1518 printf(" %s\n", _(" when the following variables are checked: VPF, VKF, LTCH, CBUFF, DCB, "));
1729 printf (" %s\n", _(" TCB, LRUS and LRUM.")); 1519 printf(" %s\n", _(" TCB, LRUS and LRUM."));
1730 1520
1731 printf (UT_SUPPORT); 1521 printf(UT_SUPPORT);
1732} 1522}
1733 1523
1734 1524void print_usage(void) {
1735 1525 printf("%s\n", _("Usage:"));
1736void print_usage(void) 1526 printf("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n", progname);
1737{
1738 printf ("%s\n", _("Usage:"));
1739 printf ("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n",progname);
1740} 1527}
diff --git a/plugins/check_overcr.c b/plugins/check_overcr.c
index 5165c828..e80d4775 100644
--- a/plugins/check_overcr.c
+++ b/plugins/check_overcr.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_overcr plugin 3 * Monitoring check_overcr plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_overcr plugin 10 * This file contains the check_overcr plugin
11* 11 *
12* This plugin attempts to contact the Over-CR collector daemon running on the 12 * This plugin attempts to contact the Over-CR collector daemon running on the
13* remote UNIX server in order to gather the requested system information. 13 * remote UNIX server in order to gather the requested system information.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_overcr"; 32const char *progname = "check_overcr";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -66,13 +66,11 @@ char *disk_name = NULL;
66char *process_name = NULL; 66char *process_name = NULL;
67char send_buffer[MAX_INPUT_BUFFER]; 67char send_buffer[MAX_INPUT_BUFFER];
68 68
69int process_arguments (int, char **); 69int process_arguments(int, char **);
70void print_usage (void); 70void print_usage(void);
71void print_help (void); 71void print_help(void);
72 72
73int 73int main(int argc, char **argv) {
74main (int argc, char **argv)
75{
76 int result = STATE_UNKNOWN; 74 int result = STATE_UNKNOWN;
77 char recv_buffer[MAX_INPUT_BUFFER]; 75 char recv_buffer[MAX_INPUT_BUFFER];
78 char temp_buffer[MAX_INPUT_BUFFER]; 76 char temp_buffer[MAX_INPUT_BUFFER];
@@ -91,66 +89,62 @@ main (int argc, char **argv)
91 int uptime_hours = 0; 89 int uptime_hours = 0;
92 int uptime_minutes = 0; 90 int uptime_minutes = 0;
93 91
94 setlocale (LC_ALL, ""); 92 setlocale(LC_ALL, "");
95 bindtextdomain (PACKAGE, LOCALEDIR); 93 bindtextdomain(PACKAGE, LOCALEDIR);
96 textdomain (PACKAGE); 94 textdomain(PACKAGE);
97 95
98 /* Parse extra opts if any */ 96 /* Parse extra opts if any */
99 argv=np_extra_opts (&argc, argv, progname); 97 argv = np_extra_opts(&argc, argv, progname);
100 98
101 if (process_arguments (argc, argv) == ERROR) 99 if (process_arguments(argc, argv) == ERROR)
102 usage4 (_("Could not parse arguments")); 100 usage4(_("Could not parse arguments"));
103 101
104 /* initialize alarm signal handling */ 102 /* initialize alarm signal handling */
105 signal (SIGALRM, socket_timeout_alarm_handler); 103 signal(SIGALRM, socket_timeout_alarm_handler);
106 104
107 /* set socket timeout */ 105 /* set socket timeout */
108 alarm (socket_timeout); 106 alarm(socket_timeout);
109 107
110 result = process_tcp_request2 (server_address, 108 result = process_tcp_request2(server_address, server_port, send_buffer, recv_buffer, sizeof(recv_buffer));
111 server_port,
112 send_buffer,
113 recv_buffer,
114 sizeof (recv_buffer));
115 109
116 switch (vars_to_check) { 110 switch (vars_to_check) {
117 111
118 case LOAD1: 112 case LOAD1:
119 case LOAD5: 113 case LOAD5:
120 case LOAD15: 114 case LOAD15:
121 115
122 if (result != STATE_OK) 116 if (result != STATE_OK)
123 die (result, _("Unknown error fetching load data\n")); 117 die(result, _("Unknown error fetching load data\n"));
124 118
125 temp_ptr = (char *) strtok (recv_buffer, "\r\n"); 119 temp_ptr = (char *)strtok(recv_buffer, "\r\n");
126 if (temp_ptr == NULL) 120 if (temp_ptr == NULL)
127 die (STATE_CRITICAL, _("Invalid response from server - no load information\n")); 121 die(STATE_CRITICAL, _("Invalid response from server - no load information\n"));
128 else 122 else
129 load_1min = strtod (temp_ptr, NULL); 123 load_1min = strtod(temp_ptr, NULL);
130 124
131 temp_ptr = (char *) strtok (NULL, "\r\n"); 125 temp_ptr = (char *)strtok(NULL, "\r\n");
132 if (temp_ptr == NULL) 126 if (temp_ptr == NULL)
133 die (STATE_CRITICAL, _("Invalid response from server after load 1\n")); 127 die(STATE_CRITICAL, _("Invalid response from server after load 1\n"));
134 else 128 else
135 load_5min = strtod (temp_ptr, NULL); 129 load_5min = strtod(temp_ptr, NULL);
136 130
137 temp_ptr = (char *) strtok (NULL, "\r\n"); 131 temp_ptr = (char *)strtok(NULL, "\r\n");
138 if (temp_ptr == NULL) 132 if (temp_ptr == NULL)
139 die (STATE_CRITICAL, _("Invalid response from server after load 5\n")); 133 die(STATE_CRITICAL, _("Invalid response from server after load 5\n"));
140 else 134 else
141 load_15min = strtod (temp_ptr, NULL); 135 load_15min = strtod(temp_ptr, NULL);
142 136
143 switch (vars_to_check) { 137 switch (vars_to_check) {
144 case LOAD1: 138 case LOAD1:
145 strcpy (temp_buffer, "1"); 139 strcpy(temp_buffer, "1");
146 load = load_1min; 140 load = load_1min;
147 break; 141 break;
148 case LOAD5: 142 case LOAD5:
149 strcpy (temp_buffer, "5"); 143 strcpy(temp_buffer, "5");
150 load = load_5min; 144 load = load_5min;
151 break; 145 break;
152 default: 146 default:
153 strcpy (temp_buffer, "15"); 147 strcpy(temp_buffer, "15");
154 load = load_15min; 148 load = load_15min;
155 break; 149 break;
156 } 150 }
@@ -160,98 +154,82 @@ main (int argc, char **argv)
160 else if (check_warning_value && (load >= warning_value)) 154 else if (check_warning_value && (load >= warning_value))
161 result = STATE_WARNING; 155 result = STATE_WARNING;
162 156
163 die (result, 157 die(result, _("Load %s - %s-min load average = %0.2f"), state_text(result), temp_buffer, load);
164 _("Load %s - %s-min load average = %0.2f"),
165 state_text(result),
166 temp_buffer,
167 load);
168 158
169 break; 159 break;
170 160
171 case DPU: 161 case DPU:
172 162
173 if (result != STATE_OK) 163 if (result != STATE_OK)
174 die (result, _("Unknown error fetching disk data\n")); 164 die(result, _("Unknown error fetching disk data\n"));
175 165
176 for (temp_ptr = (char *) strtok (recv_buffer, " "); 166 for (temp_ptr = (char *)strtok(recv_buffer, " "); temp_ptr != NULL; temp_ptr = (char *)strtok(NULL, " ")) {
177 temp_ptr != NULL;
178 temp_ptr = (char *) strtok (NULL, " ")) {
179 167
180 if (!strcmp (temp_ptr, disk_name)) { 168 if (!strcmp(temp_ptr, disk_name)) {
181 found_disk = true; 169 found_disk = true;
182 temp_ptr = (char *) strtok (NULL, "%"); 170 temp_ptr = (char *)strtok(NULL, "%");
183 if (temp_ptr == NULL) 171 if (temp_ptr == NULL)
184 die (STATE_CRITICAL, _("Invalid response from server\n")); 172 die(STATE_CRITICAL, _("Invalid response from server\n"));
185 else 173 else
186 percent_used_disk_space = strtoul (temp_ptr, NULL, 10); 174 percent_used_disk_space = strtoul(temp_ptr, NULL, 10);
187 break; 175 break;
188 } 176 }
189 177
190 temp_ptr = (char *) strtok (NULL, "\r\n"); 178 temp_ptr = (char *)strtok(NULL, "\r\n");
191 } 179 }
192 180
193 /* error if we couldn't find the info for the disk */ 181 /* error if we couldn't find the info for the disk */
194 if (!found_disk) 182 if (!found_disk)
195 die (STATE_CRITICAL, 183 die(STATE_CRITICAL, "CRITICAL - Disk '%s' non-existent or not mounted", disk_name);
196 "CRITICAL - Disk '%s' non-existent or not mounted",
197 disk_name);
198 184
199 if (check_critical_value && (percent_used_disk_space >= critical_value)) 185 if (check_critical_value && (percent_used_disk_space >= critical_value))
200 result = STATE_CRITICAL; 186 result = STATE_CRITICAL;
201 else if (check_warning_value && (percent_used_disk_space >= warning_value)) 187 else if (check_warning_value && (percent_used_disk_space >= warning_value))
202 result = STATE_WARNING; 188 result = STATE_WARNING;
203 189
204 die (result, "Disk %s - %lu%% used on %s", state_text(result), percent_used_disk_space, disk_name); 190 die(result, "Disk %s - %lu%% used on %s", state_text(result), percent_used_disk_space, disk_name);
205 191
206 break; 192 break;
207 193
208 case NETSTAT: 194 case NETSTAT:
209 195
210 if (result != STATE_OK) 196 if (result != STATE_OK)
211 die (result, _("Unknown error fetching network status\n")); 197 die(result, _("Unknown error fetching network status\n"));
212 else 198 else
213 port_connections = strtod (recv_buffer, NULL); 199 port_connections = strtod(recv_buffer, NULL);
214 200
215 if (check_critical_value && (port_connections >= critical_value)) 201 if (check_critical_value && (port_connections >= critical_value))
216 result = STATE_CRITICAL; 202 result = STATE_CRITICAL;
217 else if (check_warning_value && (port_connections >= warning_value)) 203 else if (check_warning_value && (port_connections >= warning_value))
218 result = STATE_WARNING; 204 result = STATE_WARNING;
219 205
220 die (result, 206 die(result, _("Net %s - %d connection%s on port %d"), state_text(result), port_connections, (port_connections == 1) ? "" : "s",
221 _("Net %s - %d connection%s on port %d"), 207 netstat_port);
222 state_text(result),
223 port_connections,
224 (port_connections == 1) ? "" : "s",
225 netstat_port);
226 208
227 break; 209 break;
228 210
229 case PROCS: 211 case PROCS:
230 212
231 if (result != STATE_OK) 213 if (result != STATE_OK)
232 die (result, _("Unknown error fetching process status\n")); 214 die(result, _("Unknown error fetching process status\n"));
233 215
234 temp_ptr = (char *) strtok (recv_buffer, "("); 216 temp_ptr = (char *)strtok(recv_buffer, "(");
235 if (temp_ptr == NULL) 217 if (temp_ptr == NULL)
236 die (STATE_CRITICAL, _("Invalid response from server\n")); 218 die(STATE_CRITICAL, _("Invalid response from server\n"));
237 219
238 temp_ptr = (char *) strtok (NULL, ")"); 220 temp_ptr = (char *)strtok(NULL, ")");
239 if (temp_ptr == NULL) 221 if (temp_ptr == NULL)
240 die (STATE_CRITICAL, _("Invalid response from server\n")); 222 die(STATE_CRITICAL, _("Invalid response from server\n"));
241 else 223 else
242 processes = strtod (temp_ptr, NULL); 224 processes = strtod(temp_ptr, NULL);
243 225
244 if (check_critical_value && (processes >= critical_value)) 226 if (check_critical_value && (processes >= critical_value))
245 result = STATE_CRITICAL; 227 result = STATE_CRITICAL;
246 else if (check_warning_value && (processes >= warning_value)) 228 else if (check_warning_value && (processes >= warning_value))
247 result = STATE_WARNING; 229 result = STATE_WARNING;
248 230
249 die (result, 231 die(result, _("Process %s - %d instance%s of %s running"), state_text(result), processes, (processes == 1) ? "" : "s",
250 _("Process %s - %d instance%s of %s running"), 232 process_name);
251 state_text(result),
252 processes,
253 (processes == 1) ? "" : "s",
254 process_name);
255 break; 233 break;
256 234
257 case UPTIME: 235 case UPTIME:
@@ -259,8 +237,8 @@ main (int argc, char **argv)
259 if (result != STATE_OK) 237 if (result != STATE_OK)
260 return result; 238 return result;
261 239
262 uptime_raw_hours = strtod (recv_buffer, NULL); 240 uptime_raw_hours = strtod(recv_buffer, NULL);
263 uptime_raw_minutes = (unsigned long) (uptime_raw_hours * 60.0); 241 uptime_raw_minutes = (unsigned long)(uptime_raw_hours * 60.0);
264 242
265 if (check_critical_value && (uptime_raw_minutes <= critical_value)) 243 if (check_critical_value && (uptime_raw_minutes <= critical_value))
266 result = STATE_CRITICAL; 244 result = STATE_CRITICAL;
@@ -273,46 +251,31 @@ main (int argc, char **argv)
273 uptime_raw_minutes %= 60; 251 uptime_raw_minutes %= 60;
274 uptime_minutes = uptime_raw_minutes; 252 uptime_minutes = uptime_raw_minutes;
275 253
276 die (result, 254 die(result, _("Uptime %s - Up %d days %d hours %d minutes"), state_text(result), uptime_days, uptime_hours, uptime_minutes);
277 _("Uptime %s - Up %d days %d hours %d minutes"),
278 state_text(result),
279 uptime_days,
280 uptime_hours,
281 uptime_minutes);
282 break; 255 break;
283 256
284 default: 257 default:
285 die (STATE_UNKNOWN, _("Nothing to check!\n")); 258 die(STATE_UNKNOWN, _("Nothing to check!\n"));
286 break; 259 break;
287 } 260 }
288} 261}
289 262
290
291/* process command-line arguments */ 263/* process command-line arguments */
292int 264int process_arguments(int argc, char **argv) {
293process_arguments (int argc, char **argv)
294{
295 int c; 265 int c;
296 266
297 int option = 0; 267 int option = 0;
298 static struct option longopts[] = { 268 static struct option longopts[] = {
299 {"port", required_argument, 0, 'p'}, 269 {"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'}, {"critical", required_argument, 0, 'c'},
300 {"timeout", required_argument, 0, 't'}, 270 {"warning", required_argument, 0, 'w'}, {"variable", required_argument, 0, 'v'}, {"hostname", required_argument, 0, 'H'},
301 {"critical", required_argument, 0, 'c'}, 271 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
302 {"warning", required_argument, 0, 'w'},
303 {"variable", required_argument, 0, 'v'},
304 {"hostname", required_argument, 0, 'H'},
305 {"version", no_argument, 0, 'V'},
306 {"help", no_argument, 0, 'h'},
307 {0, 0, 0, 0}
308 };
309 272
310 /* no options were supplied */ 273 /* no options were supplied */
311 if (argc < 2) 274 if (argc < 2)
312 return ERROR; 275 return ERROR;
313 276
314 /* backwards compatibility */ 277 /* backwards compatibility */
315 if (!is_option (argv[1])) { 278 if (!is_option(argv[1])) {
316 server_address = argv[1]; 279 server_address = argv[1];
317 argv[1] = argv[0]; 280 argv[1] = argv[0];
318 argv = &argv[1]; 281 argv = &argv[1];
@@ -320,150 +283,136 @@ process_arguments (int argc, char **argv)
320 } 283 }
321 284
322 for (c = 1; c < argc; c++) { 285 for (c = 1; c < argc; c++) {
323 if (strcmp ("-to", argv[c]) == 0) 286 if (strcmp("-to", argv[c]) == 0)
324 strcpy (argv[c], "-t"); 287 strcpy(argv[c], "-t");
325 else if (strcmp ("-wv", argv[c]) == 0) 288 else if (strcmp("-wv", argv[c]) == 0)
326 strcpy (argv[c], "-w"); 289 strcpy(argv[c], "-w");
327 else if (strcmp ("-cv", argv[c]) == 0) 290 else if (strcmp("-cv", argv[c]) == 0)
328 strcpy (argv[c], "-c"); 291 strcpy(argv[c], "-c");
329 } 292 }
330 293
331 while (1) { 294 while (1) {
332 c = getopt_long (argc, argv, "+hVH:t:c:w:p:v:", longopts, 295 c = getopt_long(argc, argv, "+hVH:t:c:w:p:v:", longopts, &option);
333 &option);
334 296
335 if (c == -1 || c == EOF || c == 1) 297 if (c == -1 || c == EOF || c == 1)
336 break; 298 break;
337 299
338 switch (c) { 300 switch (c) {
339 case '?': /* print short usage statement if args not parsable */ 301 case '?': /* print short usage statement if args not parsable */
340 usage5 (); 302 usage5();
341 case 'h': /* help */ 303 case 'h': /* help */
342 print_help (); 304 print_help();
343 exit (STATE_UNKNOWN); 305 exit(STATE_UNKNOWN);
344 case 'V': /* version */ 306 case 'V': /* version */
345 print_revision (progname, NP_VERSION); 307 print_revision(progname, NP_VERSION);
346 exit (STATE_UNKNOWN); 308 exit(STATE_UNKNOWN);
347 case 'H': /* hostname */ 309 case 'H': /* hostname */
348 server_address = optarg; 310 server_address = optarg;
349 break; 311 break;
350 case 'p': /* port */ 312 case 'p': /* port */
351 if (is_intnonneg (optarg)) 313 if (is_intnonneg(optarg))
352 server_port = atoi (optarg); 314 server_port = atoi(optarg);
353 else 315 else
354 die (STATE_UNKNOWN, 316 die(STATE_UNKNOWN, _("Server port an integer\n"));
355 _("Server port an integer\n"));
356 break; 317 break;
357 case 'v': /* variable */ 318 case 'v': /* variable */
358 if (strcmp (optarg, "LOAD") == 0) { 319 if (strcmp(optarg, "LOAD") == 0) {
359 strcpy (send_buffer, "LOAD\r\nQUIT\r\n"); 320 strcpy(send_buffer, "LOAD\r\nQUIT\r\n");
360 if (strcmp (optarg, "LOAD1") == 0) 321 if (strcmp(optarg, "LOAD1") == 0)
361 vars_to_check = LOAD1; 322 vars_to_check = LOAD1;
362 else if (strcmp (optarg, "LOAD5") == 0) 323 else if (strcmp(optarg, "LOAD5") == 0)
363 vars_to_check = LOAD5; 324 vars_to_check = LOAD5;
364 else if (strcmp (optarg, "LOAD15") == 0) 325 else if (strcmp(optarg, "LOAD15") == 0)
365 vars_to_check = LOAD15; 326 vars_to_check = LOAD15;
366 } 327 } else if (strcmp(optarg, "UPTIME") == 0) {
367 else if (strcmp (optarg, "UPTIME") == 0) {
368 vars_to_check = UPTIME; 328 vars_to_check = UPTIME;
369 strcpy (send_buffer, "UPTIME\r\n"); 329 strcpy(send_buffer, "UPTIME\r\n");
370 } 330 } else if (strstr(optarg, "PROC") == optarg) {
371 else if (strstr (optarg, "PROC") == optarg) {
372 vars_to_check = PROCS; 331 vars_to_check = PROCS;
373 process_name = strscpy (process_name, optarg + 4); 332 process_name = strscpy(process_name, optarg + 4);
374 sprintf (send_buffer, "PROCESS %s\r\n", process_name); 333 sprintf(send_buffer, "PROCESS %s\r\n", process_name);
375 } 334 } else if (strstr(optarg, "NET") == optarg) {
376 else if (strstr (optarg, "NET") == optarg) {
377 vars_to_check = NETSTAT; 335 vars_to_check = NETSTAT;
378 netstat_port = atoi (optarg + 3); 336 netstat_port = atoi(optarg + 3);
379 sprintf (send_buffer, "NETSTAT %d\r\n", netstat_port); 337 sprintf(send_buffer, "NETSTAT %d\r\n", netstat_port);
380 } 338 } else if (strstr(optarg, "DPU") == optarg) {
381 else if (strstr (optarg, "DPU") == optarg) {
382 vars_to_check = DPU; 339 vars_to_check = DPU;
383 strcpy (send_buffer, "DISKSPACE\r\n"); 340 strcpy(send_buffer, "DISKSPACE\r\n");
384 disk_name = strscpy (disk_name, optarg + 3); 341 disk_name = strscpy(disk_name, optarg + 3);
385 } 342 } else
386 else
387 return ERROR; 343 return ERROR;
388 break; 344 break;
389 case 'w': /* warning threshold */ 345 case 'w': /* warning threshold */
390 warning_value = strtoul (optarg, NULL, 10); 346 warning_value = strtoul(optarg, NULL, 10);
391 check_warning_value = true; 347 check_warning_value = true;
392 break; 348 break;
393 case 'c': /* critical threshold */ 349 case 'c': /* critical threshold */
394 critical_value = strtoul (optarg, NULL, 10); 350 critical_value = strtoul(optarg, NULL, 10);
395 check_critical_value = true; 351 check_critical_value = true;
396 break; 352 break;
397 case 't': /* timeout */ 353 case 't': /* timeout */
398 socket_timeout = atoi (optarg); 354 socket_timeout = atoi(optarg);
399 if (socket_timeout <= 0) 355 if (socket_timeout <= 0)
400 return ERROR; 356 return ERROR;
401 } 357 }
402
403 } 358 }
404 return OK; 359 return OK;
405} 360}
406 361
407 362void print_help(void) {
408void
409print_help (void)
410{
411 char *myport; 363 char *myport;
412 xasprintf (&myport, "%d", PORT); 364 xasprintf(&myport, "%d", PORT);
413 365
414 print_revision (progname, NP_VERSION); 366 print_revision(progname, NP_VERSION);
415 367
416 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 368 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
417 printf (COPYRIGHT, copyright, email); 369 printf(COPYRIGHT, copyright, email);
418 370
419 printf ("%s\n", _("This plugin attempts to contact the Over-CR collector daemon running on the")); 371 printf("%s\n", _("This plugin attempts to contact the Over-CR collector daemon running on the"));
420 printf ("%s\n", _("remote UNIX server in order to gather the requested system information.")); 372 printf("%s\n", _("remote UNIX server in order to gather the requested system information."));
421 373
422 printf ("\n\n"); 374 printf("\n\n");
423 375
424 print_usage (); 376 print_usage();
425 377
426 printf (UT_HELP_VRSN); 378 printf(UT_HELP_VRSN);
427 printf (UT_EXTRA_OPTS); 379 printf(UT_EXTRA_OPTS);
428 380
429 printf (UT_HOST_PORT, 'p', myport); 381 printf(UT_HOST_PORT, 'p', myport);
430 382
431 printf (" %s\n", "-w, --warning=INTEGER"); 383 printf(" %s\n", "-w, --warning=INTEGER");
432 printf (" %s\n", _("Threshold which will result in a warning status")); 384 printf(" %s\n", _("Threshold which will result in a warning status"));
433 printf (" %s\n", "-c, --critical=INTEGER"); 385 printf(" %s\n", "-c, --critical=INTEGER");
434 printf (" %s\n", _("Threshold which will result in a critical status")); 386 printf(" %s\n", _("Threshold which will result in a critical status"));
435 printf (" %s\n", "-v, --variable=STRING"); 387 printf(" %s\n", "-v, --variable=STRING");
436 printf (" %s\n", _("Variable to check. Valid variables include:")); 388 printf(" %s\n", _("Variable to check. Valid variables include:"));
437 printf (" %s\n", _("LOAD1 = 1 minute average CPU load")); 389 printf(" %s\n", _("LOAD1 = 1 minute average CPU load"));
438 printf (" %s\n", _("LOAD5 = 5 minute average CPU load")); 390 printf(" %s\n", _("LOAD5 = 5 minute average CPU load"));
439 printf (" %s\n", _("LOAD15 = 15 minute average CPU load")); 391 printf(" %s\n", _("LOAD15 = 15 minute average CPU load"));
440 printf (" %s\n", _("DPU<filesys> = percent used disk space on filesystem <filesys>")); 392 printf(" %s\n", _("DPU<filesys> = percent used disk space on filesystem <filesys>"));
441 printf (" %s\n", _("PROC<process> = number of running processes with name <process>")); 393 printf(" %s\n", _("PROC<process> = number of running processes with name <process>"));
442 printf (" %s\n", _("NET<port> = number of active connections on TCP port <port>")); 394 printf(" %s\n", _("NET<port> = number of active connections on TCP port <port>"));
443 printf (" %s\n", _("UPTIME = system uptime in seconds")); 395 printf(" %s\n", _("UPTIME = system uptime in seconds"));
444 396
445 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 397 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
446 398
447 printf (UT_VERBOSE); 399 printf(UT_VERBOSE);
448 400
449 printf ("\n"); 401 printf("\n");
450 printf ("%s\n", _("This plugin requires that Eric Molitors' Over-CR collector daemon be")); 402 printf("%s\n", _("This plugin requires that Eric Molitors' Over-CR collector daemon be"));
451 printf ("%s\n", _("running on the remote server.")); 403 printf("%s\n", _("running on the remote server."));
452 printf ("%s\n", _("Over-CR can be downloaded from http://www.molitor.org/overcr")); 404 printf("%s\n", _("Over-CR can be downloaded from http://www.molitor.org/overcr"));
453 printf ("%s\n", _("This plugin was tested with version 0.99.53 of the Over-CR collector")); 405 printf("%s\n", _("This plugin was tested with version 0.99.53 of the Over-CR collector"));
454 406
455 printf ("\n"); 407 printf("\n");
456 printf ("%s\n", _("Notes:")); 408 printf("%s\n", _("Notes:"));
457 printf (" %s\n", _("For the available options, the critical threshold value should always be")); 409 printf(" %s\n", _("For the available options, the critical threshold value should always be"));
458 printf (" %s\n", _("higher than the warning threshold value, EXCEPT with the uptime variable")); 410 printf(" %s\n", _("higher than the warning threshold value, EXCEPT with the uptime variable"));
459 411
460 printf (UT_SUPPORT); 412 printf(UT_SUPPORT);
461} 413}
462 414
463 415void print_usage(void) {
464void 416 printf("%s\n", _("Usage:"));
465print_usage (void) 417 printf("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n", progname);
466{
467 printf ("%s\n", _("Usage:"));
468 printf ("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n", progname);
469} 418}
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index 94d589e1..6613634d 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_pgsql plugin 3 * Monitoring check_pgsql plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2011 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_pgsql plugin 10 * This file contains the check_pgsql plugin
11* 11 *
12* Test whether a PostgreSQL Database is accepting connections. 12 * Test whether a PostgreSQL Database is accepting connections.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_pgsql"; 31const char *progname = "check_pgsql";
32const char *copyright = "1999-2011"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -40,22 +40,18 @@ const char *email = "devel@monitoring-plugins.org";
40#include <libpq-fe.h> 40#include <libpq-fe.h>
41#include <pg_config_manual.h> 41#include <pg_config_manual.h>
42 42
43#define DEFAULT_DB "template1" 43#define DEFAULT_DB "template1"
44#define DEFAULT_HOST "127.0.0.1" 44#define DEFAULT_HOST "127.0.0.1"
45 45
46/* return the PSQL server version as a 3-tuple */ 46/* return the PSQL server version as a 3-tuple */
47#define PSQL_SERVER_VERSION3(server_version) \ 47#define PSQL_SERVER_VERSION3(server_version) \
48 (server_version) / 10000, \ 48 (server_version) / 10000, (server_version) / 100 - (int)((server_version) / 10000) * 100, \
49 (server_version) / 100 - (int)((server_version) / 10000) * 100, \ 49 (server_version) - (int)((server_version) / 100) * 100
50 (server_version) - (int)((server_version) / 100) * 100
51/* return true if the given host is a UNIX domain socket */ 50/* return true if the given host is a UNIX domain socket */
52#define PSQL_IS_UNIX_DOMAIN_SOCKET(host) \ 51#define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
53 ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
54/* return a 3-tuple identifying a host/port independent of the socket type */ 52/* return a 3-tuple identifying a host/port independent of the socket type */
55#define PSQL_SOCKET3(host, port) \ 53#define PSQL_SOCKET3(host, port) \
56 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, \ 54 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port
57 PSQL_IS_UNIX_DOMAIN_SOCKET (host) ? "/.s.PGSQL." : ":", \
58 port
59 55
60enum { 56enum {
61 DEFAULT_PORT = 5432, 57 DEFAULT_PORT = 5432,
@@ -63,33 +59,30 @@ enum {
63 DEFAULT_CRIT = 8 59 DEFAULT_CRIT = 8
64}; 60};
65 61
62static int process_arguments(int /*argc*/, char ** /*argv*/);
63static void print_help(void);
64static bool is_pg_logname(char * /*username*/);
65static int do_query(PGconn * /*conn*/, char * /*query*/);
66void print_usage(void);
67
68static char *pghost = NULL; /* host name of the backend server */
69static char *pgport = NULL; /* port of the backend server */
70static char *pgoptions = NULL;
71static char *pgtty = NULL;
72static char dbName[NAMEDATALEN] = DEFAULT_DB;
73static char *pguser = NULL;
74static char *pgpasswd = NULL;
75static char *pgparams = NULL;
76static double twarn = (double)DEFAULT_WARN;
77static double tcrit = (double)DEFAULT_CRIT;
78static char *pgquery = NULL;
79static char *pgqueryname = NULL;
80static char *query_warning = NULL;
81static char *query_critical = NULL;
82static thresholds *qthresholds = NULL;
83static int verbose = 0;
66 84
67
68int process_arguments (int, char **);
69int validate_arguments (void);
70void print_usage (void);
71void print_help (void);
72bool is_pg_logname (char *);
73int do_query (PGconn *, char *);
74
75char *pghost = NULL; /* host name of the backend server */
76char *pgport = NULL; /* port of the backend server */
77int default_port = DEFAULT_PORT;
78char *pgoptions = NULL;
79char *pgtty = NULL;
80char dbName[NAMEDATALEN] = DEFAULT_DB;
81char *pguser = NULL;
82char *pgpasswd = NULL;
83char *pgparams = NULL;
84double twarn = (double)DEFAULT_WARN;
85double tcrit = (double)DEFAULT_CRIT;
86char *pgquery = NULL;
87#define OPTID_QUERYNAME -1000 85#define OPTID_QUERYNAME -1000
88char *pgqueryname = NULL;
89char *query_warning = NULL;
90char *query_critical = NULL;
91thresholds *qthresholds = NULL;
92int verbose = 0;
93 86
94/****************************************************************************** 87/******************************************************************************
95 88
@@ -141,78 +134,67 @@ Please note that all tags must be lowercase to use the DocBook XML DTD.
141-@@ 134-@@
142******************************************************************************/ 135******************************************************************************/
143 136
144 137int main(int argc, char **argv) {
145 138 setlocale(LC_ALL, "");
146int 139 bindtextdomain(PACKAGE, LOCALEDIR);
147main (int argc, char **argv) 140 textdomain(PACKAGE);
148{
149 PGconn *conn;
150 char *conninfo = NULL;
151
152 struct timeval start_timeval;
153 struct timeval end_timeval;
154 double elapsed_time;
155 int status = STATE_UNKNOWN;
156 int query_status = STATE_UNKNOWN;
157 141
158 /* begin, by setting the parameters for a backend connection if the 142 /* begin, by setting the parameters for a backend connection if the
159 * parameters are null, then the system will try to use reasonable 143 * parameters are null, then the system will try to use reasonable
160 * defaults by looking up environment variables or, failing that, 144 * defaults by looking up environment variables or, failing that,
161 * using hardwired constants */ 145 * using hardwired constants */
162 146
163 pgoptions = NULL; /* special options to start up the backend server */ 147 pgoptions = NULL; /* special options to start up the backend server */
164 pgtty = NULL; /* debugging tty for the backend server */ 148 pgtty = NULL; /* debugging tty for the backend server */
165
166 setlocale (LC_ALL, "");
167 bindtextdomain (PACKAGE, LOCALEDIR);
168 textdomain (PACKAGE);
169 149
170 /* Parse extra opts if any */ 150 /* Parse extra opts if any */
171 argv=np_extra_opts (&argc, argv, progname); 151 argv = np_extra_opts(&argc, argv, progname);
172 152
173 if (process_arguments (argc, argv) == ERROR) 153 if (process_arguments(argc, argv) == ERROR)
174 usage4 (_("Could not parse arguments")); 154 usage4(_("Could not parse arguments"));
175 if (verbose > 2) 155 if (verbose > 2)
176 printf("Arguments initialized\n"); 156 printf("Arguments initialized\n");
177 157
178 /* Set signal handling and alarm */ 158 /* Set signal handling and alarm */
179 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 159 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
180 usage4 (_("Cannot catch SIGALRM")); 160 usage4(_("Cannot catch SIGALRM"));
181 } 161 }
182 alarm (timeout_interval); 162 alarm(timeout_interval);
183 163
164 char *conninfo = NULL;
184 if (pgparams) 165 if (pgparams)
185 asprintf (&conninfo, "%s ", pgparams); 166 asprintf(&conninfo, "%s ", pgparams);
186 167
187 asprintf (&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName); 168 asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName);
188 if (pghost) 169 if (pghost)
189 asprintf (&conninfo, "%s host = '%s'", conninfo, pghost); 170 asprintf(&conninfo, "%s host = '%s'", conninfo, pghost);
190 if (pgport) 171 if (pgport)
191 asprintf (&conninfo, "%s port = '%s'", conninfo, pgport); 172 asprintf(&conninfo, "%s port = '%s'", conninfo, pgport);
192 if (pgoptions) 173 if (pgoptions)
193 asprintf (&conninfo, "%s options = '%s'", conninfo, pgoptions); 174 asprintf(&conninfo, "%s options = '%s'", conninfo, pgoptions);
194 /* if (pgtty) -- ignored by PQconnectdb */ 175 /* if (pgtty) -- ignored by PQconnectdb */
195 if (pguser) 176 if (pguser)
196 asprintf (&conninfo, "%s user = '%s'", conninfo, pguser); 177 asprintf(&conninfo, "%s user = '%s'", conninfo, pguser);
197 178
198 if (verbose) /* do not include password (see right below) in output */ 179 if (verbose) /* do not include password (see right below) in output */
199 printf ("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, 180 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, pgpasswd ? " password = <hidden>" : "");
200 pgpasswd ? " password = <hidden>" : "");
201 181
202 if (pgpasswd) 182 if (pgpasswd)
203 asprintf (&conninfo, "%s password = '%s'", conninfo, pgpasswd); 183 asprintf(&conninfo, "%s password = '%s'", conninfo, pgpasswd);
204 184
205 /* make a connection to the database */ 185 /* make a connection to the database */
206 gettimeofday (&start_timeval, NULL); 186 struct timeval start_timeval;
207 conn = PQconnectdb (conninfo); 187 gettimeofday(&start_timeval, NULL);
208 gettimeofday (&end_timeval, NULL); 188 PGconn *conn = PQconnectdb(conninfo);
189 struct timeval end_timeval;
190 gettimeofday(&end_timeval, NULL);
209 191
210 while (start_timeval.tv_usec > end_timeval.tv_usec) { 192 while (start_timeval.tv_usec > end_timeval.tv_usec) {
211 --end_timeval.tv_sec; 193 --end_timeval.tv_sec;
212 end_timeval.tv_usec += 1000000; 194 end_timeval.tv_usec += 1000000;
213 } 195 }
214 elapsed_time = (double)(end_timeval.tv_sec - start_timeval.tv_sec) 196 double elapsed_time =
215 + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0; 197 (double)(end_timeval.tv_sec - start_timeval.tv_sec) + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0;
216 198
217 if (verbose) 199 if (verbose)
218 printf("Time elapsed: %f\n", elapsed_time); 200 printf("Time elapsed: %f\n", elapsed_time);
@@ -220,152 +202,139 @@ main (int argc, char **argv)
220 /* check to see that the backend connection was successfully made */ 202 /* check to see that the backend connection was successfully made */
221 if (verbose) 203 if (verbose)
222 printf("Verifying connection\n"); 204 printf("Verifying connection\n");
223 if (PQstatus (conn) == CONNECTION_BAD) { 205 if (PQstatus(conn) == CONNECTION_BAD) {
224 printf (_("CRITICAL - no connection to '%s' (%s).\n"), 206 printf(_("CRITICAL - no connection to '%s' (%s).\n"), dbName, PQerrorMessage(conn));
225 dbName, PQerrorMessage (conn)); 207 PQfinish(conn);
226 PQfinish (conn);
227 return STATE_CRITICAL; 208 return STATE_CRITICAL;
228 } 209 }
229 else if (elapsed_time > tcrit) { 210
211 int status = STATE_UNKNOWN;
212 if (elapsed_time > tcrit) {
230 status = STATE_CRITICAL; 213 status = STATE_CRITICAL;
231 } 214 } else if (elapsed_time > twarn) {
232 else if (elapsed_time > twarn) {
233 status = STATE_WARNING; 215 status = STATE_WARNING;
234 } 216 } else {
235 else {
236 status = STATE_OK; 217 status = STATE_OK;
237 } 218 }
238 219
239 if (verbose) { 220 if (verbose) {
240 char *server_host = PQhost (conn); 221 char *server_host = PQhost(conn);
241 int server_version = PQserverVersion (conn); 222 int server_version = PQserverVersion(conn);
242 223
243 printf ("Successfully connected to database %s (user %s) " 224 printf("Successfully connected to database %s (user %s) "
244 "at server %s%s%s (server version: %d.%d.%d, " 225 "at server %s%s%s (server version: %d.%d.%d, "
245 "protocol version: %d, pid: %d)\n", 226 "protocol version: %d, pid: %d)\n",
246 PQdb (conn), PQuser (conn), 227 PQdb(conn), PQuser(conn), PSQL_SOCKET3(server_host, PQport(conn)), PSQL_SERVER_VERSION3(server_version),
247 PSQL_SOCKET3 (server_host, PQport (conn)), 228 PQprotocolVersion(conn), PQbackendPID(conn));
248 PSQL_SERVER_VERSION3 (server_version),
249 PQprotocolVersion (conn), PQbackendPID (conn));
250 } 229 }
251 230
252 printf (_(" %s - database %s (%f sec.)|%s\n"), 231 printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), dbName, elapsed_time,
253 state_text(status), dbName, elapsed_time, 232 fperfdata("time", elapsed_time, "s", !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false, 0));
254 fperfdata("time", elapsed_time, "s",
255 !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false,0));
256 233
234 int query_status = STATE_UNKNOWN;
257 if (pgquery) 235 if (pgquery)
258 query_status = do_query (conn, pgquery); 236 query_status = do_query(conn, pgquery);
259 237
260 if (verbose) 238 if (verbose)
261 printf("Closing connection\n"); 239 printf("Closing connection\n");
262 PQfinish (conn); 240 PQfinish(conn);
263 return (pgquery && query_status > status) ? query_status : status; 241 return (pgquery && query_status > status) ? query_status : status;
264} 242}
265 243
266
267
268/* process command-line arguments */ 244/* process command-line arguments */
269int 245int process_arguments(int argc, char **argv) {
270process_arguments (int argc, char **argv) 246 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
271{ 247 {"version", no_argument, 0, 'V'},
272 int c; 248 {"timeout", required_argument, 0, 't'},
273 249 {"critical", required_argument, 0, 'c'},
274 int option = 0; 250 {"warning", required_argument, 0, 'w'},
275 static struct option longopts[] = { 251 {"hostname", required_argument, 0, 'H'},
276 {"help", no_argument, 0, 'h'}, 252 {"logname", required_argument, 0, 'l'},
277 {"version", no_argument, 0, 'V'}, 253 {"password", required_argument, 0, 'p'},
278 {"timeout", required_argument, 0, 't'}, 254 {"authorization", required_argument, 0, 'a'},
279 {"critical", required_argument, 0, 'c'}, 255 {"port", required_argument, 0, 'P'},
280 {"warning", required_argument, 0, 'w'}, 256 {"database", required_argument, 0, 'd'},
281 {"hostname", required_argument, 0, 'H'}, 257 {"option", required_argument, 0, 'o'},
282 {"logname", required_argument, 0, 'l'}, 258 {"query", required_argument, 0, 'q'},
283 {"password", required_argument, 0, 'p'}, 259 {"queryname", required_argument, 0, OPTID_QUERYNAME},
284 {"authorization", required_argument, 0, 'a'}, 260 {"query_critical", required_argument, 0, 'C'},
285 {"port", required_argument, 0, 'P'}, 261 {"query_warning", required_argument, 0, 'W'},
286 {"database", required_argument, 0, 'd'}, 262 {"verbose", no_argument, 0, 'v'},
287 {"option", required_argument, 0, 'o'}, 263 {0, 0, 0, 0}};
288 {"query", required_argument, 0, 'q'}, 264
289 {"queryname", required_argument, 0, OPTID_QUERYNAME}, 265 while (true) {
290 {"query_critical", required_argument, 0, 'C'}, 266 int option = 0;
291 {"query_warning", required_argument, 0, 'W'}, 267 int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option);
292 {"verbose", no_argument, 0, 'v'}, 268
293 {0, 0, 0, 0} 269 if (option_char == EOF)
294 };
295
296 while (1) {
297 c = getopt_long (argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v",
298 longopts, &option);
299
300 if (c == EOF)
301 break; 270 break;
302 271
303 switch (c) { 272 switch (option_char) {
304 case '?': /* usage */ 273 case '?': /* usage */
305 usage5 (); 274 usage5();
306 case 'h': /* help */ 275 case 'h': /* help */
307 print_help (); 276 print_help();
308 exit (STATE_UNKNOWN); 277 exit(STATE_UNKNOWN);
309 case 'V': /* version */ 278 case 'V': /* version */
310 print_revision (progname, NP_VERSION); 279 print_revision(progname, NP_VERSION);
311 exit (STATE_UNKNOWN); 280 exit(STATE_UNKNOWN);
312 case 't': /* timeout period */ 281 case 't': /* timeout period */
313 if (!is_integer (optarg)) 282 if (!is_integer(optarg))
314 usage2 (_("Timeout interval must be a positive integer"), optarg); 283 usage2(_("Timeout interval must be a positive integer"), optarg);
315 else 284 else
316 timeout_interval = atoi (optarg); 285 timeout_interval = atoi(optarg);
317 break; 286 break;
318 case 'c': /* critical time threshold */ 287 case 'c': /* critical time threshold */
319 if (!is_nonnegative (optarg)) 288 if (!is_nonnegative(optarg))
320 usage2 (_("Critical threshold must be a positive integer"), optarg); 289 usage2(_("Critical threshold must be a positive integer"), optarg);
321 else 290 else
322 tcrit = strtod (optarg, NULL); 291 tcrit = strtod(optarg, NULL);
323 break; 292 break;
324 case 'w': /* warning time threshold */ 293 case 'w': /* warning time threshold */
325 if (!is_nonnegative (optarg)) 294 if (!is_nonnegative(optarg))
326 usage2 (_("Warning threshold must be a positive integer"), optarg); 295 usage2(_("Warning threshold must be a positive integer"), optarg);
327 else 296 else
328 twarn = strtod (optarg, NULL); 297 twarn = strtod(optarg, NULL);
329 break; 298 break;
330 case 'C': /* critical query threshold */ 299 case 'C': /* critical query threshold */
331 query_critical = optarg; 300 query_critical = optarg;
332 break; 301 break;
333 case 'W': /* warning query threshold */ 302 case 'W': /* warning query threshold */
334 query_warning = optarg; 303 query_warning = optarg;
335 break; 304 break;
336 case 'H': /* host */ 305 case 'H': /* host */
337 if ((*optarg != '/') && (!is_host (optarg))) 306 if ((*optarg != '/') && (!is_host(optarg)))
338 usage2 (_("Invalid hostname/address"), optarg); 307 usage2(_("Invalid hostname/address"), optarg);
339 else 308 else
340 pghost = optarg; 309 pghost = optarg;
341 break; 310 break;
342 case 'P': /* port */ 311 case 'P': /* port */
343 if (!is_integer (optarg)) 312 if (!is_integer(optarg))
344 usage2 (_("Port must be a positive integer"), optarg); 313 usage2(_("Port must be a positive integer"), optarg);
345 else 314 else
346 pgport = optarg; 315 pgport = optarg;
347 break; 316 break;
348 case 'd': /* database name */ 317 case 'd': /* database name */
349 if (strlen(optarg) >= NAMEDATALEN) { 318 if (strlen(optarg) >= NAMEDATALEN) {
350 usage2 (_("Database name exceeds the maximum length"), optarg); 319 usage2(_("Database name exceeds the maximum length"), optarg);
351 } 320 }
352 snprintf(dbName, NAMEDATALEN, "%s", optarg); 321 snprintf(dbName, NAMEDATALEN, "%s", optarg);
353 break; 322 break;
354 case 'l': /* login name */ 323 case 'l': /* login name */
355 if (!is_pg_logname (optarg)) 324 if (!is_pg_logname(optarg))
356 usage2 (_("User name is not valid"), optarg); 325 usage2(_("User name is not valid"), optarg);
357 else 326 else
358 pguser = optarg; 327 pguser = optarg;
359 break; 328 break;
360 case 'p': /* authentication password */ 329 case 'p': /* authentication password */
361 case 'a': 330 case 'a':
362 pgpasswd = optarg; 331 pgpasswd = optarg;
363 break; 332 break;
364 case 'o': 333 case 'o':
365 if (pgparams) 334 if (pgparams)
366 asprintf (&pgparams, "%s %s", pgparams, optarg); 335 asprintf(&pgparams, "%s %s", pgparams, optarg);
367 else 336 else
368 asprintf (&pgparams, "%s", optarg); 337 asprintf(&pgparams, "%s", optarg);
369 break; 338 break;
370 case 'q': 339 case 'q':
371 pgquery = optarg; 340 pgquery = optarg;
@@ -379,37 +348,8 @@ process_arguments (int argc, char **argv)
379 } 348 }
380 } 349 }
381 350
382 set_thresholds (&qthresholds, query_warning, query_critical); 351 set_thresholds(&qthresholds, query_warning, query_critical);
383
384 return validate_arguments ();
385}
386
387
388/******************************************************************************
389
390@@-
391<sect3>
392<title>validate_arguments</title>
393
394<para>&PROTO_validate_arguments;</para>
395
396<para>Given a database name, this function returns true if the string
397is a valid PostgreSQL database name, and returns false if it is
398not.</para>
399 352
400<para>Valid PostgreSQL database names are less than &NAMEDATALEN;
401characters long and consist of letters, numbers, and underscores. The
402first character cannot be a number, however.</para>
403
404</sect3>
405-@@
406******************************************************************************/
407
408
409
410int
411validate_arguments ()
412{
413 return OK; 353 return OK;
414} 354}
415 355
@@ -437,10 +377,8 @@ should be added.</para>
437-@@ 377-@@
438******************************************************************************/ 378******************************************************************************/
439 379
440 380bool is_pg_logname(char *username) {
441 381 if (strlen(username) > NAMEDATALEN - 1)
442bool is_pg_logname (char *username) {
443 if (strlen (username) > NAMEDATALEN - 1)
444 return (false); 382 return (false);
445 return (true); 383 return (true);
446} 384}
@@ -453,182 +391,155 @@ bool is_pg_logname (char *username) {
453-@@ 391-@@
454******************************************************************************/ 392******************************************************************************/
455 393
456 394void print_help(void) {
457
458void
459print_help (void)
460{
461 char *myport; 395 char *myport;
462 396
463 xasprintf (&myport, "%d", DEFAULT_PORT); 397 xasprintf(&myport, "%d", DEFAULT_PORT);
464 398
465 print_revision (progname, NP_VERSION); 399 print_revision(progname, NP_VERSION);
466 400
467 printf (COPYRIGHT, copyright, email); 401 printf(COPYRIGHT, copyright, email);
468 402
469 printf (_("Test whether a PostgreSQL Database is accepting connections.")); 403 printf(_("Test whether a PostgreSQL Database is accepting connections."));
470 404
471 printf ("\n\n"); 405 printf("\n\n");
472 406
473 print_usage (); 407 print_usage();
474 408
475 printf (UT_HELP_VRSN); 409 printf(UT_HELP_VRSN);
476 printf (UT_EXTRA_OPTS); 410 printf(UT_EXTRA_OPTS);
477 411
478 printf (UT_HOST_PORT, 'P', myport); 412 printf(UT_HOST_PORT, 'P', myport);
479 413
480 printf (" %s\n", "-d, --database=STRING"); 414 printf(" %s\n", "-d, --database=STRING");
481 printf (" %s", _("Database to check ")); 415 printf(" %s", _("Database to check "));
482 printf (_("(default: %s)\n"), DEFAULT_DB); 416 printf(_("(default: %s)\n"), DEFAULT_DB);
483 printf (" %s\n", "-l, --logname = STRING"); 417 printf(" %s\n", "-l, --logname = STRING");
484 printf (" %s\n", _("Login name of user")); 418 printf(" %s\n", _("Login name of user"));
485 printf (" %s\n", "-p, --password = STRING"); 419 printf(" %s\n", "-p, --password = STRING");
486 printf (" %s\n", _("Password (BIG SECURITY ISSUE)")); 420 printf(" %s\n", _("Password (BIG SECURITY ISSUE)"));
487 printf (" %s\n", "-o, --option = STRING"); 421 printf(" %s\n", "-o, --option = STRING");
488 printf (" %s\n", _("Connection parameters (keyword = value), see below")); 422 printf(" %s\n", _("Connection parameters (keyword = value), see below"));
489 423
490 printf (UT_WARN_CRIT); 424 printf(UT_WARN_CRIT);
491 425
492 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 426 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
493 427
494 printf (" %s\n", "-q, --query=STRING"); 428 printf(" %s\n", "-q, --query=STRING");
495 printf (" %s\n", _("SQL query to run. Only first column in first row will be read")); 429 printf(" %s\n", _("SQL query to run. Only first column in first row will be read"));
496 printf (" %s\n", "--queryname=STRING"); 430 printf(" %s\n", "--queryname=STRING");
497 printf (" %s\n", _("A name for the query, this string is used instead of the query")); 431 printf(" %s\n", _("A name for the query, this string is used instead of the query"));
498 printf (" %s\n", _("in the long output of the plugin")); 432 printf(" %s\n", _("in the long output of the plugin"));
499 printf (" %s\n", "-W, --query-warning=RANGE"); 433 printf(" %s\n", "-W, --query-warning=RANGE");
500 printf (" %s\n", _("SQL query value to result in warning status (double)")); 434 printf(" %s\n", _("SQL query value to result in warning status (double)"));
501 printf (" %s\n", "-C, --query-critical=RANGE"); 435 printf(" %s\n", "-C, --query-critical=RANGE");
502 printf (" %s\n", _("SQL query value to result in critical status (double)")); 436 printf(" %s\n", _("SQL query value to result in critical status (double)"));
503 437
504 printf (UT_VERBOSE); 438 printf(UT_VERBOSE);
505 439
506 printf ("\n"); 440 printf("\n");
507 printf (" %s\n", _("All parameters are optional.")); 441 printf(" %s\n", _("All parameters are optional."));
508 printf (" %s\n", _("This plugin tests a PostgreSQL DBMS to determine whether it is active and")); 442 printf(" %s\n", _("This plugin tests a PostgreSQL DBMS to determine whether it is active and"));
509 printf (" %s\n", _("accepting queries. In its current operation, it simply connects to the")); 443 printf(" %s\n", _("accepting queries. In its current operation, it simply connects to the"));
510 printf (" %s\n", _("specified database, and then disconnects. If no database is specified, it")); 444 printf(" %s\n", _("specified database, and then disconnects. If no database is specified, it"));
511 printf (" %s\n", _("connects to the template1 database, which is present in every functioning")); 445 printf(" %s\n", _("connects to the template1 database, which is present in every functioning"));
512 printf (" %s\n\n", _("PostgreSQL DBMS.")); 446 printf(" %s\n\n", _("PostgreSQL DBMS."));
513 447
514 printf (" %s\n", _("If a query is specified using the -q option, it will be executed after")); 448 printf(" %s\n", _("If a query is specified using the -q option, it will be executed after"));
515 printf (" %s\n", _("connecting to the server. The result from the query has to be numeric.")); 449 printf(" %s\n", _("connecting to the server. The result from the query has to be numeric."));
516 printf (" %s\n", _("Multiple SQL commands, separated by semicolon, are allowed but the result ")); 450 printf(" %s\n", _("Multiple SQL commands, separated by semicolon, are allowed but the result "));
517 printf (" %s\n", _("of the last command is taken into account only. The value of the first")); 451 printf(" %s\n", _("of the last command is taken into account only. The value of the first"));
518 printf (" %s\n", _("column in the first row is used as the check result. If a second column is")); 452 printf(" %s\n", _("column in the first row is used as the check result. If a second column is"));
519 printf (" %s\n", _("present in the result set, this is added to the plugin output with a")); 453 printf(" %s\n", _("present in the result set, this is added to the plugin output with a"));
520 printf (" %s\n", _("prefix of \"Extra Info:\". This information can be displayed in the system")); 454 printf(" %s\n", _("prefix of \"Extra Info:\". This information can be displayed in the system"));
521 printf (" %s\n\n", _("executing the plugin.")); 455 printf(" %s\n\n", _("executing the plugin."));
522 456
523 printf (" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual")); 457 printf(" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual"));
524 printf (" %s\n\n", _("for details about how to access internal statistics of the database server.")); 458 printf(" %s\n\n", _("for details about how to access internal statistics of the database server."));
525 459
526 printf (" %s\n", _("For a list of available connection parameters which may be used with the -o")); 460 printf(" %s\n", _("For a list of available connection parameters which may be used with the -o"));
527 printf (" %s\n", _("command line option, see the documentation for PQconnectdb() in the chapter")); 461 printf(" %s\n", _("command line option, see the documentation for PQconnectdb() in the chapter"));
528 printf (" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be")); 462 printf(" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be"));
529 printf (" %s\n", _("used to specify a service name in pg_service.conf to be used for additional")); 463 printf(" %s\n", _("used to specify a service name in pg_service.conf to be used for additional"));
530 printf (" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:")); 464 printf(" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:"));
531 printf (" %s\n\n", _("-o 'sslmode=require'.")); 465 printf(" %s\n\n", _("-o 'sslmode=require'."));
532 466
533 printf (" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To")); 467 printf(" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To"));
534 printf (" %s\n", _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP")); 468 printf(" %s\n", _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP"));
535 printf (" %s\n\n", _("connections (start the postmaster with the -i option).")); 469 printf(" %s\n\n", _("connections (start the postmaster with the -i option)."));
536 470
537 printf (" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be")); 471 printf(" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be"));
538 printf (" %s\n", _("able to connect to the database without a password. The plugin can also send")); 472 printf(" %s\n", _("able to connect to the database without a password. The plugin can also send"));
539 printf (" %s\n", _("a password, but no effort is made to obscure or encrypt the password.")); 473 printf(" %s\n", _("a password, but no effort is made to obscure or encrypt the password."));
540 474
541 printf (UT_SUPPORT); 475 printf(UT_SUPPORT);
542} 476}
543 477
544 478void print_usage(void) {
545 479 printf("%s\n", _("Usage:"));
546void 480 printf("%s [-H <host>] [-P <port>] [-c <critical time>] [-w <warning time>]\n", progname);
547print_usage (void) 481 printf(" [-t <timeout>] [-d <database>] [-l <logname>] [-p <password>]\n"
548{ 482 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
549 printf ("%s\n", _("Usage:"));
550 printf ("%s [-H <host>] [-P <port>] [-c <critical time>] [-w <warning time>]\n", progname);
551 printf (" [-t <timeout>] [-d <database>] [-l <logname>] [-p <password>]\n"
552 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
553} 483}
554 484
555int 485int do_query(PGconn *conn, char *query) {
556do_query (PGconn *conn, char *query)
557{
558 PGresult *res;
559
560 char *val_str;
561 char *extra_info;
562 double value;
563
564 char *endptr = NULL;
565
566 int my_status = STATE_UNKNOWN;
567
568 if (verbose) 486 if (verbose)
569 printf ("Executing SQL query \"%s\".\n", query); 487 printf("Executing SQL query \"%s\".\n", query);
570 res = PQexec (conn, query); 488 PGresult *res = PQexec(conn, query);
571 489
572 if (PGRES_TUPLES_OK != PQresultStatus (res)) { 490 if (PGRES_TUPLES_OK != PQresultStatus(res)) {
573 printf (_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), 491 printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), PQerrorMessage(conn));
574 PQerrorMessage (conn));
575 return STATE_CRITICAL; 492 return STATE_CRITICAL;
576 } 493 }
577 494
578 if (PQntuples (res) < 1) { 495 if (PQntuples(res) < 1) {
579 printf ("QUERY %s - %s.\n", _("WARNING"), _("No rows returned")); 496 printf("QUERY %s - %s.\n", _("WARNING"), _("No rows returned"));
580 return STATE_WARNING; 497 return STATE_WARNING;
581 } 498 }
582 499
583 if (PQnfields (res) < 1) { 500 if (PQnfields(res) < 1) {
584 printf ("QUERY %s - %s.\n", _("WARNING"), _("No columns returned")); 501 printf("QUERY %s - %s.\n", _("WARNING"), _("No columns returned"));
585 return STATE_WARNING; 502 return STATE_WARNING;
586 } 503 }
587 504
588 val_str = PQgetvalue (res, 0, 0); 505 char *val_str = PQgetvalue(res, 0, 0);
589 if (! val_str) { 506 if (!val_str) {
590 printf ("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned")); 507 printf("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned"));
591 return STATE_CRITICAL; 508 return STATE_CRITICAL;
592 } 509 }
593 510
594 value = strtod (val_str, &endptr); 511 char *endptr = NULL;
512 double value = strtod(val_str, &endptr);
595 if (verbose) 513 if (verbose)
596 printf ("Query result: %f\n", value); 514 printf("Query result: %f\n", value);
597 515
598 if (endptr == val_str) { 516 if (endptr == val_str) {
599 printf ("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); 517 printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str);
600 return STATE_CRITICAL; 518 return STATE_CRITICAL;
601 } 519 }
602 else if ((endptr != NULL) && (*endptr != '\0')) { 520
521 if ((endptr != NULL) && (*endptr != '\0')) {
603 if (verbose) 522 if (verbose)
604 printf ("Garbage after value: %s.\n", endptr); 523 printf("Garbage after value: %s.\n", endptr);
605 } 524 }
606 525
607 my_status = get_status (value, qthresholds); 526 int my_status = get_status(value, qthresholds);
608 printf ("QUERY %s - ", 527 printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK")
609 (my_status == STATE_OK) 528 : (my_status == STATE_WARNING) ? _("WARNING")
610 ? _("OK") 529 : (my_status == STATE_CRITICAL) ? _("CRITICAL")
611 : (my_status == STATE_WARNING) 530 : _("UNKNOWN"));
612 ? _("WARNING") 531 if (pgqueryname) {
613 : (my_status == STATE_CRITICAL) 532 printf(_("%s returned %f"), pgqueryname, value);
614 ? _("CRITICAL") 533 } else {
615 : _("UNKNOWN")); 534 printf(_("'%s' returned %f"), query, value);
616 if(pgqueryname) {
617 printf (_("%s returned %f"), pgqueryname, value);
618 }
619 else {
620 printf (_("'%s' returned %f"), query, value);
621 } 535 }
622 536
623 printf ("|query=%f;%s;%s;;\n", value, 537 printf("|query=%f;%s;%s;;\n", value, query_warning ? query_warning : "", query_critical ? query_critical : "");
624 query_warning ? query_warning : "", 538 if (PQnfields(res) > 1) {
625 query_critical ? query_critical : ""); 539 char *extra_info = PQgetvalue(res, 0, 1);
626 if (PQnfields (res) > 1) {
627 extra_info = PQgetvalue (res, 0, 1);
628 if (extra_info != NULL) { 540 if (extra_info != NULL) {
629 printf ("Extra Info: %s\n", extra_info); 541 printf("Extra Info: %s\n", extra_info);
630 } 542 }
631 } 543 }
632 return my_status; 544 return my_status;
633} 545}
634
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
index 6e162e6a..4aafaf41 100644
--- a/plugins/check_ping.c
+++ b/plugins/check_ping.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ping plugin 3 * Monitoring check_ping plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_ping plugin 10 * This file contains the check_ping plugin
11* 11 *
12* Use the ping program to check connection statistics for a remote host. 12 * Use the ping program to check connection statistics for a remote host.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_ping"; 31const char *progname = "check_ping";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -39,77 +39,73 @@ const char *email = "devel@monitoring-plugins.org";
39 39
40#include <signal.h> 40#include <signal.h>
41 41
42#define WARN_DUPLICATES "DUPLICATES FOUND! " 42#define WARN_DUPLICATES "DUPLICATES FOUND! "
43#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */ 43#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
44 44
45enum { 45enum {
46 UNKNOWN_PACKET_LOSS = 200, /* 200% */ 46 UNKNOWN_PACKET_LOSS = 200, /* 200% */
47 DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */ 47 DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */
48}; 48};
49 49
50int process_arguments (int, char **); 50static int process_arguments(int /*argc*/, char ** /*argv*/);
51int get_threshold (char *, float *, int *); 51static int get_threshold(char * /*arg*/, float * /*trta*/, int * /*tpl*/);
52int validate_arguments (void); 52static int validate_arguments(void);
53int run_ping (const char *cmd, const char *addr); 53static int run_ping(const char *cmd, const char *addr);
54int error_scan (char buf[MAX_INPUT_BUFFER], const char *addr); 54static int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr);
55void print_usage (void); 55static void print_help(void);
56void print_help (void); 56void print_usage(void);
57 57
58bool display_html = false; 58static bool display_html = false;
59int wpl = UNKNOWN_PACKET_LOSS; 59static int wpl = UNKNOWN_PACKET_LOSS;
60int cpl = UNKNOWN_PACKET_LOSS; 60static int cpl = UNKNOWN_PACKET_LOSS;
61float wrta = UNKNOWN_TRIP_TIME; 61static float wrta = UNKNOWN_TRIP_TIME;
62float crta = UNKNOWN_TRIP_TIME; 62static float crta = UNKNOWN_TRIP_TIME;
63char **addresses = NULL; 63static char **addresses = NULL;
64int n_addresses = 0; 64static int n_addresses = 0;
65int max_addr = 1; 65static int max_addr = 1;
66int max_packets = -1; 66static int max_packets = -1;
67int verbose = 0; 67static int verbose = 0;
68 68
69float rta = UNKNOWN_TRIP_TIME; 69static float rta = UNKNOWN_TRIP_TIME;
70int pl = UNKNOWN_PACKET_LOSS; 70static int pl = UNKNOWN_PACKET_LOSS;
71 71
72char *warn_text; 72static char *warn_text;
73 73
74 74int main(int argc, char **argv) {
75
76int
77main (int argc, char **argv)
78{
79 char *cmd = NULL; 75 char *cmd = NULL;
80 char *rawcmd = NULL; 76 char *rawcmd = NULL;
81 int result = STATE_UNKNOWN; 77 int result = STATE_UNKNOWN;
82 int this_result = STATE_UNKNOWN; 78 int this_result = STATE_UNKNOWN;
83 int i; 79 int i;
84 80
85 setlocale (LC_ALL, ""); 81 setlocale(LC_ALL, "");
86 setlocale (LC_NUMERIC, "C"); 82 setlocale(LC_NUMERIC, "C");
87 bindtextdomain (PACKAGE, LOCALEDIR); 83 bindtextdomain(PACKAGE, LOCALEDIR);
88 textdomain (PACKAGE); 84 textdomain(PACKAGE);
89 85
90 addresses = malloc (sizeof(char*) * max_addr); 86 addresses = malloc(sizeof(char *) * max_addr);
91 addresses[0] = NULL; 87 addresses[0] = NULL;
92 88
93 /* Parse extra opts if any */ 89 /* Parse extra opts if any */
94 argv=np_extra_opts (&argc, argv, progname); 90 argv = np_extra_opts(&argc, argv, progname);
95 91
96 if (process_arguments (argc, argv) == ERROR) 92 if (process_arguments(argc, argv) == ERROR)
97 usage4 (_("Could not parse arguments")); 93 usage4(_("Could not parse arguments"));
98 94
99 /* Set signal handling and alarm */ 95 /* Set signal handling and alarm */
100 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { 96 if (signal(SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
101 usage4 (_("Cannot catch SIGALRM")); 97 usage4(_("Cannot catch SIGALRM"));
102 } 98 }
103 99
104 /* If ./configure finds ping has timeout values, set plugin alarm slightly 100 /* If ./configure finds ping has timeout values, set plugin alarm slightly
105 * higher so that we can use response from command line ping */ 101 * higher so that we can use response from command line ping */
106#if defined(PING_PACKETS_FIRST) && defined(PING_HAS_TIMEOUT) 102#if defined(PING_PACKETS_FIRST) && defined(PING_HAS_TIMEOUT)
107 alarm (timeout_interval + 1); 103 alarm(timeout_interval + 1);
108#else 104#else
109 alarm (timeout_interval); 105 alarm(timeout_interval);
110#endif 106#endif
111 107
112 for (i = 0 ; i < n_addresses ; i++) { 108 for (i = 0; i < n_addresses; i++) {
113 109
114#ifdef PING6_COMMAND 110#ifdef PING6_COMMAND
115 if (address_family != AF_INET && is_inet6_addr(addresses[i])) 111 if (address_family != AF_INET && is_inet6_addr(addresses[i]))
@@ -120,27 +116,26 @@ main (int argc, char **argv)
120 rawcmd = strdup(PING_COMMAND); 116 rawcmd = strdup(PING_COMMAND);
121#endif 117#endif
122 118
123 /* does the host address of number of packets argument come first? */ 119 /* does the host address of number of packets argument come first? */
124#ifdef PING_PACKETS_FIRST 120#ifdef PING_PACKETS_FIRST
125# ifdef PING_HAS_TIMEOUT 121# ifdef PING_HAS_TIMEOUT
126 xasprintf (&cmd, rawcmd, timeout_interval, max_packets, addresses[i]); 122 xasprintf(&cmd, rawcmd, timeout_interval, max_packets, addresses[i]);
127# else 123# else
128 xasprintf (&cmd, rawcmd, max_packets, addresses[i]); 124 xasprintf(&cmd, rawcmd, max_packets, addresses[i]);
129# endif 125# endif
130#else 126#else
131 xasprintf (&cmd, rawcmd, addresses[i], max_packets); 127 xasprintf(&cmd, rawcmd, addresses[i], max_packets);
132#endif 128#endif
133 129
134 if (verbose >= 2) 130 if (verbose >= 2)
135 printf ("CMD: %s\n", cmd); 131 printf("CMD: %s\n", cmd);
136 132
137 /* run the command */ 133 /* run the command */
138 this_result = run_ping (cmd, addresses[i]); 134 this_result = run_ping(cmd, addresses[i]);
139 135
140 if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) { 136 if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) {
141 printf ("%s\n", cmd); 137 printf("%s\n", cmd);
142 die (STATE_UNKNOWN, 138 die(STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n"));
143 _("CRITICAL - Could not interpret output from ping command\n"));
144 } 139 }
145 140
146 if (pl >= cpl || rta >= crta || rta < 0) 141 if (pl >= cpl || rta >= crta || rta < 0)
@@ -148,267 +143,241 @@ main (int argc, char **argv)
148 else if (pl >= wpl || rta >= wrta) 143 else if (pl >= wpl || rta >= wrta)
149 this_result = STATE_WARNING; 144 this_result = STATE_WARNING;
150 else if (pl >= 0 && rta >= 0) 145 else if (pl >= 0 && rta >= 0)
151 this_result = max_state (STATE_OK, this_result); 146 this_result = max_state(STATE_OK, this_result);
152 147
153 if (n_addresses > 1 && this_result != STATE_UNKNOWN) 148 if (n_addresses > 1 && this_result != STATE_UNKNOWN)
154 die (STATE_OK, "%s is alive\n", addresses[i]); 149 die(STATE_OK, "%s is alive\n", addresses[i]);
155 150
156 if (display_html == true) 151 if (display_html == true)
157 printf ("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]); 152 printf("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]);
158 if (pl == 100) 153 if (pl == 100)
159 printf (_("PING %s - %sPacket loss = %d%%"), state_text (this_result), warn_text, 154 printf(_("PING %s - %sPacket loss = %d%%"), state_text(this_result), warn_text, pl);
160 pl);
161 else 155 else
162 printf (_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), 156 printf(_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), state_text(this_result), warn_text, pl, rta);
163 state_text (this_result), warn_text, pl, rta);
164 if (display_html == true) 157 if (display_html == true)
165 printf ("</A>"); 158 printf("</A>");
166 159
167 /* Print performance data */ 160 /* Print performance data */
168 if (pl != 100) { 161 if (pl != 100) {
169 printf("|%s", fperfdata ("rta", (double) rta, "ms", 162 printf("|%s",
170 wrta>0?true:false, wrta, 163 fperfdata("rta", (double)rta, "ms", wrta > 0 ? true : false, wrta, crta > 0 ? true : false, crta, true, 0, false, 0));
171 crta>0?true:false, crta,
172 true, 0, false, 0));
173 } else { 164 } else {
174 printf("| rta=U;%f;%f;;", wrta, crta); 165 printf("| rta=U;%f;%f;;", wrta, crta);
175 } 166 }
176 printf(" %s\n", perfdata ("pl", (long) pl, "%", 167 printf(" %s\n", perfdata("pl", (long)pl, "%", wpl > 0 ? true : false, wpl, cpl > 0 ? true : false, cpl, true, 0, false, 0));
177 wpl>0?true:false, wpl,
178 cpl>0?true:false, cpl,
179 true, 0, false, 0));
180 168
181 if (verbose >= 2) 169 if (verbose >= 2)
182 printf ("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl); 170 printf("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl);
183 171
184 result = max_state (result, this_result); 172 result = max_state(result, this_result);
185 free (rawcmd); 173 free(rawcmd);
186 free (cmd); 174 free(cmd);
187 } 175 }
188 176
189 return result; 177 return result;
190} 178}
191 179
192
193
194/* process command-line arguments */ 180/* process command-line arguments */
195int 181int process_arguments(int argc, char **argv) {
196process_arguments (int argc, char **argv)
197{
198 int c = 1; 182 int c = 1;
199 char *ptr; 183 char *ptr;
200 184
201 int option = 0; 185 int option = 0;
202 static struct option longopts[] = { 186 static struct option longopts[] = {STD_LONG_OPTS,
203 STD_LONG_OPTS, 187 {"packets", required_argument, 0, 'p'},
204 {"packets", required_argument, 0, 'p'}, 188 {"nohtml", no_argument, 0, 'n'},
205 {"nohtml", no_argument, 0, 'n'}, 189 {"link", no_argument, 0, 'L'},
206 {"link", no_argument, 0, 'L'}, 190 {"use-ipv4", no_argument, 0, '4'},
207 {"use-ipv4", no_argument, 0, '4'}, 191 {"use-ipv6", no_argument, 0, '6'},
208 {"use-ipv6", no_argument, 0, '6'}, 192 {0, 0, 0, 0}};
209 {0, 0, 0, 0}
210 };
211 193
212 if (argc < 2) 194 if (argc < 2)
213 return ERROR; 195 return ERROR;
214 196
215 for (c = 1; c < argc; c++) { 197 for (c = 1; c < argc; c++) {
216 if (strcmp ("-to", argv[c]) == 0) 198 if (strcmp("-to", argv[c]) == 0)
217 strcpy (argv[c], "-t"); 199 strcpy(argv[c], "-t");
218 if (strcmp ("-nohtml", argv[c]) == 0) 200 if (strcmp("-nohtml", argv[c]) == 0)
219 strcpy (argv[c], "-n"); 201 strcpy(argv[c], "-n");
220 } 202 }
221 203
222 while (1) { 204 while (1) {
223 c = getopt_long (argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option); 205 c = getopt_long(argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option);
224 206
225 if (c == -1 || c == EOF) 207 if (c == -1 || c == EOF)
226 break; 208 break;
227 209
228 switch (c) { 210 switch (c) {
229 case '?': /* usage */ 211 case '?': /* usage */
230 usage5 (); 212 usage5();
231 case 'h': /* help */ 213 case 'h': /* help */
232 print_help (); 214 print_help();
233 exit (STATE_UNKNOWN); 215 exit(STATE_UNKNOWN);
234 break; 216 break;
235 case 'V': /* version */ 217 case 'V': /* version */
236 print_revision (progname, NP_VERSION); 218 print_revision(progname, NP_VERSION);
237 exit (STATE_UNKNOWN); 219 exit(STATE_UNKNOWN);
238 break; 220 break;
239 case 't': /* timeout period */ 221 case 't': /* timeout period */
240 timeout_interval = atoi (optarg); 222 timeout_interval = atoi(optarg);
241 break; 223 break;
242 case 'v': /* verbose mode */ 224 case 'v': /* verbose mode */
243 verbose++; 225 verbose++;
244 break; 226 break;
245 case '4': /* IPv4 only */ 227 case '4': /* IPv4 only */
246 address_family = AF_INET; 228 address_family = AF_INET;
247 break; 229 break;
248 case '6': /* IPv6 only */ 230 case '6': /* IPv6 only */
249#ifdef USE_IPV6 231#ifdef USE_IPV6
250 address_family = AF_INET6; 232 address_family = AF_INET6;
251#else 233#else
252 usage (_("IPv6 support not available\n")); 234 usage(_("IPv6 support not available\n"));
253#endif 235#endif
254 break; 236 break;
255 case 'H': /* hostname */ 237 case 'H': /* hostname */
256 ptr=optarg; 238 ptr = optarg;
257 while (1) { 239 while (1) {
258 n_addresses++; 240 n_addresses++;
259 if (n_addresses > max_addr) { 241 if (n_addresses > max_addr) {
260 max_addr *= 2; 242 max_addr *= 2;
261 addresses = realloc (addresses, sizeof(char*) * max_addr); 243 addresses = realloc(addresses, sizeof(char *) * max_addr);
262 if (addresses == NULL) 244 if (addresses == NULL)
263 die (STATE_UNKNOWN, _("Could not realloc() addresses\n")); 245 die(STATE_UNKNOWN, _("Could not realloc() addresses\n"));
264 } 246 }
265 addresses[n_addresses-1] = ptr; 247 addresses[n_addresses - 1] = ptr;
266 if ((ptr = index (ptr, ','))) { 248 if ((ptr = index(ptr, ','))) {
267 strcpy (ptr, ""); 249 strcpy(ptr, "");
268 ptr += sizeof(char); 250 ptr += sizeof(char);
269 } else { 251 } else {
270 break; 252 break;
271 } 253 }
272 } 254 }
273 break; 255 break;
274 case 'p': /* number of packets to send */ 256 case 'p': /* number of packets to send */
275 if (is_intnonneg (optarg)) 257 if (is_intnonneg(optarg))
276 max_packets = atoi (optarg); 258 max_packets = atoi(optarg);
277 else 259 else
278 usage2 (_("<max_packets> (%s) must be a non-negative number\n"), optarg); 260 usage2(_("<max_packets> (%s) must be a non-negative number\n"), optarg);
279 break; 261 break;
280 case 'n': /* no HTML */ 262 case 'n': /* no HTML */
281 display_html = false; 263 display_html = false;
282 break; 264 break;
283 case 'L': /* show HTML */ 265 case 'L': /* show HTML */
284 display_html = true; 266 display_html = true;
285 break; 267 break;
286 case 'c': 268 case 'c':
287 get_threshold (optarg, &crta, &cpl); 269 get_threshold(optarg, &crta, &cpl);
288 break; 270 break;
289 case 'w': 271 case 'w':
290 get_threshold (optarg, &wrta, &wpl); 272 get_threshold(optarg, &wrta, &wpl);
291 break; 273 break;
292 } 274 }
293 } 275 }
294 276
295 c = optind; 277 c = optind;
296 if (c == argc) 278 if (c == argc)
297 return validate_arguments (); 279 return validate_arguments();
298 280
299 if (addresses[0] == NULL) { 281 if (addresses[0] == NULL) {
300 if (!is_host (argv[c])) { 282 if (!is_host(argv[c])) {
301 usage2 (_("Invalid hostname/address"), argv[c]); 283 usage2(_("Invalid hostname/address"), argv[c]);
302 } else { 284 } else {
303 addresses[0] = argv[c++]; 285 addresses[0] = argv[c++];
304 n_addresses++; 286 n_addresses++;
305 if (c == argc) 287 if (c == argc)
306 return validate_arguments (); 288 return validate_arguments();
307 } 289 }
308 } 290 }
309 291
310 if (wpl == UNKNOWN_PACKET_LOSS) { 292 if (wpl == UNKNOWN_PACKET_LOSS) {
311 if (!is_intpercent (argv[c])) { 293 if (!is_intpercent(argv[c])) {
312 printf (_("<wpl> (%s) must be an integer percentage\n"), argv[c]); 294 printf(_("<wpl> (%s) must be an integer percentage\n"), argv[c]);
313 return ERROR; 295 return ERROR;
314 } else { 296 } else {
315 wpl = atoi (argv[c++]); 297 wpl = atoi(argv[c++]);
316 if (c == argc) 298 if (c == argc)
317 return validate_arguments (); 299 return validate_arguments();
318 } 300 }
319 } 301 }
320 302
321 if (cpl == UNKNOWN_PACKET_LOSS) { 303 if (cpl == UNKNOWN_PACKET_LOSS) {
322 if (!is_intpercent (argv[c])) { 304 if (!is_intpercent(argv[c])) {
323 printf (_("<cpl> (%s) must be an integer percentage\n"), argv[c]); 305 printf(_("<cpl> (%s) must be an integer percentage\n"), argv[c]);
324 return ERROR; 306 return ERROR;
325 } else { 307 } else {
326 cpl = atoi (argv[c++]); 308 cpl = atoi(argv[c++]);
327 if (c == argc) 309 if (c == argc)
328 return validate_arguments (); 310 return validate_arguments();
329 } 311 }
330 } 312 }
331 313
332 if (wrta < 0.0) { 314 if (wrta < 0.0) {
333 if (is_negative (argv[c])) { 315 if (is_negative(argv[c])) {
334 printf (_("<wrta> (%s) must be a non-negative number\n"), argv[c]); 316 printf(_("<wrta> (%s) must be a non-negative number\n"), argv[c]);
335 return ERROR; 317 return ERROR;
336 } else { 318 } else {
337 wrta = atof (argv[c++]); 319 wrta = atof(argv[c++]);
338 if (c == argc) 320 if (c == argc)
339 return validate_arguments (); 321 return validate_arguments();
340 } 322 }
341 } 323 }
342 324
343 if (crta < 0.0) { 325 if (crta < 0.0) {
344 if (is_negative (argv[c])) { 326 if (is_negative(argv[c])) {
345 printf (_("<crta> (%s) must be a non-negative number\n"), argv[c]); 327 printf(_("<crta> (%s) must be a non-negative number\n"), argv[c]);
346 return ERROR; 328 return ERROR;
347 } else { 329 } else {
348 crta = atof (argv[c++]); 330 crta = atof(argv[c++]);
349 if (c == argc) 331 if (c == argc)
350 return validate_arguments (); 332 return validate_arguments();
351 } 333 }
352 } 334 }
353 335
354 if (max_packets == -1) { 336 if (max_packets == -1) {
355 if (is_intnonneg (argv[c])) { 337 if (is_intnonneg(argv[c])) {
356 max_packets = atoi (argv[c++]); 338 max_packets = atoi(argv[c++]);
357 } else { 339 } else {
358 printf (_("<max_packets> (%s) must be a non-negative number\n"), argv[c]); 340 printf(_("<max_packets> (%s) must be a non-negative number\n"), argv[c]);
359 return ERROR; 341 return ERROR;
360 } 342 }
361 } 343 }
362 344
363 return validate_arguments (); 345 return validate_arguments();
364} 346}
365 347
366 348int get_threshold(char *arg, float *trta, int *tpl) {
367 349 if (is_intnonneg(arg) && sscanf(arg, "%f", trta) == 1)
368int
369get_threshold (char *arg, float *trta, int *tpl)
370{
371 if (is_intnonneg (arg) && sscanf (arg, "%f", trta) == 1)
372 return OK; 350 return OK;
373 else if (strpbrk (arg, ",:") && strstr (arg, "%") && sscanf (arg, "%f%*[:,]%d%%", trta, tpl) == 2) 351 else if (strpbrk(arg, ",:") && strstr(arg, "%") && sscanf(arg, "%f%*[:,]%d%%", trta, tpl) == 2)
374 return OK; 352 return OK;
375 else if (strstr (arg, "%") && sscanf (arg, "%d%%", tpl) == 1) 353 else if (strstr(arg, "%") && sscanf(arg, "%d%%", tpl) == 1)
376 return OK; 354 return OK;
377 355
378 usage2 (_("%s: Warning threshold must be integer or percentage!\n\n"), arg); 356 usage2(_("%s: Warning threshold must be integer or percentage!\n\n"), arg);
379 return STATE_UNKNOWN; 357 return STATE_UNKNOWN;
380} 358}
381 359
382 360int validate_arguments() {
383
384int
385validate_arguments ()
386{
387 float max_seconds; 361 float max_seconds;
388 int i; 362 int i;
389 363
390 if (wrta < 0.0) { 364 if (wrta < 0.0) {
391 printf (_("<wrta> was not set\n")); 365 printf(_("<wrta> was not set\n"));
392 return ERROR; 366 return ERROR;
393 } 367 } else if (crta < 0.0) {
394 else if (crta < 0.0) { 368 printf(_("<crta> was not set\n"));
395 printf (_("<crta> was not set\n"));
396 return ERROR; 369 return ERROR;
397 } 370 } else if (wpl == UNKNOWN_PACKET_LOSS) {
398 else if (wpl == UNKNOWN_PACKET_LOSS) { 371 printf(_("<wpl> was not set\n"));
399 printf (_("<wpl> was not set\n"));
400 return ERROR; 372 return ERROR;
401 } 373 } else if (cpl == UNKNOWN_PACKET_LOSS) {
402 else if (cpl == UNKNOWN_PACKET_LOSS) { 374 printf(_("<cpl> was not set\n"));
403 printf (_("<cpl> was not set\n"));
404 return ERROR; 375 return ERROR;
405 } 376 } else if (wrta > crta) {
406 else if (wrta > crta) { 377 printf(_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta);
407 printf (_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta);
408 return ERROR; 378 return ERROR;
409 } 379 } else if (wpl > cpl) {
410 else if (wpl > cpl) { 380 printf(_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl);
411 printf (_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl);
412 return ERROR; 381 return ERROR;
413 } 382 }
414 383
@@ -419,68 +388,61 @@ validate_arguments ()
419 if (max_seconds > timeout_interval) 388 if (max_seconds > timeout_interval)
420 timeout_interval = (int)max_seconds; 389 timeout_interval = (int)max_seconds;
421 390
422 for (i=0; i<n_addresses; i++) { 391 for (i = 0; i < n_addresses; i++) {
423 if (!is_host(addresses[i])) 392 if (!is_host(addresses[i]))
424 usage2 (_("Invalid hostname/address"), addresses[i]); 393 usage2(_("Invalid hostname/address"), addresses[i]);
425 } 394 }
426 395
427 if (n_addresses == 0) { 396 if (n_addresses == 0) {
428 usage (_("You must specify a server address or host name")); 397 usage(_("You must specify a server address or host name"));
429 } 398 }
430 399
431 return OK; 400 return OK;
432} 401}
433 402
434 403int run_ping(const char *cmd, const char *addr) {
435
436int
437run_ping (const char *cmd, const char *addr)
438{
439 char buf[MAX_INPUT_BUFFER]; 404 char buf[MAX_INPUT_BUFFER];
440 int result = STATE_UNKNOWN; 405 int result = STATE_UNKNOWN;
441 int match; 406 int match;
442 407
443 if ((child_process = spopen (cmd)) == NULL) 408 if ((child_process = spopen(cmd)) == NULL)
444 die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); 409 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
445 410
446 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 411 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
447 if (child_stderr == NULL) 412 if (child_stderr == NULL)
448 printf (_("Cannot open stderr for %s\n"), cmd); 413 printf(_("Cannot open stderr for %s\n"), cmd);
449 414
450 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) { 415 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) {
451 416
452 if (verbose >= 3) 417 if (verbose >= 3)
453 printf("Output: %s", buf); 418 printf("Output: %s", buf);
454 419
455 result = max_state (result, error_scan (buf, addr)); 420 result = max_state(result, error_scan(buf, addr));
456 421
457 /* get the percent loss statistics */ 422 /* get the percent loss statistics */
458 match = 0; 423 match = 0;
459 if((sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 424 if ((sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n", &pl, &match) && match) ||
460 (sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) || 425 (sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n", &pl, &match) && match) ||
461 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) || 426 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n", &pl, &match) && match) ||
462 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% packet loss%n",&pl,&match) && match) || 427 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% packet loss%n", &pl, &match) && match) ||
463 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% loss, time%n",&pl,&match) && match) || 428 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% loss, time%n", &pl, &match) && match) ||
464 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time%n",&pl,&match) && match) || 429 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% loss, time%n", &pl, &match) && match) ||
465 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time%n",&pl,&match) && match) || 430 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% packet loss, time%n", &pl, &match) && match) ||
466 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 431 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n", &pl, &match) && match) ||
467 (sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 432 (sscanf(buf, "%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n", &pl, &match) && match) ||
468 (sscanf(buf,"%*[^(](%d%% %*[^)])%n",&pl,&match) && match) 433 (sscanf(buf, "%*[^(](%d%% %*[^)])%n", &pl, &match) && match))
469 )
470 continue; 434 continue;
471 435
472 /* get the round trip average */ 436 /* get the round trip average */
473 else 437 else if ((sscanf(buf, "round-trip min/avg/max = %*f/%f/%*f%n", &rta, &match) && match) ||
474 if((sscanf(buf,"round-trip min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) || 438 (sscanf(buf, "round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
475 (sscanf(buf,"round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 439 (sscanf(buf, "round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
476 (sscanf(buf,"round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 440 (sscanf(buf, "round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
477 (sscanf(buf,"round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 441 (sscanf(buf, "round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
478 (sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 442 (sscanf(buf, "round-trip (ms) min/avg/max = %*f/%f/%*f%n", &rta, &match) && match) ||
479 (sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) || 443 (sscanf(buf, "round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
480 (sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 444 (sscanf(buf, "rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n", &rta, &match) && match) ||
481 (sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n",&rta,&match) && match) || 445 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &rta, &match) && match))
482 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &rta, &match) && match)
483 )
484 continue; 446 continue;
485 } 447 }
486 448
@@ -490,16 +452,14 @@ run_ping (const char *cmd, const char *addr)
490 452
491 /* check stderr, setting at least WARNING if there is output here */ 453 /* check stderr, setting at least WARNING if there is output here */
492 /* Add warning into warn_text */ 454 /* Add warning into warn_text */
493 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) { 455 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_stderr)) {
494 if ( 456 if (!strstr(buf, "WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP") && !strstr(buf, "Warning: time of day goes back")
495 ! strstr(buf,"WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP")
496 && ! strstr(buf,"Warning: time of day goes back")
497 457
498 ) { 458 ) {
499 if (verbose >= 3) { 459 if (verbose >= 3) {
500 printf("Got stderr: %s", buf); 460 printf("Got stderr: %s", buf);
501 } 461 }
502 if ((result=error_scan(buf, addr)) == STATE_OK) { 462 if ((result = error_scan(buf, addr)) == STATE_OK) {
503 result = STATE_WARNING; 463 result = STATE_WARNING;
504 if (warn_text == NULL) { 464 if (warn_text == NULL) {
505 warn_text = strdup(_("System call sent warnings to stderr ")); 465 warn_text = strdup(_("System call sent warnings to stderr "));
@@ -510,10 +470,9 @@ run_ping (const char *cmd, const char *addr)
510 } 470 }
511 } 471 }
512 472
513 (void) fclose (child_stderr); 473 (void)fclose(child_stderr);
514
515 474
516 spclose (child_process); 475 spclose(child_process);
517 476
518 if (warn_text == NULL) 477 if (warn_text == NULL)
519 warn_text = strdup(""); 478 warn_text = strdup("");
@@ -521,100 +480,86 @@ run_ping (const char *cmd, const char *addr)
521 return result; 480 return result;
522} 481}
523 482
524 483int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) {
525 484 if (strstr(buf, "Network is unreachable") || strstr(buf, "Destination Net Unreachable") || strstr(buf, "No route"))
526int 485 die(STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr);
527error_scan (char buf[MAX_INPUT_BUFFER], const char *addr) 486 else if (strstr(buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable"))
528{ 487 die(STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr);
529 if (strstr (buf, "Network is unreachable") || 488 else if (strstr(buf, "Destination Port Unreachable") || strstr(buf, "Port unreachable"))
530 strstr (buf, "Destination Net Unreachable") || 489 die(STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr);
531 strstr (buf, "No route") 490 else if (strstr(buf, "Destination Protocol Unreachable"))
532 ) 491 die(STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr);
533 die (STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr); 492 else if (strstr(buf, "Destination Net Prohibited"))
534 else if (strstr (buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable")) 493 die(STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr);
535 die (STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr); 494 else if (strstr(buf, "Destination Host Prohibited"))
536 else if (strstr (buf, "Destination Port Unreachable") || strstr(buf, "Port unreachable")) 495 die(STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr);
537 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr); 496 else if (strstr(buf, "Packet filtered") || strstr(buf, "Administratively prohibited"))
538 else if (strstr (buf, "Destination Protocol Unreachable")) 497 die(STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr);
539 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr); 498 else if (strstr(buf, "unknown host"))
540 else if (strstr (buf, "Destination Net Prohibited")) 499 die(STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
541 die (STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr); 500 else if (strstr(buf, "Time to live exceeded") || strstr(buf, "Time exceeded"))
542 else if (strstr (buf, "Destination Host Prohibited")) 501 die(STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
543 die (STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr); 502 else if (strstr(buf, "Destination unreachable: "))
544 else if (strstr (buf, "Packet filtered") || strstr(buf, "Administratively prohibited")) 503 die(STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
545 die (STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr); 504
546 else if (strstr (buf, "unknown host" )) 505 if (strstr(buf, "(DUP!)") || strstr(buf, "DUPLICATES FOUND")) {
547 die (STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
548 else if (strstr (buf, "Time to live exceeded") || strstr(buf, "Time exceeded"))
549 die (STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
550 else if (strstr (buf, "Destination unreachable: "))
551 die (STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
552
553 if (strstr (buf, "(DUP!)") || strstr (buf, "DUPLICATES FOUND")) {
554 if (warn_text == NULL) 506 if (warn_text == NULL)
555 warn_text = strdup (_(WARN_DUPLICATES)); 507 warn_text = strdup(_(WARN_DUPLICATES));
556 else if (! strstr (warn_text, _(WARN_DUPLICATES)) && 508 else if (!strstr(warn_text, _(WARN_DUPLICATES)) && xasprintf(&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1)
557 xasprintf (&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) 509 die(STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
558 die (STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
559 return (STATE_WARNING); 510 return (STATE_WARNING);
560 } 511 }
561 512
562 return (STATE_OK); 513 return (STATE_OK);
563} 514}
564 515
516void print_help(void) {
517 print_revision(progname, NP_VERSION);
565 518
519 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
520 printf(COPYRIGHT, copyright, email);
566 521
567void 522 printf(_("Use ping to check connection statistics for a remote host."));
568print_help (void)
569{
570 print_revision (progname, NP_VERSION);
571
572 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
573 printf (COPYRIGHT, copyright, email);
574
575 printf (_("Use ping to check connection statistics for a remote host."));
576 523
577 printf ("\n\n"); 524 printf("\n\n");
578 525
579 print_usage (); 526 print_usage();
580 527
581 printf (UT_HELP_VRSN); 528 printf(UT_HELP_VRSN);
582 printf (UT_EXTRA_OPTS); 529 printf(UT_EXTRA_OPTS);
583 530
584 printf (UT_IPv46); 531 printf(UT_IPv46);
585 532
586 printf (" %s\n", "-H, --hostname=HOST"); 533 printf(" %s\n", "-H, --hostname=HOST");
587 printf (" %s\n", _("host to ping")); 534 printf(" %s\n", _("host to ping"));
588 printf (" %s\n", "-w, --warning=THRESHOLD"); 535 printf(" %s\n", "-w, --warning=THRESHOLD");
589 printf (" %s\n", _("warning threshold pair")); 536 printf(" %s\n", _("warning threshold pair"));
590 printf (" %s\n", "-c, --critical=THRESHOLD"); 537 printf(" %s\n", "-c, --critical=THRESHOLD");
591 printf (" %s\n", _("critical threshold pair")); 538 printf(" %s\n", _("critical threshold pair"));
592 printf (" %s\n", "-p, --packets=INTEGER"); 539 printf(" %s\n", "-p, --packets=INTEGER");
593 printf (" %s ", _("number of ICMP ECHO packets to send")); 540 printf(" %s ", _("number of ICMP ECHO packets to send"));
594 printf (_("(Default: %d)\n"), DEFAULT_MAX_PACKETS); 541 printf(_("(Default: %d)\n"), DEFAULT_MAX_PACKETS);
595 printf (" %s\n", "-L, --link"); 542 printf(" %s\n", "-L, --link");
596 printf (" %s\n", _("show HTML in the plugin output (obsoleted by urlize)")); 543 printf(" %s\n", _("show HTML in the plugin output (obsoleted by urlize)"));
597 544
598 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 545 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
599 546
600 printf ("\n"); 547 printf("\n");
601 printf ("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel")); 548 printf("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel"));
602 printf ("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the")); 549 printf("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the"));
603 printf ("%s\n", _("percentage of packet loss to trigger an alarm state.")); 550 printf("%s\n", _("percentage of packet loss to trigger an alarm state."));
604 551
605 printf ("\n"); 552 printf("\n");
606 printf ("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss")); 553 printf("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss"));
607 printf ("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output")); 554 printf("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output"));
608 printf ("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in")); 555 printf("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in"));
609 printf ("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/")); 556 printf("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/"));
610 557
611 printf (UT_SUPPORT); 558 printf(UT_SUPPORT);
612} 559}
613 560
614void 561void print_usage(void) {
615print_usage (void) 562 printf("%s\n", _("Usage:"));
616{ 563 printf("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
617 printf ("%s\n", _("Usage:")); 564 printf(" [-p packets] [-t timeout] [-4|-6]\n");
618 printf ("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
619 printf (" [-p packets] [-t timeout] [-4|-6]\n");
620} 565}
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index 1fcbd981..5777ba07 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -3,7 +3,7 @@
3* Monitoring check_procs plugin 3* Monitoring check_procs plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2008 Monitoring Plugins Development Team 6* Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -36,7 +36,7 @@
36 36
37const char *progname = "check_procs"; 37const char *progname = "check_procs";
38const char *program_name = "check_procs"; /* Required for coreutils libs */ 38const char *program_name = "check_procs"; /* Required for coreutils libs */
39const char *copyright = "2000-2008"; 39const char *copyright = "2000-2024";
40const char *email = "devel@monitoring-plugins.org"; 40const char *email = "devel@monitoring-plugins.org";
41 41
42#include "common.h" 42#include "common.h"
diff --git a/plugins/check_radius.c b/plugins/check_radius.c
index 6b32710a..8ed19e55 100644
--- a/plugins/check_radius.c
+++ b/plugins/check_radius.c
@@ -3,7 +3,7 @@
3* Monitoring check_radius plugin 3* Monitoring check_radius plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 1999-2008 Monitoring Plugins Development Team 6* Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -29,7 +29,7 @@
29*****************************************************************************/ 29*****************************************************************************/
30 30
31const char *progname = "check_radius"; 31const char *progname = "check_radius";
32const char *copyright = "2000-2008"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
diff --git a/plugins/check_real.c b/plugins/check_real.c
index 15e035b6..369a88b1 100644
--- a/plugins/check_real.c
+++ b/plugins/check_real.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_real plugin 3 * Monitoring check_real plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_real plugin 10 * This file contains the check_real plugin
11* 11 *
12* This plugin tests the REAL service on the specified host. 12 * This plugin tests the REAL service on the specified host.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_real"; 31const char *progname = "check_real";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -37,121 +37,111 @@ const char *email = "devel@monitoring-plugins.org";
37#include "utils.h" 37#include "utils.h"
38 38
39enum { 39enum {
40 PORT = 554 40 PORT = 554
41}; 41};
42 42
43#define EXPECT "RTSP/1." 43#define EXPECT "RTSP/1."
44#define URL "" 44#define URL ""
45 45
46int process_arguments (int, char **); 46static int process_arguments(int, char **);
47int validate_arguments (void); 47static void print_help(void);
48void print_help (void); 48void print_usage(void);
49void print_usage (void); 49
50 50static int server_port = PORT;
51int server_port = PORT; 51static char *server_address;
52char *server_address; 52static char *host_name;
53char *host_name; 53static char *server_url = NULL;
54char *server_url = NULL; 54static char *server_expect;
55char *server_expect; 55static int warning_time = 0;
56int warning_time = 0; 56static bool check_warning_time = false;
57bool check_warning_time = false; 57static int critical_time = 0;
58int critical_time = 0; 58static bool check_critical_time = false;
59bool check_critical_time = false; 59static bool verbose = false;
60bool verbose = false; 60
61 61int main(int argc, char **argv) {
62 62 setlocale(LC_ALL, "");
63 63 bindtextdomain(PACKAGE, LOCALEDIR);
64int 64 textdomain(PACKAGE);
65main (int argc, char **argv)
66{
67 int sd;
68 int result = STATE_UNKNOWN;
69 char buffer[MAX_INPUT_BUFFER];
70 char *status_line = NULL;
71
72 setlocale (LC_ALL, "");
73 bindtextdomain (PACKAGE, LOCALEDIR);
74 textdomain (PACKAGE);
75 65
76 /* Parse extra opts if any */ 66 /* Parse extra opts if any */
77 argv=np_extra_opts (&argc, argv, progname); 67 argv = np_extra_opts(&argc, argv, progname);
78 68
79 if (process_arguments (argc, argv) == ERROR) 69 if (process_arguments(argc, argv) == ERROR)
80 usage4 (_("Could not parse arguments")); 70 usage4(_("Could not parse arguments"));
81 71
82 /* initialize alarm signal handling */ 72 /* initialize alarm signal handling */
83 signal (SIGALRM, socket_timeout_alarm_handler); 73 signal(SIGALRM, socket_timeout_alarm_handler);
84 74
85 /* set socket timeout */ 75 /* set socket timeout */
86 alarm (socket_timeout); 76 alarm(socket_timeout);
87 time (&start_time); 77 time(&start_time);
88 78
89 /* try to connect to the host at the given port number */ 79 /* try to connect to the host at the given port number */
90 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) 80 int socket;
91 die (STATE_CRITICAL, _("Unable to connect to %s on port %d\n"), 81 if (my_tcp_connect(server_address, server_port, &socket) != STATE_OK)
92 server_address, server_port); 82 die(STATE_CRITICAL, _("Unable to connect to %s on port %d\n"), server_address, server_port);
93 83
94 /* Part I - Server Check */ 84 /* Part I - Server Check */
95 85
96 /* send the OPTIONS request */ 86 /* send the OPTIONS request */
97 sprintf (buffer, "OPTIONS rtsp://%s:%d RTSP/1.0\r\n", host_name, server_port); 87 char buffer[MAX_INPUT_BUFFER];
98 result = send (sd, buffer, strlen (buffer), 0); 88 sprintf(buffer, "OPTIONS rtsp://%s:%d RTSP/1.0\r\n", host_name, server_port);
89 int result = send(socket, buffer, strlen(buffer), 0);
99 90
100 /* send the header sync */ 91 /* send the header sync */
101 sprintf (buffer, "CSeq: 1\r\n"); 92 sprintf(buffer, "CSeq: 1\r\n");
102 result = send (sd, buffer, strlen (buffer), 0); 93 result = send(socket, buffer, strlen(buffer), 0);
103 94
104 /* send a newline so the server knows we're done with the request */ 95 /* send a newline so the server knows we're done with the request */
105 sprintf (buffer, "\r\n"); 96 sprintf(buffer, "\r\n");
106 result = send (sd, buffer, strlen (buffer), 0); 97 result = send(socket, buffer, strlen(buffer), 0);
107 98
108 /* watch for the REAL connection string */ 99 /* watch for the REAL connection string */
109 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0); 100 result = recv(socket, buffer, MAX_INPUT_BUFFER - 1, 0);
110 101
111 /* return a CRITICAL status if we couldn't read any data */ 102 /* return a CRITICAL status if we couldn't read any data */
112 if (result == -1) 103 if (result == -1)
113 die (STATE_CRITICAL, _("No data received from %s\n"), host_name); 104 die(STATE_CRITICAL, _("No data received from %s\n"), host_name);
114 105
106 char *status_line = NULL;
115 /* make sure we find the response we are looking for */ 107 /* make sure we find the response we are looking for */
116 if (!strstr (buffer, server_expect)) { 108 if (!strstr(buffer, server_expect)) {
117 if (server_port == PORT) 109 if (server_port == PORT)
118 printf ("%s\n", _("Invalid REAL response received from host")); 110 printf("%s\n", _("Invalid REAL response received from host"));
119 else 111 else
120 printf (_("Invalid REAL response received from host on port %d\n"), 112 printf(_("Invalid REAL response received from host on port %d\n"), server_port);
121 server_port); 113 } else {
122 }
123 else {
124 /* else we got the REAL string, so check the return code */ 114 /* else we got the REAL string, so check the return code */
125 115
126 time (&end_time); 116 time(&end_time);
127 117
128 result = STATE_OK; 118 result = STATE_OK;
129 119
130 status_line = (char *) strtok (buffer, "\n"); 120 status_line = (char *)strtok(buffer, "\n");
131 121
132 if (strstr (status_line, "200")) 122 if (strstr(status_line, "200"))
133 result = STATE_OK; 123 result = STATE_OK;
134 124
135 /* client errors result in a warning state */ 125 /* client errors result in a warning state */
136 else if (strstr (status_line, "400")) 126 else if (strstr(status_line, "400"))
137 result = STATE_WARNING; 127 result = STATE_WARNING;
138 else if (strstr (status_line, "401")) 128 else if (strstr(status_line, "401"))
139 result = STATE_WARNING; 129 result = STATE_WARNING;
140 else if (strstr (status_line, "402")) 130 else if (strstr(status_line, "402"))
141 result = STATE_WARNING; 131 result = STATE_WARNING;
142 else if (strstr (status_line, "403")) 132 else if (strstr(status_line, "403"))
143 result = STATE_WARNING; 133 result = STATE_WARNING;
144 else if (strstr (status_line, "404")) 134 else if (strstr(status_line, "404"))
145 result = STATE_WARNING; 135 result = STATE_WARNING;
146 136
147 /* server errors result in a critical state */ 137 /* server errors result in a critical state */
148 else if (strstr (status_line, "500")) 138 else if (strstr(status_line, "500"))
149 result = STATE_CRITICAL; 139 result = STATE_CRITICAL;
150 else if (strstr (status_line, "501")) 140 else if (strstr(status_line, "501"))
151 result = STATE_CRITICAL; 141 result = STATE_CRITICAL;
152 else if (strstr (status_line, "502")) 142 else if (strstr(status_line, "502"))
153 result = STATE_CRITICAL; 143 result = STATE_CRITICAL;
154 else if (strstr (status_line, "503")) 144 else if (strstr(status_line, "503"))
155 result = STATE_CRITICAL; 145 result = STATE_CRITICAL;
156 146
157 else 147 else
@@ -159,74 +149,70 @@ main (int argc, char **argv)
159 } 149 }
160 150
161 /* Part II - Check stream exists and is ok */ 151 /* Part II - Check stream exists and is ok */
162 if ((result == STATE_OK )&& (server_url != NULL) ) { 152 if ((result == STATE_OK) && (server_url != NULL)) {
163 153
164 /* Part I - Server Check */ 154 /* Part I - Server Check */
165 155
166 /* send the DESCRIBE request */ 156 /* send the DESCRIBE request */
167 sprintf (buffer, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n", host_name, 157 sprintf(buffer, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n", host_name, server_port, server_url);
168 server_port, server_url); 158 result = send(socket, buffer, strlen(buffer), 0);
169 result = send (sd, buffer, strlen (buffer), 0);
170 159
171 /* send the header sync */ 160 /* send the header sync */
172 sprintf (buffer, "CSeq: 2\r\n"); 161 sprintf(buffer, "CSeq: 2\r\n");
173 result = send (sd, buffer, strlen (buffer), 0); 162 result = send(socket, buffer, strlen(buffer), 0);
174 163
175 /* send a newline so the server knows we're done with the request */ 164 /* send a newline so the server knows we're done with the request */
176 sprintf (buffer, "\r\n"); 165 sprintf(buffer, "\r\n");
177 result = send (sd, buffer, strlen (buffer), 0); 166 result = send(socket, buffer, strlen(buffer), 0);
178 167
179 /* watch for the REAL connection string */ 168 /* watch for the REAL connection string */
180 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0); 169 result = recv(socket, buffer, MAX_INPUT_BUFFER - 1, 0);
181 buffer[result] = '\0'; /* null terminate received buffer */ 170 buffer[result] = '\0'; /* null terminate received buffer */
182 171
183 /* return a CRITICAL status if we couldn't read any data */ 172 /* return a CRITICAL status if we couldn't read any data */
184 if (result == -1) { 173 if (result == -1) {
185 printf (_("No data received from host\n")); 174 printf(_("No data received from host\n"));
186 result = STATE_CRITICAL; 175 result = STATE_CRITICAL;
187 } 176 } else {
188 else {
189 /* make sure we find the response we are looking for */ 177 /* make sure we find the response we are looking for */
190 if (!strstr (buffer, server_expect)) { 178 if (!strstr(buffer, server_expect)) {
191 if (server_port == PORT) 179 if (server_port == PORT)
192 printf ("%s\n", _("Invalid REAL response received from host")); 180 printf("%s\n", _("Invalid REAL response received from host"));
193 else 181 else
194 printf (_("Invalid REAL response received from host on port %d\n"), 182 printf(_("Invalid REAL response received from host on port %d\n"), server_port);
195 server_port); 183 } else {
196 }
197 else {
198 184
199 /* else we got the REAL string, so check the return code */ 185 /* else we got the REAL string, so check the return code */
200 186
201 time (&end_time); 187 time(&end_time);
202 188
203 result = STATE_OK; 189 result = STATE_OK;
204 190
205 status_line = (char *) strtok (buffer, "\n"); 191 status_line = (char *)strtok(buffer, "\n");
206 192
207 if (strstr (status_line, "200")) 193 if (strstr(status_line, "200"))
208 result = STATE_OK; 194 result = STATE_OK;
209 195
210 /* client errors result in a warning state */ 196 /* client errors result in a warning state */
211 else if (strstr (status_line, "400")) 197 else if (strstr(status_line, "400"))
212 result = STATE_WARNING; 198 result = STATE_WARNING;
213 else if (strstr (status_line, "401")) 199 else if (strstr(status_line, "401"))
214 result = STATE_WARNING; 200 result = STATE_WARNING;
215 else if (strstr (status_line, "402")) 201 else if (strstr(status_line, "402"))
216 result = STATE_WARNING; 202 result = STATE_WARNING;
217 else if (strstr (status_line, "403")) 203 else if (strstr(status_line, "403"))
218 result = STATE_WARNING; 204 result = STATE_WARNING;
219 else if (strstr (status_line, "404")) 205 else if (strstr(status_line, "404"))
220 result = STATE_WARNING; 206 result = STATE_WARNING;
221 207
222 /* server errors result in a critical state */ 208 /* server errors result in a critical state */
223 else if (strstr (status_line, "500")) 209 else if (strstr(status_line, "500"))
224 result = STATE_CRITICAL; 210 result = STATE_CRITICAL;
225 else if (strstr (status_line, "501")) 211 else if (strstr(status_line, "501"))
226 result = STATE_CRITICAL; 212 result = STATE_CRITICAL;
227 else if (strstr (status_line, "502")) 213 else if (strstr(status_line, "502"))
228 result = STATE_CRITICAL; 214 result = STATE_CRITICAL;
229 else if (strstr (status_line, "503")) 215 else if (strstr(status_line, "503"))
230 result = STATE_CRITICAL; 216 result = STATE_CRITICAL;
231 217
232 else 218 else
@@ -238,217 +224,177 @@ main (int argc, char **argv)
238 /* Return results */ 224 /* Return results */
239 if (result == STATE_OK) { 225 if (result == STATE_OK) {
240 226
241 if (check_critical_time 227 if (check_critical_time && (end_time - start_time) > critical_time)
242 && (end_time - start_time) > critical_time) result = STATE_CRITICAL; 228 result = STATE_CRITICAL;
243 else if (check_warning_time 229 else if (check_warning_time && (end_time - start_time) > warning_time)
244 && (end_time - start_time) > warning_time) result = 230 result = STATE_WARNING;
245 STATE_WARNING;
246 231
247 /* Put some HTML in here to create a dynamic link */ 232 /* Put some HTML in here to create a dynamic link */
248 printf (_("REAL %s - %d second response time\n"), 233 printf(_("REAL %s - %d second response time\n"), state_text(result), (int)(end_time - start_time));
249 state_text (result), 234 } else
250 (int) (end_time - start_time)); 235 printf("%s\n", status_line);
251 }
252 else
253 printf ("%s\n", status_line);
254 236
255 /* close the connection */ 237 /* close the connection */
256 close (sd); 238 close(socket);
257 239
258 /* reset the alarm */ 240 /* reset the alarm */
259 alarm (0); 241 alarm(0);
260 242
261 return result; 243 return result;
262} 244}
263 245
264
265
266/* process command-line arguments */ 246/* process command-line arguments */
267int 247int process_arguments(int argc, char **argv) {
268process_arguments (int argc, char **argv) 248 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, {"IPaddress", required_argument, 0, 'I'},
269{ 249 {"expect", required_argument, 0, 'e'}, {"url", required_argument, 0, 'u'},
270 int c; 250 {"port", required_argument, 0, 'p'}, {"critical", required_argument, 0, 'c'},
271 251 {"warning", required_argument, 0, 'w'}, {"timeout", required_argument, 0, 't'},
272 int option = 0; 252 {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'},
273 static struct option longopts[] = { 253 {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
274 {"hostname", required_argument, 0, 'H'},
275 {"IPaddress", required_argument, 0, 'I'},
276 {"expect", required_argument, 0, 'e'},
277 {"url", required_argument, 0, 'u'},
278 {"port", required_argument, 0, 'p'},
279 {"critical", required_argument, 0, 'c'},
280 {"warning", required_argument, 0, 'w'},
281 {"timeout", required_argument, 0, 't'},
282 {"verbose", no_argument, 0, 'v'},
283 {"version", no_argument, 0, 'V'},
284 {"help", no_argument, 0, 'h'},
285 {0, 0, 0, 0}
286 };
287 254
288 if (argc < 2) 255 if (argc < 2)
289 return ERROR; 256 return ERROR;
290 257
291 for (c = 1; c < argc; c++) { 258 for (int i = 1; i < argc; i++) {
292 if (strcmp ("-to", argv[c]) == 0) 259 if (strcmp("-to", argv[i]) == 0)
293 strcpy (argv[c], "-t"); 260 strcpy(argv[i], "-t");
294 else if (strcmp ("-wt", argv[c]) == 0) 261 else if (strcmp("-wt", argv[i]) == 0)
295 strcpy (argv[c], "-w"); 262 strcpy(argv[i], "-w");
296 else if (strcmp ("-ct", argv[c]) == 0) 263 else if (strcmp("-ct", argv[i]) == 0)
297 strcpy (argv[c], "-c"); 264 strcpy(argv[i], "-c");
298 } 265 }
299 266
300 while (1) { 267 int option_char;
301 c = getopt_long (argc, argv, "+hvVI:H:e:u:p:w:c:t:", longopts, 268 while (true) {
302 &option); 269 int option = 0;
270 option_char = getopt_long(argc, argv, "+hvVI:H:e:u:p:w:c:t:", longopts, &option);
303 271
304 if (c == -1 || c == EOF) 272 if (option_char == -1 || option_char == EOF)
305 break; 273 break;
306 274
307 switch (c) { 275 switch (option_char) {
308 case 'I': /* hostname */ 276 case 'I': /* hostname */
309 case 'H': /* hostname */ 277 case 'H': /* hostname */
310 if (server_address) 278 if (server_address)
311 break; 279 break;
312 else if (is_host (optarg)) 280 else if (is_host(optarg))
313 server_address = optarg; 281 server_address = optarg;
314 else 282 else
315 usage2 (_("Invalid hostname/address"), optarg); 283 usage2(_("Invalid hostname/address"), optarg);
316 break; 284 break;
317 case 'e': /* string to expect in response header */ 285 case 'e': /* string to expect in response header */
318 server_expect = optarg; 286 server_expect = optarg;
319 break; 287 break;
320 case 'u': /* server URL */ 288 case 'u': /* server URL */
321 server_url = optarg; 289 server_url = optarg;
322 break; 290 break;
323 case 'p': /* port */ 291 case 'p': /* port */
324 if (is_intpos (optarg)) { 292 if (is_intpos(optarg)) {
325 server_port = atoi (optarg); 293 server_port = atoi(optarg);
326 } 294 } else {
327 else { 295 usage4(_("Port must be a positive integer"));
328 usage4 (_("Port must be a positive integer"));
329 } 296 }
330 break; 297 break;
331 case 'w': /* warning time threshold */ 298 case 'w': /* warning time threshold */
332 if (is_intnonneg (optarg)) { 299 if (is_intnonneg(optarg)) {
333 warning_time = atoi (optarg); 300 warning_time = atoi(optarg);
334 check_warning_time = true; 301 check_warning_time = true;
335 } 302 } else {
336 else { 303 usage4(_("Warning time must be a positive integer"));
337 usage4 (_("Warning time must be a positive integer"));
338 } 304 }
339 break; 305 break;
340 case 'c': /* critical time threshold */ 306 case 'c': /* critical time threshold */
341 if (is_intnonneg (optarg)) { 307 if (is_intnonneg(optarg)) {
342 critical_time = atoi (optarg); 308 critical_time = atoi(optarg);
343 check_critical_time = true; 309 check_critical_time = true;
344 } 310 } else {
345 else { 311 usage4(_("Critical time must be a positive integer"));
346 usage4 (_("Critical time must be a positive integer"));
347 } 312 }
348 break; 313 break;
349 case 'v': /* verbose */ 314 case 'v': /* verbose */
350 verbose = true; 315 verbose = true;
351 break; 316 break;
352 case 't': /* timeout */ 317 case 't': /* timeout */
353 if (is_intnonneg (optarg)) { 318 if (is_intnonneg(optarg)) {
354 socket_timeout = atoi (optarg); 319 socket_timeout = atoi(optarg);
355 } 320 } else {
356 else { 321 usage4(_("Timeout interval must be a positive integer"));
357 usage4 (_("Timeout interval must be a positive integer"));
358 } 322 }
359 break; 323 break;
360 case 'V': /* version */ 324 case 'V': /* version */
361 print_revision (progname, NP_VERSION); 325 print_revision(progname, NP_VERSION);
362 exit (STATE_UNKNOWN); 326 exit(STATE_UNKNOWN);
363 case 'h': /* help */ 327 case 'h': /* help */
364 print_help (); 328 print_help();
365 exit (STATE_UNKNOWN); 329 exit(STATE_UNKNOWN);
366 case '?': /* usage */ 330 case '?': /* usage */
367 usage5 (); 331 usage5();
368 } 332 }
369 } 333 }
370 334
371 c = optind; 335 option_char = optind;
372 if (server_address==NULL && argc>c) { 336 if (server_address == NULL && argc > option_char) {
373 if (is_host (argv[c])) { 337 if (is_host(argv[option_char])) {
374 server_address = argv[c++]; 338 server_address = argv[option_char++];
375 } 339 } else {
376 else { 340 usage2(_("Invalid hostname/address"), argv[option_char]);
377 usage2 (_("Invalid hostname/address"), argv[c]);
378 } 341 }
379 } 342 }
380 343
381 if (server_address==NULL) 344 if (server_address == NULL)
382 usage4 (_("You must provide a server to check")); 345 usage4(_("You must provide a server to check"));
383 346
384 if (host_name==NULL) 347 if (host_name == NULL)
385 host_name = strdup (server_address); 348 host_name = strdup(server_address);
386 349
387 if (server_expect == NULL) 350 if (server_expect == NULL)
388 server_expect = strdup(EXPECT); 351 server_expect = strdup(EXPECT);
389 352
390 return validate_arguments ();
391}
392
393
394
395int
396validate_arguments (void)
397{
398 return OK; 353 return OK;
399} 354}
400 355
401 356void print_help(void) {
402
403void
404print_help (void)
405{
406 char *myport; 357 char *myport;
407 xasprintf (&myport, "%d", PORT); 358 xasprintf(&myport, "%d", PORT);
408 359
409 print_revision (progname, NP_VERSION); 360 print_revision(progname, NP_VERSION);
410 361
411 printf ("Copyright (c) 1999 Pedro Leite <leite@cic.ua.pt>\n"); 362 printf("Copyright (c) 1999 Pedro Leite <leite@cic.ua.pt>\n");
412 printf (COPYRIGHT, copyright, email); 363 printf(COPYRIGHT, copyright, email);
413 364
414 printf ("%s\n", _("This plugin tests the REAL service on the specified host.")); 365 printf("%s\n", _("This plugin tests the REAL service on the specified host."));
415 366
416 printf ("\n\n"); 367 printf("\n\n");
417 368
418 print_usage (); 369 print_usage();
419 370
420 printf (UT_HELP_VRSN); 371 printf(UT_HELP_VRSN);
421 printf (UT_EXTRA_OPTS); 372 printf(UT_EXTRA_OPTS);
422 373
423 printf (UT_HOST_PORT, 'p', myport); 374 printf(UT_HOST_PORT, 'p', myport);
424 375
425 printf (" %s\n", "-u, --url=STRING"); 376 printf(" %s\n", "-u, --url=STRING");
426 printf (" %s\n", _("Connect to this url")); 377 printf(" %s\n", _("Connect to this url"));
427 printf (" %s\n", "-e, --expect=STRING"); 378 printf(" %s\n", "-e, --expect=STRING");
428 printf (_("String to expect in first line of server response (default: %s)\n"), 379 printf(_("String to expect in first line of server response (default: %s)\n"), EXPECT);
429 EXPECT);
430 380
431 printf (UT_WARN_CRIT); 381 printf(UT_WARN_CRIT);
432 382
433 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 383 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
434 384
435 printf (UT_VERBOSE); 385 printf(UT_VERBOSE);
436 386
437 printf ("\n"); 387 printf("\n");
438 printf ("%s\n", _("This plugin will attempt to open an RTSP connection with the host.")); 388 printf("%s\n", _("This plugin will attempt to open an RTSP connection with the host."));
439 printf ("%s\n", _("Successful connects return STATE_OK, refusals and timeouts return")); 389 printf("%s\n", _("Successful connects return STATE_OK, refusals and timeouts return"));
440 printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful connects,")); 390 printf("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful connects,"));
441 printf ("%s\n", _("but incorrect response messages from the host result in STATE_WARNING return")); 391 printf("%s\n", _("but incorrect response messages from the host result in STATE_WARNING return"));
442 printf ("%s\n", _("values.")); 392 printf("%s\n", _("values."));
443 393
444 printf (UT_SUPPORT); 394 printf(UT_SUPPORT);
445} 395}
446 396
447 397void print_usage(void) {
448 398 printf("%s\n", _("Usage:"));
449void 399 printf("%s -H host [-e expect] [-p port] [-w warn] [-c crit] [-t timeout] [-v]\n", progname);
450print_usage (void)
451{
452 printf ("%s\n", _("Usage:"));
453 printf ("%s -H host [-e expect] [-p port] [-w warn] [-c crit] [-t timeout] [-v]\n", progname);
454} 400}
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
index 986c3e18..bc175287 100644
--- a/plugins/check_smtp.c
+++ b/plugins/check_smtp.c
@@ -3,7 +3,7 @@
3* Monitoring check_smtp plugin 3* Monitoring check_smtp plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2023 Monitoring Plugins Development Team 6* Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -29,7 +29,7 @@
29*****************************************************************************/ 29*****************************************************************************/
30 30
31const char *progname = "check_smtp"; 31const char *progname = "check_smtp";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index 937b3a5d..c1d8e2dd 100644
--- a/plugins/check_snmp.c
+++ b/plugins/check_snmp.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_snmp plugin 3 * Monitoring check_snmp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_snmp plugin 10 * This file contains the check_snmp plugin
11* 11 *
12* Check status of remote machines and obtain system information via SNMP 12 * Check status of remote machines and obtain system information via SNMP
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_snmp"; 31const char *progname = "check_snmp";
32const char *copyright = "1999-2007"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -37,136 +37,143 @@ const char *email = "devel@monitoring-plugins.org";
37#include "utils.h" 37#include "utils.h"
38#include "utils_cmd.h" 38#include "utils_cmd.h"
39 39
40#define DEFAULT_COMMUNITY "public" 40#define DEFAULT_COMMUNITY "public"
41#define DEFAULT_PORT "161" 41#define DEFAULT_PORT "161"
42#define DEFAULT_MIBLIST "ALL" 42#define DEFAULT_MIBLIST "ALL"
43#define DEFAULT_PROTOCOL "1" 43#define DEFAULT_PROTOCOL "1"
44#define DEFAULT_RETRIES 5 44#define DEFAULT_RETRIES 5
45#define DEFAULT_AUTH_PROTOCOL "MD5" 45#define DEFAULT_AUTH_PROTOCOL "MD5"
46#define DEFAULT_PRIV_PROTOCOL "DES" 46#define DEFAULT_PRIV_PROTOCOL "DES"
47#define DEFAULT_DELIMITER "=" 47#define DEFAULT_DELIMITER "="
48#define DEFAULT_OUTPUT_DELIMITER " " 48#define DEFAULT_OUTPUT_DELIMITER " "
49#define DEFAULT_BUFFER_SIZE 100 49#define DEFAULT_BUFFER_SIZE 100
50 50
51#define mark(a) ((a)!=0?"*":"") 51#define mark(a) ((a) != 0 ? "*" : "")
52 52
53#define CHECK_UNDEF 0 53#define CHECK_UNDEF 0
54#define CRIT_PRESENT 1 54#define CRIT_PRESENT 1
55#define CRIT_STRING 2 55#define CRIT_STRING 2
56#define CRIT_REGEX 4 56#define CRIT_REGEX 4
57#define WARN_PRESENT 8 57#define WARN_PRESENT 8
58#define WARN_STRING 16
59#define WARN_REGEX 32
60 58
61#define OID_COUNT_STEP 8 59#define OID_COUNT_STEP 8
62 60
63/* Longopts only arguments */ 61/* Longopts only arguments */
64#define L_CALCULATE_RATE CHAR_MAX+1 62#define L_CALCULATE_RATE CHAR_MAX + 1
65#define L_RATE_MULTIPLIER CHAR_MAX+2 63#define L_RATE_MULTIPLIER CHAR_MAX + 2
66#define L_INVERT_SEARCH CHAR_MAX+3 64#define L_INVERT_SEARCH CHAR_MAX + 3
67#define L_OFFSET CHAR_MAX+4 65#define L_OFFSET CHAR_MAX + 4
68#define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX+5 66#define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX + 5
69 67
70/* Gobble to string - stop incrementing c when c[0] match one of the 68/* Gobble to string - stop incrementing c when c[0] match one of the
71 * characters in s */ 69 * characters in s */
72#define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; } 70#define GOBBLE_TOS(c, s) \
71 while (c[0] != '\0' && strchr(s, c[0]) == NULL) { \
72 c++; \
73 }
73/* Given c, keep track of backslashes (bk) and double-quotes (dq) 74/* Given c, keep track of backslashes (bk) and double-quotes (dq)
74 * from c[0] */ 75 * from c[0] */
75#define COUNT_SEQ(c, bk, dq) switch(c[0]) {\ 76#define COUNT_SEQ(c, bk, dq) \
76 case '\\': \ 77 switch (c[0]) { \
77 if (bk) bk--; \ 78 case '\\': \
78 else bk++; \ 79 if (bk) \
79 break; \ 80 bk--; \
80 case '"': \ 81 else \
81 if (!dq) { dq++; } \ 82 bk++; \
82 else if(!bk) { dq--; } \ 83 break; \
83 else { bk--; } \ 84 case '"': \
84 break; \ 85 if (!dq) { \
86 dq++; \
87 } else if (!bk) { \
88 dq--; \
89 } else { \
90 bk--; \
91 } \
92 break; \
85 } 93 }
86 94
87 95static int process_arguments(int, char **);
88 96static int validate_arguments(void);
89int process_arguments (int, char **); 97static char *thisarg(char *str);
90int validate_arguments (void); 98static char *nextarg(char *str);
91char *thisarg (char *str); 99void print_usage(void);
92char *nextarg (char *str); 100static void print_help(void);
93void print_usage (void); 101static char *multiply(char *str);
94void print_help (void);
95char *multiply (char *str);
96 102
97#include "regex.h" 103#include "regex.h"
98char regex_expect[MAX_INPUT_BUFFER] = ""; 104static char regex_expect[MAX_INPUT_BUFFER] = "";
99regex_t preg; 105static regex_t preg;
100regmatch_t pmatch[10]; 106static regmatch_t pmatch[10];
101char errbuf[MAX_INPUT_BUFFER] = ""; 107static char errbuf[MAX_INPUT_BUFFER] = "";
102char perfstr[MAX_INPUT_BUFFER] = "| "; 108static char perfstr[MAX_INPUT_BUFFER] = "| ";
103int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 109static int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
104int eflags = 0; 110static int eflags = 0;
105int errcode, excode; 111static int errcode, excode;
106 112
107char *server_address = NULL; 113static char *server_address = NULL;
108char *community = NULL; 114static char *community = NULL;
109char **contextargs = NULL; 115static char **contextargs = NULL;
110char *context = NULL; 116static char *context = NULL;
111char **authpriv = NULL; 117static char **authpriv = NULL;
112char *proto = NULL; 118static char *proto = NULL;
113char *seclevel = NULL; 119static char *seclevel = NULL;
114char *secname = NULL; 120static char *secname = NULL;
115char *authproto = NULL; 121static char *authproto = NULL;
116char *privproto = NULL; 122static char *privproto = NULL;
117char *authpasswd = NULL; 123static char *authpasswd = NULL;
118char *privpasswd = NULL; 124static char *privpasswd = NULL;
119int nulloid = STATE_UNKNOWN; 125static int nulloid = STATE_UNKNOWN;
120char **oids = NULL; 126static char **oids = NULL;
121size_t oids_size = 0; 127static size_t oids_size = 0;
122char *label; 128static char *label;
123char *units; 129static char *units;
124char *port; 130static char *port;
125char *snmpcmd; 131static char *snmpcmd;
126char string_value[MAX_INPUT_BUFFER] = ""; 132static char string_value[MAX_INPUT_BUFFER] = "";
127int invert_search=0; 133static int invert_search = 0;
128char **labels = NULL; 134static char **labels = NULL;
129char **unitv = NULL; 135static char **unitv = NULL;
130size_t nlabels = 0; 136static size_t nlabels = 0;
131size_t labels_size = OID_COUNT_STEP; 137static size_t labels_size = OID_COUNT_STEP;
132size_t nunits = 0; 138static size_t nunits = 0;
133size_t unitv_size = OID_COUNT_STEP; 139static size_t unitv_size = OID_COUNT_STEP;
134size_t numoids = 0; 140static size_t numoids = 0;
135int numauthpriv = 0; 141static int numauthpriv = 0;
136int numcontext = 0; 142static int numcontext = 0;
137int verbose = 0; 143static int verbose = 0;
138bool usesnmpgetnext = false; 144static bool usesnmpgetnext = false;
139char *warning_thresholds = NULL; 145static char *warning_thresholds = NULL;
140char *critical_thresholds = NULL; 146static char *critical_thresholds = NULL;
141thresholds **thlds; 147static thresholds **thlds;
142size_t thlds_size = OID_COUNT_STEP; 148static size_t thlds_size = OID_COUNT_STEP;
143double *response_value; 149static double *response_value;
144size_t response_size = OID_COUNT_STEP; 150static size_t response_size = OID_COUNT_STEP;
145int retries = 0; 151static int retries = 0;
146int *eval_method; 152static int *eval_method;
147size_t eval_size = OID_COUNT_STEP; 153static size_t eval_size = OID_COUNT_STEP;
148char *delimiter; 154static char *delimiter;
149char *output_delim; 155static char *output_delim;
150char *miblist = NULL; 156static char *miblist = NULL;
151bool needmibs = false; 157static bool needmibs = false;
152int calculate_rate = 0; 158static int calculate_rate = 0;
153double offset = 0.0; 159static double offset = 0.0;
154int rate_multiplier = 1; 160static int rate_multiplier = 1;
155state_data *previous_state; 161static state_data *previous_state;
156double *previous_value; 162static double *previous_value;
157size_t previous_size = OID_COUNT_STEP; 163static size_t previous_size = OID_COUNT_STEP;
158int perf_labels = 1; 164static int perf_labels = 1;
159char* ip_version = ""; 165static char *ip_version = "";
160double multiplier = 1.0; 166static double multiplier = 1.0;
161char *fmtstr = ""; 167static char *fmtstr = "";
162bool fmtstr_set = false; 168static bool fmtstr_set = false;
163char buffer[DEFAULT_BUFFER_SIZE]; 169static char buffer[DEFAULT_BUFFER_SIZE];
164bool ignore_mib_parsing_errors = false; 170static bool ignore_mib_parsing_errors = false;
165 171
166static char *fix_snmp_range(char *th) 172static char *fix_snmp_range(char *th) {
167{ 173 double left;
168 double left, right; 174 double right;
169 char *colon, *ret; 175 char *colon;
176 char *ret;
170 177
171 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0') 178 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0')
172 return th; 179 return th;
@@ -184,12 +191,12 @@ static char *fix_snmp_range(char *th)
184 return ret; 191 return ret;
185} 192}
186 193
187int 194int main(int argc, char **argv) {
188main (int argc, char **argv) 195 int len;
189{ 196 int total_oids;
190 int len, total_oids;
191 size_t line; 197 size_t line;
192 unsigned int bk_count = 0, dq_count = 0; 198 unsigned int bk_count = 0;
199 unsigned int dq_count = 0;
193 int iresult = STATE_UNKNOWN; 200 int iresult = STATE_UNKNOWN;
194 int result = STATE_UNKNOWN; 201 int result = STATE_UNKNOWN;
195 int return_code = 0; 202 int return_code = 0;
@@ -202,80 +209,83 @@ main (int argc, char **argv)
202 char *outbuff; 209 char *outbuff;
203 char *ptr = NULL; 210 char *ptr = NULL;
204 char *show = NULL; 211 char *show = NULL;
205 char *th_warn=NULL; 212 char *th_warn = NULL;
206 char *th_crit=NULL; 213 char *th_crit = NULL;
207 char type[8] = ""; 214 char type[8] = "";
208 output chld_out, chld_err; 215 output chld_out;
209 char *previous_string=NULL; 216 output chld_err;
210 char *ap=NULL; 217 char *previous_string = NULL;
211 char *state_string=NULL; 218 char *ap = NULL;
212 size_t response_length, current_length, string_length; 219 char *state_string = NULL;
213 char *temp_string=NULL; 220 size_t response_length;
214 char *quote_string=NULL; 221 size_t current_length;
222 size_t string_length;
223 char *temp_string = NULL;
224 char *quote_string = NULL;
215 time_t current_time; 225 time_t current_time;
216 double temp_double; 226 double temp_double;
217 time_t duration; 227 time_t duration;
218 char *conv = "12345678"; 228 char *conv = "12345678";
219 int is_counter=0; 229 int is_counter = 0;
220 230
221 setlocale (LC_ALL, ""); 231 setlocale(LC_ALL, "");
222 bindtextdomain (PACKAGE, LOCALEDIR); 232 bindtextdomain(PACKAGE, LOCALEDIR);
223 textdomain (PACKAGE); 233 textdomain(PACKAGE);
224 234
225 labels = malloc (labels_size * sizeof(*labels)); 235 labels = malloc(labels_size * sizeof(*labels));
226 unitv = malloc (unitv_size * sizeof(*unitv)); 236 unitv = malloc(unitv_size * sizeof(*unitv));
227 thlds = malloc (thlds_size * sizeof(*thlds)); 237 thlds = malloc(thlds_size * sizeof(*thlds));
228 response_value = malloc (response_size * sizeof(*response_value)); 238 response_value = malloc(response_size * sizeof(*response_value));
229 previous_value = malloc (previous_size * sizeof(*previous_value)); 239 previous_value = malloc(previous_size * sizeof(*previous_value));
230 eval_method = calloc (eval_size, sizeof(*eval_method)); 240 eval_method = calloc(eval_size, sizeof(*eval_method));
231 oids = calloc(oids_size, sizeof (char *)); 241 oids = calloc(oids_size, sizeof(char *));
232 242
233 label = strdup ("SNMP"); 243 label = strdup("SNMP");
234 units = strdup (""); 244 units = strdup("");
235 port = strdup (DEFAULT_PORT); 245 port = strdup(DEFAULT_PORT);
236 outbuff = strdup (""); 246 outbuff = strdup("");
237 delimiter = strdup (" = "); 247 delimiter = strdup(" = ");
238 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER); 248 output_delim = strdup(DEFAULT_OUTPUT_DELIMITER);
239 timeout_interval = DEFAULT_SOCKET_TIMEOUT; 249 timeout_interval = DEFAULT_SOCKET_TIMEOUT;
240 retries = DEFAULT_RETRIES; 250 retries = DEFAULT_RETRIES;
241 251
242 np_init( (char *) progname, argc, argv ); 252 np_init((char *)progname, argc, argv);
243 253
244 /* Parse extra opts if any */ 254 /* Parse extra opts if any */
245 argv=np_extra_opts (&argc, argv, progname); 255 argv = np_extra_opts(&argc, argv, progname);
246 256
247 np_set_args(argc, argv); 257 np_set_args(argc, argv);
248 258
249 time(&current_time); 259 time(&current_time);
250 260
251 if (process_arguments (argc, argv) == ERROR) 261 if (process_arguments(argc, argv) == ERROR)
252 usage4 (_("Could not parse arguments")); 262 usage4(_("Could not parse arguments"));
253 263
254 if(calculate_rate) { 264 if (calculate_rate) {
255 if (!strcmp(label, "SNMP")) 265 if (!strcmp(label, "SNMP"))
256 label = strdup("SNMP RATE"); 266 label = strdup("SNMP RATE");
257 267
258 size_t i = 0; 268 size_t i = 0;
259 269
260 previous_state = np_state_read(); 270 previous_state = np_state_read();
261 if(previous_state!=NULL) { 271 if (previous_state != NULL) {
262 /* Split colon separated values */ 272 /* Split colon separated values */
263 previous_string = strdup((char *) previous_state->data); 273 previous_string = strdup((char *)previous_state->data);
264 while((ap = strsep(&previous_string, ":")) != NULL) { 274 while ((ap = strsep(&previous_string, ":")) != NULL) {
265 if(verbose>2) 275 if (verbose > 2)
266 printf("State for %zd=%s\n", i, ap); 276 printf("State for %zd=%s\n", i, ap);
267 while (i >= previous_size) { 277 while (i >= previous_size) {
268 previous_size += OID_COUNT_STEP; 278 previous_size += OID_COUNT_STEP;
269 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value)); 279 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value));
270 } 280 }
271 previous_value[i++]=strtod(ap,NULL); 281 previous_value[i++] = strtod(ap, NULL);
272 } 282 }
273 } 283 }
274 } 284 }
275 285
276 /* Populate the thresholds */ 286 /* Populate the thresholds */
277 th_warn=warning_thresholds; 287 th_warn = warning_thresholds;
278 th_crit=critical_thresholds; 288 th_crit = critical_thresholds;
279 for (size_t i = 0; i < numoids; i++) { 289 for (size_t i = 0; i < numoids; i++) {
280 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL; 290 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
281 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL; 291 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
@@ -289,53 +299,52 @@ main (int argc, char **argv)
289 } 299 }
290 300
291 /* Skip empty thresholds, while avoiding segfault */ 301 /* Skip empty thresholds, while avoiding segfault */
292 set_thresholds(&thlds[i], 302 set_thresholds(&thlds[i], w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL, c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
293 w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
294 c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
295 if (w) { 303 if (w) {
296 th_warn=strchr(th_warn, ','); 304 th_warn = strchr(th_warn, ',');
297 if (th_warn) th_warn++; 305 if (th_warn)
306 th_warn++;
298 free(w); 307 free(w);
299 } 308 }
300 if (c) { 309 if (c) {
301 th_crit=strchr(th_crit, ','); 310 th_crit = strchr(th_crit, ',');
302 if (th_crit) th_crit++; 311 if (th_crit)
312 th_crit++;
303 free(c); 313 free(c);
304 } 314 }
305 } 315 }
306 316
307 /* Create the command array to execute */ 317 /* Create the command array to execute */
308 if(usesnmpgetnext) { 318 if (usesnmpgetnext) {
309 snmpcmd = strdup (PATH_TO_SNMPGETNEXT); 319 snmpcmd = strdup(PATH_TO_SNMPGETNEXT);
310 }else{ 320 } else {
311 snmpcmd = strdup (PATH_TO_SNMPGET); 321 snmpcmd = strdup(PATH_TO_SNMPGET);
312 } 322 }
313 323
314 /* 10 arguments to pass before context and authpriv options + 1 for host and numoids. Add one for terminating NULL */ 324 /* 10 arguments to pass before context and authpriv options + 1 for host and numoids. Add one for terminating NULL */
315 325
316 unsigned index = 0; 326 unsigned index = 0;
317 command_line = calloc (11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof (char *)); 327 command_line = calloc(11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof(char *));
318 328
319 command_line[index++] = snmpcmd; 329 command_line[index++] = snmpcmd;
320 command_line[index++] = strdup ("-Le"); 330 command_line[index++] = strdup("-Le");
321 command_line[index++] = strdup ("-t"); 331 command_line[index++] = strdup("-t");
322 xasprintf (&command_line[index++], "%d", timeout_interval); 332 xasprintf(&command_line[index++], "%d", timeout_interval);
323 command_line[index++] = strdup ("-r"); 333 command_line[index++] = strdup("-r");
324 xasprintf (&command_line[index++], "%d", retries); 334 xasprintf(&command_line[index++], "%d", retries);
325 command_line[index++] = strdup ("-m"); 335 command_line[index++] = strdup("-m");
326 command_line[index++] = strdup (miblist); 336 command_line[index++] = strdup(miblist);
327 command_line[index++] = "-v"; 337 command_line[index++] = "-v";
328 command_line[index++] = strdup (proto); 338 command_line[index++] = strdup(proto);
329 339
330 xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s", 340 xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s", snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''",
331 snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto); 341 proto);
332 342
333 if (ignore_mib_parsing_errors) { 343 if (ignore_mib_parsing_errors) {
334 command_line[index++] = "-Pe"; 344 command_line[index++] = "-Pe";
335 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth); 345 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth);
336 } 346 }
337 347
338
339 for (int i = 0; i < numcontext; i++) { 348 for (int i = 0; i < numcontext; i++) {
340 command_line[index++] = contextargs[i]; 349 command_line[index++] = contextargs[i];
341 } 350 }
@@ -344,12 +353,9 @@ main (int argc, char **argv)
344 command_line[index++] = authpriv[i]; 353 command_line[index++] = authpriv[i];
345 } 354 }
346 355
347 xasprintf (&command_line[index++], "%s:%s", server_address, port); 356 xasprintf(&command_line[index++], "%s:%s", server_address, port);
348 357
349 xasprintf(&cl_hidden_auth, "%s [context] [authpriv] %s:%s", 358 xasprintf(&cl_hidden_auth, "%s [context] [authpriv] %s:%s", cl_hidden_auth, server_address, port);
350 cl_hidden_auth,
351 server_address,
352 port);
353 359
354 for (size_t i = 0; i < numoids; i++) { 360 for (size_t i = 0; i < numoids; i++) {
355 command_line[index++] = oids[i]; 361 command_line[index++] = oids[i];
@@ -359,17 +365,17 @@ main (int argc, char **argv)
359 command_line[index++] = NULL; 365 command_line[index++] = NULL;
360 366
361 if (verbose) { 367 if (verbose) {
362 printf ("%s\n", cl_hidden_auth); 368 printf("%s\n", cl_hidden_auth);
363 } 369 }
364 370
365 /* Set signal handling and alarm */ 371 /* Set signal handling and alarm */
366 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) { 372 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
367 usage4 (_("Cannot catch SIGALRM")); 373 usage4(_("Cannot catch SIGALRM"));
368 } 374 }
369 alarm(timeout_interval * retries + 5); 375 alarm(timeout_interval * retries + 5);
370 376
371 /* Run the command */ 377 /* Run the command */
372 return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0); 378 return_code = cmd_run_array(command_line, &chld_out, &chld_err, 0);
373 379
374 /* disable alarm again */ 380 /* disable alarm again */
375 alarm(0); 381 alarm(0);
@@ -379,80 +385,74 @@ main (int argc, char **argv)
379 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis 385 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
380 */ 386 */
381 if (return_code != 0) 387 if (return_code != 0)
382 external_error=1; 388 external_error = 1;
383 if (chld_out.lines == 0) 389 if (chld_out.lines == 0)
384 external_error=1; 390 external_error = 1;
385 if (external_error) { 391 if (external_error) {
386 if (chld_err.lines > 0) { 392 if (chld_err.lines > 0) {
387 printf (_("External command error: %s\n"), chld_err.line[0]); 393 printf(_("External command error: %s\n"), chld_err.line[0]);
388 for (size_t i = 1; i < chld_err.lines; i++) { 394 for (size_t i = 1; i < chld_err.lines; i++) {
389 printf ("%s\n", chld_err.line[i]); 395 printf("%s\n", chld_err.line[i]);
390 } 396 }
391 } else { 397 } else {
392 printf(_("External command error with no output (return code: %d)\n"), return_code); 398 printf(_("External command error with no output (return code: %d)\n"), return_code);
393 } 399 }
394 exit (STATE_UNKNOWN); 400 exit(STATE_UNKNOWN);
395 } 401 }
396 402
397 if (verbose) { 403 if (verbose) {
398 for (size_t i = 0; i < chld_out.lines; i++) { 404 for (size_t i = 0; i < chld_out.lines; i++) {
399 printf ("%s\n", chld_out.line[i]); 405 printf("%s\n", chld_out.line[i]);
400 } 406 }
401 } 407 }
402 408
403 line = 0; 409 line = 0;
404 total_oids = 0; 410 total_oids = 0;
405 for (size_t i = 0; line < chld_out.lines && i < numoids ; line++, i++, total_oids++) { 411 for (size_t i = 0; line < chld_out.lines && i < numoids; line++, i++, total_oids++) {
406 if(calculate_rate) 412 if (calculate_rate)
407 conv = "%.10g"; 413 conv = "%.10g";
408 else 414 else
409 conv = "%.0f"; 415 conv = "%.0f";
410 416
411 ptr = chld_out.line[line]; 417 ptr = chld_out.line[line];
412 oidname = strpcpy (oidname, ptr, delimiter); 418 oidname = strpcpy(oidname, ptr, delimiter);
413 response = strstr (ptr, delimiter); 419 response = strstr(ptr, delimiter);
414 if (response == NULL) 420 if (response == NULL)
415 break; 421 break;
416 422
417 if (verbose > 2) { 423 if (verbose > 2) {
418 printf("Processing oid %zi (line %zi)\n oidname: %s\n response: %s\n", i+1, line+1, oidname, response); 424 printf("Processing oid %zi (line %zi)\n oidname: %s\n response: %s\n", i + 1, line + 1, oidname, response);
419 } 425 }
420 426
421 /* Clean up type array - Sol10 does not necessarily zero it out */ 427 /* Clean up type array - Sol10 does not necessarily zero it out */
422 bzero(type, sizeof(type)); 428 bzero(type, sizeof(type));
423 429
424 is_counter=0; 430 is_counter = 0;
425 /* We strip out the datatype indicator for PHBs */ 431 /* We strip out the datatype indicator for PHBs */
426 if (strstr (response, "Gauge: ")) { 432 if (strstr(response, "Gauge: ")) {
427 show = multiply (strstr (response, "Gauge: ") + 7); 433 show = multiply(strstr(response, "Gauge: ") + 7);
428 } 434 } else if (strstr(response, "Gauge32: ")) {
429 else if (strstr (response, "Gauge32: ")) { 435 show = multiply(strstr(response, "Gauge32: ") + 9);
430 show = multiply (strstr (response, "Gauge32: ") + 9); 436 } else if (strstr(response, "Counter32: ")) {
431 } 437 show = strstr(response, "Counter32: ") + 11;
432 else if (strstr (response, "Counter32: ")) { 438 is_counter = 1;
433 show = strstr (response, "Counter32: ") + 11; 439 if (!calculate_rate)
434 is_counter=1;
435 if(!calculate_rate)
436 strcpy(type, "c"); 440 strcpy(type, "c");
437 } 441 } else if (strstr(response, "Counter64: ")) {
438 else if (strstr (response, "Counter64: ")) { 442 show = strstr(response, "Counter64: ") + 11;
439 show = strstr (response, "Counter64: ") + 11; 443 is_counter = 1;
440 is_counter=1; 444 if (!calculate_rate)
441 if(!calculate_rate)
442 strcpy(type, "c"); 445 strcpy(type, "c");
443 } 446 } else if (strstr(response, "INTEGER: ")) {
444 else if (strstr (response, "INTEGER: ")) { 447 show = multiply(strstr(response, "INTEGER: ") + 9);
445 show = multiply (strstr (response, "INTEGER: ") + 9);
446 448
447 if (fmtstr_set) { 449 if (fmtstr_set) {
448 conv = fmtstr; 450 conv = fmtstr;
449 } 451 }
450 } 452 } else if (strstr(response, "OID: ")) {
451 else if (strstr (response, "OID: ")) { 453 show = strstr(response, "OID: ") + 5;
452 show = strstr (response, "OID: ") + 5; 454 } else if (strstr(response, "STRING: ")) {
453 } 455 show = strstr(response, "STRING: ") + 8;
454 else if (strstr (response, "STRING: ")) {
455 show = strstr (response, "STRING: ") + 8;
456 conv = "%.10g"; 456 conv = "%.10g";
457 457
458 /* Get the rest of the string on multi-line strings */ 458 /* Get the rest of the string on multi-line strings */
@@ -466,15 +466,17 @@ main (int argc, char **argv)
466 466
467 if (dq_count) { /* unfinished line */ 467 if (dq_count) { /* unfinished line */
468 /* copy show verbatim first */ 468 /* copy show verbatim first */
469 if (!mult_resp) mult_resp = strdup(""); 469 if (!mult_resp)
470 xasprintf (&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show); 470 mult_resp = strdup("");
471 xasprintf(&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show);
471 /* then strip out unmatched double-quote from single-line output */ 472 /* then strip out unmatched double-quote from single-line output */
472 if (show[0] == '"') show++; 473 if (show[0] == '"')
474 show++;
473 475
474 /* Keep reading until we match end of double-quoted string */ 476 /* Keep reading until we match end of double-quoted string */
475 for (line++; line < chld_out.lines; line++) { 477 for (line++; line < chld_out.lines; line++) {
476 ptr = chld_out.line[line]; 478 ptr = chld_out.line[line];
477 xasprintf (&mult_resp, "%s%s\n", mult_resp, ptr); 479 xasprintf(&mult_resp, "%s%s\n", mult_resp, ptr);
478 480
479 COUNT_SEQ(ptr, bk_count, dq_count) 481 COUNT_SEQ(ptr, bk_count, dq_count)
480 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') { 482 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
@@ -483,15 +485,14 @@ main (int argc, char **argv)
483 COUNT_SEQ(ptr, bk_count, dq_count) 485 COUNT_SEQ(ptr, bk_count, dq_count)
484 } 486 }
485 /* Break for loop before next line increment when done */ 487 /* Break for loop before next line increment when done */
486 if (!dq_count) break; 488 if (!dq_count)
489 break;
487 } 490 }
488 } 491 }
489 492
490 } 493 } else if (strstr(response, "Timeticks: ")) {
491 else if (strstr (response, "Timeticks: ")) { 494 show = strstr(response, "Timeticks: ");
492 show = strstr (response, "Timeticks: "); 495 } else
493 }
494 else
495 show = response + 3; 496 show = response + 3;
496 497
497 iresult = STATE_DEPENDENT; 498 iresult = STATE_DEPENDENT;
@@ -502,68 +503,67 @@ main (int argc, char **argv)
502 if (verbose > 2) { 503 if (verbose > 2) {
503 print_thresholds(" thresholds", thlds[i]); 504 print_thresholds(" thresholds", thlds[i]);
504 } 505 }
505 ptr = strpbrk (show, "-0123456789"); 506 ptr = strpbrk(show, "-0123456789");
506 if (ptr == NULL){ 507 if (ptr == NULL) {
507 if (nulloid == 3) 508 if (nulloid == 3)
508 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show); 509 die(STATE_UNKNOWN, _("No valid data returned (%s)\n"), show);
509 else if (nulloid == 0) 510 else if (nulloid == 0)
510 die (STATE_OK,_("No valid data returned (%s)\n"), show); 511 die(STATE_OK, _("No valid data returned (%s)\n"), show);
511 else if (nulloid == 1) 512 else if (nulloid == 1)
512 die (STATE_WARNING,_("No valid data returned (%s)\n"), show); 513 die(STATE_WARNING, _("No valid data returned (%s)\n"), show);
513 else if (nulloid == 2) 514 else if (nulloid == 2)
514 die (STATE_CRITICAL,_("No valid data returned (%s)\n"), show); 515 die(STATE_CRITICAL, _("No valid data returned (%s)\n"), show);
515 } 516 }
516 while (i >= response_size) { 517 while (i >= response_size) {
517 response_size += OID_COUNT_STEP; 518 response_size += OID_COUNT_STEP;
518 response_value = realloc(response_value, response_size * sizeof(*response_value)); 519 response_value = realloc(response_value, response_size * sizeof(*response_value));
519 } 520 }
520 response_value[i] = strtod (ptr, NULL) + offset; 521 response_value[i] = strtod(ptr, NULL) + offset;
521 522
522 if(calculate_rate) { 523 if (calculate_rate) {
523 if (previous_state!=NULL) { 524 if (previous_state != NULL) {
524 duration = current_time-previous_state->time; 525 duration = current_time - previous_state->time;
525 if(duration<=0) 526 if (duration <= 0)
526 die(STATE_UNKNOWN,_("Time duration between plugin calls is invalid")); 527 die(STATE_UNKNOWN, _("Time duration between plugin calls is invalid"));
527 temp_double = response_value[i]-previous_value[i]; 528 temp_double = response_value[i] - previous_value[i];
528 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */ 529 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */
529 if(is_counter) { 530 if (is_counter) {
530 if(temp_double<(double)0.0) 531 if (temp_double < (double)0.0)
531 temp_double+=(double)4294967296.0; /* 2^32 */ 532 temp_double += (double)4294967296.0; /* 2^32 */
532 if(temp_double<(double)0.0) 533 if (temp_double < (double)0.0)
533 temp_double+=(double)18446744069414584320.0; /* 2^64-2^32 */; 534 temp_double += (double)18446744069414584320.0; /* 2^64-2^32 */
535 ;
534 } 536 }
535 /* Convert to per second, then use multiplier */ 537 /* Convert to per second, then use multiplier */
536 temp_double = temp_double/duration*rate_multiplier; 538 temp_double = temp_double / duration * rate_multiplier;
537 iresult = get_status(temp_double, thlds[i]); 539 iresult = get_status(temp_double, thlds[i]);
538 xasprintf (&show, conv, temp_double); 540 xasprintf(&show, conv, temp_double);
539 } 541 }
540 } else { 542 } else {
541 iresult = get_status(response_value[i], thlds[i]); 543 iresult = get_status(response_value[i], thlds[i]);
542 xasprintf (&show, conv, response_value[i]); 544 xasprintf(&show, conv, response_value[i]);
543 } 545 }
544 } 546 }
545 547
546 /* Process this block for string matching */ 548 /* Process this block for string matching */
547 else if (eval_size > i && eval_method[i] & CRIT_STRING) { 549 else if (eval_size > i && eval_method[i] & CRIT_STRING) {
548 if (strcmp (show, string_value)) 550 if (strcmp(show, string_value))
549 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK; 551 iresult = (invert_search == 0) ? STATE_CRITICAL : STATE_OK;
550 else 552 else
551 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL; 553 iresult = (invert_search == 0) ? STATE_OK : STATE_CRITICAL;
552 } 554 }
553 555
554 /* Process this block for regex matching */ 556 /* Process this block for regex matching */
555 else if (eval_size > i && eval_method[i] & CRIT_REGEX) { 557 else if (eval_size > i && eval_method[i] & CRIT_REGEX) {
556 excode = regexec (&preg, response, 10, pmatch, eflags); 558 excode = regexec(&preg, response, 10, pmatch, eflags);
557 if (excode == 0) { 559 if (excode == 0) {
558 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL; 560 iresult = (invert_search == 0) ? STATE_OK : STATE_CRITICAL;
559 } 561 } else if (excode != REG_NOMATCH) {
560 else if (excode != REG_NOMATCH) { 562 regerror(excode, &preg, errbuf, MAX_INPUT_BUFFER);
561 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER); 563 printf(_("Execute Error: %s\n"), errbuf);
562 printf (_("Execute Error: %s\n"), errbuf); 564 exit(STATE_CRITICAL);
563 exit (STATE_CRITICAL); 565 } else {
564 } 566 iresult = (invert_search == 0) ? STATE_CRITICAL : STATE_OK;
565 else {
566 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK;
567 } 567 }
568 } 568 }
569 569
@@ -579,294 +579,283 @@ main (int argc, char **argv)
579 } 579 }
580 580
581 /* Result is the worst outcome of all the OIDs tested */ 581 /* Result is the worst outcome of all the OIDs tested */
582 result = max_state (result, iresult); 582 result = max_state(result, iresult);
583 583
584 /* Prepend a label for this OID if there is one */ 584 /* Prepend a label for this OID if there is one */
585 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) 585 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
586 xasprintf (&outbuff, "%s%s%s %s%s%s", outbuff, 586 xasprintf(&outbuff, "%s%s%s %s%s%s", outbuff, (i == 0) ? " " : output_delim, labels[i], mark(iresult), show, mark(iresult));
587 (i == 0) ? " " : output_delim,
588 labels[i], mark (iresult), show, mark (iresult));
589 else 587 else
590 xasprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim, 588 xasprintf(&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim, mark(iresult), show, mark(iresult));
591 mark (iresult), show, mark (iresult));
592 589
593 /* Append a unit string for this OID if there is one */ 590 /* Append a unit string for this OID if there is one */
594 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL) 591 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
595 xasprintf (&outbuff, "%s %s", outbuff, unitv[i]); 592 xasprintf(&outbuff, "%s %s", outbuff, unitv[i]);
596 593
597 /* Write perfdata with whatever can be parsed by strtod, if possible */ 594 /* Write perfdata with whatever can be parsed by strtod, if possible */
598 ptr = NULL; 595 ptr = NULL;
599 strtod(show, &ptr); 596 strtod(show, &ptr);
600 if (ptr > show) { 597 if (ptr > show) {
601 if (perf_labels && nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) 598 if (perf_labels && nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
602 temp_string=labels[i]; 599 temp_string = labels[i];
603 else 600 else
604 temp_string=oidname; 601 temp_string = oidname;
605 if (strpbrk (temp_string, " ='\"") == NULL) { 602 if (strpbrk(temp_string, " ='\"") == NULL) {
606 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); 603 strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
607 } else { 604 } else {
608 if (strpbrk (temp_string, "'") == NULL) { 605 if (strpbrk(temp_string, "'") == NULL) {
609 quote_string="'"; 606 quote_string = "'";
610 } else { 607 } else {
611 quote_string="\""; 608 quote_string = "\"";
612 } 609 }
613 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1); 610 strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
614 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); 611 strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
615 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1); 612 strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
616 } 613 }
617 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1); 614 strncat(perfstr, "=", sizeof(perfstr) - strlen(perfstr) - 1);
618 len = sizeof(perfstr)-strlen(perfstr)-1; 615 len = sizeof(perfstr) - strlen(perfstr) - 1;
619 strncat(perfstr, show, len>ptr-show ? ptr-show : len); 616 strncat(perfstr, show, len > ptr - show ? ptr - show : len);
620 617
621 if (strcmp(type, "") != 0) { 618 if (strcmp(type, "") != 0) {
622 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1); 619 strncat(perfstr, type, sizeof(perfstr) - strlen(perfstr) - 1);
623 } 620 }
624 621
625 if (warning_thresholds) { 622 if (warning_thresholds) {
626 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 623 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
627 if(thlds[i]->warning && thlds[i]->warning->text) 624 if (thlds[i]->warning && thlds[i]->warning->text)
628 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr)-strlen(perfstr)-1); 625 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr) - strlen(perfstr) - 1);
629 } 626 }
630 627
631 if (critical_thresholds) { 628 if (critical_thresholds) {
632 if (!warning_thresholds) 629 if (!warning_thresholds)
633 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 630 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
634 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 631 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
635 if(thlds[i]->critical && thlds[i]->critical->text) 632 if (thlds[i]->critical && thlds[i]->critical->text)
636 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr)-strlen(perfstr)-1); 633 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr) - strlen(perfstr) - 1);
637 } 634 }
638 635
639 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); 636 strncat(perfstr, " ", sizeof(perfstr) - strlen(perfstr) - 1);
640 } 637 }
641 } 638 }
642 639
643 /* Save state data, as all data collected now */ 640 /* Save state data, as all data collected now */
644 if(calculate_rate) { 641 if (calculate_rate) {
645 string_length=1024; 642 string_length = 1024;
646 state_string=malloc(string_length); 643 state_string = malloc(string_length);
647 if(state_string==NULL) 644 if (state_string == NULL)
648 die(STATE_UNKNOWN, _("Cannot malloc")); 645 die(STATE_UNKNOWN, _("Cannot malloc"));
649 646
650 current_length=0; 647 current_length = 0;
651 for(int i = 0; i < total_oids; i++) { 648 for (int i = 0; i < total_oids; i++) {
652 xasprintf(&temp_string,"%.0f",response_value[i]); 649 xasprintf(&temp_string, "%.0f", response_value[i]);
653 if(temp_string==NULL) 650 if (temp_string == NULL)
654 die(STATE_UNKNOWN,_("Cannot asprintf()")); 651 die(STATE_UNKNOWN, _("Cannot asprintf()"));
655 response_length = strlen(temp_string); 652 response_length = strlen(temp_string);
656 if(current_length+response_length>string_length) { 653 if (current_length + response_length > string_length) {
657 string_length=current_length+1024; 654 string_length = current_length + 1024;
658 state_string=realloc(state_string,string_length); 655 state_string = realloc(state_string, string_length);
659 if(state_string==NULL) 656 if (state_string == NULL)
660 die(STATE_UNKNOWN, _("Cannot realloc()")); 657 die(STATE_UNKNOWN, _("Cannot realloc()"));
661 } 658 }
662 strcpy(&state_string[current_length],temp_string); 659 strcpy(&state_string[current_length], temp_string);
663 current_length=current_length+response_length; 660 current_length = current_length + response_length;
664 state_string[current_length]=':'; 661 state_string[current_length] = ':';
665 current_length++; 662 current_length++;
666 free(temp_string); 663 free(temp_string);
667 } 664 }
668 state_string[--current_length]='\0'; 665 state_string[--current_length] = '\0';
669 if (verbose > 2) 666 if (verbose > 2)
670 printf("State string=%s\n",state_string); 667 printf("State string=%s\n", state_string);
671 668
672 /* This is not strictly the same as time now, but any subtle variations will cancel out */ 669 /* This is not strictly the same as time now, but any subtle variations will cancel out */
673 np_state_write_string(current_time, state_string ); 670 np_state_write_string(current_time, state_string);
674 if(previous_state==NULL) { 671 if (previous_state == NULL) {
675 /* Or should this be highest state? */ 672 /* Or should this be highest state? */
676 die( STATE_OK, _("No previous data to calculate rate - assume okay" ) ); 673 die(STATE_OK, _("No previous data to calculate rate - assume okay"));
677 } 674 }
678 } 675 }
679 676
680 printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr); 677 printf("%s %s -%s %s\n", label, state_text(result), outbuff, perfstr);
681 if (mult_resp) printf ("%s", mult_resp); 678 if (mult_resp)
679 printf("%s", mult_resp);
682 680
683 return result; 681 return result;
684} 682}
685 683
686
687
688/* process command-line arguments */ 684/* process command-line arguments */
689int 685int process_arguments(int argc, char **argv) {
690process_arguments (int argc, char **argv) 686 static struct option longopts[] = {STD_LONG_OPTS,
691{ 687 {"community", required_argument, 0, 'C'},
692 char *ptr; 688 {"oid", required_argument, 0, 'o'},
693 int c = 1; 689 {"object", required_argument, 0, 'o'},
694 size_t j = 0, jj = 0; 690 {"delimiter", required_argument, 0, 'd'},
695 691 {"nulloid", required_argument, 0, 'z'},
696 int option = 0; 692 {"output-delimiter", required_argument, 0, 'D'},
697 static struct option longopts[] = { 693 {"string", required_argument, 0, 's'},
698 STD_LONG_OPTS, 694 {"timeout", required_argument, 0, 't'},
699 {"community", required_argument, 0, 'C'}, 695 {"regex", required_argument, 0, 'r'},
700 {"oid", required_argument, 0, 'o'}, 696 {"ereg", required_argument, 0, 'r'},
701 {"object", required_argument, 0, 'o'}, 697 {"eregi", required_argument, 0, 'R'},
702 {"delimiter", required_argument, 0, 'd'}, 698 {"label", required_argument, 0, 'l'},
703 {"nulloid", required_argument, 0, 'z'}, 699 {"units", required_argument, 0, 'u'},
704 {"output-delimiter", required_argument, 0, 'D'}, 700 {"port", required_argument, 0, 'p'},
705 {"string", required_argument, 0, 's'}, 701 {"retries", required_argument, 0, 'e'},
706 {"timeout", required_argument, 0, 't'}, 702 {"miblist", required_argument, 0, 'm'},
707 {"regex", required_argument, 0, 'r'}, 703 {"protocol", required_argument, 0, 'P'},
708 {"ereg", required_argument, 0, 'r'}, 704 {"context", required_argument, 0, 'N'},
709 {"eregi", required_argument, 0, 'R'}, 705 {"seclevel", required_argument, 0, 'L'},
710 {"label", required_argument, 0, 'l'}, 706 {"secname", required_argument, 0, 'U'},
711 {"units", required_argument, 0, 'u'}, 707 {"authproto", required_argument, 0, 'a'},
712 {"port", required_argument, 0, 'p'}, 708 {"privproto", required_argument, 0, 'x'},
713 {"retries", required_argument, 0, 'e'}, 709 {"authpasswd", required_argument, 0, 'A'},
714 {"miblist", required_argument, 0, 'm'}, 710 {"privpasswd", required_argument, 0, 'X'},
715 {"protocol", required_argument, 0, 'P'}, 711 {"next", no_argument, 0, 'n'},
716 {"context", required_argument, 0, 'N'}, 712 {"rate", no_argument, 0, L_CALCULATE_RATE},
717 {"seclevel", required_argument, 0, 'L'}, 713 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER},
718 {"secname", required_argument, 0, 'U'}, 714 {"offset", required_argument, 0, L_OFFSET},
719 {"authproto", required_argument, 0, 'a'}, 715 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
720 {"privproto", required_argument, 0, 'x'}, 716 {"perf-oids", no_argument, 0, 'O'},
721 {"authpasswd", required_argument, 0, 'A'}, 717 {"ipv4", no_argument, 0, '4'},
722 {"privpasswd", required_argument, 0, 'X'}, 718 {"ipv6", no_argument, 0, '6'},
723 {"next", no_argument, 0, 'n'}, 719 {"multiplier", required_argument, 0, 'M'},
724 {"rate", no_argument, 0, L_CALCULATE_RATE}, 720 {"fmtstr", required_argument, 0, 'f'},
725 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER}, 721 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
726 {"offset", required_argument, 0, L_OFFSET}, 722 {0, 0, 0, 0}};
727 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
728 {"perf-oids", no_argument, 0, 'O'},
729 {"ipv4", no_argument, 0, '4'},
730 {"ipv6", no_argument, 0, '6'},
731 {"multiplier", required_argument, 0, 'M'},
732 {"fmtstr", required_argument, 0, 'f'},
733 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
734 {0, 0, 0, 0}
735 };
736 723
737 if (argc < 2) 724 if (argc < 2)
738 return ERROR; 725 return ERROR;
739 726
740 /* reverse compatibility for very old non-POSIX usage forms */ 727 /* reverse compatibility for very old non-POSIX usage forms */
741 for (c = 1; c < argc; c++) { 728 for (int c = 1; c < argc; c++) {
742 if (strcmp ("-to", argv[c]) == 0) 729 if (strcmp("-to", argv[c]) == 0)
743 strcpy (argv[c], "-t"); 730 strcpy(argv[c], "-t");
744 if (strcmp ("-wv", argv[c]) == 0) 731 if (strcmp("-wv", argv[c]) == 0)
745 strcpy (argv[c], "-w"); 732 strcpy(argv[c], "-w");
746 if (strcmp ("-cv", argv[c]) == 0) 733 if (strcmp("-cv", argv[c]) == 0)
747 strcpy (argv[c], "-c"); 734 strcpy(argv[c], "-c");
748 } 735 }
749 736
750 while (1) { 737 size_t j = 0;
751 c = getopt_long (argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:M:f:z:", 738 size_t jj = 0;
752 longopts, &option); 739 while (true) {
740 int option = 0;
741 int option_char = getopt_long(argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:M:f:z:", longopts, &option);
753 742
754 if (c == -1 || c == EOF) 743 if (option_char == -1 || option_char == EOF)
755 break; 744 break;
756 745
757 switch (c) { 746 switch (option_char) {
758 case '?': /* usage */ 747 case '?': /* usage */
759 usage5 (); 748 usage5();
760 case 'h': /* help */ 749 case 'h': /* help */
761 print_help (); 750 print_help();
762 exit (STATE_UNKNOWN); 751 exit(STATE_UNKNOWN);
763 case 'V': /* version */ 752 case 'V': /* version */
764 print_revision (progname, NP_VERSION); 753 print_revision(progname, NP_VERSION);
765 exit (STATE_UNKNOWN); 754 exit(STATE_UNKNOWN);
766 case 'v': /* verbose */ 755 case 'v': /* verbose */
767 verbose++; 756 verbose++;
768 break; 757 break;
769 758
770 /* Connection info */ 759 /* Connection info */
771 case 'C': /* group or community */ 760 case 'C': /* group or community */
772 community = optarg; 761 community = optarg;
773 break; 762 break;
774 case 'H': /* Host or server */ 763 case 'H': /* Host or server */
775 server_address = optarg; 764 server_address = optarg;
776 break; 765 break;
777 case 'p': /* TCP port number */ 766 case 'p': /* TCP port number */
778 port = optarg; 767 port = optarg;
779 break; 768 break;
780 case 'm': /* List of MIBS */ 769 case 'm': /* List of MIBS */
781 miblist = optarg; 770 miblist = optarg;
782 break; 771 break;
783 case 'n': /* usesnmpgetnext */ 772 case 'n': /* usesnmpgetnext */
784 usesnmpgetnext = true; 773 usesnmpgetnext = true;
785 break; 774 break;
786 case 'P': /* SNMP protocol version */ 775 case 'P': /* SNMP protocol version */
787 proto = optarg; 776 proto = optarg;
788 break; 777 break;
789 case 'N': /* SNMPv3 context */ 778 case 'N': /* SNMPv3 context */
790 context = optarg; 779 context = optarg;
791 break; 780 break;
792 case 'L': /* security level */ 781 case 'L': /* security level */
793 seclevel = optarg; 782 seclevel = optarg;
794 break; 783 break;
795 case 'U': /* security username */ 784 case 'U': /* security username */
796 secname = optarg; 785 secname = optarg;
797 break; 786 break;
798 case 'a': /* auth protocol */ 787 case 'a': /* auth protocol */
799 authproto = optarg; 788 authproto = optarg;
800 break; 789 break;
801 case 'x': /* priv protocol */ 790 case 'x': /* priv protocol */
802 privproto = optarg; 791 privproto = optarg;
803 break; 792 break;
804 case 'A': /* auth passwd */ 793 case 'A': /* auth passwd */
805 authpasswd = optarg; 794 authpasswd = optarg;
806 break; 795 break;
807 case 'X': /* priv passwd */ 796 case 'X': /* priv passwd */
808 privpasswd = optarg; 797 privpasswd = optarg;
809 break; 798 break;
810 case 't': /* timeout period */ 799 case 't': /* timeout period */
811 if (!is_integer (optarg)) 800 if (!is_integer(optarg))
812 usage2 (_("Timeout interval must be a positive integer"), optarg); 801 usage2(_("Timeout interval must be a positive integer"), optarg);
813 else 802 else
814 timeout_interval = atoi (optarg); 803 timeout_interval = atoi(optarg);
815 break; 804 break;
816 805
817 /* Test parameters */ 806 /* Test parameters */
818 case 'c': /* critical threshold */ 807 case 'c': /* critical threshold */
819 critical_thresholds = optarg; 808 critical_thresholds = optarg;
820 break; 809 break;
821 case 'w': /* warning threshold */ 810 case 'w': /* warning threshold */
822 warning_thresholds = optarg; 811 warning_thresholds = optarg;
823 break; 812 break;
824 case 'e': /* PRELIMINARY - may change */ 813 case 'e': /* PRELIMINARY - may change */
825 case 'E': /* PRELIMINARY - may change */ 814 case 'E': /* PRELIMINARY - may change */
826 if (!is_integer (optarg)) 815 if (!is_integer(optarg))
827 usage2 (_("Retries interval must be a positive integer"), optarg); 816 usage2(_("Retries interval must be a positive integer"), optarg);
828 else 817 else
829 retries = atoi(optarg); 818 retries = atoi(optarg);
830 break; 819 break;
831 case 'o': /* object identifier */ 820 case 'o': /* object identifier */
832 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) { 821 if (strspn(optarg, "0123456789.,") != strlen(optarg)) {
833 /* 822 /*
834 * we have something other than digits, periods and comas, 823 * we have something other than digits, periods and comas,
835 * so we have a mib variable, rather than just an SNMP OID, 824 * so we have a mib variable, rather than just an SNMP OID,
836 * so we have to actually read the mib files 825 * so we have to actually read the mib files
837 */ 826 */
838 needmibs = true; 827 needmibs = true;
839 } 828 }
840 for (ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) { 829 for (char *ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) {
841 while (j >= oids_size) { 830 while (j >= oids_size) {
842 oids_size += OID_COUNT_STEP; 831 oids_size += OID_COUNT_STEP;
843 oids = realloc(oids, oids_size * sizeof (*oids)); 832 oids = realloc(oids, oids_size * sizeof(*oids));
844 } 833 }
845 oids[j] = strdup(ptr); 834 oids[j] = strdup(ptr);
846 } 835 }
847 numoids = j; 836 numoids = j;
848 if (c == 'E' || c == 'e') { 837 if (option_char == 'E' || option_char == 'e') {
849 jj++; 838 jj++;
850 while (j+1 >= eval_size) { 839 while (j + 1 >= eval_size) {
851 eval_size += OID_COUNT_STEP; 840 eval_size += OID_COUNT_STEP;
852 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method)); 841 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
853 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8); 842 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8);
854 } 843 }
855 if (c == 'E') 844 if (option_char == 'E')
856 eval_method[j+1] |= WARN_PRESENT; 845 eval_method[j + 1] |= WARN_PRESENT;
857 else if (c == 'e') 846 else if (option_char == 'e')
858 eval_method[j+1] |= CRIT_PRESENT; 847 eval_method[j + 1] |= CRIT_PRESENT;
859 } 848 }
860 break; 849 break;
861 case 'z': /* Null OID Return Check */ 850 case 'z': /* Null OID Return Check */
862 if (!is_integer (optarg)) 851 if (!is_integer(optarg))
863 usage2 (_("Exit status must be a positive integer"), optarg); 852 usage2(_("Exit status must be a positive integer"), optarg);
864 else 853 else
865 nulloid = atoi(optarg); 854 nulloid = atoi(optarg);
866 break; 855 break;
867 case 's': /* string or substring */ 856 case 's': /* string or substring */
868 strncpy (string_value, optarg, sizeof (string_value) - 1); 857 strncpy(string_value, optarg, sizeof(string_value) - 1);
869 string_value[sizeof (string_value) - 1] = 0; 858 string_value[sizeof(string_value) - 1] = 0;
870 while (jj >= eval_size) { 859 while (jj >= eval_size) {
871 eval_size += OID_COUNT_STEP; 860 eval_size += OID_COUNT_STEP;
872 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method)); 861 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
@@ -874,17 +863,17 @@ process_arguments (int argc, char **argv)
874 } 863 }
875 eval_method[jj++] = CRIT_STRING; 864 eval_method[jj++] = CRIT_STRING;
876 break; 865 break;
877 case 'R': /* regex */ 866 case 'R': /* regex */
878 cflags = REG_ICASE; 867 cflags = REG_ICASE;
879 // fall through 868 // fall through
880 case 'r': /* regex */ 869 case 'r': /* regex */
881 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 870 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
882 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1); 871 strncpy(regex_expect, optarg, sizeof(regex_expect) - 1);
883 regex_expect[sizeof (regex_expect) - 1] = 0; 872 regex_expect[sizeof(regex_expect) - 1] = 0;
884 errcode = regcomp (&preg, regex_expect, cflags); 873 errcode = regcomp(&preg, regex_expect, cflags);
885 if (errcode != 0) { 874 if (errcode != 0) {
886 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 875 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
887 printf (_("Could Not Compile Regular Expression")); 876 printf(_("Could Not Compile Regular Expression"));
888 return ERROR; 877 return ERROR;
889 } 878 }
890 while (jj >= eval_size) { 879 while (jj >= eval_size) {
@@ -895,64 +884,64 @@ process_arguments (int argc, char **argv)
895 eval_method[jj++] = CRIT_REGEX; 884 eval_method[jj++] = CRIT_REGEX;
896 break; 885 break;
897 886
898 /* Format */ 887 /* Format */
899 case 'd': /* delimiter */ 888 case 'd': /* delimiter */
900 delimiter = strscpy (delimiter, optarg); 889 delimiter = strscpy(delimiter, optarg);
901 break; 890 break;
902 case 'D': /* output-delimiter */ 891 case 'D': /* output-delimiter */
903 output_delim = strscpy (output_delim, optarg); 892 output_delim = strscpy(output_delim, optarg);
904 break; 893 break;
905 case 'l': /* label */ 894 case 'l': /* label */
906 nlabels++; 895 nlabels++;
907 if (nlabels > labels_size) { 896 if (nlabels > labels_size) {
908 labels_size += 8; 897 labels_size += 8;
909 labels = realloc (labels, labels_size * sizeof(*labels)); 898 labels = realloc(labels, labels_size * sizeof(*labels));
910 if (labels == NULL) 899 if (labels == NULL)
911 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels); 900 die(STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
912 } 901 }
913 labels[nlabels - 1] = optarg; 902 labels[nlabels - 1] = optarg;
914 ptr = thisarg (optarg); 903 char *ptr = thisarg(optarg);
915 labels[nlabels - 1] = ptr; 904 labels[nlabels - 1] = ptr;
916 if (ptr[0] == '\'') 905 if (ptr[0] == '\'')
917 labels[nlabels - 1] = ptr + 1; 906 labels[nlabels - 1] = ptr + 1;
918 while (ptr && (ptr = nextarg (ptr))) { 907 while (ptr && (ptr = nextarg(ptr))) {
919 nlabels++; 908 nlabels++;
920 if (nlabels > labels_size) { 909 if (nlabels > labels_size) {
921 labels_size += 8; 910 labels_size += 8;
922 labels = realloc (labels, labels_size * sizeof(*labels)); 911 labels = realloc(labels, labels_size * sizeof(*labels));
923 if (labels == NULL) 912 if (labels == NULL)
924 die (STATE_UNKNOWN, _("Could not reallocate labels\n")); 913 die(STATE_UNKNOWN, _("Could not reallocate labels\n"));
925 } 914 }
926 ptr = thisarg (ptr); 915 ptr = thisarg(ptr);
927 if (ptr[0] == '\'') 916 if (ptr[0] == '\'')
928 labels[nlabels - 1] = ptr + 1; 917 labels[nlabels - 1] = ptr + 1;
929 else 918 else
930 labels[nlabels - 1] = ptr; 919 labels[nlabels - 1] = ptr;
931 } 920 }
932 break; 921 break;
933 case 'u': /* units */ 922 case 'u': /* units */
934 units = optarg; 923 units = optarg;
935 nunits++; 924 nunits++;
936 if (nunits > unitv_size) { 925 if (nunits > unitv_size) {
937 unitv_size += 8; 926 unitv_size += 8;
938 unitv = realloc (unitv, unitv_size * sizeof(*unitv)); 927 unitv = realloc(unitv, unitv_size * sizeof(*unitv));
939 if (unitv == NULL) 928 if (unitv == NULL)
940 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits); 929 die(STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
941 } 930 }
942 unitv[nunits - 1] = optarg; 931 unitv[nunits - 1] = optarg;
943 ptr = thisarg (optarg); 932 ptr = thisarg(optarg);
944 unitv[nunits - 1] = ptr; 933 unitv[nunits - 1] = ptr;
945 if (ptr[0] == '\'') 934 if (ptr[0] == '\'')
946 unitv[nunits - 1] = ptr + 1; 935 unitv[nunits - 1] = ptr + 1;
947 while (ptr && (ptr = nextarg (ptr))) { 936 while (ptr && (ptr = nextarg(ptr))) {
948 if (nunits > unitv_size) { 937 if (nunits > unitv_size) {
949 unitv_size += 8; 938 unitv_size += 8;
950 unitv = realloc (unitv, unitv_size * sizeof(*unitv)); 939 unitv = realloc(unitv, unitv_size * sizeof(*unitv));
951 if (units == NULL) 940 if (units == NULL)
952 die (STATE_UNKNOWN, _("Could not realloc() units\n")); 941 die(STATE_UNKNOWN, _("Could not realloc() units\n"));
953 } 942 }
954 nunits++; 943 nunits++;
955 ptr = thisarg (ptr); 944 ptr = thisarg(ptr);
956 if (ptr[0] == '\'') 945 if (ptr[0] == '\'')
957 unitv[nunits - 1] = ptr + 1; 946 unitv[nunits - 1] = ptr + 1;
958 else 947 else
@@ -960,38 +949,38 @@ process_arguments (int argc, char **argv)
960 } 949 }
961 break; 950 break;
962 case L_CALCULATE_RATE: 951 case L_CALCULATE_RATE:
963 if(calculate_rate==0) 952 if (calculate_rate == 0)
964 np_enable_state(NULL, 1); 953 np_enable_state(NULL, 1);
965 calculate_rate = 1; 954 calculate_rate = 1;
966 break; 955 break;
967 case L_RATE_MULTIPLIER: 956 case L_RATE_MULTIPLIER:
968 if(!is_integer(optarg)||((rate_multiplier=atoi(optarg))<=0)) 957 if (!is_integer(optarg) || ((rate_multiplier = atoi(optarg)) <= 0))
969 usage2(_("Rate multiplier must be a positive integer"),optarg); 958 usage2(_("Rate multiplier must be a positive integer"), optarg);
970 break; 959 break;
971 case L_OFFSET: 960 case L_OFFSET:
972 offset=strtod(optarg,NULL); 961 offset = strtod(optarg, NULL);
973 break; 962 break;
974 case L_INVERT_SEARCH: 963 case L_INVERT_SEARCH:
975 invert_search=1; 964 invert_search = 1;
976 break; 965 break;
977 case 'O': 966 case 'O':
978 perf_labels=0; 967 perf_labels = 0;
979 break; 968 break;
980 case '4': 969 case '4':
981 break; 970 break;
982 case '6': 971 case '6':
983 xasprintf(&ip_version, "udp6:"); 972 xasprintf(&ip_version, "udp6:");
984 if(verbose>2) 973 if (verbose > 2)
985 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n"); 974 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n");
986 break; 975 break;
987 case 'M': 976 case 'M':
988 if ( strspn( optarg, "0123456789.," ) == strlen( optarg ) ) { 977 if (strspn(optarg, "0123456789.,") == strlen(optarg)) {
989 multiplier=strtod(optarg,NULL); 978 multiplier = strtod(optarg, NULL);
990 } 979 }
991 break; 980 break;
992 case 'f': 981 case 'f':
993 if (multiplier != 1.0) { 982 if (multiplier != 1.0) {
994 fmtstr=optarg; 983 fmtstr = optarg;
995 fmtstr_set = true; 984 fmtstr_set = true;
996 } 985 }
997 break; 986 break;
@@ -1004,12 +993,11 @@ process_arguments (int argc, char **argv)
1004 server_address = argv[optind]; 993 server_address = argv[optind];
1005 994
1006 if (community == NULL) 995 if (community == NULL)
1007 community = strdup (DEFAULT_COMMUNITY); 996 community = strdup(DEFAULT_COMMUNITY);
1008 997
1009 return validate_arguments (); 998 return validate_arguments();
1010} 999}
1011 1000
1012
1013/****************************************************************************** 1001/******************************************************************************
1014 1002
1015@@- 1003@@-
@@ -1028,17 +1016,13 @@ selected.</para>
1028-@@ 1016-@@
1029******************************************************************************/ 1017******************************************************************************/
1030 1018
1031 1019static int validate_arguments() {
1032
1033int
1034validate_arguments ()
1035{
1036 /* check whether to load locally installed MIBS (CPU/disk intensive) */ 1020 /* check whether to load locally installed MIBS (CPU/disk intensive) */
1037 if (miblist == NULL) { 1021 if (miblist == NULL) {
1038 if (needmibs) { 1022 if (needmibs) {
1039 miblist = strdup (DEFAULT_MIBLIST); 1023 miblist = strdup(DEFAULT_MIBLIST);
1040 }else{ 1024 } else {
1041 miblist = ""; /* don't read any mib files for numeric oids */ 1025 miblist = ""; /* don't read any mib files for numeric oids */
1042 } 1026 }
1043 } 1027 }
1044 1028
@@ -1053,18 +1037,17 @@ validate_arguments ()
1053 if (proto == NULL) 1037 if (proto == NULL)
1054 xasprintf(&proto, DEFAULT_PROTOCOL); 1038 xasprintf(&proto, DEFAULT_PROTOCOL);
1055 1039
1056 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */ 1040 if ((strcmp(proto, "1") == 0) || (strcmp(proto, "2c") == 0)) { /* snmpv1 or snmpv2c */
1057 numauthpriv = 2; 1041 numauthpriv = 2;
1058 authpriv = calloc (numauthpriv, sizeof (char *)); 1042 authpriv = calloc(numauthpriv, sizeof(char *));
1059 authpriv[0] = strdup ("-c"); 1043 authpriv[0] = strdup("-c");
1060 authpriv[1] = strdup (community); 1044 authpriv[1] = strdup(community);
1061 } 1045 } else if (strcmp(proto, "3") == 0) { /* snmpv3 args */
1062 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
1063 if (!(context == NULL)) { 1046 if (!(context == NULL)) {
1064 numcontext = 2; 1047 numcontext = 2;
1065 contextargs = calloc (numcontext, sizeof (char *)); 1048 contextargs = calloc(numcontext, sizeof(char *));
1066 contextargs[0] = strdup ("-n"); 1049 contextargs[0] = strdup("-n");
1067 contextargs[1] = strdup (context); 1050 contextargs[1] = strdup(context);
1068 } 1051 }
1069 1052
1070 if (seclevel == NULL) 1053 if (seclevel == NULL)
@@ -1075,284 +1058,266 @@ validate_arguments ()
1075 1058
1076 if (strcmp(seclevel, "noAuthNoPriv") == 0) { 1059 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
1077 numauthpriv = 4; 1060 numauthpriv = 4;
1078 authpriv = calloc (numauthpriv, sizeof (char *)); 1061 authpriv = calloc(numauthpriv, sizeof(char *));
1079 authpriv[0] = strdup ("-l"); 1062 authpriv[0] = strdup("-l");
1080 authpriv[1] = strdup ("noAuthNoPriv"); 1063 authpriv[1] = strdup("noAuthNoPriv");
1081 authpriv[2] = strdup ("-u"); 1064 authpriv[2] = strdup("-u");
1082 authpriv[3] = strdup (secname); 1065 authpriv[3] = strdup(secname);
1083 } else { 1066 } else {
1084 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) { 1067 if (!((strcmp(seclevel, "authNoPriv") == 0) || (strcmp(seclevel, "authPriv") == 0))) {
1085 usage2 (_("Invalid seclevel"), seclevel); 1068 usage2(_("Invalid seclevel"), seclevel);
1086 } 1069 }
1087 1070
1088 if (authproto == NULL ) 1071 if (authproto == NULL)
1089 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL); 1072 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
1090 1073
1091 if (authpasswd == NULL) 1074 if (authpasswd == NULL)
1092 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd"); 1075 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
1093 1076
1094 if ( strcmp(seclevel, "authNoPriv") == 0 ) { 1077 if (strcmp(seclevel, "authNoPriv") == 0) {
1095 numauthpriv = 8; 1078 numauthpriv = 8;
1096 authpriv = calloc (numauthpriv, sizeof (char *)); 1079 authpriv = calloc(numauthpriv, sizeof(char *));
1097 authpriv[0] = strdup ("-l"); 1080 authpriv[0] = strdup("-l");
1098 authpriv[1] = strdup ("authNoPriv"); 1081 authpriv[1] = strdup("authNoPriv");
1099 authpriv[2] = strdup ("-a"); 1082 authpriv[2] = strdup("-a");
1100 authpriv[3] = strdup (authproto); 1083 authpriv[3] = strdup(authproto);
1101 authpriv[4] = strdup ("-u"); 1084 authpriv[4] = strdup("-u");
1102 authpriv[5] = strdup (secname); 1085 authpriv[5] = strdup(secname);
1103 authpriv[6] = strdup ("-A"); 1086 authpriv[6] = strdup("-A");
1104 authpriv[7] = strdup (authpasswd); 1087 authpriv[7] = strdup(authpasswd);
1105 } else if ( strcmp(seclevel, "authPriv") == 0 ) { 1088 } else if (strcmp(seclevel, "authPriv") == 0) {
1106 if (privproto == NULL ) 1089 if (privproto == NULL)
1107 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL); 1090 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
1108 1091
1109 if (privpasswd == NULL) 1092 if (privpasswd == NULL)
1110 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd"); 1093 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
1111 1094
1112 numauthpriv = 12; 1095 numauthpriv = 12;
1113 authpriv = calloc (numauthpriv, sizeof (char *)); 1096 authpriv = calloc(numauthpriv, sizeof(char *));
1114 authpriv[0] = strdup ("-l"); 1097 authpriv[0] = strdup("-l");
1115 authpriv[1] = strdup ("authPriv"); 1098 authpriv[1] = strdup("authPriv");
1116 authpriv[2] = strdup ("-a"); 1099 authpriv[2] = strdup("-a");
1117 authpriv[3] = strdup (authproto); 1100 authpriv[3] = strdup(authproto);
1118 authpriv[4] = strdup ("-u"); 1101 authpriv[4] = strdup("-u");
1119 authpriv[5] = strdup (secname); 1102 authpriv[5] = strdup(secname);
1120 authpriv[6] = strdup ("-A"); 1103 authpriv[6] = strdup("-A");
1121 authpriv[7] = strdup (authpasswd); 1104 authpriv[7] = strdup(authpasswd);
1122 authpriv[8] = strdup ("-x"); 1105 authpriv[8] = strdup("-x");
1123 authpriv[9] = strdup (privproto); 1106 authpriv[9] = strdup(privproto);
1124 authpriv[10] = strdup ("-X"); 1107 authpriv[10] = strdup("-X");
1125 authpriv[11] = strdup (privpasswd); 1108 authpriv[11] = strdup(privpasswd);
1126 } 1109 }
1127 } 1110 }
1128 1111
1129 } 1112 } else {
1130 else { 1113 usage2(_("Invalid SNMP version"), proto);
1131 usage2 (_("Invalid SNMP version"), proto);
1132 } 1114 }
1133 1115
1134 return OK; 1116 return OK;
1135} 1117}
1136 1118
1137
1138
1139/* trim leading whitespace 1119/* trim leading whitespace
1140 if there is a leading quote, make sure it balances */ 1120 if there is a leading quote, make sure it balances */
1141 1121
1142char * 1122static char *thisarg(char *str) {
1143thisarg (char *str) 1123 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
1144{ 1124 if (str[0] == '\'') { /* handle SIMPLE quoted strings */
1145 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 1125 if (strlen(str) == 1 || !strstr(str + 1, "'"))
1146 if (str[0] == '\'') { /* handle SIMPLE quoted strings */ 1126 die(STATE_UNKNOWN, _("Unbalanced quotes\n"));
1147 if (strlen (str) == 1 || !strstr (str + 1, "'"))
1148 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
1149 } 1127 }
1150 return str; 1128 return str;
1151} 1129}
1152 1130
1153
1154
1155/* if there's a leading quote, advance to the trailing quote 1131/* if there's a leading quote, advance to the trailing quote
1156 set the trailing quote to '\x0' 1132 set the trailing quote to '\x0'
1157 if the string continues, advance beyond the comma */ 1133 if the string continues, advance beyond the comma */
1158 1134
1159char * 1135static char *nextarg(char *str) {
1160nextarg (char *str)
1161{
1162 if (str[0] == '\'') { 1136 if (str[0] == '\'') {
1163 str[0] = 0; 1137 str[0] = 0;
1164 if (strlen (str) > 1) { 1138 if (strlen(str) > 1) {
1165 str = strstr (str + 1, "'"); 1139 str = strstr(str + 1, "'");
1166 return (++str); 1140 return (++str);
1167 } 1141 } else {
1168 else {
1169 return NULL; 1142 return NULL;
1170 } 1143 }
1171 } 1144 }
1172 if (str[0] == ',') { 1145 if (str[0] == ',') {
1173 str[0] = 0; 1146 str[0] = 0;
1174 if (strlen (str) > 1) { 1147 if (strlen(str) > 1) {
1175 return (++str); 1148 return (++str);
1176 } 1149 } else {
1177 else {
1178 return NULL; 1150 return NULL;
1179 } 1151 }
1180 } 1152 }
1181 if ((str = strstr (str, ",")) && strlen (str) > 1) { 1153 if ((str = strstr(str, ",")) && strlen(str) > 1) {
1182 str[0] = 0; 1154 str[0] = 0;
1183 return (++str); 1155 return (++str);
1184 } 1156 }
1185 return NULL; 1157 return NULL;
1186} 1158}
1187 1159
1188
1189
1190/* multiply result (values 0 < n < 1 work as divider) */ 1160/* multiply result (values 0 < n < 1 work as divider) */
1191char * 1161static char *multiply(char *str) {
1192multiply (char *str) 1162 if (multiplier == 1)
1193{ 1163 return (str);
1194 char *endptr;
1195 double val;
1196 char *conv = "%f";
1197
1198 if(multiplier == 1)
1199 return(str);
1200 1164
1201 if(verbose>2) 1165 if (verbose > 2)
1202 printf(" multiply input: %s\n", str); 1166 printf(" multiply input: %s\n", str);
1203 1167
1204 val = strtod (str, &endptr); 1168 char *endptr;
1169 double val = strtod(str, &endptr);
1205 if ((val == 0.0) && (endptr == str)) { 1170 if ((val == 0.0) && (endptr == str)) {
1206 die(STATE_UNKNOWN, _("multiplier set (%.1f), but input is not a number: %s"), multiplier, str); 1171 die(STATE_UNKNOWN, _("multiplier set (%.1f), but input is not a number: %s"), multiplier, str);
1207 } 1172 }
1208 1173
1209 if(verbose>2) 1174 if (verbose > 2)
1210 printf(" multiply extracted double: %f\n", val); 1175 printf(" multiply extracted double: %f\n", val);
1176
1211 val *= multiplier; 1177 val *= multiplier;
1178 char *conv = "%f";
1212 if (fmtstr_set) { 1179 if (fmtstr_set) {
1213 conv = fmtstr; 1180 conv = fmtstr;
1214 } 1181 }
1215 if (val == (int)val) { 1182 if (val == (int)val) {
1216 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val); 1183 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val);
1217 } else { 1184 } else {
1218 if(verbose>2) 1185 if (verbose > 2)
1219 printf(" multiply using format: %s\n", conv); 1186 printf(" multiply using format: %s\n", conv);
1220 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val); 1187 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val);
1221 } 1188 }
1222 if(verbose>2) 1189 if (verbose > 2)
1223 printf(" multiply result: %s\n", buffer); 1190 printf(" multiply result: %s\n", buffer);
1224 return buffer; 1191 return buffer;
1225} 1192}
1226 1193
1194static void print_help(void) {
1195 print_revision(progname, NP_VERSION);
1227 1196
1228void 1197 printf(COPYRIGHT, copyright, email);
1229print_help (void)
1230{
1231 print_revision (progname, NP_VERSION);
1232
1233 printf (COPYRIGHT, copyright, email);
1234 1198
1235 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP")); 1199 printf("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
1236 1200
1237 printf ("\n\n"); 1201 printf("\n\n");
1238 1202
1239 print_usage (); 1203 print_usage();
1240 1204
1241 printf (UT_HELP_VRSN); 1205 printf(UT_HELP_VRSN);
1242 printf (UT_EXTRA_OPTS); 1206 printf(UT_EXTRA_OPTS);
1243 printf (UT_IPv46); 1207 printf(UT_IPv46);
1244 1208
1245 printf (UT_HOST_PORT, 'p', DEFAULT_PORT); 1209 printf(UT_HOST_PORT, 'p', DEFAULT_PORT);
1246 1210
1247 /* SNMP and Authentication Protocol */ 1211 /* SNMP and Authentication Protocol */
1248 printf (" %s\n", "-n, --next"); 1212 printf(" %s\n", "-n, --next");
1249 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET")); 1213 printf(" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
1250 printf (" %s\n", "-P, --protocol=[1|2c|3]"); 1214 printf(" %s\n", "-P, --protocol=[1|2c|3]");
1251 printf (" %s\n", _("SNMP protocol version")); 1215 printf(" %s\n", _("SNMP protocol version"));
1252 printf (" %s\n", "-N, --context=CONTEXT"); 1216 printf(" %s\n", "-N, --context=CONTEXT");
1253 printf (" %s\n", _("SNMPv3 context")); 1217 printf(" %s\n", _("SNMPv3 context"));
1254 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]"); 1218 printf(" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
1255 printf (" %s\n", _("SNMPv3 securityLevel")); 1219 printf(" %s\n", _("SNMPv3 securityLevel"));
1256 printf (" %s\n", "-a, --authproto=AUTHENTICATION_PROTOCOL"); 1220 printf(" %s\n", "-a, --authproto=AUTHENTICATION_PROTOCOL");
1257 printf (" %s\n", _("SNMPv3 authentication protocol (default MD5), available options depend on the specific version of the net-snmp tools")); 1221 printf(" %s\n",
1258 printf (" %s\n", _("if < 5.8 SHA (1) and MD5 should be available, if >= 5.8 additionally SHA-224, SHA-256, SHA-384 and SHA-512")); 1222 _("SNMPv3 authentication protocol (default MD5), available options depend on the specific version of the net-snmp tools"));
1259 printf (" %s\n", "-x, --privproto=PRIVACY_PROTOCOL"); 1223 printf(" %s\n", _("if < 5.8 SHA (1) and MD5 should be available, if >= 5.8 additionally SHA-224, SHA-256, SHA-384 and SHA-512"));
1260 printf (" %s\n", _("SNMPv3 privacy protocol (default DES), available options depend on the specific version of the net-snmp tools")); 1224 printf(" %s\n", "-x, --privproto=PRIVACY_PROTOCOL");
1261 printf (" %s\n", _("if < 5.8 DES and AES should be available, if >= 5.8 additionally AES-192 and AES-256")); 1225 printf(" %s\n", _("SNMPv3 privacy protocol (default DES), available options depend on the specific version of the net-snmp tools"));
1226 printf(" %s\n", _("if < 5.8 DES and AES should be available, if >= 5.8 additionally AES-192 and AES-256"));
1262 1227
1263 /* Authentication Tokens*/ 1228 /* Authentication Tokens*/
1264 printf (" %s\n", "-C, --community=STRING"); 1229 printf(" %s\n", "-C, --community=STRING");
1265 printf (" %s ", _("Optional community string for SNMP communication")); 1230 printf(" %s ", _("Optional community string for SNMP communication"));
1266 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY); 1231 printf("(%s \"%s\")\n", _("default is"), DEFAULT_COMMUNITY);
1267 printf (" %s\n", "-U, --secname=USERNAME"); 1232 printf(" %s\n", "-U, --secname=USERNAME");
1268 printf (" %s\n", _("SNMPv3 username")); 1233 printf(" %s\n", _("SNMPv3 username"));
1269 printf (" %s\n", "-A, --authpasswd=PASSWORD"); 1234 printf(" %s\n", "-A, --authpasswd=PASSWORD");
1270 printf (" %s\n", _("SNMPv3 authentication password")); 1235 printf(" %s\n", _("SNMPv3 authentication password"));
1271 printf (" %s\n", "-X, --privpasswd=PASSWORD"); 1236 printf(" %s\n", "-X, --privpasswd=PASSWORD");
1272 printf (" %s\n", _("SNMPv3 privacy password")); 1237 printf(" %s\n", _("SNMPv3 privacy password"));
1273 1238
1274 /* OID Stuff */ 1239 /* OID Stuff */
1275 printf (" %s\n", "-o, --oid=OID(s)"); 1240 printf(" %s\n", "-o, --oid=OID(s)");
1276 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query")); 1241 printf(" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
1277 printf (" %s\n", "-m, --miblist=STRING"); 1242 printf(" %s\n", "-m, --miblist=STRING");
1278 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'")); 1243 printf(" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
1279 printf (" %s\n", _("for symbolic OIDs.)")); 1244 printf(" %s\n", _("for symbolic OIDs.)"));
1280 printf (" %s\n", "-d, --delimiter=STRING"); 1245 printf(" %s\n", "-d, --delimiter=STRING");
1281 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER); 1246 printf(" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
1282 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered")); 1247 printf(" %s\n", _("Any data on the right hand side of the delimiter is considered"));
1283 printf (" %s\n", _("to be the data that should be used in the evaluation.")); 1248 printf(" %s\n", _("to be the data that should be used in the evaluation."));
1284 printf (" %s\n", "-z, --nulloid=#"); 1249 printf(" %s\n", "-z, --nulloid=#");
1285 printf (" %s\n", _("If the check returns a 0 length string or NULL value")); 1250 printf(" %s\n", _("If the check returns a 0 length string or NULL value"));
1286 printf (" %s\n", _("This option allows you to choose what status you want it to exit")); 1251 printf(" %s\n", _("This option allows you to choose what status you want it to exit"));
1287 printf (" %s\n", _("Excluding this option renders the default exit of 3(STATE_UNKNOWN)")); 1252 printf(" %s\n", _("Excluding this option renders the default exit of 3(STATE_UNKNOWN)"));
1288 printf (" %s\n", _("0 = OK")); 1253 printf(" %s\n", _("0 = OK"));
1289 printf (" %s\n", _("1 = WARNING")); 1254 printf(" %s\n", _("1 = WARNING"));
1290 printf (" %s\n", _("2 = CRITICAL")); 1255 printf(" %s\n", _("2 = CRITICAL"));
1291 printf (" %s\n", _("3 = UNKNOWN")); 1256 printf(" %s\n", _("3 = UNKNOWN"));
1292 1257
1293 /* Tests Against Integers */ 1258 /* Tests Against Integers */
1294 printf (" %s\n", "-w, --warning=THRESHOLD(s)"); 1259 printf(" %s\n", "-w, --warning=THRESHOLD(s)");
1295 printf (" %s\n", _("Warning threshold range(s)")); 1260 printf(" %s\n", _("Warning threshold range(s)"));
1296 printf (" %s\n", "-c, --critical=THRESHOLD(s)"); 1261 printf(" %s\n", "-c, --critical=THRESHOLD(s)");
1297 printf (" %s\n", _("Critical threshold range(s)")); 1262 printf(" %s\n", _("Critical threshold range(s)"));
1298 printf (" %s\n", "--rate"); 1263 printf(" %s\n", "--rate");
1299 printf (" %s\n", _("Enable rate calculation. See 'Rate Calculation' below")); 1264 printf(" %s\n", _("Enable rate calculation. See 'Rate Calculation' below"));
1300 printf (" %s\n", "--rate-multiplier"); 1265 printf(" %s\n", "--rate-multiplier");
1301 printf (" %s\n", _("Converts rate per second. For example, set to 60 to convert to per minute")); 1266 printf(" %s\n", _("Converts rate per second. For example, set to 60 to convert to per minute"));
1302 printf (" %s\n", "--offset=OFFSET"); 1267 printf(" %s\n", "--offset=OFFSET");
1303 printf (" %s\n", _("Add/subtract the specified OFFSET to numeric sensor data")); 1268 printf(" %s\n", _("Add/subtract the specified OFFSET to numeric sensor data"));
1304 1269
1305 /* Tests Against Strings */ 1270 /* Tests Against Strings */
1306 printf (" %s\n", "-s, --string=STRING"); 1271 printf(" %s\n", "-s, --string=STRING");
1307 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match")); 1272 printf(" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
1308 printf (" %s\n", "-r, --ereg=REGEX"); 1273 printf(" %s\n", "-r, --ereg=REGEX");
1309 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches")); 1274 printf(" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
1310 printf (" %s\n", "-R, --eregi=REGEX"); 1275 printf(" %s\n", "-R, --eregi=REGEX");
1311 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches")); 1276 printf(" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
1312 printf (" %s\n", "--invert-search"); 1277 printf(" %s\n", "--invert-search");
1313 printf (" %s\n", _("Invert search result (CRITICAL if found)")); 1278 printf(" %s\n", _("Invert search result (CRITICAL if found)"));
1314 1279
1315 /* Output Formatting */ 1280 /* Output Formatting */
1316 printf (" %s\n", "-l, --label=STRING"); 1281 printf(" %s\n", "-l, --label=STRING");
1317 printf (" %s\n", _("Prefix label for output from plugin")); 1282 printf(" %s\n", _("Prefix label for output from plugin"));
1318 printf (" %s\n", "-u, --units=STRING"); 1283 printf(" %s\n", "-u, --units=STRING");
1319 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.').")); 1284 printf(" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
1320 printf (" %s\n", "-D, --output-delimiter=STRING"); 1285 printf(" %s\n", "-D, --output-delimiter=STRING");
1321 printf (" %s\n", _("Separates output on multiple OID requests")); 1286 printf(" %s\n", _("Separates output on multiple OID requests"));
1322 printf (" %s\n", "-M, --multiplier=FLOAT"); 1287 printf(" %s\n", "-M, --multiplier=FLOAT");
1323 printf (" %s\n", _("Multiplies current value, 0 < n < 1 works as divider, defaults to 1")); 1288 printf(" %s\n", _("Multiplies current value, 0 < n < 1 works as divider, defaults to 1"));
1324 printf (" %s\n", "-f, --fmtstr=STRING"); 1289 printf(" %s\n", "-f, --fmtstr=STRING");
1325 printf (" %s\n", _("C-style format string for float values (see option -M)")); 1290 printf(" %s\n", _("C-style format string for float values (see option -M)"));
1326 1291
1327 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1292 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1328 printf (" %s\n", _("NOTE the final timeout value is calculated using this formula: timeout_interval * retries + 5")); 1293 printf(" %s\n", _("NOTE the final timeout value is calculated using this formula: timeout_interval * retries + 5"));
1329 printf (" %s\n", "-e, --retries=INTEGER"); 1294 printf(" %s\n", "-e, --retries=INTEGER");
1330 printf (" %s%i\n", _("Number of retries to be used in the requests, default: "), DEFAULT_RETRIES); 1295 printf(" %s%i\n", _("Number of retries to be used in the requests, default: "), DEFAULT_RETRIES);
1331 1296
1332 printf (" %s\n", "-O, --perf-oids"); 1297 printf(" %s\n", "-O, --perf-oids");
1333 printf (" %s\n", _("Label performance data with OIDs instead of --label's")); 1298 printf(" %s\n", _("Label performance data with OIDs instead of --label's"));
1334 1299
1335 printf (" %s\n", "--ignore-mib-parsing-errors"); 1300 printf(" %s\n", "--ignore-mib-parsing-errors");
1336 printf (" %s\n", _("Tell snmpget to not print errors encountered when parsing MIB files")); 1301 printf(" %s\n", _("Tell snmpget to not print errors encountered when parsing MIB files"));
1337 1302
1338 printf (UT_VERBOSE); 1303 printf(UT_VERBOSE);
1339 1304
1340 printf ("\n"); 1305 printf("\n");
1341 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package.")); 1306 printf("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
1342 printf ("%s\n", _("if you don't have the package installed, you will need to download it from")); 1307 printf("%s\n", _("if you don't have the package installed, you will need to download it from"));
1343 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin.")); 1308 printf("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
1344 1309
1345 printf ("\n"); 1310 printf("\n");
1346 printf ("%s\n", _("Notes:")); 1311 printf("%s\n", _("Notes:"));
1347 printf (" %s\n", _("- Multiple OIDs (and labels) may be indicated by a comma or space-delimited ")); 1312 printf(" %s\n", _("- Multiple OIDs (and labels) may be indicated by a comma or space-delimited "));
1348 printf (" %s\n", _("list (lists with internal spaces must be quoted).")); 1313 printf(" %s\n", _("list (lists with internal spaces must be quoted)."));
1349 1314
1350 printf(" -%s", UT_THRESHOLDS_NOTES); 1315 printf(" -%s", UT_THRESHOLDS_NOTES);
1351 1316
1352 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'")); 1317 printf(" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
1353 printf (" %s\n", _("- Note that only one string and one regex may be checked at present")); 1318 printf(" %s\n", _("- Note that only one string and one regex may be checked at present"));
1354 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value")); 1319 printf(" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
1355 printf (" %s\n", _("returned from the SNMP query is an unsigned integer.")); 1320 printf(" %s\n", _("returned from the SNMP query is an unsigned integer."));
1356 1321
1357 printf("\n"); 1322 printf("\n");
1358 printf("%s\n", _("Rate Calculation:")); 1323 printf("%s\n", _("Rate Calculation:"));
@@ -1364,19 +1329,15 @@ print_help (void)
1364 printf(" %s\n", _("The state is uniquely determined by the arguments to the plugin, so")); 1329 printf(" %s\n", _("The state is uniquely determined by the arguments to the plugin, so"));
1365 printf(" %s\n", _("changing the arguments will create a new state file.")); 1330 printf(" %s\n", _("changing the arguments will create a new state file."));
1366 1331
1367 printf (UT_SUPPORT); 1332 printf(UT_SUPPORT);
1368} 1333}
1369 1334
1370 1335void print_usage(void) {
1371 1336 printf("%s\n", _("Usage:"));
1372void 1337 printf("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n", progname);
1373print_usage (void) 1338 printf("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
1374{ 1339 printf("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1375 printf ("%s\n", _("Usage:")); 1340 printf("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
1376 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname); 1341 printf("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd] [-4|6]\n");
1377 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n"); 1342 printf("[-M multiplier [-f format]]\n");
1378 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1379 printf ("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
1380 printf ("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd] [-4|6]\n");
1381 printf ("[-M multiplier [-f format]]\n");
1382} 1343}
diff --git a/plugins/check_ssh.c b/plugins/check_ssh.c
index d162e42f..8e29fa98 100644
--- a/plugins/check_ssh.c
+++ b/plugins/check_ssh.c
@@ -3,7 +3,7 @@
3* Monitoring check_ssh plugin 3* Monitoring check_ssh plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6* Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -29,7 +29,7 @@
29*****************************************************************************/ 29*****************************************************************************/
30 30
31const char *progname = "check_ssh"; 31const char *progname = "check_ssh";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "./common.h" 35#include "./common.h"
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c
index 01dd35eb..c13ac767 100644
--- a/plugins/check_tcp.c
+++ b/plugins/check_tcp.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_tcp plugin 3 * Monitoring check_tcp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2013 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_tcp plugin 10 * This file contains the check_tcp plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* $Id$ 26 * $Id$
27* 27 *
28*****************************************************************************/ 28 *****************************************************************************/
29 29
30/* progname "check_tcp" changes depending on symlink called */ 30/* progname "check_tcp" changes depending on symlink called */
31char *progname; 31char *progname;
32const char *copyright = "1999-2008"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -43,17 +43,17 @@ const char *email = "devel@monitoring-plugins.org";
43#ifdef HAVE_SSL 43#ifdef HAVE_SSL
44static bool check_cert = false; 44static bool check_cert = false;
45static int days_till_exp_warn, days_till_exp_crit; 45static int days_till_exp_warn, days_till_exp_crit;
46# define my_recv(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_read(buf, len) : read(sd, buf, len)) 46# define my_recv(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
47# define my_send(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0)) 47# define my_send(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
48#else 48#else
49# define my_recv(buf, len) read(sd, buf, len) 49# define my_recv(buf, len) read(sd, buf, len)
50# define my_send(buf, len) send(sd, buf, len, 0) 50# define my_send(buf, len) send(sd, buf, len, 0)
51#endif 51#endif
52 52
53/* int my_recv(char *, size_t); */ 53/* int my_recv(char *, size_t); */
54static int process_arguments (int, char **); 54static int process_arguments(int /*argc*/, char ** /*argv*/);
55void print_help (void); 55static void print_help(void);
56void print_usage (void); 56void print_usage(void);
57 57
58#define EXPECT server_expect[0] 58#define EXPECT server_expect[0]
59static char *SERVICE = "TCP"; 59static char *SERVICE = "TCP";
@@ -91,38 +91,29 @@ static char *sni = NULL;
91static bool sni_specified = false; 91static bool sni_specified = false;
92#endif 92#endif
93 93
94#define FLAG_SSL 0x01 94#define FLAG_SSL 0x01
95#define FLAG_VERBOSE 0x02 95#define FLAG_VERBOSE 0x02
96#define FLAG_TIME_WARN 0x04 96#define FLAG_TIME_WARN 0x04
97#define FLAG_TIME_CRIT 0x08 97#define FLAG_TIME_CRIT 0x08
98#define FLAG_HIDE_OUTPUT 0x10 98#define FLAG_HIDE_OUTPUT 0x10
99static size_t flags; 99static size_t flags;
100 100
101int 101int main(int argc, char **argv) {
102main (int argc, char **argv) 102 setlocale(LC_ALL, "");
103{ 103 bindtextdomain(PACKAGE, LOCALEDIR);
104 int result = STATE_UNKNOWN; 104 textdomain(PACKAGE);
105 char *status = NULL;
106 struct timeval tv;
107 struct timeval timeout;
108 int match = -1;
109 fd_set rfds;
110
111 FD_ZERO(&rfds);
112
113 setlocale (LC_ALL, "");
114 bindtextdomain (PACKAGE, LOCALEDIR);
115 textdomain (PACKAGE);
116 105
117 /* determine program- and service-name quickly */ 106 /* determine program- and service-name quickly */
118 progname = strrchr(argv[0], '/'); 107 progname = strrchr(argv[0], '/');
119 if(progname != NULL) progname++; 108 if (progname != NULL)
120 else progname = argv[0]; 109 progname++;
110 else
111 progname = argv[0];
121 112
122 size_t prog_name_len = strlen(progname); 113 size_t prog_name_len = strlen(progname);
123 if(prog_name_len > 6 && !memcmp(progname, "check_", 6)) { 114 if (prog_name_len > 6 && !memcmp(progname, "check_", 6)) {
124 SERVICE = strdup(progname + 6); 115 SERVICE = strdup(progname + 6);
125 for(size_t i = 0; i < prog_name_len - 6; i++) 116 for (size_t i = 0; i < prog_name_len - 6; i++)
126 SERVICE[i] = toupper(SERVICE[i]); 117 SERVICE[i] = toupper(SERVICE[i]);
127 } 118 }
128 119
@@ -133,23 +124,19 @@ main (int argc, char **argv)
133 /* determine defaults for this service's protocol */ 124 /* determine defaults for this service's protocol */
134 if (!strncmp(SERVICE, "UDP", 3)) { 125 if (!strncmp(SERVICE, "UDP", 3)) {
135 PROTOCOL = IPPROTO_UDP; 126 PROTOCOL = IPPROTO_UDP;
136 } 127 } else if (!strncmp(SERVICE, "FTP", 3)) {
137 else if (!strncmp(SERVICE, "FTP", 3)) {
138 EXPECT = "220"; 128 EXPECT = "220";
139 QUIT = "QUIT\r\n"; 129 QUIT = "QUIT\r\n";
140 PORT = 21; 130 PORT = 21;
141 } 131 } else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) {
142 else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) {
143 EXPECT = "+OK"; 132 EXPECT = "+OK";
144 QUIT = "QUIT\r\n"; 133 QUIT = "QUIT\r\n";
145 PORT = 110; 134 PORT = 110;
146 } 135 } else if (!strncmp(SERVICE, "SMTP", 4)) {
147 else if (!strncmp(SERVICE, "SMTP", 4)) {
148 EXPECT = "220"; 136 EXPECT = "220";
149 QUIT = "QUIT\r\n"; 137 QUIT = "QUIT\r\n";
150 PORT = 25; 138 PORT = 25;
151 } 139 } else if (!strncmp(SERVICE, "IMAP", 4)) {
152 else if (!strncmp(SERVICE, "IMAP", 4)) {
153 EXPECT = "* OK"; 140 EXPECT = "* OK";
154 QUIT = "a1 LOGOUT\r\n"; 141 QUIT = "a1 LOGOUT\r\n";
155 PORT = 143; 142 PORT = 143;
@@ -160,27 +147,23 @@ main (int argc, char **argv)
160 QUIT = "a1 LOGOUT\r\n"; 147 QUIT = "a1 LOGOUT\r\n";
161 flags |= FLAG_SSL; 148 flags |= FLAG_SSL;
162 PORT = 993; 149 PORT = 993;
163 } 150 } else if (!strncmp(SERVICE, "SPOP", 4)) {
164 else if (!strncmp(SERVICE, "SPOP", 4)) {
165 EXPECT = "+OK"; 151 EXPECT = "+OK";
166 QUIT = "QUIT\r\n"; 152 QUIT = "QUIT\r\n";
167 flags |= FLAG_SSL; 153 flags |= FLAG_SSL;
168 PORT = 995; 154 PORT = 995;
169 } 155 } else if (!strncmp(SERVICE, "SSMTP", 5)) {
170 else if (!strncmp(SERVICE, "SSMTP", 5)) {
171 EXPECT = "220"; 156 EXPECT = "220";
172 QUIT = "QUIT\r\n"; 157 QUIT = "QUIT\r\n";
173 flags |= FLAG_SSL; 158 flags |= FLAG_SSL;
174 PORT = 465; 159 PORT = 465;
175 } 160 } else if (!strncmp(SERVICE, "JABBER", 6)) {
176 else if (!strncmp(SERVICE, "JABBER", 6)) {
177 SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n"; 161 SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n";
178 EXPECT = "<?xml version=\'1.0\'"; 162 EXPECT = "<?xml version=\'1.0\'";
179 QUIT = "</stream:stream>\n"; 163 QUIT = "</stream:stream>\n";
180 flags |= FLAG_HIDE_OUTPUT; 164 flags |= FLAG_HIDE_OUTPUT;
181 PORT = 5222; 165 PORT = 5222;
182 } 166 } else if (!strncmp(SERVICE, "NNTPS", 5)) {
183 else if (!strncmp (SERVICE, "NNTPS", 5)) {
184 server_expect_count = 2; 167 server_expect_count = 2;
185 server_expect[0] = "200"; 168 server_expect[0] = "200";
186 server_expect[1] = "201"; 169 server_expect[1] = "201";
@@ -189,83 +172,86 @@ main (int argc, char **argv)
189 PORT = 563; 172 PORT = 563;
190 } 173 }
191#endif 174#endif
192 else if (!strncmp (SERVICE, "NNTP", 4)) { 175 else if (!strncmp(SERVICE, "NNTP", 4)) {
193 server_expect_count = 2; 176 server_expect_count = 2;
194 server_expect = malloc(sizeof(char *) * server_expect_count); 177 server_expect = malloc(sizeof(char *) * server_expect_count);
195 server_expect[0] = strdup("200"); 178 server_expect[0] = strdup("200");
196 server_expect[1] = strdup("201"); 179 server_expect[1] = strdup("201");
197 QUIT = "QUIT\r\n"; 180 QUIT = "QUIT\r\n";
198 PORT = 119; 181 PORT = 119;
199 } 182 } else if (!strncmp(SERVICE, "CLAMD", 5)) {
200 else if (!strncmp(SERVICE, "CLAMD", 5)) {
201 SEND = "PING"; 183 SEND = "PING";
202 EXPECT = "PONG"; 184 EXPECT = "PONG";
203 QUIT = NULL; 185 QUIT = NULL;
204 PORT = 3310; 186 PORT = 3310;
205 } 187 }
206 /* fallthrough check, so it's supposed to use reverse matching */ 188 /* fallthrough check, so it's supposed to use reverse matching */
207 else if (strcmp (SERVICE, "TCP")) 189 else if (strcmp(SERVICE, "TCP"))
208 usage (_("CRITICAL - Generic check_tcp called with unknown service\n")); 190 usage(_("CRITICAL - Generic check_tcp called with unknown service\n"));
209 191
210 server_address = "127.0.0.1"; 192 server_address = "127.0.0.1";
211 server_port = PORT; 193 server_port = PORT;
212 server_send = SEND; 194 server_send = SEND;
213 server_quit = QUIT; 195 server_quit = QUIT;
214 status = NULL; 196 char *status = NULL;
215 197
216 /* Parse extra opts if any */ 198 /* Parse extra opts if any */
217 argv=np_extra_opts (&argc, argv, progname); 199 argv = np_extra_opts(&argc, argv, progname);
218 200
219 if (process_arguments (argc, argv) == ERROR) 201 if (process_arguments(argc, argv) == ERROR)
220 usage4 (_("Could not parse arguments")); 202 usage4(_("Could not parse arguments"));
221 203
222 if(flags & FLAG_VERBOSE) { 204 if (flags & FLAG_VERBOSE) {
223 printf("Using service %s\n", SERVICE); 205 printf("Using service %s\n", SERVICE);
224 printf("Port: %d\n", server_port); 206 printf("Port: %d\n", server_port);
225 printf("flags: 0x%x\n", (int)flags); 207 printf("flags: 0x%x\n", (int)flags);
226 } 208 }
227 209
228 if(EXPECT && !server_expect_count) 210 if (EXPECT && !server_expect_count)
229 server_expect_count++; 211 server_expect_count++;
230 212
231 if(PROTOCOL==IPPROTO_UDP && !(server_expect_count && server_send)){ 213 if (PROTOCOL == IPPROTO_UDP && !(server_expect_count && server_send)) {
232 usage(_("With UDP checks, a send/expect string must be specified.")); 214 usage(_("With UDP checks, a send/expect string must be specified."));
233 } 215 }
234 216
235 /* set up the timer */ 217 /* set up the timer */
236 signal (SIGALRM, socket_timeout_alarm_handler); 218 signal(SIGALRM, socket_timeout_alarm_handler);
237 alarm (socket_timeout); 219 alarm(socket_timeout);
238 220
239 /* try to connect to the host at the given port number */ 221 /* try to connect to the host at the given port number */
240 gettimeofday (&tv, NULL); 222 struct timeval tv;
223 gettimeofday(&tv, NULL);
241 224
242 result = np_net_connect (server_address, server_port, &sd, PROTOCOL); 225 int result = STATE_UNKNOWN;
243 if (result == STATE_CRITICAL) return econn_refuse_state; 226 result = np_net_connect(server_address, server_port, &sd, PROTOCOL);
227 if (result == STATE_CRITICAL)
228 return econn_refuse_state;
244 229
245#ifdef HAVE_SSL 230#ifdef HAVE_SSL
246 if (flags & FLAG_SSL){ 231 if (flags & FLAG_SSL) {
247 result = np_net_ssl_init_with_hostname(sd, (sni_specified ? sni : NULL)); 232 result = np_net_ssl_init_with_hostname(sd, (sni_specified ? sni : NULL));
248 if (result == STATE_OK && check_cert) { 233 if (result == STATE_OK && check_cert) {
249 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); 234 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
250 } 235 }
251 } 236 }
252 if(result != STATE_OK){ 237 if (result != STATE_OK) {
253 if(sd) close(sd); 238 if (sd)
239 close(sd);
254 np_net_ssl_cleanup(); 240 np_net_ssl_cleanup();
255 return result; 241 return result;
256 } 242 }
257#endif /* HAVE_SSL */ 243#endif /* HAVE_SSL */
258 244
259 if (server_send != NULL) { /* Something to send? */ 245 if (server_send != NULL) { /* Something to send? */
260 my_send(server_send, strlen(server_send)); 246 my_send(server_send, strlen(server_send));
261 } 247 }
262 248
263 if (delay > 0) { 249 if (delay > 0) {
264 tv.tv_sec += delay; 250 tv.tv_sec += delay;
265 sleep (delay); 251 sleep(delay);
266 } 252 }
267 253
268 if(flags & FLAG_VERBOSE) { 254 if (flags & FLAG_VERBOSE) {
269 if (server_send) { 255 if (server_send) {
270 printf("Send string: %s\n", server_send); 256 printf("Send string: %s\n", server_send);
271 } 257 }
@@ -273,13 +259,17 @@ main (int argc, char **argv)
273 printf("Quit string: %s\n", server_quit); 259 printf("Quit string: %s\n", server_quit);
274 } 260 }
275 printf("server_expect_count: %d\n", (int)server_expect_count); 261 printf("server_expect_count: %d\n", (int)server_expect_count);
276 for(size_t i = 0; i < server_expect_count; i++) 262 for (size_t i = 0; i < server_expect_count; i++)
277 printf("\t%zd: %s\n", i, server_expect[i]); 263 printf("\t%zd: %s\n", i, server_expect[i]);
278 } 264 }
279 265
280 /* if(len) later on, we know we have a non-NULL response */ 266 /* if(len) later on, we know we have a non-NULL response */
281 ssize_t len = 0; 267 ssize_t len = 0;
282 268
269 int match = -1;
270 struct timeval timeout;
271 fd_set rfds;
272 FD_ZERO(&rfds);
283 if (server_expect_count) { 273 if (server_expect_count) {
284 ssize_t received = 0; 274 ssize_t received = 0;
285 275
@@ -294,17 +284,14 @@ main (int argc, char **argv)
294 if (maxbytes && len >= maxbytes) 284 if (maxbytes && len >= maxbytes)
295 break; 285 break;
296 286
297 if ((match = np_expect_match(status, 287 if ((match = np_expect_match(status, server_expect, server_expect_count, match_flags)) != NP_MATCH_RETRY)
298 server_expect,
299 server_expect_count,
300 match_flags)) != NP_MATCH_RETRY)
301 break; 288 break;
302 289
303 /* some protocols wait for further input, so make sure we don't wait forever */ 290 /* some protocols wait for further input, so make sure we don't wait forever */
304 FD_SET(sd, &rfds); 291 FD_SET(sd, &rfds);
305 timeout.tv_sec = READ_TIMEOUT; 292 timeout.tv_sec = READ_TIMEOUT;
306 timeout.tv_usec = 0; 293 timeout.tv_usec = 0;
307 if(select(sd + 1, &rfds, NULL, NULL, &timeout) <= 0) 294 if (select(sd + 1, &rfds, NULL, NULL, &timeout) <= 0)
308 break; 295 break;
309 } 296 }
310 297
@@ -313,26 +300,26 @@ main (int argc, char **argv)
313 300
314 /* no data when expected, so return critical */ 301 /* no data when expected, so return critical */
315 if (len == 0) 302 if (len == 0)
316 die (STATE_CRITICAL, _("No data received from host\n")); 303 die(STATE_CRITICAL, _("No data received from host\n"));
317 304
318 /* print raw output if we're debugging */ 305 /* print raw output if we're debugging */
319 if(flags & FLAG_VERBOSE) 306 if (flags & FLAG_VERBOSE)
320 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", 307 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", (int)len + 1, status);
321 (int)len + 1, status);
322 /* strip whitespace from end of output */ 308 /* strip whitespace from end of output */
323 while(--len > 0 && isspace(status[len])) 309 while (--len > 0 && isspace(status[len]))
324 status[len] = '\0'; 310 status[len] = '\0';
325 } 311 }
326 312
327 if (server_quit != NULL) { 313 if (server_quit != NULL) {
328 my_send(server_quit, strlen(server_quit)); 314 my_send(server_quit, strlen(server_quit));
329 } 315 }
330 if (sd) close (sd); 316 if (sd)
317 close(sd);
331#ifdef HAVE_SSL 318#ifdef HAVE_SSL
332 np_net_ssl_cleanup(); 319 np_net_ssl_cleanup();
333#endif 320#endif
334 321
335 microsec = deltime (tv); 322 microsec = deltime(tv);
336 elapsed_time = (double)microsec / 1.0e6; 323 elapsed_time = (double)microsec / 1.0e6;
337 324
338 if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time) 325 if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time)
@@ -341,142 +328,123 @@ main (int argc, char **argv)
341 result = STATE_WARNING; 328 result = STATE_WARNING;
342 329
343 /* did we get the response we hoped? */ 330 /* did we get the response we hoped? */
344 if(match == NP_MATCH_FAILURE && result != STATE_CRITICAL) 331 if (match == NP_MATCH_FAILURE && result != STATE_CRITICAL)
345 result = expect_mismatch_state; 332 result = expect_mismatch_state;
346 333
347 /* reset the alarm */ 334 /* reset the alarm */
348 alarm (0); 335 alarm(0);
349 336
350 /* this is a bit stupid, because we don't want to print the 337 /* this is a bit stupid, because we don't want to print the
351 * response time (which can look ok to the user) if we didn't get 338 * response time (which can look ok to the user) if we didn't get
352 * the response we were looking for. if-else */ 339 * the response we were looking for. if-else */
353 printf("%s %s - ", SERVICE, state_text(result)); 340 printf("%s %s - ", SERVICE, state_text(result));
354 341
355 if(match == NP_MATCH_FAILURE && len && !(flags & FLAG_HIDE_OUTPUT)) 342 if (match == NP_MATCH_FAILURE && len && !(flags & FLAG_HIDE_OUTPUT))
356 printf("Unexpected response from host/socket: %s", status); 343 printf("Unexpected response from host/socket: %s", status);
357 else { 344 else {
358 if(match == NP_MATCH_FAILURE) 345 if (match == NP_MATCH_FAILURE)
359 printf("Unexpected response from host/socket on "); 346 printf("Unexpected response from host/socket on ");
360 else 347 else
361 printf("%.3f second response time on ", elapsed_time); 348 printf("%.3f second response time on ", elapsed_time);
362 if(server_address[0] != '/') { 349 if (server_address[0] != '/') {
363 if (host_specified) 350 if (host_specified)
364 printf("%s port %d", 351 printf("%s port %d", server_address, server_port);
365 server_address, server_port);
366 else 352 else
367 printf("port %d", server_port); 353 printf("port %d", server_port);
368 } 354 } else
369 else
370 printf("socket %s", server_address); 355 printf("socket %s", server_address);
371 } 356 }
372 357
373 if (match != NP_MATCH_FAILURE && !(flags & FLAG_HIDE_OUTPUT) && len) 358 if (match != NP_MATCH_FAILURE && !(flags & FLAG_HIDE_OUTPUT) && len)
374 printf (" [%s]", status); 359 printf(" [%s]", status);
375 360
376 /* perf-data doesn't apply when server doesn't talk properly, 361 /* perf-data doesn't apply when server doesn't talk properly,
377 * so print all zeroes on warn and crit. Use fperfdata since 362 * so print all zeroes on warn and crit. Use fperfdata since
378 * localisation settings can make different outputs */ 363 * localisation settings can make different outputs */
379 if(match == NP_MATCH_FAILURE) 364 if (match == NP_MATCH_FAILURE)
380 printf ("|%s", 365 printf("|%s", fperfdata("time", elapsed_time, "s", (flags & FLAG_TIME_WARN ? true : false), 0,
381 fperfdata ("time", elapsed_time, "s", 366 (flags & FLAG_TIME_CRIT ? true : false), 0, true, 0, true, socket_timeout));
382 (flags & FLAG_TIME_WARN ? true : false), 0,
383 (flags & FLAG_TIME_CRIT ? true : false), 0,
384 true, 0,
385 true, socket_timeout)
386 );
387 else 367 else
388 printf("|%s", 368 printf("|%s", fperfdata("time", elapsed_time, "s", (flags & FLAG_TIME_WARN ? true : false), warning_time,
389 fperfdata ("time", elapsed_time, "s", 369 (flags & FLAG_TIME_CRIT ? true : false), critical_time, true, 0, true, socket_timeout));
390 (flags & FLAG_TIME_WARN ? true : false), warning_time,
391 (flags & FLAG_TIME_CRIT ? true : false), critical_time,
392 true, 0,
393 true, socket_timeout)
394 );
395 370
396 putchar('\n'); 371 putchar('\n');
397 return result; 372 return result;
398} 373}
399 374
400
401
402/* process command-line arguments */ 375/* process command-line arguments */
403static int process_arguments (int argc, char **argv) { 376static int process_arguments(int argc, char **argv) {
404 int c;
405 bool escape = false;
406 char *temp;
407
408 enum { 377 enum {
409 SNI_OPTION = CHAR_MAX + 1 378 SNI_OPTION = CHAR_MAX + 1
410 }; 379 };
411 380
412 int option = 0; 381 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
413 static struct option longopts[] = { 382 {"critical", required_argument, 0, 'c'},
414 {"hostname", required_argument, 0, 'H'}, 383 {"warning", required_argument, 0, 'w'},
415 {"critical", required_argument, 0, 'c'}, 384 {"critical-codes", required_argument, 0, 'C'},
416 {"warning", required_argument, 0, 'w'}, 385 {"warning-codes", required_argument, 0, 'W'},
417 {"critical-codes", required_argument, 0, 'C'}, 386 {"timeout", required_argument, 0, 't'},
418 {"warning-codes", required_argument, 0, 'W'}, 387 {"protocol", required_argument, 0, 'P'}, /* FIXME: Unhandled */
419 {"timeout", required_argument, 0, 't'}, 388 {"port", required_argument, 0, 'p'},
420 {"protocol", required_argument, 0, 'P'}, /* FIXME: Unhandled */ 389 {"escape", no_argument, 0, 'E'},
421 {"port", required_argument, 0, 'p'}, 390 {"all", no_argument, 0, 'A'},
422 {"escape", no_argument, 0, 'E'}, 391 {"send", required_argument, 0, 's'},
423 {"all", no_argument, 0, 'A'}, 392 {"expect", required_argument, 0, 'e'},
424 {"send", required_argument, 0, 's'}, 393 {"maxbytes", required_argument, 0, 'm'},
425 {"expect", required_argument, 0, 'e'}, 394 {"quit", required_argument, 0, 'q'},
426 {"maxbytes", required_argument, 0, 'm'}, 395 {"jail", no_argument, 0, 'j'},
427 {"quit", required_argument, 0, 'q'}, 396 {"delay", required_argument, 0, 'd'},
428 {"jail", no_argument, 0, 'j'}, 397 {"refuse", required_argument, 0, 'r'},
429 {"delay", required_argument, 0, 'd'}, 398 {"mismatch", required_argument, 0, 'M'},
430 {"refuse", required_argument, 0, 'r'}, 399 {"use-ipv4", no_argument, 0, '4'},
431 {"mismatch", required_argument, 0, 'M'}, 400 {"use-ipv6", no_argument, 0, '6'},
432 {"use-ipv4", no_argument, 0, '4'}, 401 {"verbose", no_argument, 0, 'v'},
433 {"use-ipv6", no_argument, 0, '6'}, 402 {"version", no_argument, 0, 'V'},
434 {"verbose", no_argument, 0, 'v'}, 403 {"help", no_argument, 0, 'h'},
435 {"version", no_argument, 0, 'V'}, 404 {"ssl", no_argument, 0, 'S'},
436 {"help", no_argument, 0, 'h'}, 405 {"sni", required_argument, 0, SNI_OPTION},
437 {"ssl", no_argument, 0, 'S'}, 406 {"certificate", required_argument, 0, 'D'},
438 {"sni", required_argument, 0, SNI_OPTION}, 407 {0, 0, 0, 0}};
439 {"certificate", required_argument, 0, 'D'},
440 {0, 0, 0, 0}
441 };
442 408
443 if (argc < 2) 409 if (argc < 2)
444 usage4 (_("No arguments found")); 410 usage4(_("No arguments found"));
445 411
446 /* backwards compatibility */ 412 /* backwards compatibility */
447 for (c = 1; c < argc; c++) { 413 for (int i = 1; i < argc; i++) {
448 if (strcmp ("-to", argv[c]) == 0) 414 if (strcmp("-to", argv[i]) == 0)
449 strcpy (argv[c], "-t"); 415 strcpy(argv[i], "-t");
450 else if (strcmp ("-wt", argv[c]) == 0) 416 else if (strcmp("-wt", argv[i]) == 0)
451 strcpy (argv[c], "-w"); 417 strcpy(argv[i], "-w");
452 else if (strcmp ("-ct", argv[c]) == 0) 418 else if (strcmp("-ct", argv[i]) == 0)
453 strcpy (argv[c], "-c"); 419 strcpy(argv[i], "-c");
454 } 420 }
455 421
456 if (!is_option (argv[1])) { 422 if (!is_option(argv[1])) {
457 server_address = argv[1]; 423 server_address = argv[1];
458 argv[1] = argv[0]; 424 argv[1] = argv[0];
459 argv = &argv[1]; 425 argv = &argv[1];
460 argc--; 426 argc--;
461 } 427 }
462 428
463 while (1) { 429 int option_char;
464 c = getopt_long (argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:", 430 bool escape = false;
465 longopts, &option); 431 while (true) {
432 int option = 0;
433 option_char = getopt_long(argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:", longopts, &option);
466 434
467 if (c == -1 || c == EOF || c == 1) 435 if (option_char == -1 || option_char == EOF || option_char == 1)
468 break; 436 break;
469 437
470 switch (c) { 438 switch (option_char) {
471 case '?': /* print short usage statement if args not parsable */ 439 case '?': /* print short usage statement if args not parsable */
472 usage5 (); 440 usage5();
473 case 'h': /* help */ 441 case 'h': /* help */
474 print_help (); 442 print_help();
475 exit (STATE_UNKNOWN); 443 exit(STATE_UNKNOWN);
476 case 'V': /* version */ 444 case 'V': /* version */
477 print_revision (progname, NP_VERSION); 445 print_revision(progname, NP_VERSION);
478 exit (STATE_UNKNOWN); 446 exit(STATE_UNKNOWN);
479 case 'v': /* verbose mode */ 447 case 'v': /* verbose mode */
480 flags |= FLAG_VERBOSE; 448 flags |= FLAG_VERBOSE;
481 match_flags |= NP_MATCH_VERBOSE; 449 match_flags |= NP_MATCH_VERBOSE;
482 break; 450 break;
@@ -487,43 +455,43 @@ static int process_arguments (int argc, char **argv) {
487#ifdef USE_IPV6 455#ifdef USE_IPV6
488 address_family = AF_INET6; 456 address_family = AF_INET6;
489#else 457#else
490 usage4 (_("IPv6 support not available")); 458 usage4(_("IPv6 support not available"));
491#endif 459#endif
492 break; 460 break;
493 case 'H': /* hostname */ 461 case 'H': /* hostname */
494 host_specified = true; 462 host_specified = true;
495 server_address = optarg; 463 server_address = optarg;
496 break; 464 break;
497 case 'c': /* critical */ 465 case 'c': /* critical */
498 critical_time = strtod (optarg, NULL); 466 critical_time = strtod(optarg, NULL);
499 flags |= FLAG_TIME_CRIT; 467 flags |= FLAG_TIME_CRIT;
500 break; 468 break;
501 case 'j': /* hide output */ 469 case 'j': /* hide output */
502 flags |= FLAG_HIDE_OUTPUT; 470 flags |= FLAG_HIDE_OUTPUT;
503 break; 471 break;
504 case 'w': /* warning */ 472 case 'w': /* warning */
505 warning_time = strtod (optarg, NULL); 473 warning_time = strtod(optarg, NULL);
506 flags |= FLAG_TIME_WARN; 474 flags |= FLAG_TIME_WARN;
507 break; 475 break;
508 case 'C': 476 case 'C':
509 crit_codes = realloc (crit_codes, ++crit_codes_count); 477 crit_codes = realloc(crit_codes, ++crit_codes_count);
510 crit_codes[crit_codes_count - 1] = optarg; 478 crit_codes[crit_codes_count - 1] = optarg;
511 break; 479 break;
512 case 'W': 480 case 'W':
513 warn_codes = realloc (warn_codes, ++warn_codes_count); 481 warn_codes = realloc(warn_codes, ++warn_codes_count);
514 warn_codes[warn_codes_count - 1] = optarg; 482 warn_codes[warn_codes_count - 1] = optarg;
515 break; 483 break;
516 case 't': /* timeout */ 484 case 't': /* timeout */
517 if (!is_intpos (optarg)) 485 if (!is_intpos(optarg))
518 usage4 (_("Timeout interval must be a positive integer")); 486 usage4(_("Timeout interval must be a positive integer"));
519 else 487 else
520 socket_timeout = atoi (optarg); 488 socket_timeout = atoi(optarg);
521 break; 489 break;
522 case 'p': /* port */ 490 case 'p': /* port */
523 if (!is_intpos (optarg)) 491 if (!is_intpos(optarg))
524 usage4 (_("Port must be a positive integer")); 492 usage4(_("Port must be a positive integer"));
525 else 493 else
526 server_port = atoi (optarg); 494 server_port = atoi(optarg);
527 break; 495 break;
528 case 'E': 496 case 'E':
529 escape = true; 497 escape = true;
@@ -537,16 +505,16 @@ static int process_arguments (int argc, char **argv) {
537 case 'e': /* expect string (may be repeated) */ 505 case 'e': /* expect string (may be repeated) */
538 match_flags &= ~NP_MATCH_EXACT; 506 match_flags &= ~NP_MATCH_EXACT;
539 if (server_expect_count == 0) 507 if (server_expect_count == 0)
540 server_expect = malloc (sizeof (char *) * (++server_expect_count)); 508 server_expect = malloc(sizeof(char *) * (++server_expect_count));
541 else 509 else
542 server_expect = realloc (server_expect, sizeof (char *) * (++server_expect_count)); 510 server_expect = realloc(server_expect, sizeof(char *) * (++server_expect_count));
543 server_expect[server_expect_count - 1] = optarg; 511 server_expect[server_expect_count - 1] = optarg;
544 break; 512 break;
545 case 'm': 513 case 'm':
546 if (!is_intpos (optarg)) 514 if (!is_intpos(optarg))
547 usage4 (_("Maxbytes must be a positive integer")); 515 usage4(_("Maxbytes must be a positive integer"));
548 else 516 else
549 maxbytes = strtol (optarg, NULL, 0); 517 maxbytes = strtol(optarg, NULL, 0);
550 break; 518 break;
551 case 'q': 519 case 'q':
552 if (escape) 520 if (escape)
@@ -555,62 +523,62 @@ static int process_arguments (int argc, char **argv) {
555 xasprintf(&server_quit, "%s\r\n", optarg); 523 xasprintf(&server_quit, "%s\r\n", optarg);
556 break; 524 break;
557 case 'r': 525 case 'r':
558 if (!strncmp(optarg,"ok",2)) 526 if (!strncmp(optarg, "ok", 2))
559 econn_refuse_state = STATE_OK; 527 econn_refuse_state = STATE_OK;
560 else if (!strncmp(optarg,"warn",4)) 528 else if (!strncmp(optarg, "warn", 4))
561 econn_refuse_state = STATE_WARNING; 529 econn_refuse_state = STATE_WARNING;
562 else if (!strncmp(optarg,"crit",4)) 530 else if (!strncmp(optarg, "crit", 4))
563 econn_refuse_state = STATE_CRITICAL; 531 econn_refuse_state = STATE_CRITICAL;
564 else 532 else
565 usage4 (_("Refuse must be one of ok, warn, crit")); 533 usage4(_("Refuse must be one of ok, warn, crit"));
566 break; 534 break;
567 case 'M': 535 case 'M':
568 if (!strncmp(optarg,"ok",2)) 536 if (!strncmp(optarg, "ok", 2))
569 expect_mismatch_state = STATE_OK; 537 expect_mismatch_state = STATE_OK;
570 else if (!strncmp(optarg,"warn",4)) 538 else if (!strncmp(optarg, "warn", 4))
571 expect_mismatch_state = STATE_WARNING; 539 expect_mismatch_state = STATE_WARNING;
572 else if (!strncmp(optarg,"crit",4)) 540 else if (!strncmp(optarg, "crit", 4))
573 expect_mismatch_state = STATE_CRITICAL; 541 expect_mismatch_state = STATE_CRITICAL;
574 else 542 else
575 usage4 (_("Mismatch must be one of ok, warn, crit")); 543 usage4(_("Mismatch must be one of ok, warn, crit"));
576 break; 544 break;
577 case 'd': 545 case 'd':
578 if (is_intpos (optarg)) 546 if (is_intpos(optarg))
579 delay = atoi (optarg); 547 delay = atoi(optarg);
580 else 548 else
581 usage4 (_("Delay must be a positive integer")); 549 usage4(_("Delay must be a positive integer"));
582 break; 550 break;
583 case 'D': /* Check SSL cert validity - days 'til certificate expiration */ 551 case 'D': { /* Check SSL cert validity - days 'til certificate expiration */
584#ifdef HAVE_SSL 552#ifdef HAVE_SSL
585# ifdef USE_OPENSSL /* XXX */ 553# ifdef USE_OPENSSL /* XXX */
586 if ((temp=strchr(optarg,','))!=NULL) { 554 char *temp;
587 *temp='\0'; 555 if ((temp = strchr(optarg, ',')) != NULL) {
588 if (!is_intnonneg (optarg)) 556 *temp = '\0';
589 usage2 (_("Invalid certificate expiration period"), optarg); 557 if (!is_intnonneg(optarg))
590 days_till_exp_warn = atoi (optarg); 558 usage2(_("Invalid certificate expiration period"), optarg);
591 *temp=','; 559 days_till_exp_warn = atoi(optarg);
592 temp++; 560 *temp = ',';
593 if (!is_intnonneg (temp)) 561 temp++;
594 usage2 (_("Invalid certificate expiration period"), temp); 562 if (!is_intnonneg(temp))
595 days_till_exp_crit = atoi (temp); 563 usage2(_("Invalid certificate expiration period"), temp);
596 } 564 days_till_exp_crit = atoi(temp);
597 else { 565 } else {
598 days_till_exp_crit=0; 566 days_till_exp_crit = 0;
599 if (!is_intnonneg (optarg)) 567 if (!is_intnonneg(optarg))
600 usage2 (_("Invalid certificate expiration period"), optarg); 568 usage2(_("Invalid certificate expiration period"), optarg);
601 days_till_exp_warn = atoi (optarg); 569 days_till_exp_warn = atoi(optarg);
602 } 570 }
603 check_cert = true; 571 check_cert = true;
604 flags |= FLAG_SSL; 572 flags |= FLAG_SSL;
605 break; 573 } break;
606# endif /* USE_OPENSSL */ 574# endif /* USE_OPENSSL */
607#endif 575#endif
608 /* fallthrough if we don't have ssl */ 576 /* fallthrough if we don't have ssl */
609 case 'S': 577 case 'S':
610#ifdef HAVE_SSL 578#ifdef HAVE_SSL
611 flags |= FLAG_SSL; 579 flags |= FLAG_SSL;
612#else 580#else
613 die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); 581 die(STATE_UNKNOWN, _("Invalid option - SSL is not available"));
614#endif 582#endif
615 break; 583 break;
616 case SNI_OPTION: 584 case SNI_OPTION:
@@ -619,7 +587,7 @@ static int process_arguments (int argc, char **argv) {
619 sni_specified = true; 587 sni_specified = true;
620 sni = optarg; 588 sni = optarg;
621#else 589#else
622 die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); 590 die(STATE_UNKNOWN, _("Invalid option - SSL is not available"));
623#endif 591#endif
624 break; 592 break;
625 case 'A': 593 case 'A':
@@ -628,87 +596,81 @@ static int process_arguments (int argc, char **argv) {
628 } 596 }
629 } 597 }
630 598
631 c = optind; 599 option_char = optind;
632 if(!host_specified && c < argc) 600 if (!host_specified && option_char < argc)
633 server_address = strdup (argv[c++]); 601 server_address = strdup(argv[option_char++]);
634 602
635 if (server_address == NULL) 603 if (server_address == NULL)
636 usage4 (_("You must provide a server address")); 604 usage4(_("You must provide a server address"));
637 else if (server_address[0] != '/' && !is_host(server_address)) 605 else if (server_address[0] != '/' && !is_host(server_address))
638 die (STATE_CRITICAL, "%s %s - %s: %s\n", SERVICE, state_text(STATE_CRITICAL), _("Invalid hostname, address or socket"), server_address); 606 die(STATE_CRITICAL, "%s %s - %s: %s\n", SERVICE, state_text(STATE_CRITICAL), _("Invalid hostname, address or socket"),
607 server_address);
639 608
640 return OK; 609 return OK;
641} 610}
642 611
643 612void print_help(void) {
644void 613 print_revision(progname, NP_VERSION);
645print_help (void) 614
646{ 615 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
647 print_revision (progname, NP_VERSION); 616 printf(COPYRIGHT, copyright, email);
648 617
649 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 618 printf(_("This plugin tests %s connections with the specified host (or unix socket).\n\n"), SERVICE);
650 printf (COPYRIGHT, copyright, email); 619
651 620 print_usage();
652 printf (_("This plugin tests %s connections with the specified host (or unix socket).\n\n"), 621
653 SERVICE); 622 printf(UT_HELP_VRSN);
654 623 printf(UT_EXTRA_OPTS);
655 print_usage (); 624
656 625 printf(UT_HOST_PORT, 'p', "none");
657 printf (UT_HELP_VRSN); 626
658 printf (UT_EXTRA_OPTS); 627 printf(UT_IPv46);
659 628
660 printf (UT_HOST_PORT, 'p', "none"); 629 printf(" %s\n", "-E, --escape");
661 630 printf(" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option"));
662 printf (UT_IPv46); 631 printf(" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit"));
663 632 printf(" %s\n", "-s, --send=STRING");
664 printf (" %s\n", "-E, --escape"); 633 printf(" %s\n", _("String to send to the server"));
665 printf (" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option")); 634 printf(" %s\n", "-e, --expect=STRING");
666 printf (" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit")); 635 printf(" %s %s\n", _("String to expect in server response"), _("(may be repeated)"));
667 printf (" %s\n", "-s, --send=STRING"); 636 printf(" %s\n", "-A, --all");
668 printf (" %s\n", _("String to send to the server")); 637 printf(" %s\n", _("All expect strings need to occur in server response. Default is any"));
669 printf (" %s\n", "-e, --expect=STRING"); 638 printf(" %s\n", "-q, --quit=STRING");
670 printf (" %s %s\n", _("String to expect in server response"), _("(may be repeated)")); 639 printf(" %s\n", _("String to send server to initiate a clean close of the connection"));
671 printf (" %s\n", "-A, --all"); 640 printf(" %s\n", "-r, --refuse=ok|warn|crit");
672 printf (" %s\n", _("All expect strings need to occur in server response. Default is any")); 641 printf(" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)"));
673 printf (" %s\n", "-q, --quit=STRING"); 642 printf(" %s\n", "-M, --mismatch=ok|warn|crit");
674 printf (" %s\n", _("String to send server to initiate a clean close of the connection")); 643 printf(" %s\n", _("Accept expected string mismatches with states ok, warn, crit (default: warn)"));
675 printf (" %s\n", "-r, --refuse=ok|warn|crit"); 644 printf(" %s\n", "-j, --jail");
676 printf (" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)")); 645 printf(" %s\n", _("Hide output from TCP socket"));
677 printf (" %s\n", "-M, --mismatch=ok|warn|crit"); 646 printf(" %s\n", "-m, --maxbytes=INTEGER");
678 printf (" %s\n", _("Accept expected string mismatches with states ok, warn, crit (default: warn)")); 647 printf(" %s\n", _("Close connection once more than this number of bytes are received"));
679 printf (" %s\n", "-j, --jail"); 648 printf(" %s\n", "-d, --delay=INTEGER");
680 printf (" %s\n", _("Hide output from TCP socket")); 649 printf(" %s\n", _("Seconds to wait between sending string and polling for response"));
681 printf (" %s\n", "-m, --maxbytes=INTEGER");
682 printf (" %s\n", _("Close connection once more than this number of bytes are received"));
683 printf (" %s\n", "-d, --delay=INTEGER");
684 printf (" %s\n", _("Seconds to wait between sending string and polling for response"));
685 650
686#ifdef HAVE_SSL 651#ifdef HAVE_SSL
687 printf (" %s\n", "-D, --certificate=INTEGER[,INTEGER]"); 652 printf(" %s\n", "-D, --certificate=INTEGER[,INTEGER]");
688 printf (" %s\n", _("Minimum number of days a certificate has to be valid.")); 653 printf(" %s\n", _("Minimum number of days a certificate has to be valid."));
689 printf (" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0).")); 654 printf(" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0)."));
690 printf (" %s\n", "-S, --ssl"); 655 printf(" %s\n", "-S, --ssl");
691 printf (" %s\n", _("Use SSL for the connection.")); 656 printf(" %s\n", _("Use SSL for the connection."));
692 printf (" %s\n", "--sni=STRING"); 657 printf(" %s\n", "--sni=STRING");
693 printf (" %s\n", _("SSL server_name")); 658 printf(" %s\n", _("SSL server_name"));
694#endif 659#endif
695 660
696 printf (UT_WARN_CRIT); 661 printf(UT_WARN_CRIT);
697 662
698 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 663 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
699 664
700 printf (UT_VERBOSE); 665 printf(UT_VERBOSE);
701 666
702 printf (UT_SUPPORT); 667 printf(UT_SUPPORT);
703} 668}
704 669
705 670void print_usage(void) {
706void 671 printf("%s\n", _("Usage:"));
707print_usage (void) 672 printf("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n", progname);
708{ 673 printf("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n");
709 printf ("%s\n", _("Usage:")); 674 printf("[-t <timeout seconds>] [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n");
710 printf ("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n",progname); 675 printf("[-D <warn days cert expire>[,<crit days cert expire>]] [-S <use SSL>] [-E]\n");
711 printf ("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n");
712 printf ("[-t <timeout seconds>] [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n");
713 printf ("[-D <warn days cert expire>[,<crit days cert expire>]] [-S <use SSL>] [-E]\n");
714} 676}
diff --git a/plugins/check_time.c b/plugins/check_time.c
index f50ea427..d1f50683 100644
--- a/plugins/check_time.c
+++ b/plugins/check_time.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_time plugin 3 * Monitoring check_time plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_time plugin 10 * This file contains the check_time plugin
11* 11 *
12* This plugin will check the time difference with the specified host. 12 * This plugin will check the time difference with the specified host.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_time"; 31const char *progname = "check_time";
32const char *copyright = "1999-2007"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -40,55 +40,51 @@ enum {
40 TIME_PORT = 37 40 TIME_PORT = 37
41}; 41};
42 42
43#define UNIX_EPOCH 2208988800UL 43#define UNIX_EPOCH 2208988800UL
44 44
45uint32_t raw_server_time; 45static uint32_t raw_server_time;
46unsigned long server_time, diff_time; 46static unsigned long server_time, diff_time;
47int warning_time = 0; 47static int warning_time = 0;
48bool check_warning_time = false; 48static bool check_warning_time = false;
49int critical_time = 0; 49static int critical_time = 0;
50bool check_critical_time = false; 50static bool check_critical_time = false;
51unsigned long warning_diff = 0; 51static unsigned long warning_diff = 0;
52bool check_warning_diff = false; 52static bool check_warning_diff = false;
53unsigned long critical_diff = 0; 53static unsigned long critical_diff = 0;
54bool check_critical_diff = false; 54static bool check_critical_diff = false;
55int server_port = TIME_PORT; 55static int server_port = TIME_PORT;
56char *server_address = NULL; 56static char *server_address = NULL;
57bool use_udp = false; 57static bool use_udp = false;
58 58
59int process_arguments (int, char **); 59static int process_arguments(int, char **);
60void print_help (void); 60static void print_help(void);
61void print_usage (void); 61void print_usage(void);
62 62
63int 63int main(int argc, char **argv) {
64main (int argc, char **argv) 64 setlocale(LC_ALL, "");
65{ 65 bindtextdomain(PACKAGE, LOCALEDIR);
66 int sd; 66 textdomain(PACKAGE);
67 int result = STATE_UNKNOWN;
68 time_t conntime;
69
70 setlocale (LC_ALL, "");
71 bindtextdomain (PACKAGE, LOCALEDIR);
72 textdomain (PACKAGE);
73 67
74 /* Parse extra opts if any */ 68 /* Parse extra opts if any */
75 argv=np_extra_opts (&argc, argv, progname); 69 argv = np_extra_opts(&argc, argv, progname);
76 70
77 if (process_arguments (argc, argv) == ERROR) 71 if (process_arguments(argc, argv) == ERROR)
78 usage4 (_("Could not parse arguments")); 72 usage4(_("Could not parse arguments"));
79 73
80 /* initialize alarm signal handling */ 74 /* initialize alarm signal handling */
81 signal (SIGALRM, socket_timeout_alarm_handler); 75 signal(SIGALRM, socket_timeout_alarm_handler);
82 76
83 /* set socket timeout */ 77 /* set socket timeout */
84 alarm (socket_timeout); 78 alarm(socket_timeout);
85 time (&start_time); 79 time(&start_time);
86 80
81 int socket;
82 int result = STATE_UNKNOWN;
87 /* try to connect to the host at the given port number */ 83 /* try to connect to the host at the given port number */
88 if (use_udp) { 84 if (use_udp) {
89 result = my_udp_connect (server_address, server_port, &sd); 85 result = my_udp_connect(server_address, server_port, &socket);
90 } else { 86 } else {
91 result = my_tcp_connect (server_address, server_port, &sd); 87 result = my_tcp_connect(server_address, server_port, &socket);
92 } 88 }
93 89
94 if (result != STATE_OK) { 90 if (result != STATE_OK) {
@@ -98,34 +94,30 @@ main (int argc, char **argv)
98 result = STATE_WARNING; 94 result = STATE_WARNING;
99 else 95 else
100 result = STATE_UNKNOWN; 96 result = STATE_UNKNOWN;
101 die (result, 97 die(result, _("TIME UNKNOWN - could not connect to server %s, port %d\n"), server_address, server_port);
102 _("TIME UNKNOWN - could not connect to server %s, port %d\n"),
103 server_address, server_port);
104 } 98 }
105 99
106 if (use_udp) { 100 if (use_udp) {
107 if (send (sd, "", 0, 0) < 0) { 101 if (send(socket, "", 0, 0) < 0) {
108 if (check_critical_time) 102 if (check_critical_time)
109 result = STATE_CRITICAL; 103 result = STATE_CRITICAL;
110 else if (check_warning_time) 104 else if (check_warning_time)
111 result = STATE_WARNING; 105 result = STATE_WARNING;
112 else 106 else
113 result = STATE_UNKNOWN; 107 result = STATE_UNKNOWN;
114 die (result, 108 die(result, _("TIME UNKNOWN - could not send UDP request to server %s, port %d\n"), server_address, server_port);
115 _("TIME UNKNOWN - could not send UDP request to server %s, port %d\n"),
116 server_address, server_port);
117 } 109 }
118 } 110 }
119 111
120 /* watch for the connection string */ 112 /* watch for the connection string */
121 result = recv (sd, (void *)&raw_server_time, sizeof (raw_server_time), 0); 113 result = recv(socket, (void *)&raw_server_time, sizeof(raw_server_time), 0);
122 114
123 /* close the connection */ 115 /* close the connection */
124 close (sd); 116 close(socket);
125 117
126 /* reset the alarm */ 118 /* reset the alarm */
127 time (&end_time); 119 time(&end_time);
128 alarm (0); 120 alarm(0);
129 121
130 /* return a WARNING status if we couldn't read any data */ 122 /* return a WARNING status if we couldn't read any data */
131 if (result <= 0) { 123 if (result <= 0) {
@@ -135,240 +127,205 @@ main (int argc, char **argv)
135 result = STATE_WARNING; 127 result = STATE_WARNING;
136 else 128 else
137 result = STATE_UNKNOWN; 129 result = STATE_UNKNOWN;
138 die (result, 130 die(result, _("TIME UNKNOWN - no data received from server %s, port %d\n"), server_address, server_port);
139 _("TIME UNKNOWN - no data received from server %s, port %d\n"),
140 server_address, server_port);
141 } 131 }
142 132
143 result = STATE_OK; 133 result = STATE_OK;
144 134
145 conntime = (end_time - start_time); 135 time_t conntime = (end_time - start_time);
146 if (check_critical_time&& conntime > critical_time) 136 if (check_critical_time && conntime > critical_time)
147 result = STATE_CRITICAL; 137 result = STATE_CRITICAL;
148 else if (check_warning_time && conntime > warning_time) 138 else if (check_warning_time && conntime > warning_time)
149 result = STATE_WARNING; 139 result = STATE_WARNING;
150 140
151 if (result != STATE_OK) 141 if (result != STATE_OK)
152 die (result, _("TIME %s - %d second response time|%s\n"), 142 die(result, _("TIME %s - %d second response time|%s\n"), state_text(result), (int)conntime,
153 state_text (result), (int)conntime, 143 perfdata("time", (long)conntime, "s", check_warning_time, (long)warning_time, check_critical_time, (long)critical_time, true, 0,
154 perfdata ("time", (long)conntime, "s", 144 false, 0));
155 check_warning_time, (long)warning_time, 145
156 check_critical_time, (long)critical_time, 146 server_time = ntohl(raw_server_time) - UNIX_EPOCH;
157 true, 0, false, 0));
158
159 server_time = ntohl (raw_server_time) - UNIX_EPOCH;
160 if (server_time > (unsigned long)end_time) 147 if (server_time > (unsigned long)end_time)
161 diff_time = server_time - (unsigned long)end_time; 148 diff_time = server_time - (unsigned long)end_time;
162 else 149 else
163 diff_time = (unsigned long)end_time - server_time; 150 diff_time = (unsigned long)end_time - server_time;
164 151
165 if (check_critical_diff&& diff_time > critical_diff) 152 if (check_critical_diff && diff_time > critical_diff)
166 result = STATE_CRITICAL; 153 result = STATE_CRITICAL;
167 else if (check_warning_diff&& diff_time > warning_diff) 154 else if (check_warning_diff && diff_time > warning_diff)
168 result = STATE_WARNING; 155 result = STATE_WARNING;
169 156
170 printf (_("TIME %s - %lu second time difference|%s %s\n"), 157 printf(_("TIME %s - %lu second time difference|%s %s\n"), state_text(result), diff_time,
171 state_text (result), diff_time, 158 perfdata("time", (long)conntime, "s", check_warning_time, (long)warning_time, check_critical_time, (long)critical_time, true, 0,
172 perfdata ("time", (long)conntime, "s", 159 false, 0),
173 check_warning_time, (long)warning_time, 160 perfdata("offset", diff_time, "s", check_warning_diff, warning_diff, check_critical_diff, critical_diff, true, 0, false, 0));
174 check_critical_time, (long)critical_time,
175 true, 0, false, 0),
176 perfdata ("offset", diff_time, "s",
177 check_warning_diff, warning_diff,
178 check_critical_diff, critical_diff,
179 true, 0, false, 0));
180 return result; 161 return result;
181} 162}
182 163
183
184
185/* process command-line arguments */ 164/* process command-line arguments */
186int 165int process_arguments(int argc, char **argv) {
187process_arguments (int argc, char **argv) 166 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
188{ 167 {"warning-variance", required_argument, 0, 'w'},
189 int c; 168 {"critical-variance", required_argument, 0, 'c'},
190 169 {"warning-connect", required_argument, 0, 'W'},
191 int option = 0; 170 {"critical-connect", required_argument, 0, 'C'},
192 static struct option longopts[] = { 171 {"port", required_argument, 0, 'p'},
193 {"hostname", required_argument, 0, 'H'}, 172 {"udp", no_argument, 0, 'u'},
194 {"warning-variance", required_argument, 0, 'w'}, 173 {"timeout", required_argument, 0, 't'},
195 {"critical-variance", required_argument, 0, 'c'}, 174 {"version", no_argument, 0, 'V'},
196 {"warning-connect", required_argument, 0, 'W'}, 175 {"help", no_argument, 0, 'h'},
197 {"critical-connect", required_argument, 0, 'C'}, 176 {0, 0, 0, 0}};
198 {"port", required_argument, 0, 'p'},
199 {"udp", no_argument, 0, 'u'},
200 {"timeout", required_argument, 0, 't'},
201 {"version", no_argument, 0, 'V'},
202 {"help", no_argument, 0, 'h'},
203 {0, 0, 0, 0}
204 };
205 177
206 if (argc < 2) 178 if (argc < 2)
207 usage ("\n"); 179 usage("\n");
208 180
209 for (c = 1; c < argc; c++) { 181 for (int i = 1; i < argc; i++) {
210 if (strcmp ("-to", argv[c]) == 0) 182 if (strcmp("-to", argv[i]) == 0)
211 strcpy (argv[c], "-t"); 183 strcpy(argv[i], "-t");
212 else if (strcmp ("-wd", argv[c]) == 0) 184 else if (strcmp("-wd", argv[i]) == 0)
213 strcpy (argv[c], "-w"); 185 strcpy(argv[i], "-w");
214 else if (strcmp ("-cd", argv[c]) == 0) 186 else if (strcmp("-cd", argv[i]) == 0)
215 strcpy (argv[c], "-c"); 187 strcpy(argv[i], "-c");
216 else if (strcmp ("-wt", argv[c]) == 0) 188 else if (strcmp("-wt", argv[i]) == 0)
217 strcpy (argv[c], "-W"); 189 strcpy(argv[i], "-W");
218 else if (strcmp ("-ct", argv[c]) == 0) 190 else if (strcmp("-ct", argv[i]) == 0)
219 strcpy (argv[c], "-C"); 191 strcpy(argv[i], "-C");
220 } 192 }
221 193
194 int option_char;
222 while (true) { 195 while (true) {
223 c = getopt_long (argc, argv, "hVH:w:c:W:C:p:t:u", longopts, 196 int option = 0;
224 &option); 197 option_char = getopt_long(argc, argv, "hVH:w:c:W:C:p:t:u", longopts, &option);
225 198
226 if (c == -1 || c == EOF) 199 if (option_char == -1 || option_char == EOF)
227 break; 200 break;
228 201
229 switch (c) { 202 switch (option_char) {
230 case '?': /* print short usage statement if args not parsable */ 203 case '?': /* print short usage statement if args not parsable */
231 usage5 (); 204 usage5();
232 case 'h': /* help */ 205 case 'h': /* help */
233 print_help (); 206 print_help();
234 exit (STATE_UNKNOWN); 207 exit(STATE_UNKNOWN);
235 case 'V': /* version */ 208 case 'V': /* version */
236 print_revision (progname, NP_VERSION); 209 print_revision(progname, NP_VERSION);
237 exit (STATE_UNKNOWN); 210 exit(STATE_UNKNOWN);
238 case 'H': /* hostname */ 211 case 'H': /* hostname */
239 if (!is_host (optarg)) 212 if (!is_host(optarg))
240 usage2 (_("Invalid hostname/address"), optarg); 213 usage2(_("Invalid hostname/address"), optarg);
241 server_address = optarg; 214 server_address = optarg;
242 break; 215 break;
243 case 'w': /* warning-variance */ 216 case 'w': /* warning-variance */
244 if (is_intnonneg (optarg)) { 217 if (is_intnonneg(optarg)) {
245 warning_diff = strtoul (optarg, NULL, 10); 218 warning_diff = strtoul(optarg, NULL, 10);
246 check_warning_diff = true; 219 check_warning_diff = true;
247 } 220 } else if (strspn(optarg, "0123456789:,") > 0) {
248 else if (strspn (optarg, "0123456789:,") > 0) { 221 if (sscanf(optarg, "%lu%*[:,]%d", &warning_diff, &warning_time) == 2) {
249 if (sscanf (optarg, "%lu%*[:,]%d", &warning_diff, &warning_time) == 2) {
250 check_warning_diff = true; 222 check_warning_diff = true;
251 check_warning_time = true; 223 check_warning_time = true;
224 } else {
225 usage4(_("Warning thresholds must be a positive integer"));
252 } 226 }
253 else { 227 } else {
254 usage4 (_("Warning thresholds must be a positive integer")); 228 usage4(_("Warning threshold must be a positive integer"));
255 }
256 }
257 else {
258 usage4 (_("Warning threshold must be a positive integer"));
259 } 229 }
260 break; 230 break;
261 case 'c': /* critical-variance */ 231 case 'c': /* critical-variance */
262 if (is_intnonneg (optarg)) { 232 if (is_intnonneg(optarg)) {
263 critical_diff = strtoul (optarg, NULL, 10); 233 critical_diff = strtoul(optarg, NULL, 10);
264 check_critical_diff = true; 234 check_critical_diff = true;
265 } 235 } else if (strspn(optarg, "0123456789:,") > 0) {
266 else if (strspn (optarg, "0123456789:,") > 0) { 236 if (sscanf(optarg, "%lu%*[:,]%d", &critical_diff, &critical_time) == 2) {
267 if (sscanf (optarg, "%lu%*[:,]%d", &critical_diff, &critical_time) ==
268 2) {
269 check_critical_diff = true; 237 check_critical_diff = true;
270 check_critical_time = true; 238 check_critical_time = true;
239 } else {
240 usage4(_("Critical thresholds must be a positive integer"));
271 } 241 }
272 else { 242 } else {
273 usage4 (_("Critical thresholds must be a positive integer")); 243 usage4(_("Critical threshold must be a positive integer"));
274 }
275 }
276 else {
277 usage4 (_("Critical threshold must be a positive integer"));
278 } 244 }
279 break; 245 break;
280 case 'W': /* warning-connect */ 246 case 'W': /* warning-connect */
281 if (!is_intnonneg (optarg)) 247 if (!is_intnonneg(optarg))
282 usage4 (_("Warning threshold must be a positive integer")); 248 usage4(_("Warning threshold must be a positive integer"));
283 else 249 else
284 warning_time = atoi (optarg); 250 warning_time = atoi(optarg);
285 check_warning_time = true; 251 check_warning_time = true;
286 break; 252 break;
287 case 'C': /* critical-connect */ 253 case 'C': /* critical-connect */
288 if (!is_intnonneg (optarg)) 254 if (!is_intnonneg(optarg))
289 usage4 (_("Critical threshold must be a positive integer")); 255 usage4(_("Critical threshold must be a positive integer"));
290 else 256 else
291 critical_time = atoi (optarg); 257 critical_time = atoi(optarg);
292 check_critical_time = true; 258 check_critical_time = true;
293 break; 259 break;
294 case 'p': /* port */ 260 case 'p': /* port */
295 if (!is_intnonneg (optarg)) 261 if (!is_intnonneg(optarg))
296 usage4 (_("Port must be a positive integer")); 262 usage4(_("Port must be a positive integer"));
297 else 263 else
298 server_port = atoi (optarg); 264 server_port = atoi(optarg);
299 break; 265 break;
300 case 't': /* timeout */ 266 case 't': /* timeout */
301 if (!is_intnonneg (optarg)) 267 if (!is_intnonneg(optarg))
302 usage2 (_("Timeout interval must be a positive integer"), optarg); 268 usage2(_("Timeout interval must be a positive integer"), optarg);
303 else 269 else
304 socket_timeout = atoi (optarg); 270 socket_timeout = atoi(optarg);
305 break; 271 break;
306 case 'u': /* udp */ 272 case 'u': /* udp */
307 use_udp = true; 273 use_udp = true;
308 } 274 }
309 } 275 }
310 276
311 c = optind; 277 option_char = optind;
312 if (server_address == NULL) { 278 if (server_address == NULL) {
313 if (argc > c) { 279 if (argc > option_char) {
314 if (!is_host (argv[c])) 280 if (!is_host(argv[option_char]))
315 usage2 (_("Invalid hostname/address"), optarg); 281 usage2(_("Invalid hostname/address"), optarg);
316 server_address = argv[c]; 282 server_address = argv[option_char];
317 } 283 } else {
318 else { 284 usage4(_("Hostname was not supplied"));
319 usage4 (_("Hostname was not supplied"));
320 } 285 }
321 } 286 }
322 287
323 return OK; 288 return OK;
324} 289}
325 290
326 291void print_help(void) {
327
328void
329print_help (void)
330{
331 char *myport; 292 char *myport;
332 xasprintf (&myport, "%d", TIME_PORT); 293 xasprintf(&myport, "%d", TIME_PORT);
333 294
334 print_revision (progname, NP_VERSION); 295 print_revision(progname, NP_VERSION);
335 296
336 printf ("Copyright (c) 1999 Ethan Galstad\n"); 297 printf("Copyright (c) 1999 Ethan Galstad\n");
337 printf (COPYRIGHT, copyright, email); 298 printf(COPYRIGHT, copyright, email);
338 299
339 printf ("%s\n", _("This plugin will check the time on the specified host.")); 300 printf("%s\n", _("This plugin will check the time on the specified host."));
340 301
341 printf ("\n\n"); 302 printf("\n\n");
342 303
343 print_usage (); 304 print_usage();
344 305
345 printf (UT_HELP_VRSN); 306 printf(UT_HELP_VRSN);
346 printf (UT_EXTRA_OPTS); 307 printf(UT_EXTRA_OPTS);
347 308
348 printf (UT_HOST_PORT, 'p', myport); 309 printf(UT_HOST_PORT, 'p', myport);
349 310
350 printf (" %s\n", "-u, --udp"); 311 printf(" %s\n", "-u, --udp");
351 printf (" %s\n", _("Use UDP to connect, not TCP")); 312 printf(" %s\n", _("Use UDP to connect, not TCP"));
352 printf (" %s\n", "-w, --warning-variance=INTEGER"); 313 printf(" %s\n", "-w, --warning-variance=INTEGER");
353 printf (" %s\n", _("Time difference (sec.) necessary to result in a warning status")); 314 printf(" %s\n", _("Time difference (sec.) necessary to result in a warning status"));
354 printf (" %s\n", "-c, --critical-variance=INTEGER"); 315 printf(" %s\n", "-c, --critical-variance=INTEGER");
355 printf (" %s\n", _("Time difference (sec.) necessary to result in a critical status")); 316 printf(" %s\n", _("Time difference (sec.) necessary to result in a critical status"));
356 printf (" %s\n", "-W, --warning-connect=INTEGER"); 317 printf(" %s\n", "-W, --warning-connect=INTEGER");
357 printf (" %s\n", _("Response time (sec.) necessary to result in warning status")); 318 printf(" %s\n", _("Response time (sec.) necessary to result in warning status"));
358 printf (" %s\n", "-C, --critical-connect=INTEGER"); 319 printf(" %s\n", "-C, --critical-connect=INTEGER");
359 printf (" %s\n", _("Response time (sec.) necessary to result in critical status")); 320 printf(" %s\n", _("Response time (sec.) necessary to result in critical status"));
360 321
361 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 322 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
362 323
363 printf (UT_SUPPORT); 324 printf(UT_SUPPORT);
364} 325}
365 326
366 327void print_usage(void) {
367 328 printf("%s\n", _("Usage:"));
368void 329 printf("%s -H <host_address> [-p port] [-u] [-w variance] [-c variance]\n", progname);
369print_usage (void) 330 printf(" [-W connect_time] [-C connect_time] [-t timeout]\n");
370{
371 printf ("%s\n", _("Usage:"));
372 printf ("%s -H <host_address> [-p port] [-u] [-w variance] [-c variance]\n",progname);
373 printf (" [-W connect_time] [-C connect_time] [-t timeout]\n");
374} 331}
diff --git a/plugins/check_ups.c b/plugins/check_ups.c
index 380ff3bc..adb7ab81 100644
--- a/plugins/check_ups.c
+++ b/plugins/check_ups.c
@@ -6,7 +6,7 @@
6 * Copyright (c) 2000 Tom Shields 6 * Copyright (c) 2000 Tom Shields
7 * 2004 Alain Richard <alain.richard@equation.fr> 7 * 2004 Alain Richard <alain.richard@equation.fr>
8 * 2004 Arnaud Quette <arnaud.quette@mgeups.com> 8 * 2004 Arnaud Quette <arnaud.quette@mgeups.com>
9 * Copyright (c) 2002-2023 Monitoring Plugins Development Team 9 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
10 * 10 *
11 * Description: 11 * Description:
12 * 12 *
@@ -33,14 +33,16 @@
33 *****************************************************************************/ 33 *****************************************************************************/
34 34
35const char *progname = "check_ups"; 35const char *progname = "check_ups";
36const char *copyright = "2000-2023"; 36const char *copyright = "2000-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
40#include "netutils.h" 40#include "netutils.h"
41#include "utils.h" 41#include "utils.h"
42 42
43enum { PORT = 3493 }; 43enum {
44 PORT = 3493
45};
44 46
45#define UPS_NONE 0 /* no supported options */ 47#define UPS_NONE 0 /* no supported options */
46#define UPS_UTILITY 1 /* supports utility line */ 48#define UPS_UTILITY 1 /* supports utility line */
@@ -66,7 +68,9 @@ enum { PORT = 3493 };
66#define UPSSTATUS_UNKNOWN 4096 68#define UPSSTATUS_UNKNOWN 4096
67#define UPSSTATUS_ALARM 8192 69#define UPSSTATUS_ALARM 8192
68 70
69enum { NOSUCHVAR = ERROR - 1 }; 71enum {
72 NOSUCHVAR = ERROR - 1
73};
70 74
71typedef struct ups_config { 75typedef struct ups_config {
72 unsigned int server_port; 76 unsigned int server_port;
@@ -141,7 +145,6 @@ int main(int argc, char **argv) {
141 return STATE_CRITICAL; 145 return STATE_CRITICAL;
142 } 146 }
143 147
144
145 if (supported_options & UPS_STATUS) { 148 if (supported_options & UPS_STATUS) {
146 149
147 ups_status = strdup(""); 150 ups_status = strdup("");
@@ -151,8 +154,7 @@ int main(int argc, char **argv) {
151 if (config.status & UPSSTATUS_OFF) { 154 if (config.status & UPSSTATUS_OFF) {
152 xasprintf(&ups_status, "Off"); 155 xasprintf(&ups_status, "Off");
153 result = STATE_CRITICAL; 156 result = STATE_CRITICAL;
154 } else if ((config.status & (UPSSTATUS_OB | UPSSTATUS_LB)) == 157 } else if ((config.status & (UPSSTATUS_OB | UPSSTATUS_LB)) == (UPSSTATUS_OB | UPSSTATUS_LB)) {
155 (UPSSTATUS_OB | UPSSTATUS_LB)) {
156 xasprintf(&ups_status, _("On Battery, Low Battery")); 158 xasprintf(&ups_status, _("On Battery, Low Battery"));
157 result = STATE_CRITICAL; 159 result = STATE_CRITICAL;
158 } else { 160 } else {
@@ -171,8 +173,7 @@ int main(int argc, char **argv) {
171 xasprintf(&ups_status, "%s%s", ups_status, _(", Calibrating")); 173 xasprintf(&ups_status, "%s%s", ups_status, _(", Calibrating"));
172 } 174 }
173 if (config.status & UPSSTATUS_RB) { 175 if (config.status & UPSSTATUS_RB) {
174 xasprintf(&ups_status, "%s%s", ups_status, 176 xasprintf(&ups_status, "%s%s", ups_status, _(", Replace Battery"));
175 _(", Replace Battery"));
176 result = max_state(result, STATE_WARNING); 177 result = max_state(result, STATE_WARNING);
177 } 178 }
178 if (config.status & UPSSTATUS_BYPASS) { 179 if (config.status & UPSSTATUS_BYPASS) {
@@ -233,24 +234,16 @@ int main(int argc, char **argv) {
233 } 234 }
234 235
235 if (config.check_variable == UPS_UTILITY) { 236 if (config.check_variable == UPS_UTILITY) {
236 if (config.check_crit && 237 if (config.check_crit && ups_utility_deviation >= config.critical_value) {
237 ups_utility_deviation >= config.critical_value) {
238 result = STATE_CRITICAL; 238 result = STATE_CRITICAL;
239 } else if (config.check_warn && 239 } else if (config.check_warn && ups_utility_deviation >= config.warning_value) {
240 ups_utility_deviation >= config.warning_value) {
241 result = max_state(result, STATE_WARNING); 240 result = max_state(result, STATE_WARNING);
242 } 241 }
243 xasprintf(&data, "%s", 242 xasprintf(&data, "%s",
244 perfdata("voltage", (long)(1000 * ups_utility_voltage), 243 perfdata("voltage", (long)(1000 * ups_utility_voltage), "mV", config.check_warn, (long)(1000 * config.warning_value),
245 "mV", config.check_warn, 244 config.check_crit, (long)(1000 * config.critical_value), true, 0, false, 0));
246 (long)(1000 * config.warning_value),
247 config.check_crit,
248 (long)(1000 * config.critical_value), true, 0,
249 false, 0));
250 } else { 245 } else {
251 xasprintf(&data, "%s", 246 xasprintf(&data, "%s", perfdata("voltage", (long)(1000 * ups_utility_voltage), "mV", false, 0, false, 0, true, 0, false, 0));
252 perfdata("voltage", (long)(1000 * ups_utility_voltage),
253 "mV", false, 0, false, 0, true, 0, false, 0));
254 } 247 }
255 } 248 }
256 249
@@ -268,22 +261,16 @@ int main(int argc, char **argv) {
268 xasprintf(&message, "%sBatt=%3.1f%% ", message, ups_battery_percent); 261 xasprintf(&message, "%sBatt=%3.1f%% ", message, ups_battery_percent);
269 262
270 if (config.check_variable == UPS_BATTPCT) { 263 if (config.check_variable == UPS_BATTPCT) {
271 if (config.check_crit && 264 if (config.check_crit && ups_battery_percent <= config.critical_value) {
272 ups_battery_percent <= config.critical_value) {
273 result = STATE_CRITICAL; 265 result = STATE_CRITICAL;
274 } else if (config.check_warn && 266 } else if (config.check_warn && ups_battery_percent <= config.warning_value) {
275 ups_battery_percent <= config.warning_value) {
276 result = max_state(result, STATE_WARNING); 267 result = max_state(result, STATE_WARNING);
277 } 268 }
278 xasprintf(&data, "%s %s", data, 269 xasprintf(&data, "%s %s", data,
279 perfdata("battery", (long)ups_battery_percent, "%", 270 perfdata("battery", (long)ups_battery_percent, "%", config.check_warn, (long)(config.warning_value),
280 config.check_warn, (long)(config.warning_value), 271 config.check_crit, (long)(config.critical_value), true, 0, true, 100));
281 config.check_crit, (long)(config.critical_value),
282 true, 0, true, 100));
283 } else { 272 } else {
284 xasprintf(&data, "%s %s", data, 273 xasprintf(&data, "%s %s", data, perfdata("battery", (long)ups_battery_percent, "%", false, 0, false, 0, true, 0, true, 100));
285 perfdata("battery", (long)ups_battery_percent, "%", false,
286 0, false, 0, true, 0, true, 100));
287 } 274 }
288 } 275 }
289 276
@@ -301,22 +288,16 @@ int main(int argc, char **argv) {
301 xasprintf(&message, "%sLoad=%3.1f%% ", message, ups_load_percent); 288 xasprintf(&message, "%sLoad=%3.1f%% ", message, ups_load_percent);
302 289
303 if (config.check_variable == UPS_LOADPCT) { 290 if (config.check_variable == UPS_LOADPCT) {
304 if (config.check_crit && 291 if (config.check_crit && ups_load_percent >= config.critical_value) {
305 ups_load_percent >= config.critical_value) {
306 result = STATE_CRITICAL; 292 result = STATE_CRITICAL;
307 } else if (config.check_warn && 293 } else if (config.check_warn && ups_load_percent >= config.warning_value) {
308 ups_load_percent >= config.warning_value) {
309 result = max_state(result, STATE_WARNING); 294 result = max_state(result, STATE_WARNING);
310 } 295 }
311 xasprintf(&data, "%s %s", data, 296 xasprintf(&data, "%s %s", data,
312 perfdata("load", (long)ups_load_percent, "%", 297 perfdata("load", (long)ups_load_percent, "%", config.check_warn, (long)(config.warning_value), config.check_crit,
313 config.check_warn, (long)(config.warning_value), 298 (long)(config.critical_value), true, 0, true, 100));
314 config.check_crit, (long)(config.critical_value),
315 true, 0, true, 100));
316 } else { 299 } else {
317 xasprintf(&data, "%s %s", data, 300 xasprintf(&data, "%s %s", data, perfdata("load", (long)ups_load_percent, "%", false, 0, false, 0, true, 0, true, 100));
318 perfdata("load", (long)ups_load_percent, "%", false, 0,
319 false, 0, true, 0, true, 100));
320 } 301 }
321 } 302 }
322 303
@@ -345,19 +326,14 @@ int main(int argc, char **argv) {
345 if (config.check_variable == UPS_TEMP) { 326 if (config.check_variable == UPS_TEMP) {
346 if (config.check_crit && ups_temperature >= config.critical_value) { 327 if (config.check_crit && ups_temperature >= config.critical_value) {
347 result = STATE_CRITICAL; 328 result = STATE_CRITICAL;
348 } else if (config.check_warn && 329 } else if (config.check_warn && ups_temperature >= config.warning_value) {
349 ups_temperature >= config.warning_value) {
350 result = max_state(result, STATE_WARNING); 330 result = max_state(result, STATE_WARNING);
351 } 331 }
352 xasprintf(&data, "%s %s", data, 332 xasprintf(&data, "%s %s", data,
353 perfdata("temp", (long)ups_temperature, tunits, 333 perfdata("temp", (long)ups_temperature, tunits, config.check_warn, (long)(config.warning_value), config.check_crit,
354 config.check_warn, (long)(config.warning_value), 334 (long)(config.critical_value), true, 0, false, 0));
355 config.check_crit, (long)(config.critical_value),
356 true, 0, false, 0));
357 } else { 335 } else {
358 xasprintf(&data, "%s %s", data, 336 xasprintf(&data, "%s %s", data, perfdata("temp", (long)ups_temperature, tunits, false, 0, false, 0, true, 0, false, 0));
359 perfdata("temp", (long)ups_temperature, tunits, false, 0,
360 false, 0, true, 0, false, 0));
361 } 337 }
362 } 338 }
363 339
@@ -376,19 +352,14 @@ int main(int argc, char **argv) {
376 if (config.check_variable == UPS_REALPOWER) { 352 if (config.check_variable == UPS_REALPOWER) {
377 if (config.check_crit && ups_realpower >= config.critical_value) { 353 if (config.check_crit && ups_realpower >= config.critical_value) {
378 result = STATE_CRITICAL; 354 result = STATE_CRITICAL;
379 } else if (config.check_warn && 355 } else if (config.check_warn && ups_realpower >= config.warning_value) {
380 ups_realpower >= config.warning_value) {
381 result = max_state(result, STATE_WARNING); 356 result = max_state(result, STATE_WARNING);
382 } 357 }
383 xasprintf(&data, "%s %s", data, 358 xasprintf(&data, "%s %s", data,
384 perfdata("realpower", (long)ups_realpower, "W", 359 perfdata("realpower", (long)ups_realpower, "W", config.check_warn, (long)(config.warning_value), config.check_crit,
385 config.check_warn, (long)(config.warning_value), 360 (long)(config.critical_value), true, 0, false, 0));
386 config.check_crit, (long)(config.critical_value),
387 true, 0, false, 0));
388 } else { 361 } else {
389 xasprintf(&data, "%s %s", data, 362 xasprintf(&data, "%s %s", data, perfdata("realpower", (long)ups_realpower, "W", false, 0, false, 0, true, 0, false, 0));
390 perfdata("realpower", (long)ups_realpower, "W", false, 0,
391 false, 0, true, 0, false, 0));
392 } 363 }
393 } 364 }
394 365
@@ -425,8 +396,7 @@ int determine_status(ups_config *config, int *supported_options) {
425 char temp_buffer[MAX_INPUT_BUFFER]; 396 char temp_buffer[MAX_INPUT_BUFFER];
426 397
427 strcpy(temp_buffer, recv_buffer); 398 strcpy(temp_buffer, recv_buffer);
428 for (char *ptr = (char *)strtok(temp_buffer, " "); ptr != NULL; 399 for (char *ptr = (char *)strtok(temp_buffer, " "); ptr != NULL; ptr = (char *)strtok(NULL, " ")) {
429 ptr = (char *)strtok(NULL, " ")) {
430 if (!strcmp(ptr, "OFF")) { 400 if (!strcmp(ptr, "OFF")) {
431 config->status |= UPSSTATUS_OFF; 401 config->status |= UPSSTATUS_OFF;
432 } else if (!strcmp(ptr, "OL")) { 402 } else if (!strcmp(ptr, "OL")) {
@@ -467,8 +437,7 @@ int get_ups_variable(const char *varname, char *buf, const ups_config config) {
467 437
468 /* create the command string to send to the UPS daemon */ 438 /* create the command string to send to the UPS daemon */
469 /* Add LOGOUT to avoid read failure logs */ 439 /* Add LOGOUT to avoid read failure logs */
470 int res = snprintf(send_buffer, sizeof(send_buffer), 440 int res = snprintf(send_buffer, sizeof(send_buffer), "GET VAR %s %s\nLOGOUT\n", config.ups_name, varname);
471 "GET VAR %s %s\nLOGOUT\n", config.ups_name, varname);
472 if ((res > 0) && ((size_t)res >= sizeof(send_buffer))) { 441 if ((res > 0) && ((size_t)res >= sizeof(send_buffer))) {
473 printf("%s\n", _("UPS name to long for buffer")); 442 printf("%s\n", _("UPS name to long for buffer"));
474 return ERROR; 443 return ERROR;
@@ -477,9 +446,7 @@ int get_ups_variable(const char *varname, char *buf, const ups_config config) {
477 char temp_buffer[MAX_INPUT_BUFFER]; 446 char temp_buffer[MAX_INPUT_BUFFER];
478 447
479 /* send the command to the daemon and get a response back */ 448 /* send the command to the daemon and get a response back */
480 if (process_tcp_request(config.server_address, config.server_port, 449 if (process_tcp_request(config.server_address, config.server_port, send_buffer, temp_buffer, sizeof(temp_buffer)) != STATE_OK) {
481 send_buffer, temp_buffer,
482 sizeof(temp_buffer)) != STATE_OK) {
483 printf("%s\n", _("Invalid response received from host")); 450 printf("%s\n", _("Invalid response received from host"));
484 return ERROR; 451 return ERROR;
485 } 452 }
@@ -496,8 +463,7 @@ int get_ups_variable(const char *varname, char *buf, const ups_config config) {
496 ptr[len - 1] = 0; 463 ptr[len - 1] = 0;
497 } 464 }
498 if (strcmp(ptr, "ERR UNKNOWN-UPS") == 0) { 465 if (strcmp(ptr, "ERR UNKNOWN-UPS") == 0) {
499 printf(_("CRITICAL - no such UPS '%s' on that host\n"), 466 printf(_("CRITICAL - no such UPS '%s' on that host\n"), config.ups_name);
500 config.ups_name);
501 return ERROR; 467 return ERROR;
502 } 468 }
503 469
@@ -694,8 +660,7 @@ void print_help(void) {
694 printf(" %s\n", "-T, --temperature"); 660 printf(" %s\n", "-T, --temperature");
695 printf(" %s\n", _("Output of temperatures in Celsius")); 661 printf(" %s\n", _("Output of temperatures in Celsius"));
696 printf(" %s\n", "-v, --variable=STRING"); 662 printf(" %s\n", "-v, --variable=STRING");
697 printf(" %s %s\n", _("Valid values for STRING are"), 663 printf(" %s %s\n", _("Valid values for STRING are"), "LINE, TEMP, BATTPCT, LOADPCT or REALPOWER");
698 "LINE, TEMP, BATTPCT, LOADPCT or REALPOWER");
699 664
700 printf(UT_WARN_CRIT); 665 printf(UT_WARN_CRIT);
701 666
@@ -731,8 +696,7 @@ void print_help(void) {
731 "with Russell Kroll's")); 696 "with Russell Kroll's"));
732 printf(" %s\n", _("Network UPS Tools be installed on the remote host. If " 697 printf(" %s\n", _("Network UPS Tools be installed on the remote host. If "
733 "you do not have the")); 698 "you do not have the"));
734 printf(" %s\n", 699 printf(" %s\n", _("package installed on your system, you can download it from"));
735 _("package installed on your system, you can download it from"));
736 printf(" %s\n", _("http://www.networkupstools.org")); 700 printf(" %s\n", _("http://www.networkupstools.org"));
737 701
738 printf(UT_SUPPORT); 702 printf(UT_SUPPORT);
diff --git a/plugins/check_users.c b/plugins/check_users.c
index 89b95369..f1e1c39d 100644
--- a/plugins/check_users.c
+++ b/plugins/check_users.c
@@ -1,71 +1,69 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_users plugin 3 * Monitoring check_users plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2012 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_users plugin 10 * This file contains the check_users plugin
11* 11 *
12* This plugin checks the number of users currently logged in on the local 12 * This plugin checks the number of users currently logged in on the local
13* system and generates an error if the number exceeds the thresholds 13 * system and generates an error if the number exceeds the thresholds
14* specified. 14 * specified.
15* 15 *
16* 16 *
17* This program is free software: you can redistribute it and/or modify 17 * This program is free software: you can redistribute it and/or modify
18* it under the terms of the GNU General Public License as published by 18 * it under the terms of the GNU General Public License as published by
19* the Free Software Foundation, either version 3 of the License, or 19 * the Free Software Foundation, either version 3 of the License, or
20* (at your option) any later version. 20 * (at your option) any later version.
21* 21 *
22* This program is distributed in the hope that it will be useful, 22 * This program is distributed in the hope that it will be useful,
23* but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25* GNU General Public License for more details. 25 * GNU General Public License for more details.
26* 26 *
27* You should have received a copy of the GNU General Public License 27 * You should have received a copy of the GNU General Public License
28* along with this program. If not, see <http://www.gnu.org/licenses/>. 28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29* 29 *
30* 30 *
31*****************************************************************************/ 31 *****************************************************************************/
32 32
33const char *progname = "check_users"; 33const char *progname = "check_users";
34const char *copyright = "2000-2007"; 34const char *copyright = "2000-2024";
35const char *email = "devel@monitoring-plugins.org"; 35const char *email = "devel@monitoring-plugins.org";
36 36
37#include "common.h" 37#include "common.h"
38#include "utils.h" 38#include "utils.h"
39 39
40#if HAVE_WTSAPI32_H 40#if HAVE_WTSAPI32_H
41# include <windows.h> 41# include <windows.h>
42# include <wtsapi32.h> 42# include <wtsapi32.h>
43# undef ERROR 43# undef ERROR
44# define ERROR -1 44# define ERROR -1
45#elif HAVE_UTMPX_H 45#elif HAVE_UTMPX_H
46# include <utmpx.h> 46# include <utmpx.h>
47#else 47#else
48# include "popen.h" 48# include "popen.h"
49#endif 49#endif
50 50
51#ifdef HAVE_LIBSYSTEMD 51#ifdef HAVE_LIBSYSTEMD
52#include <systemd/sd-daemon.h> 52# include <systemd/sd-daemon.h>
53#include <systemd/sd-login.h> 53# include <systemd/sd-login.h>
54#endif 54#endif
55 55
56#define possibly_set(a,b) ((a) == 0 ? (b) : 0) 56#define possibly_set(a, b) ((a) == 0 ? (b) : 0)
57 57
58int process_arguments (int, char **); 58static int process_arguments(int, char **);
59void print_help (void); 59static void print_help(void);
60void print_usage (void); 60void print_usage(void);
61 61
62char *warning_range = NULL; 62static char *warning_range = NULL;
63char *critical_range = NULL; 63static char *critical_range = NULL;
64thresholds *thlds = NULL; 64static thresholds *thlds = NULL;
65 65
66int 66int main(int argc, char **argv) {
67main (int argc, char **argv)
68{
69 int users = -1; 67 int users = -1;
70 int result = STATE_UNKNOWN; 68 int result = STATE_UNKNOWN;
71#if HAVE_WTSAPI32_H 69#if HAVE_WTSAPI32_H
@@ -78,74 +76,71 @@ main (int argc, char **argv)
78 char input_buffer[MAX_INPUT_BUFFER]; 76 char input_buffer[MAX_INPUT_BUFFER];
79#endif 77#endif
80 78
81 setlocale (LC_ALL, ""); 79 setlocale(LC_ALL, "");
82 bindtextdomain (PACKAGE, LOCALEDIR); 80 bindtextdomain(PACKAGE, LOCALEDIR);
83 textdomain (PACKAGE); 81 textdomain(PACKAGE);
84 82
85 /* Parse extra opts if any */ 83 /* Parse extra opts if any */
86 argv = np_extra_opts (&argc, argv, progname); 84 argv = np_extra_opts(&argc, argv, progname);
87 85
88 if (process_arguments (argc, argv) == ERROR) 86 if (process_arguments(argc, argv) == ERROR)
89 usage4 (_("Could not parse arguments")); 87 usage4(_("Could not parse arguments"));
90 88
91 users = 0; 89 users = 0;
92 90
93#ifdef HAVE_LIBSYSTEMD 91#ifdef HAVE_LIBSYSTEMD
94 if (sd_booted () > 0) 92 if (sd_booted() > 0)
95 users = sd_get_sessions (NULL); 93 users = sd_get_sessions(NULL);
96 else { 94 else {
97#endif 95#endif
98#if HAVE_WTSAPI32_H 96#if HAVE_WTSAPI32_H
99 if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 97 if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &wtsinfo, &wtscount)) {
100 0, 1, &wtsinfo, &wtscount)) { 98 printf(_("Could not enumerate RD sessions: %d\n"), GetLastError());
101 printf(_("Could not enumerate RD sessions: %d\n"), GetLastError()); 99 return STATE_UNKNOWN;
102 return STATE_UNKNOWN; 100 }
103 }
104 101
105 for (index = 0; index < wtscount; index++) { 102 for (index = 0; index < wtscount; index++) {
106 LPTSTR username; 103 LPTSTR username;
107 DWORD size; 104 DWORD size;
108 int len; 105 int len;
109 106
110 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 107 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, wtsinfo[index].SessionId, WTSUserName, &username, &size))
111 wtsinfo[index].SessionId, WTSUserName, &username, &size)) 108 continue;
112 continue;
113 109
114 len = lstrlen(username); 110 len = lstrlen(username);
115 111
116 WTSFreeMemory(username); 112 WTSFreeMemory(username);
117 113
118 if (len == 0) 114 if (len == 0)
119 continue; 115 continue;
120 116
121 if (wtsinfo[index].State == WTSActive || 117 if (wtsinfo[index].State == WTSActive || wtsinfo[index].State == WTSDisconnected)
122 wtsinfo[index].State == WTSDisconnected) 118 users++;
123 users++; 119 }
124 }
125 120
126 WTSFreeMemory(wtsinfo); 121 WTSFreeMemory(wtsinfo);
127#elif HAVE_UTMPX_H 122#elif HAVE_UTMPX_H
128 /* get currently logged users from utmpx */ 123 /* get currently logged users from utmpx */
129 setutxent (); 124 setutxent();
130 125
131 while ((putmpx = getutxent ()) != NULL) 126 while ((putmpx = getutxent()) != NULL)
132 if (putmpx->ut_type == USER_PROCESS) 127 if (putmpx->ut_type == USER_PROCESS)
133 users++; 128 users++;
134 129
135 endutxent (); 130 endutxent();
136#else 131#else
137 /* run the command */ 132 /* run the command */
138 child_process = spopen (WHO_COMMAND); 133 child_process = spopen(WHO_COMMAND);
139 if (child_process == NULL) { 134 if (child_process == NULL) {
140 printf (_("Could not open pipe: %s\n"), WHO_COMMAND); 135 printf(_("Could not open pipe: %s\n"), WHO_COMMAND);
141 return STATE_UNKNOWN; 136 return STATE_UNKNOWN;
142 } 137 }
143 138
144 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 139 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
145 if (child_stderr == NULL) 140 if (child_stderr == NULL)
146 printf (_("Could not open stderr for %s\n"), WHO_COMMAND); 141 printf(_("Could not open stderr for %s\n"), WHO_COMMAND);
147 142
148 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 143 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
149 /* increment 'users' on all lines except total user count */ 144 /* increment 'users' on all lines except total user count */
150 if (input_buffer[0] != '#') { 145 if (input_buffer[0] != '#') {
151 users++; 146 users++;
@@ -153,18 +148,18 @@ main (int argc, char **argv)
153 } 148 }
154 149
155 /* get total logged in users */ 150 /* get total logged in users */
156 if (sscanf (input_buffer, _("# users=%d"), &users) == 1) 151 if (sscanf(input_buffer, _("# users=%d"), &users) == 1)
157 break; 152 break;
158 } 153 }
159 154
160 /* check STDERR */ 155 /* check STDERR */
161 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) 156 if (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
162 result = possibly_set (result, STATE_UNKNOWN); 157 result = possibly_set(result, STATE_UNKNOWN);
163 (void) fclose (child_stderr); 158 (void)fclose(child_stderr);
164 159
165 /* close the pipe */ 160 /* close the pipe */
166 if (spclose (child_process)) 161 if (spclose(child_process))
167 result = possibly_set (result, STATE_UNKNOWN); 162 result = possibly_set(result, STATE_UNKNOWN);
168#endif 163#endif
169#ifdef HAVE_LIBSYSTEMD 164#ifdef HAVE_LIBSYSTEMD
170 } 165 }
@@ -174,109 +169,99 @@ main (int argc, char **argv)
174 result = get_status((double)users, thlds); 169 result = get_status((double)users, thlds);
175 170
176 if (result == STATE_UNKNOWN) 171 if (result == STATE_UNKNOWN)
177 printf ("%s\n", _("Unable to read output")); 172 printf("%s\n", _("Unable to read output"));
178 else { 173 else {
179 printf (_("USERS %s - %d users currently logged in |%s\n"), 174 printf(_("USERS %s - %d users currently logged in |%s\n"), state_text(result), users,
180 state_text(result), users, 175 sperfdata_int("users", users, "", warning_range, critical_range, true, 0, false, 0));
181 sperfdata_int("users", users, "", warning_range,
182 critical_range, true, 0, false, 0));
183 } 176 }
184 177
185 return result; 178 return result;
186} 179}
187 180
188/* process command-line arguments */ 181/* process command-line arguments */
189int 182int process_arguments(int argc, char **argv) {
190process_arguments (int argc, char **argv) 183 static struct option longopts[] = {{"critical", required_argument, 0, 'c'},
191{ 184 {"warning", required_argument, 0, 'w'},
192 int c; 185 {"version", no_argument, 0, 'V'},
193 int option = 0; 186 {"help", no_argument, 0, 'h'},
194 static struct option longopts[] = { 187 {0, 0, 0, 0}};
195 {"critical", required_argument, 0, 'c'},
196 {"warning", required_argument, 0, 'w'},
197 {"version", no_argument, 0, 'V'},
198 {"help", no_argument, 0, 'h'},
199 {0, 0, 0, 0}
200 };
201 188
202 if (argc < 2) 189 if (argc < 2)
203 usage ("\n"); 190 usage("\n");
204 191
192 int option_char;
205 while (true) { 193 while (true) {
206 c = getopt_long (argc, argv, "+hVvc:w:", longopts, &option); 194 int option = 0;
195 option_char = getopt_long(argc, argv, "+hVvc:w:", longopts, &option);
207 196
208 if (c == -1 || c == EOF || c == 1) 197 if (option_char == -1 || option_char == EOF || option_char == 1)
209 break; 198 break;
210 199
211 switch (c) { 200 switch (option_char) {
212 case '?': /* print short usage statement if args not parsable */ 201 case '?': /* print short usage statement if args not parsable */
213 usage5 (); 202 usage5();
214 case 'h': /* help */ 203 case 'h': /* help */
215 print_help (); 204 print_help();
216 exit (STATE_UNKNOWN); 205 exit(STATE_UNKNOWN);
217 case 'V': /* version */ 206 case 'V': /* version */
218 print_revision (progname, NP_VERSION); 207 print_revision(progname, NP_VERSION);
219 exit (STATE_UNKNOWN); 208 exit(STATE_UNKNOWN);
220 case 'c': /* critical */ 209 case 'c': /* critical */
221 critical_range = optarg; 210 critical_range = optarg;
222 break; 211 break;
223 case 'w': /* warning */ 212 case 'w': /* warning */
224 warning_range = optarg; 213 warning_range = optarg;
225 break; 214 break;
226 } 215 }
227 } 216 }
228 217
229 c = optind; 218 option_char = optind;
230 219
231 if (warning_range == NULL && argc > c) 220 if (warning_range == NULL && argc > option_char)
232 warning_range = argv[c++]; 221 warning_range = argv[option_char++];
233 222
234 if (critical_range == NULL && argc > c) 223 if (critical_range == NULL && argc > option_char)
235 critical_range = argv[c++]; 224 critical_range = argv[option_char++];
236 225
237 /* this will abort in case of invalid ranges */ 226 /* this will abort in case of invalid ranges */
238 set_thresholds (&thlds, warning_range, critical_range); 227 set_thresholds(&thlds, warning_range, critical_range);
239 228
240 if (!thlds->warning) { 229 if (!thlds->warning) {
241 usage4 (_("Warning threshold must be a valid range expression")); 230 usage4(_("Warning threshold must be a valid range expression"));
242 } 231 }
243 232
244 if (!thlds->critical) { 233 if (!thlds->critical) {
245 usage4 (_("Critical threshold must be a valid range expression")); 234 usage4(_("Critical threshold must be a valid range expression"));
246 } 235 }
247 236
248 return OK; 237 return OK;
249} 238}
250 239
251void 240void print_help(void) {
252print_help (void) 241 print_revision(progname, NP_VERSION);
253{
254 print_revision (progname, NP_VERSION);
255 242
256 printf ("Copyright (c) 1999 Ethan Galstad\n"); 243 printf("Copyright (c) 1999 Ethan Galstad\n");
257 printf (COPYRIGHT, copyright, email); 244 printf(COPYRIGHT, copyright, email);
258 245
259 printf ("%s\n", _("This plugin checks the number of users currently logged in on the local")); 246 printf("%s\n", _("This plugin checks the number of users currently logged in on the local"));
260 printf ("%s\n", _("system and generates an error if the number exceeds the thresholds specified.")); 247 printf("%s\n", _("system and generates an error if the number exceeds the thresholds specified."));
261 248
262 printf ("\n\n"); 249 printf("\n\n");
263 250
264 print_usage (); 251 print_usage();
265 252
266 printf (UT_HELP_VRSN); 253 printf(UT_HELP_VRSN);
267 printf (UT_EXTRA_OPTS); 254 printf(UT_EXTRA_OPTS);
268 255
269 printf (" %s\n", "-w, --warning=RANGE_EXPRESSION"); 256 printf(" %s\n", "-w, --warning=RANGE_EXPRESSION");
270 printf (" %s\n", _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION")); 257 printf(" %s\n", _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION"));
271 printf (" %s\n", "-c, --critical=RANGE_EXPRESSION"); 258 printf(" %s\n", "-c, --critical=RANGE_EXPRESSION");
272 printf (" %s\n", _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION")); 259 printf(" %s\n", _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION"));
273 260
274 printf (UT_SUPPORT); 261 printf(UT_SUPPORT);
275} 262}
276 263
277void 264void print_usage(void) {
278print_usage (void) 265 printf("%s\n", _("Usage:"));
279{ 266 printf("%s -w <users> -c <users>\n", progname);
280 printf ("%s\n", _("Usage:"));
281 printf ("%s -w <users> -c <users>\n", progname);
282} 267}
diff --git a/plugins/negate.c b/plugins/negate.c
index c5fe7e13..7e52fe67 100644
--- a/plugins/negate.c
+++ b/plugins/negate.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring negate plugin 3 * Monitoring negate plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2002-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the negate plugin 10 * This file contains the negate plugin
11* 11 *
12* Negates the status of a plugin (returns OK for CRITICAL, and vice-versa). 12 * Negates the status of a plugin (returns OK for CRITICAL, and vice-versa).
13* Can also perform custom state switching. 13 * Can also perform custom state switching.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "negate"; 32const char *progname = "negate";
33const char *copyright = "2002-2008"; 33const char *copyright = "2002-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#define DEFAULT_TIMEOUT 11 36#define DEFAULT_TIMEOUT 11
@@ -41,13 +41,11 @@ const char *email = "devel@monitoring-plugins.org";
41 41
42#include <ctype.h> 42#include <ctype.h>
43 43
44/* char *command_line; */ 44static const char **process_arguments(int /*argc*/, char ** /*argv*/);
45 45static void validate_arguments(char ** /*command_line*/);
46static const char **process_arguments (int, char **); 46static void print_help(void);
47void validate_arguments (char **); 47void print_usage(void);
48void print_help (void); 48static bool subst_text = false;
49void print_usage (void);
50bool subst_text = false;
51 49
52static int state[4] = { 50static int state[4] = {
53 STATE_OK, 51 STATE_OK,
@@ -56,185 +54,165 @@ static int state[4] = {
56 STATE_UNKNOWN, 54 STATE_UNKNOWN,
57}; 55};
58 56
59int 57int main(int argc, char **argv) {
60main (int argc, char **argv) 58 setlocale(LC_ALL, "");
61{ 59 bindtextdomain(PACKAGE, LOCALEDIR);
62 int result = STATE_UNKNOWN; 60 textdomain(PACKAGE);
63 char *sub;
64 char **command_line;
65 output chld_out, chld_err;
66
67 setlocale (LC_ALL, "");
68 bindtextdomain (PACKAGE, LOCALEDIR);
69 textdomain (PACKAGE);
70 61
71 timeout_interval = DEFAULT_TIMEOUT; 62 timeout_interval = DEFAULT_TIMEOUT;
72 63
73 command_line = (char **) process_arguments (argc, argv); 64 char **command_line = (char **)process_arguments(argc, argv);
74 65
75 /* Set signal handling and alarm */ 66 /* Set signal handling and alarm */
76 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) 67 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR)
77 die (STATE_UNKNOWN, _("Cannot catch SIGALRM")); 68 die(STATE_UNKNOWN, _("Cannot catch SIGALRM"));
78 69
79 (void) alarm ((unsigned) timeout_interval); 70 (void)alarm((unsigned)timeout_interval);
71
72 int result = STATE_UNKNOWN;
73 output chld_out;
74 output chld_err;
80 75
81 /* catch when the command is quoted */ 76 /* catch when the command is quoted */
82 if(command_line[1] == NULL) { 77 if (command_line[1] == NULL) {
83 result = cmd_run (command_line[0], &chld_out, &chld_err, 0); 78 result = cmd_run(command_line[0], &chld_out, &chld_err, 0);
84 } else { 79 } else {
85 result = cmd_run_array (command_line, &chld_out, &chld_err, 0); 80 result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
86 } 81 }
87 if (chld_err.lines > 0) { 82 if (chld_err.lines > 0) {
88 for (size_t i = 0; i < chld_err.lines; i++) { 83 for (size_t i = 0; i < chld_err.lines; i++) {
89 fprintf (stderr, "%s\n", chld_err.line[i]); 84 fprintf(stderr, "%s\n", chld_err.line[i]);
90 } 85 }
91 } 86 }
92 87
93 /* Return UNKNOWN or worse if no output is returned */ 88 /* Return UNKNOWN or worse if no output is returned */
94 if (chld_out.lines == 0) 89 if (chld_out.lines == 0)
95 die (max_state_alt (result, STATE_UNKNOWN), _("No data returned from command\n")); 90 die(max_state_alt(result, STATE_UNKNOWN), _("No data returned from command\n"));
96 91
92 char *sub;
97 for (size_t i = 0; i < chld_out.lines; i++) { 93 for (size_t i = 0; i < chld_out.lines; i++) {
98 if (subst_text && result >= 0 && result <= 4 && result != state[result]) { 94 if (subst_text && result >= 0 && result <= 4 && result != state[result]) {
99 /* Loop over each match found */ 95 /* Loop over each match found */
100 while ((sub = strstr (chld_out.line[i], state_text (result)))) { 96 while ((sub = strstr(chld_out.line[i], state_text(result)))) {
101 /* Terminate the first part and skip over the string we'll substitute */ 97 /* Terminate the first part and skip over the string we'll substitute */
102 *sub = '\0'; 98 *sub = '\0';
103 sub += strlen (state_text (result)); 99 sub += strlen(state_text(result));
104 /* then put everything back together */ 100 /* then put everything back together */
105 xasprintf (&chld_out.line[i], "%s%s%s", chld_out.line[i], state_text (state[result]), sub); 101 xasprintf(&chld_out.line[i], "%s%s%s", chld_out.line[i], state_text(state[result]), sub);
106 } 102 }
107 } 103 }
108 printf ("%s\n", chld_out.line[i]); 104 printf("%s\n", chld_out.line[i]);
109 } 105 }
110 106
111 if (result >= 0 && result <= 4) { 107 if (result >= 0 && result <= 4) {
112 exit (state[result]); 108 exit(state[result]);
113 } else { 109 } else {
114 exit (result); 110 exit(result);
115 } 111 }
116} 112}
117 113
118
119/* process command-line arguments */ 114/* process command-line arguments */
120static const char ** 115static const char **process_arguments(int argc, char **argv) {
121process_arguments (int argc, char **argv) 116 static struct option longopts[] = {{"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'},
122{ 117 {"timeout", required_argument, 0, 't'}, {"timeout-result", required_argument, 0, 'T'},
123 int c; 118 {"ok", required_argument, 0, 'o'}, {"warning", required_argument, 0, 'w'},
119 {"critical", required_argument, 0, 'c'}, {"unknown", required_argument, 0, 'u'},
120 {"substitute", no_argument, 0, 's'}, {0, 0, 0, 0}};
121
124 bool permute = true; 122 bool permute = true;
123 while (true) {
124 int option = 0;
125 int option_char = getopt_long(argc, argv, "+hVt:T:o:w:c:u:s", longopts, &option);
125 126
126 int option = 0; 127 if (option_char == -1 || option_char == EOF)
127 static struct option longopts[] = {
128 {"help", no_argument, 0, 'h'},
129 {"version", no_argument, 0, 'V'},
130 {"timeout", required_argument, 0, 't'},
131 {"timeout-result", required_argument, 0, 'T'},
132 {"ok", required_argument, 0, 'o'},
133 {"warning", required_argument, 0, 'w'},
134 {"critical", required_argument, 0, 'c'},
135 {"unknown", required_argument, 0, 'u'},
136 {"substitute", no_argument, 0, 's'},
137 {0, 0, 0, 0}
138 };
139
140 while (1) {
141 c = getopt_long (argc, argv, "+hVt:T:o:w:c:u:s", longopts, &option);
142
143 if (c == -1 || c == EOF)
144 break; 128 break;
145 129
146 switch (c) { 130 switch (option_char) {
147 case '?': /* help */ 131 case '?': /* help */
148 usage5 (); 132 usage5();
149 break; 133 break;
150 case 'h': /* help */ 134 case 'h': /* help */
151 print_help (); 135 print_help();
152 exit (EXIT_SUCCESS); 136 exit(EXIT_SUCCESS);
153 break; 137 break;
154 case 'V': /* version */ 138 case 'V': /* version */
155 print_revision (progname, NP_VERSION); 139 print_revision(progname, NP_VERSION);
156 exit (EXIT_SUCCESS); 140 exit(EXIT_SUCCESS);
157 case 't': /* timeout period */ 141 case 't': /* timeout period */
158 if (!is_integer (optarg)) 142 if (!is_integer(optarg))
159 usage2 (_("Timeout interval must be a positive integer"), optarg); 143 usage2(_("Timeout interval must be a positive integer"), optarg);
160 else 144 else
161 timeout_interval = atoi (optarg); 145 timeout_interval = atoi(optarg);
162 break; 146 break;
163 case 'T': /* Result to return on timeouts */ 147 case 'T': /* Result to return on timeouts */
164 if ((timeout_state = mp_translate_state(optarg)) == ERROR) 148 if ((timeout_state = mp_translate_state(optarg)) == ERROR)
165 usage4 (_("Timeout result must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 149 usage4(_("Timeout result must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
166 break; 150 break;
167 case 'o': /* replacement for OK */ 151 case 'o': /* replacement for OK */
168 if ((state[STATE_OK] = mp_translate_state(optarg)) == ERROR) 152 if ((state[STATE_OK] = mp_translate_state(optarg)) == ERROR)
169 usage4 (_("Ok must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 153 usage4(_("Ok must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
170 permute = false; 154 permute = false;
171 break; 155 break;
172 156
173 case 'w': /* replacement for WARNING */ 157 case 'w': /* replacement for WARNING */
174 if ((state[STATE_WARNING] = mp_translate_state(optarg)) == ERROR) 158 if ((state[STATE_WARNING] = mp_translate_state(optarg)) == ERROR)
175 usage4 (_("Warning must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 159 usage4(_("Warning must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
176 permute = false; 160 permute = false;
177 break; 161 break;
178 case 'c': /* replacement for CRITICAL */ 162 case 'c': /* replacement for CRITICAL */
179 if ((state[STATE_CRITICAL] = mp_translate_state(optarg)) == ERROR) 163 if ((state[STATE_CRITICAL] = mp_translate_state(optarg)) == ERROR)
180 usage4 (_("Critical must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 164 usage4(_("Critical must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
181 permute = false; 165 permute = false;
182 break; 166 break;
183 case 'u': /* replacement for UNKNOWN */ 167 case 'u': /* replacement for UNKNOWN */
184 if ((state[STATE_UNKNOWN] = mp_translate_state(optarg)) == ERROR) 168 if ((state[STATE_UNKNOWN] = mp_translate_state(optarg)) == ERROR)
185 usage4 (_("Unknown must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 169 usage4(_("Unknown must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
186 permute = false; 170 permute = false;
187 break; 171 break;
188 case 's': /* Substitute status text */ 172 case 's': /* Substitute status text */
189 subst_text = true; 173 subst_text = true;
190 break; 174 break;
191 } 175 }
192 } 176 }
193 177
194 validate_arguments (&argv[optind]); 178 validate_arguments(&argv[optind]);
195 179
196 if (permute) { /* No [owcu] switch specified, default to this */ 180 if (permute) { /* No [owcu] switch specified, default to this */
197 state[STATE_OK] = STATE_CRITICAL; 181 state[STATE_OK] = STATE_CRITICAL;
198 state[STATE_CRITICAL] = STATE_OK; 182 state[STATE_CRITICAL] = STATE_OK;
199 } 183 }
200 184
201 return (const char **) &argv[optind]; 185 return (const char **)&argv[optind];
202} 186}
203 187
204 188void validate_arguments(char **command_line) {
205void
206validate_arguments (char **command_line)
207{
208 if (command_line[0] == NULL) 189 if (command_line[0] == NULL)
209 usage4 (_("Could not parse arguments")); 190 usage4(_("Could not parse arguments"));
210 191
211 if (strncmp(command_line[0],"/",1) != 0 && strncmp(command_line[0],"./",2) != 0) 192 if (strncmp(command_line[0], "/", 1) != 0 && strncmp(command_line[0], "./", 2) != 0)
212 usage4 (_("Require path to command")); 193 usage4(_("Require path to command"));
213} 194}
214 195
196void print_help(void) {
197 print_revision(progname, NP_VERSION);
215 198
216void 199 printf(COPYRIGHT, copyright, email);
217print_help (void)
218{
219 print_revision (progname, NP_VERSION);
220 200
221 printf (COPYRIGHT, copyright, email); 201 printf("%s\n", _("Negates only the return code of a plugin (returns OK for CRITICAL and vice-versa) by default."));
202 printf("%s\n", _("Additional switches can be used to control:\n"));
203 printf("\t - which state becomes what\n");
204 printf("\t - changing the plugin output text to match the return code");
222 205
223 printf ("%s\n", _("Negates only the return code of a plugin (returns OK for CRITICAL and vice-versa) by default.")); 206 printf("\n\n");
224 printf ("%s\n", _("Additional switches can be used to control:\n"));
225 printf ("\t - which state becomes what\n");
226 printf ("\t - changing the plugin output text to match the return code");
227 207
228 printf ("\n\n"); 208 print_usage();
229 209
230 print_usage (); 210 printf(UT_HELP_VRSN);
231 211
232 printf (UT_HELP_VRSN); 212 printf(UT_PLUG_TIMEOUT, timeout_interval);
233 213 printf(" %s\n", _("Keep timeout longer than the plugin timeout to retain CRITICAL status."));
234 printf (UT_PLUG_TIMEOUT, timeout_interval); 214 printf(" -T, --timeout-result=STATUS\n");
235 printf (" %s\n", _("Keep timeout longer than the plugin timeout to retain CRITICAL status.")); 215 printf(" %s\n", _("Custom result on Negate timeouts; see below for STATUS definition\n"));
236 printf (" -T, --timeout-result=STATUS\n");
237 printf (" %s\n", _("Custom result on Negate timeouts; see below for STATUS definition\n"));
238 216
239 printf(" -o, --ok=STATUS\n"); 217 printf(" -o, --ok=STATUS\n");
240 printf(" -w, --warning=STATUS\n"); 218 printf(" -w, --warning=STATUS\n");
@@ -246,31 +224,27 @@ print_help (void)
246 printf(" -s, --substitute\n"); 224 printf(" -s, --substitute\n");
247 printf(_(" Substitute output text as well. Will only substitute text in CAPITALS\n")); 225 printf(_(" Substitute output text as well. Will only substitute text in CAPITALS\n"));
248 226
249 printf ("\n"); 227 printf("\n");
250 printf ("%s\n", _("Examples:")); 228 printf("%s\n", _("Examples:"));
251 printf (" %s\n", "negate /usr/local/nagios/libexec/check_ping -H host"); 229 printf(" %s\n", "negate /usr/local/nagios/libexec/check_ping -H host");
252 printf (" %s\n", _("Run check_ping and invert result. Must use full path to plugin")); 230 printf(" %s\n", _("Run check_ping and invert result. Must use full path to plugin"));
253 printf (" %s\n", "negate -w OK -c UNKNOWN /usr/local/nagios/libexec/check_procs -a 'vi negate.c'"); 231 printf(" %s\n", "negate -w OK -c UNKNOWN /usr/local/nagios/libexec/check_procs -a 'vi negate.c'");
254 printf (" %s\n", _("This will return OK instead of WARNING and UNKNOWN instead of CRITICAL")); 232 printf(" %s\n", _("This will return OK instead of WARNING and UNKNOWN instead of CRITICAL"));
255 printf ("\n"); 233 printf("\n");
256 printf ("%s\n", _("Notes:")); 234 printf("%s\n", _("Notes:"));
257 printf (" %s\n", _("This plugin is a wrapper to take the output of another plugin and invert it.")); 235 printf(" %s\n", _("This plugin is a wrapper to take the output of another plugin and invert it."));
258 printf (" %s\n", _("The full path of the plugin must be provided.")); 236 printf(" %s\n", _("The full path of the plugin must be provided."));
259 printf (" %s\n", _("If the wrapped plugin returns OK, the wrapper will return CRITICAL.")); 237 printf(" %s\n", _("If the wrapped plugin returns OK, the wrapper will return CRITICAL."));
260 printf (" %s\n", _("If the wrapped plugin returns CRITICAL, the wrapper will return OK.")); 238 printf(" %s\n", _("If the wrapped plugin returns CRITICAL, the wrapper will return OK."));
261 printf (" %s\n", _("Otherwise, the output state of the wrapped plugin is unchanged.")); 239 printf(" %s\n", _("Otherwise, the output state of the wrapped plugin is unchanged."));
262 printf ("\n"); 240 printf("\n");
263 printf (" %s\n", _("Using timeout-result, it is possible to override the timeout behaviour or a")); 241 printf(" %s\n", _("Using timeout-result, it is possible to override the timeout behaviour or a"));
264 printf (" %s\n", _("plugin by setting the negate timeout a bit lower.")); 242 printf(" %s\n", _("plugin by setting the negate timeout a bit lower."));
265 243
266 printf (UT_SUPPORT); 244 printf(UT_SUPPORT);
267} 245}
268 246
269 247void print_usage(void) {
270 248 printf("%s\n", _("Usage:"));
271void 249 printf("%s [-t timeout] [-Towcu STATE] [-s] <definition of wrapped plugin>\n", progname);
272print_usage (void)
273{
274 printf ("%s\n", _("Usage:"));
275 printf ("%s [-t timeout] [-Towcu STATE] [-s] <definition of wrapped plugin>\n", progname);
276} 250}
diff --git a/plugins/netutils.c b/plugins/netutils.c
index c6af248e..ee81912a 100644
--- a/plugins/netutils.c
+++ b/plugins/netutils.c
@@ -1,31 +1,31 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins network utilities 3 * Monitoring Plugins network utilities
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) 6 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
7* Copyright (c) 2003-2008 Monitoring Plugins Development Team 7 * Copyright (c) 2003-2024 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains commons functions used in many of the plugins. 11 * This file contains commons functions used in many of the plugins.
12* 12 *
13* 13 *
14* This program is free software: you can redistribute it and/or modify 14 * This program is free software: you can redistribute it and/or modify
15* it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
16* the Free Software Foundation, either version 3 of the License, or 16 * the Free Software Foundation, either version 3 of the License, or
17* (at your option) any later version. 17 * (at your option) any later version.
18* 18 *
19* This program is distributed in the hope that it will be useful, 19 * This program is distributed in the hope that it will be useful,
20* but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22* GNU General Public License for more details. 22 * GNU General Public License for more details.
23* 23 *
24* You should have received a copy of the GNU General Public License 24 * You should have received a copy of the GNU General Public License
25* along with this program. If not, see <http://www.gnu.org/licenses/>. 25 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26* 26 *
27* 27 *
28*****************************************************************************/ 28 *****************************************************************************/
29 29
30#include "common.h" 30#include "common.h"
31#include "netutils.h" 31#include "netutils.h"
@@ -42,25 +42,19 @@ int address_family = AF_INET;
42#endif 42#endif
43 43
44/* handles socket timeouts */ 44/* handles socket timeouts */
45void 45void socket_timeout_alarm_handler(int sig) {
46socket_timeout_alarm_handler (int sig)
47{
48 if (sig == SIGALRM) 46 if (sig == SIGALRM)
49 printf (_("%s - Socket timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout); 47 printf(_("%s - Socket timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout);
50 else 48 else
51 printf (_("%s - Abnormal timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout); 49 printf(_("%s - Abnormal timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout);
52 50
53 exit (socket_timeout_state); 51 exit(socket_timeout_state);
54} 52}
55 53
56
57/* connects to a host on a specified tcp port, sends a string, and gets a 54/* connects to a host on a specified tcp port, sends a string, and gets a
58 response. loops on select-recv until timeout or eof to get all of a 55 response. loops on select-recv until timeout or eof to get all of a
59 multi-packet answer */ 56 multi-packet answer */
60int 57int process_tcp_request2(const char *server_address, int server_port, const char *send_buffer, char *recv_buffer, int recv_size) {
61process_tcp_request2 (const char *server_address, int server_port,
62 const char *send_buffer, char *recv_buffer, int recv_size)
63{
64 58
65 int result; 59 int result;
66 int send_result; 60 int send_result;
@@ -70,13 +64,13 @@ process_tcp_request2 (const char *server_address, int server_port,
70 fd_set readfds; 64 fd_set readfds;
71 int recv_length = 0; 65 int recv_length = 0;
72 66
73 result = np_net_connect (server_address, server_port, &sd, IPPROTO_TCP); 67 result = np_net_connect(server_address, server_port, &sd, IPPROTO_TCP);
74 if (result != STATE_OK) 68 if (result != STATE_OK)
75 return STATE_CRITICAL; 69 return STATE_CRITICAL;
76 70
77 send_result = send (sd, send_buffer, strlen (send_buffer), 0); 71 send_result = send(sd, send_buffer, strlen(send_buffer), 0);
78 if (send_result<0 || (size_t)send_result!=strlen(send_buffer)) { 72 if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) {
79 printf ("%s\n", _("Send failed")); 73 printf("%s\n", _("Send failed"));
80 result = STATE_WARNING; 74 result = STATE_WARNING;
81 } 75 }
82 76
@@ -85,38 +79,32 @@ process_tcp_request2 (const char *server_address, int server_port,
85 minus one for data from the host */ 79 minus one for data from the host */
86 tv.tv_sec = socket_timeout - 1; 80 tv.tv_sec = socket_timeout - 1;
87 tv.tv_usec = 0; 81 tv.tv_usec = 0;
88 FD_ZERO (&readfds); 82 FD_ZERO(&readfds);
89 FD_SET (sd, &readfds); 83 FD_SET(sd, &readfds);
90 select (sd + 1, &readfds, NULL, NULL, &tv); 84 select(sd + 1, &readfds, NULL, NULL, &tv);
91 85
92 /* make sure some data has arrived */ 86 /* make sure some data has arrived */
93 if (!FD_ISSET (sd, &readfds)) { /* it hasn't */ 87 if (!FD_ISSET(sd, &readfds)) { /* it hasn't */
94 if (!recv_length) { 88 if (!recv_length) {
95 strcpy (recv_buffer, ""); 89 strcpy(recv_buffer, "");
96 printf ("%s\n", _("No data was received from host!")); 90 printf("%s\n", _("No data was received from host!"));
97 result = STATE_WARNING; 91 result = STATE_WARNING;
98 } 92 } else { /* this one failed, but previous ones worked */
99 else { /* this one failed, but previous ones worked */
100 recv_buffer[recv_length] = 0; 93 recv_buffer[recv_length] = 0;
101 } 94 }
102 break; 95 break;
103 } 96 } else { /* it has */
104 else { /* it has */ 97 recv_result = recv(sd, recv_buffer + recv_length, (size_t)recv_size - recv_length - 1, 0);
105 recv_result =
106 recv (sd, recv_buffer + recv_length,
107 (size_t)recv_size - recv_length - 1, 0);
108 if (recv_result == -1) { 98 if (recv_result == -1) {
109 /* recv failed, bail out */ 99 /* recv failed, bail out */
110 strcpy (recv_buffer + recv_length, ""); 100 strcpy(recv_buffer + recv_length, "");
111 result = STATE_WARNING; 101 result = STATE_WARNING;
112 break; 102 break;
113 } 103 } else if (recv_result == 0) {
114 else if (recv_result == 0) {
115 /* end of file ? */ 104 /* end of file ? */
116 recv_buffer[recv_length] = 0; 105 recv_buffer[recv_length] = 0;
117 break; 106 break;
118 } 107 } else { /* we got data! */
119 else { /* we got data! */
120 recv_length += recv_result; 108 recv_length += recv_result;
121 if (recv_length >= recv_size - 1) { 109 if (recv_length >= recv_size - 1) {
122 /* buffer full, we're done */ 110 /* buffer full, we're done */
@@ -129,42 +117,35 @@ process_tcp_request2 (const char *server_address, int server_port,
129 } 117 }
130 /* end while(1) */ 118 /* end while(1) */
131 119
132 close (sd); 120 close(sd);
133 return result; 121 return result;
134} 122}
135 123
136
137/* connects to a host on a specified port, sends a string, and gets a 124/* connects to a host on a specified port, sends a string, and gets a
138 response */ 125 response */
139int 126int process_request(const char *server_address, int server_port, int proto, const char *send_buffer, char *recv_buffer, int recv_size) {
140process_request (const char *server_address, int server_port, int proto,
141 const char *send_buffer, char *recv_buffer, int recv_size)
142{
143 int result; 127 int result;
144 int sd; 128 int sd;
145 129
146 result = STATE_OK; 130 result = STATE_OK;
147 131
148 result = np_net_connect (server_address, server_port, &sd, proto); 132 result = np_net_connect(server_address, server_port, &sd, proto);
149 if (result != STATE_OK) 133 if (result != STATE_OK)
150 return STATE_CRITICAL; 134 return STATE_CRITICAL;
151 135
152 result = send_request (sd, proto, send_buffer, recv_buffer, recv_size); 136 result = send_request(sd, proto, send_buffer, recv_buffer, recv_size);
153 137
154 close (sd); 138 close(sd);
155 139
156 return result; 140 return result;
157} 141}
158 142
159
160/* opens a tcp or udp connection to a remote host or local socket */ 143/* opens a tcp or udp connection to a remote host or local socket */
161int 144int np_net_connect(const char *host_name, int port, int *sd, int proto) {
162np_net_connect (const char *host_name, int port, int *sd, int proto) 145 /* send back STATE_UNKOWN if there's an error
163{ 146 send back STATE_OK if we connect
164 /* send back STATE_UNKOWN if there's an error 147 send back STATE_CRITICAL if we can't connect.
165 send back STATE_OK if we connect 148 Let upstream figure out what to send to the user. */
166 send back STATE_CRITICAL if we can't connect.
167 Let upstream figure out what to send to the user. */
168 struct addrinfo hints; 149 struct addrinfo hints;
169 struct addrinfo *r, *res; 150 struct addrinfo *r, *res;
170 struct sockaddr_un su; 151 struct sockaddr_un su;
@@ -176,13 +157,13 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
176 socktype = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; 157 socktype = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
177 158
178 /* as long as it doesn't start with a '/', it's assumed a host or ip */ 159 /* as long as it doesn't start with a '/', it's assumed a host or ip */
179 if (!is_socket){ 160 if (!is_socket) {
180 memset (&hints, 0, sizeof (hints)); 161 memset(&hints, 0, sizeof(hints));
181 hints.ai_family = address_family; 162 hints.ai_family = address_family;
182 hints.ai_protocol = proto; 163 hints.ai_protocol = proto;
183 hints.ai_socktype = socktype; 164 hints.ai_socktype = socktype;
184 165
185 len = strlen (host_name); 166 len = strlen(host_name);
186 /* check for an [IPv6] address (and strip the brackets) */ 167 /* check for an [IPv6] address (and strip the brackets) */
187 if (len >= 2 && host_name[0] == '[' && host_name[len - 1] == ']') { 168 if (len >= 2 && host_name[0] == '[' && host_name[len - 1] == ']') {
188 host_name++; 169 host_name++;
@@ -190,29 +171,29 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
190 } 171 }
191 if (len >= sizeof(host)) 172 if (len >= sizeof(host))
192 return STATE_UNKNOWN; 173 return STATE_UNKNOWN;
193 memcpy (host, host_name, len); 174 memcpy(host, host_name, len);
194 host[len] = '\0'; 175 host[len] = '\0';
195 snprintf (port_str, sizeof (port_str), "%d", port); 176 snprintf(port_str, sizeof(port_str), "%d", port);
196 result = getaddrinfo (host, port_str, &hints, &res); 177 result = getaddrinfo(host, port_str, &hints, &res);
197 178
198 if (result != 0) { 179 if (result != 0) {
199 printf ("%s\n", gai_strerror (result)); 180 printf("%s\n", gai_strerror(result));
200 return STATE_UNKNOWN; 181 return STATE_UNKNOWN;
201 } 182 }
202 183
203 r = res; 184 r = res;
204 while (r) { 185 while (r) {
205 /* attempt to create a socket */ 186 /* attempt to create a socket */
206 *sd = socket (r->ai_family, socktype, r->ai_protocol); 187 *sd = socket(r->ai_family, socktype, r->ai_protocol);
207 188
208 if (*sd < 0) { 189 if (*sd < 0) {
209 printf ("%s\n", _("Socket creation failed")); 190 printf("%s\n", _("Socket creation failed"));
210 freeaddrinfo (r); 191 freeaddrinfo(r);
211 return STATE_UNKNOWN; 192 return STATE_UNKNOWN;
212 } 193 }
213 194
214 /* attempt to open a connection */ 195 /* attempt to open a connection */
215 result = connect (*sd, r->ai_addr, r->ai_addrlen); 196 result = connect(*sd, r->ai_addr, r->ai_addrlen);
216 197
217 if (result == 0) { 198 if (result == 0) {
218 was_refused = false; 199 was_refused = false;
@@ -227,21 +208,21 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
227 } 208 }
228 } 209 }
229 210
230 close (*sd); 211 close(*sd);
231 r = r->ai_next; 212 r = r->ai_next;
232 } 213 }
233 freeaddrinfo (res); 214 freeaddrinfo(res);
234 } 215 }
235 /* else the hostname is interpreted as a path to a unix socket */ 216 /* else the hostname is interpreted as a path to a unix socket */
236 else { 217 else {
237 if(strlen(host_name) >= UNIX_PATH_MAX){ 218 if (strlen(host_name) >= UNIX_PATH_MAX) {
238 die(STATE_UNKNOWN, _("Supplied path too long unix domain socket")); 219 die(STATE_UNKNOWN, _("Supplied path too long unix domain socket"));
239 } 220 }
240 memset(&su, 0, sizeof(su)); 221 memset(&su, 0, sizeof(su));
241 su.sun_family = AF_UNIX; 222 su.sun_family = AF_UNIX;
242 strncpy(su.sun_path, host_name, UNIX_PATH_MAX); 223 strncpy(su.sun_path, host_name, UNIX_PATH_MAX);
243 *sd = socket(PF_UNIX, SOCK_STREAM, 0); 224 *sd = socket(PF_UNIX, SOCK_STREAM, 0);
244 if(*sd < 0){ 225 if (*sd < 0) {
245 die(STATE_UNKNOWN, _("Socket creation failed")); 226 die(STATE_UNKNOWN, _("Socket creation failed"));
246 } 227 }
247 result = connect(*sd, (struct sockaddr *)&su, sizeof(su)); 228 result = connect(*sd, (struct sockaddr *)&su, sizeof(su));
@@ -259,37 +240,32 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
259 if (is_socket) 240 if (is_socket)
260 printf("connect to file socket %s: %s\n", host_name, strerror(errno)); 241 printf("connect to file socket %s: %s\n", host_name, strerror(errno));
261 else 242 else
262 printf("connect to address %s and port %d: %s\n", 243 printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno));
263 host_name, port, strerror(errno));
264 return STATE_CRITICAL; 244 return STATE_CRITICAL;
265 break; 245 break;
266 default: /* it's a logic error if we do not end up in STATE_(OK|WARNING|CRITICAL) */ 246 default: /* it's a logic error if we do not end up in STATE_(OK|WARNING|CRITICAL) */
267 return STATE_UNKNOWN; 247 return STATE_UNKNOWN;
268 break; 248 break;
269 } 249 }
270 } 250 } else {
271 else {
272 if (is_socket) 251 if (is_socket)
273 printf("connect to file socket %s: %s\n", host_name, strerror(errno)); 252 printf("connect to file socket %s: %s\n", host_name, strerror(errno));
274 else 253 else
275 printf("connect to address %s and port %d: %s\n", 254 printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno));
276 host_name, port, strerror(errno));
277 return STATE_CRITICAL; 255 return STATE_CRITICAL;
278 } 256 }
279} 257}
280 258
281int 259int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer, int recv_size) {
282send_request (int sd, int proto, const char *send_buffer, char *recv_buffer, int recv_size)
283{
284 int result = STATE_OK; 260 int result = STATE_OK;
285 int send_result; 261 int send_result;
286 int recv_result; 262 int recv_result;
287 struct timeval tv; 263 struct timeval tv;
288 fd_set readfds; 264 fd_set readfds;
289 265
290 send_result = send (sd, send_buffer, strlen (send_buffer), 0); 266 send_result = send(sd, send_buffer, strlen(send_buffer), 0);
291 if (send_result<0 || (size_t)send_result!=strlen(send_buffer)) { 267 if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) {
292 printf ("%s\n", _("Send failed")); 268 printf("%s\n", _("Send failed"));
293 result = STATE_WARNING; 269 result = STATE_WARNING;
294 } 270 }
295 271
@@ -297,26 +273,25 @@ send_request (int sd, int proto, const char *send_buffer, char *recv_buffer, int
297 for data from the host */ 273 for data from the host */
298 tv.tv_sec = socket_timeout - 1; 274 tv.tv_sec = socket_timeout - 1;
299 tv.tv_usec = 0; 275 tv.tv_usec = 0;
300 FD_ZERO (&readfds); 276 FD_ZERO(&readfds);
301 FD_SET (sd, &readfds); 277 FD_SET(sd, &readfds);
302 select (sd + 1, &readfds, NULL, NULL, &tv); 278 select(sd + 1, &readfds, NULL, NULL, &tv);
303 279
304 /* make sure some data has arrived */ 280 /* make sure some data has arrived */
305 if (!FD_ISSET (sd, &readfds)) { 281 if (!FD_ISSET(sd, &readfds)) {
306 strcpy (recv_buffer, ""); 282 strcpy(recv_buffer, "");
307 printf ("%s\n", _("No data was received from host!")); 283 printf("%s\n", _("No data was received from host!"));
308 result = STATE_WARNING; 284 result = STATE_WARNING;
309 } 285 }
310 286
311 else { 287 else {
312 recv_result = recv (sd, recv_buffer, (size_t)recv_size - 1, 0); 288 recv_result = recv(sd, recv_buffer, (size_t)recv_size - 1, 0);
313 if (recv_result == -1) { 289 if (recv_result == -1) {
314 strcpy (recv_buffer, ""); 290 strcpy(recv_buffer, "");
315 if (proto != IPPROTO_TCP) 291 if (proto != IPPROTO_TCP)
316 printf ("%s\n", _("Receive failed")); 292 printf("%s\n", _("Receive failed"));
317 result = STATE_WARNING; 293 result = STATE_WARNING;
318 } 294 } else
319 else
320 recv_buffer[recv_result] = 0; 295 recv_buffer[recv_result] = 0;
321 296
322 /* die returned string */ 297 /* die returned string */
@@ -325,51 +300,46 @@ send_request (int sd, int proto, const char *send_buffer, char *recv_buffer, int
325 return result; 300 return result;
326} 301}
327 302
328 303bool is_host(const char *address) {
329bool is_host (const char *address) { 304 if (is_addr(address) || is_hostname(address))
330 if (is_addr (address) || is_hostname (address))
331 return (true); 305 return (true);
332 306
333 return (false); 307 return (false);
334} 308}
335 309
336void 310void host_or_die(const char *str) {
337host_or_die(const char *str) 311 if (!str || (!is_addr(str) && !is_hostname(str)))
338{
339 if(!str || (!is_addr(str) && !is_hostname(str)))
340 usage_va(_("Invalid hostname/address - %s"), str); 312 usage_va(_("Invalid hostname/address - %s"), str);
341} 313}
342 314
343bool is_addr (const char *address) { 315bool is_addr(const char *address) {
344#ifdef USE_IPV6 316#ifdef USE_IPV6
345 if (address_family == AF_INET && is_inet_addr (address)) 317 if (address_family == AF_INET && is_inet_addr(address))
346 return true; 318 return true;
347 else if (address_family == AF_INET6 && is_inet6_addr (address)) 319 else if (address_family == AF_INET6 && is_inet6_addr(address))
348 return true; 320 return true;
349#else 321#else
350 if (is_inet_addr (address)) 322 if (is_inet_addr(address))
351 return (true); 323 return (true);
352#endif 324#endif
353 325
354 return (false); 326 return (false);
355} 327}
356 328
357int 329int dns_lookup(const char *in, struct sockaddr_storage *ss, int family) {
358dns_lookup (const char *in, struct sockaddr_storage *ss, int family)
359{
360 struct addrinfo hints; 330 struct addrinfo hints;
361 struct addrinfo *res; 331 struct addrinfo *res;
362 int retval; 332 int retval;
363 333
364 memset (&hints, 0, sizeof(struct addrinfo)); 334 memset(&hints, 0, sizeof(struct addrinfo));
365 hints.ai_family = family; 335 hints.ai_family = family;
366 336
367 retval = getaddrinfo (in, NULL, &hints, &res); 337 retval = getaddrinfo(in, NULL, &hints, &res);
368 if (retval != 0) 338 if (retval != 0)
369 return false; 339 return false;
370 340
371 if (ss != NULL) 341 if (ss != NULL)
372 memcpy (ss, res->ai_addr, res->ai_addrlen); 342 memcpy(ss, res->ai_addr, res->ai_addrlen);
373 freeaddrinfo (res); 343 freeaddrinfo(res);
374 return true; 344 return true;
375} 345}
diff --git a/plugins/picohttpparser/picohttpparser.c b/plugins/picohttpparser/picohttpparser.c
index d0bfac62..2ae92d66 100644
--- a/plugins/picohttpparser/picohttpparser.c
+++ b/plugins/picohttpparser/picohttpparser.c
@@ -28,623 +28,610 @@
28#include <stddef.h> 28#include <stddef.h>
29#include <string.h> 29#include <string.h>
30#ifdef __SSE4_2__ 30#ifdef __SSE4_2__
31#ifdef _MSC_VER 31# ifdef _MSC_VER
32#include <nmmintrin.h> 32# include <nmmintrin.h>
33#else 33# else
34#include <x86intrin.h> 34# include <x86intrin.h>
35#endif 35# endif
36#endif 36#endif
37#include "picohttpparser.h" 37#include "picohttpparser.h"
38 38
39#if __GNUC__ >= 3 39#if __GNUC__ >= 3
40#define likely(x) __builtin_expect(!!(x), 1) 40# define likely(x) __builtin_expect(!!(x), 1)
41#define unlikely(x) __builtin_expect(!!(x), 0) 41# define unlikely(x) __builtin_expect(!!(x), 0)
42#else 42#else
43#define likely(x) (x) 43# define likely(x) (x)
44#define unlikely(x) (x) 44# define unlikely(x) (x)
45#endif 45#endif
46 46
47#ifdef _MSC_VER 47#ifdef _MSC_VER
48#define ALIGNED(n) _declspec(align(n)) 48# define ALIGNED(n) _declspec(align(n))
49#else 49#else
50#define ALIGNED(n) __attribute__((aligned(n))) 50# define ALIGNED(n) __attribute__((aligned(n)))
51#endif 51#endif
52 52
53#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c)-040u < 0137u) 53#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c)-040u < 0137u)
54 54
55#define CHECK_EOF() \ 55#define CHECK_EOF() \
56 if (buf == buf_end) { \ 56 if (buf == buf_end) { \
57 *ret = -2; \ 57 *ret = -2; \
58 return NULL; \ 58 return NULL; \
59 } 59 }
60 60
61#define EXPECT_CHAR_NO_CHECK(ch) \ 61#define EXPECT_CHAR_NO_CHECK(ch) \
62 if (*buf++ != ch) { \ 62 if (*buf++ != ch) { \
63 *ret = -1; \ 63 *ret = -1; \
64 return NULL; \ 64 return NULL; \
65 } 65 }
66 66
67#define EXPECT_CHAR(ch) \ 67#define EXPECT_CHAR(ch) \
68 CHECK_EOF(); \ 68 CHECK_EOF(); \
69 EXPECT_CHAR_NO_CHECK(ch); 69 EXPECT_CHAR_NO_CHECK(ch);
70 70
71#define ADVANCE_TOKEN(tok, toklen) \ 71#define ADVANCE_TOKEN(tok, toklen) \
72 do { \ 72 do { \
73 const char *tok_start = buf; \ 73 const char *tok_start = buf; \
74 static const char ALIGNED(16) ranges2[16] = "\000\040\177\177"; \ 74 static const char ALIGNED(16) ranges2[16] = "\000\040\177\177"; \
75 int found2; \ 75 int found2; \
76 buf = findchar_fast(buf, buf_end, ranges2, 4, &found2); \ 76 buf = findchar_fast(buf, buf_end, ranges2, 4, &found2); \
77 if (!found2) { \ 77 if (!found2) { \
78 CHECK_EOF(); \ 78 CHECK_EOF(); \
79 } \ 79 } \
80 while (1) { \ 80 while (1) { \
81 if (*buf == ' ') { \ 81 if (*buf == ' ') { \
82 break; \ 82 break; \
83 } else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \ 83 } else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \
84 if ((unsigned char)*buf < '\040' || *buf == '\177') { \ 84 if ((unsigned char)*buf < '\040' || *buf == '\177') { \
85 *ret = -1; \ 85 *ret = -1; \
86 return NULL; \ 86 return NULL; \
87 } \ 87 } \
88 } \ 88 } \
89 ++buf; \ 89 ++buf; \
90 CHECK_EOF(); \ 90 CHECK_EOF(); \
91 } \ 91 } \
92 tok = tok_start; \ 92 tok = tok_start; \
93 toklen = buf - tok_start; \ 93 toklen = buf - tok_start; \
94 } while (0) 94 } while (0)
95 95
96static const char *token_char_map = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 96static const char *token_char_map = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
97 "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0" 97 "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0"
98 "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1" 98 "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1"
99 "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0" 99 "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0"
100 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 100 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
101 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 101 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
102 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 102 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
103 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 103 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
104 104
105static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found) 105static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found) {
106{ 106 *found = 0;
107 *found = 0;
108#if __SSE4_2__ 107#if __SSE4_2__
109 if (likely(buf_end - buf >= 16)) { 108 if (likely(buf_end - buf >= 16)) {
110 __m128i ranges16 = _mm_loadu_si128((const __m128i *)ranges); 109 __m128i ranges16 = _mm_loadu_si128((const __m128i *)ranges);
111 110
112 size_t left = (buf_end - buf) & ~15; 111 size_t left = (buf_end - buf) & ~15;
113 do { 112 do {
114 __m128i b16 = _mm_loadu_si128((const __m128i *)buf); 113 __m128i b16 = _mm_loadu_si128((const __m128i *)buf);
115 int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS); 114 int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS);
116 if (unlikely(r != 16)) { 115 if (unlikely(r != 16)) {
117 buf += r; 116 buf += r;
118 *found = 1; 117 *found = 1;
119 break; 118 break;
120 } 119 }
121 buf += 16; 120 buf += 16;
122 left -= 16; 121 left -= 16;
123 } while (likely(left != 0)); 122 } while (likely(left != 0));
124 } 123 }
125#else 124#else
126 /* suppress unused parameter warning */ 125 /* suppress unused parameter warning */
127 (void)buf_end; 126 (void)buf_end;
128 (void)ranges; 127 (void)ranges;
129 (void)ranges_size; 128 (void)ranges_size;
130#endif 129#endif
131 return buf; 130 return buf;
132} 131}
133 132
134static const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token, size_t *token_len, int *ret) 133static const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token, size_t *token_len, int *ret) {
135{ 134 const char *token_start = buf;
136 const char *token_start = buf;
137 135
138#ifdef __SSE4_2__ 136#ifdef __SSE4_2__
139 static const char ALIGNED(16) ranges1[16] = "\0\010" /* allow HT */ 137 static const char ALIGNED(16) ranges1[16] = "\0\010" /* allow HT */
140 "\012\037" /* allow SP and up to but not including DEL */ 138 "\012\037" /* allow SP and up to but not including DEL */
141 "\177\177"; /* allow chars w. MSB set */ 139 "\177\177"; /* allow chars w. MSB set */
142 int found; 140 int found;
143 buf = findchar_fast(buf, buf_end, ranges1, 6, &found); 141 buf = findchar_fast(buf, buf_end, ranges1, 6, &found);
144 if (found) 142 if (found)
145 goto FOUND_CTL; 143 goto FOUND_CTL;
146#else 144#else
147 /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */ 145 /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */
148 while (likely(buf_end - buf >= 8)) { 146 while (likely(buf_end - buf >= 8)) {
149#define DOIT() \ 147# define DOIT() \
150 do { \ 148 do { \
151 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \ 149 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \
152 goto NonPrintable; \ 150 goto NonPrintable; \
153 ++buf; \ 151 ++buf; \
154 } while (0) 152 } while (0)
155 DOIT(); 153 DOIT();
156 DOIT(); 154 DOIT();
157 DOIT(); 155 DOIT();
158 DOIT(); 156 DOIT();
159 DOIT(); 157 DOIT();
160 DOIT(); 158 DOIT();
161 DOIT(); 159 DOIT();
162 DOIT(); 160 DOIT();
163#undef DOIT 161# undef DOIT
164 continue; 162 continue;
165 NonPrintable: 163 NonPrintable:
166 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) { 164 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) {
167 goto FOUND_CTL; 165 goto FOUND_CTL;
168 } 166 }
169 ++buf; 167 ++buf;
170 } 168 }
171#endif 169#endif
172 for (;; ++buf) { 170 for (;; ++buf) {
173 CHECK_EOF(); 171 CHECK_EOF();
174 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { 172 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) {
175 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) { 173 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) {
176 goto FOUND_CTL; 174 goto FOUND_CTL;
177 } 175 }
178 } 176 }
179 } 177 }
180FOUND_CTL: 178FOUND_CTL:
181 if (likely(*buf == '\015')) { 179 if (likely(*buf == '\015')) {
182 ++buf; 180 ++buf;
183 EXPECT_CHAR('\012'); 181 EXPECT_CHAR('\012');
184 *token_len = buf - 2 - token_start; 182 *token_len = buf - 2 - token_start;
185 } else if (*buf == '\012') { 183 } else if (*buf == '\012') {
186 *token_len = buf - token_start; 184 *token_len = buf - token_start;
187 ++buf; 185 ++buf;
188 } else { 186 } else {
189 *ret = -1; 187 *ret = -1;
190 return NULL; 188 return NULL;
191 } 189 }
192 *token = token_start; 190 *token = token_start;
193 191
194 return buf; 192 return buf;
195} 193}
196 194
197static const char *is_complete(const char *buf, const char *buf_end, size_t last_len, int *ret) 195static const char *is_complete(const char *buf, const char *buf_end, size_t last_len, int *ret) {
198{ 196 int ret_cnt = 0;
199 int ret_cnt = 0; 197 buf = last_len < 3 ? buf : buf + last_len - 3;
200 buf = last_len < 3 ? buf : buf + last_len - 3; 198
201 199 while (1) {
202 while (1) { 200 CHECK_EOF();
203 CHECK_EOF(); 201 if (*buf == '\015') {
204 if (*buf == '\015') { 202 ++buf;
205 ++buf; 203 CHECK_EOF();
206 CHECK_EOF(); 204 EXPECT_CHAR('\012');
207 EXPECT_CHAR('\012'); 205 ++ret_cnt;
208 ++ret_cnt; 206 } else if (*buf == '\012') {
209 } else if (*buf == '\012') { 207 ++buf;
210 ++buf; 208 ++ret_cnt;
211 ++ret_cnt; 209 } else {
212 } else { 210 ++buf;
213 ++buf; 211 ret_cnt = 0;
214 ret_cnt = 0; 212 }
215 } 213 if (ret_cnt == 2) {
216 if (ret_cnt == 2) { 214 return buf;
217 return buf; 215 }
218 } 216 }
219 } 217
220 218 *ret = -2;
221 *ret = -2; 219 return NULL;
222 return NULL;
223} 220}
224 221
225#define PARSE_INT(valp_, mul_) \ 222#define PARSE_INT(valp_, mul_) \
226 if (*buf < '0' || '9' < *buf) { \ 223 if (*buf < '0' || '9' < *buf) { \
227 buf++; \ 224 buf++; \
228 *ret = -1; \ 225 *ret = -1; \
229 return NULL; \ 226 return NULL; \
230 } \ 227 } \
231 *(valp_) = (mul_) * (*buf++ - '0'); 228 *(valp_) = (mul_) * (*buf++ - '0');
232 229
233#define PARSE_INT_3(valp_) \ 230#define PARSE_INT_3(valp_) \
234 do { \ 231 do { \
235 int res_ = 0; \ 232 int res_ = 0; \
236 PARSE_INT(&res_, 100) \ 233 PARSE_INT(&res_, 100) \
237 *valp_ = res_; \ 234 *valp_ = res_; \
238 PARSE_INT(&res_, 10) \ 235 PARSE_INT(&res_, 10) \
239 *valp_ += res_; \ 236 *valp_ += res_; \
240 PARSE_INT(&res_, 1) \ 237 PARSE_INT(&res_, 1) \
241 *valp_ += res_; \ 238 *valp_ += res_; \
242 } while (0) 239 } while (0)
243 240
244/* returned pointer is always within [buf, buf_end), or null */ 241/* returned pointer is always within [buf, buf_end), or null */
245static const char *parse_http_version(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *ret) 242static const char *parse_http_version(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *ret) {
246{ 243 /* we want at least [HTTP/1.<two chars>] to try to parse */
247 /* we want at least [HTTP/1.<two chars>] to try to parse */ 244 if (buf_end - buf < 9) {
248 if (buf_end - buf < 9) { 245 *ret = -2;
249 *ret = -2; 246 return NULL;
250 return NULL; 247 }
251 } 248 EXPECT_CHAR_NO_CHECK('H');
252 EXPECT_CHAR_NO_CHECK('H'); 249 EXPECT_CHAR_NO_CHECK('T');
253 EXPECT_CHAR_NO_CHECK('T'); 250 EXPECT_CHAR_NO_CHECK('T');
254 EXPECT_CHAR_NO_CHECK('T'); 251 EXPECT_CHAR_NO_CHECK('P');
255 EXPECT_CHAR_NO_CHECK('P'); 252 EXPECT_CHAR_NO_CHECK('/');
256 EXPECT_CHAR_NO_CHECK('/'); 253 PARSE_INT(major_version, 1);
257 PARSE_INT(major_version, 1); 254 if (*major_version == 1) {
258 if (*major_version == 1) { 255 EXPECT_CHAR_NO_CHECK('.');
259 EXPECT_CHAR_NO_CHECK('.'); 256 PARSE_INT(minor_version, 1);
260 PARSE_INT(minor_version, 1); 257 } else {
261 } else { 258 *minor_version = 0;
262 *minor_version = 0; 259 }
263 } 260 return buf;
264 return buf;
265} 261}
266 262
267static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers, 263static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers, size_t max_headers,
268 size_t max_headers, int *ret) 264 int *ret) {
269{ 265 for (;; ++*num_headers) {
270 for (;; ++*num_headers) { 266 CHECK_EOF();
271 CHECK_EOF(); 267 if (*buf == '\015') {
272 if (*buf == '\015') { 268 ++buf;
273 ++buf; 269 EXPECT_CHAR('\012');
274 EXPECT_CHAR('\012'); 270 break;
275 break; 271 } else if (*buf == '\012') {
276 } else if (*buf == '\012') { 272 ++buf;
277 ++buf; 273 break;
278 break; 274 }
279 } 275 if (*num_headers == max_headers) {
280 if (*num_headers == max_headers) { 276 *ret = -1;
281 *ret = -1; 277 return NULL;
282 return NULL; 278 }
283 } 279 if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\t'))) {
284 if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\t'))) { 280 /* parsing name, but do not discard SP before colon, see
285 /* parsing name, but do not discard SP before colon, see 281 * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */
286 * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */ 282 headers[*num_headers].name = buf;
287 headers[*num_headers].name = buf; 283 static const char ALIGNED(16) ranges1[] = "\x00 " /* control chars and up to SP */
288 static const char ALIGNED(16) ranges1[] = "\x00 " /* control chars and up to SP */ 284 "\"\"" /* 0x22 */
289 "\"\"" /* 0x22 */ 285 "()" /* 0x28,0x29 */
290 "()" /* 0x28,0x29 */ 286 ",," /* 0x2c */
291 ",," /* 0x2c */ 287 "//" /* 0x2f */
292 "//" /* 0x2f */ 288 ":@" /* 0x3a-0x40 */
293 ":@" /* 0x3a-0x40 */ 289 "[]" /* 0x5b-0x5d */
294 "[]" /* 0x5b-0x5d */ 290 "{\377"; /* 0x7b-0xff */
295 "{\377"; /* 0x7b-0xff */ 291 int found;
296 int found; 292 buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found);
297 buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found); 293 if (!found) {
298 if (!found) { 294 CHECK_EOF();
299 CHECK_EOF(); 295 }
300 } 296 while (1) {
301 while (1) { 297 if (*buf == ':') {
302 if (*buf == ':') { 298 break;
303 break; 299 } else if (!token_char_map[(unsigned char)*buf]) {
304 } else if (!token_char_map[(unsigned char)*buf]) { 300 *ret = -1;
305 *ret = -1; 301 return NULL;
306 return NULL; 302 }
307 } 303 ++buf;
308 ++buf; 304 CHECK_EOF();
309 CHECK_EOF(); 305 }
310 } 306 if ((headers[*num_headers].name_len = buf - headers[*num_headers].name) == 0) {
311 if ((headers[*num_headers].name_len = buf - headers[*num_headers].name) == 0) { 307 *ret = -1;
312 *ret = -1; 308 return NULL;
313 return NULL; 309 }
314 } 310 ++buf;
315 ++buf; 311 for (;; ++buf) {
316 for (;; ++buf) { 312 CHECK_EOF();
317 CHECK_EOF(); 313 if (!(*buf == ' ' || *buf == '\t')) {
318 if (!(*buf == ' ' || *buf == '\t')) { 314 break;
319 break; 315 }
320 } 316 }
321 } 317 } else {
322 } else { 318 headers[*num_headers].name = NULL;
323 headers[*num_headers].name = NULL; 319 headers[*num_headers].name_len = 0;
324 headers[*num_headers].name_len = 0; 320 }
325 } 321 const char *value;
326 const char *value; 322 size_t value_len;
327 size_t value_len; 323 if ((buf = get_token_to_eol(buf, buf_end, &value, &value_len, ret)) == NULL) {
328 if ((buf = get_token_to_eol(buf, buf_end, &value, &value_len, ret)) == NULL) { 324 return NULL;
329 return NULL; 325 }
330 } 326 /* remove trailing SPs and HTABs */
331 /* remove trailing SPs and HTABs */ 327 const char *value_end = value + value_len;
332 const char *value_end = value + value_len; 328 for (; value_end != value; --value_end) {
333 for (; value_end != value; --value_end) { 329 const char c = *(value_end - 1);
334 const char c = *(value_end - 1); 330 if (!(c == ' ' || c == '\t')) {
335 if (!(c == ' ' || c == '\t')) { 331 break;
336 break; 332 }
337 } 333 }
338 } 334 headers[*num_headers].value = value;
339 headers[*num_headers].value = value; 335 headers[*num_headers].value_len = value_end - value;
340 headers[*num_headers].value_len = value_end - value; 336 }
341 } 337 return buf;
342 return buf;
343} 338}
344 339
345static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path, 340static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path,
346 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, 341 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers,
347 size_t max_headers, int *ret) 342 size_t max_headers, int *ret) {
348{ 343 /* skip first empty line (some clients add CRLF after POST content) */
349 /* skip first empty line (some clients add CRLF after POST content) */ 344 CHECK_EOF();
350 CHECK_EOF(); 345 if (*buf == '\015') {
351 if (*buf == '\015') { 346 ++buf;
352 ++buf; 347 EXPECT_CHAR('\012');
353 EXPECT_CHAR('\012'); 348 } else if (*buf == '\012') {
354 } else if (*buf == '\012') { 349 ++buf;
355 ++buf; 350 }
356 } 351
357 352 /* parse request line */
358 /* parse request line */ 353 ADVANCE_TOKEN(*method, *method_len);
359 ADVANCE_TOKEN(*method, *method_len); 354 do {
360 do { 355 ++buf;
361 ++buf; 356 } while (*buf == ' ');
362 } while (*buf == ' '); 357 ADVANCE_TOKEN(*path, *path_len);
363 ADVANCE_TOKEN(*path, *path_len); 358 do {
364 do { 359 ++buf;
365 ++buf; 360 } while (*buf == ' ');
366 } while (*buf == ' '); 361 if (*method_len == 0 || *path_len == 0) {
367 if (*method_len == 0 || *path_len == 0) { 362 *ret = -1;
368 *ret = -1; 363 return NULL;
369 return NULL; 364 }
370 } 365 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) {
371 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) { 366 return NULL;
372 return NULL; 367 }
373 } 368 if (*buf == '\015') {
374 if (*buf == '\015') { 369 ++buf;
375 ++buf; 370 EXPECT_CHAR('\012');
376 EXPECT_CHAR('\012'); 371 } else if (*buf == '\012') {
377 } else if (*buf == '\012') { 372 ++buf;
378 ++buf; 373 } else {
379 } else { 374 *ret = -1;
380 *ret = -1; 375 return NULL;
381 return NULL; 376 }
382 } 377
383 378 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
384 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
385} 379}
386 380
387int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path, 381int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
388 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len) 382 int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len) {
389{ 383 const char *buf = buf_start, *buf_end = buf_start + len;
390 const char *buf = buf_start, *buf_end = buf_start + len; 384 size_t max_headers = *num_headers;
391 size_t max_headers = *num_headers; 385 int r;
392 int r; 386
393 387 *method = NULL;
394 *method = NULL; 388 *method_len = 0;
395 *method_len = 0; 389 *path = NULL;
396 *path = NULL; 390 *path_len = 0;
397 *path_len = 0; 391 *major_version = -1;
398 *major_version = -1; 392 *minor_version = -1;
399 *minor_version = -1; 393 *num_headers = 0;
400 *num_headers = 0; 394
401 395 /* if last_len != 0, check if the request is complete (a fast countermeasure
402 /* if last_len != 0, check if the request is complete (a fast countermeasure 396 against slowloris */
403 against slowloris */ 397 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
404 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) { 398 return r;
405 return r; 399 }
406 } 400
407 401 if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, major_version, minor_version, headers, num_headers,
408 if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, major_version, minor_version, headers, num_headers, max_headers, 402 max_headers, &r)) == NULL) {
409 &r)) == NULL) { 403 return r;
410 return r; 404 }
411 } 405
412 406 return (int)(buf - buf_start);
413 return (int)(buf - buf_start);
414} 407}
415 408
416static const char *parse_response(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *status, const char **msg, 409static const char *parse_response(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *status,
417 size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret) 410 const char **msg, size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers,
418{ 411 int *ret) {
419 /* parse "HTTP/1.x" */ 412 /* parse "HTTP/1.x" */
420 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) { 413 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) {
421 return NULL; 414 return NULL;
422 } 415 }
423 /* skip space */ 416 /* skip space */
424 if (*buf != ' ') { 417 if (*buf != ' ') {
425 *ret = -1; 418 *ret = -1;
426 return NULL; 419 return NULL;
427 } 420 }
428 do { 421 do {
429 ++buf; 422 ++buf;
430 } while (*buf == ' '); 423 } while (*buf == ' ');
431 /* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse */ 424 /* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse */
432 if (buf_end - buf < 4) { 425 if (buf_end - buf < 4) {
433 *ret = -2; 426 *ret = -2;
434 return NULL; 427 return NULL;
435 } 428 }
436 PARSE_INT_3(status); 429 PARSE_INT_3(status);
437 430
438 /* get message including preceding space */ 431 /* get message including preceding space */
439 if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) { 432 if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) {
440 return NULL; 433 return NULL;
441 } 434 }
442 if (*msg_len == 0) { 435 if (*msg_len == 0) {
443 /* ok */ 436 /* ok */
444 } else if (**msg == ' ') { 437 } else if (**msg == ' ') {
445 /* remove preceding space */ 438 /* remove preceding space */
446 do { 439 do {
447 ++*msg; 440 ++*msg;
448 --*msg_len; 441 --*msg_len;
449 } while (**msg == ' '); 442 } while (**msg == ' ');
450 } else { 443 } else {
451 /* garbage found after status code */ 444 /* garbage found after status code */
452 *ret = -1; 445 *ret = -1;
453 return NULL; 446 return NULL;
454 } 447 }
455 448
456 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret); 449 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
457} 450}
458 451
459int phr_parse_response(const char *buf_start, size_t len, int *major_version, int *minor_version, int *status, const char **msg, size_t *msg_len, 452int phr_parse_response(const char *buf_start, size_t len, int *major_version, int *minor_version, int *status, const char **msg,
460 struct phr_header *headers, size_t *num_headers, size_t last_len) 453 size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t last_len) {
461{ 454 const char *buf = buf_start, *buf_end = buf + len;
462 const char *buf = buf_start, *buf_end = buf + len; 455 size_t max_headers = *num_headers;
463 size_t max_headers = *num_headers; 456 int r;
464 int r; 457
465 458 *major_version = -1;
466 *major_version = -1; 459 *minor_version = -1;
467 *minor_version = -1; 460 *status = 0;
468 *status = 0; 461 *msg = NULL;
469 *msg = NULL; 462 *msg_len = 0;
470 *msg_len = 0; 463 *num_headers = 0;
471 *num_headers = 0; 464
472 465 /* if last_len != 0, check if the response is complete (a fast countermeasure
473 /* if last_len != 0, check if the response is complete (a fast countermeasure 466 against slowloris */
474 against slowloris */ 467 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
475 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) { 468 return r;
476 return r; 469 }
477 } 470
478 471 if ((buf = parse_response(buf, buf_end, major_version, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) ==
479 if ((buf = parse_response(buf, buf_end, major_version, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) == NULL) { 472 NULL) {
480 return r; 473 return r;
481 } 474 }
482 475
483 return (int)(buf - buf_start); 476 return (int)(buf - buf_start);
484} 477}
485 478
486int phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len) 479int phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len) {
487{ 480 const char *buf = buf_start, *buf_end = buf + len;
488 const char *buf = buf_start, *buf_end = buf + len; 481 size_t max_headers = *num_headers;
489 size_t max_headers = *num_headers; 482 int r;
490 int r;
491 483
492 *num_headers = 0; 484 *num_headers = 0;
493 485
494 /* if last_len != 0, check if the response is complete (a fast countermeasure 486 /* if last_len != 0, check if the response is complete (a fast countermeasure
495 against slowloris */ 487 against slowloris */
496 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) { 488 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
497 return r; 489 return r;
498 } 490 }
499 491
500 if ((buf = parse_headers(buf, buf_end, headers, num_headers, max_headers, &r)) == NULL) { 492 if ((buf = parse_headers(buf, buf_end, headers, num_headers, max_headers, &r)) == NULL) {
501 return r; 493 return r;
502 } 494 }
503 495
504 return (int)(buf - buf_start); 496 return (int)(buf - buf_start);
505} 497}
506 498
507enum { 499enum {
508 CHUNKED_IN_CHUNK_SIZE, 500 CHUNKED_IN_CHUNK_SIZE,
509 CHUNKED_IN_CHUNK_EXT, 501 CHUNKED_IN_CHUNK_EXT,
510 CHUNKED_IN_CHUNK_DATA, 502 CHUNKED_IN_CHUNK_DATA,
511 CHUNKED_IN_CHUNK_CRLF, 503 CHUNKED_IN_CHUNK_CRLF,
512 CHUNKED_IN_TRAILERS_LINE_HEAD, 504 CHUNKED_IN_TRAILERS_LINE_HEAD,
513 CHUNKED_IN_TRAILERS_LINE_MIDDLE 505 CHUNKED_IN_TRAILERS_LINE_MIDDLE
514}; 506};
515 507
516static int decode_hex(int ch) 508static int decode_hex(int ch) {
517{ 509 if ('0' <= ch && ch <= '9') {
518 if ('0' <= ch && ch <= '9') { 510 return ch - '0';
519 return ch - '0'; 511 } else if ('A' <= ch && ch <= 'F') {
520 } else if ('A' <= ch && ch <= 'F') { 512 return ch - 'A' + 0xa;
521 return ch - 'A' + 0xa; 513 } else if ('a' <= ch && ch <= 'f') {
522 } else if ('a' <= ch && ch <= 'f') { 514 return ch - 'a' + 0xa;
523 return ch - 'a' + 0xa; 515 } else {
524 } else { 516 return -1;
525 return -1; 517 }
526 }
527} 518}
528 519
529ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *_bufsz) 520ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *_bufsz) {
530{ 521 size_t dst = 0, src = 0, bufsz = *_bufsz;
531 size_t dst = 0, src = 0, bufsz = *_bufsz; 522 ssize_t ret = -2; /* incomplete */
532 ssize_t ret = -2; /* incomplete */ 523
533 524 while (1) {
534 while (1) { 525 switch (decoder->_state) {
535 switch (decoder->_state) { 526 case CHUNKED_IN_CHUNK_SIZE:
536 case CHUNKED_IN_CHUNK_SIZE: 527 for (;; ++src) {
537 for (;; ++src) { 528 int v;
538 int v; 529 if (src == bufsz)
539 if (src == bufsz) 530 goto Exit;
540 goto Exit; 531 if ((v = decode_hex(buf[src])) == -1) {
541 if ((v = decode_hex(buf[src])) == -1) { 532 if (decoder->_hex_count == 0) {
542 if (decoder->_hex_count == 0) { 533 ret = -1;
543 ret = -1; 534 goto Exit;
544 goto Exit; 535 }
545 } 536 break;
546 break; 537 }
547 } 538 if (decoder->_hex_count == sizeof(size_t) * 2) {
548 if (decoder->_hex_count == sizeof(size_t) * 2) { 539 ret = -1;
549 ret = -1; 540 goto Exit;
550 goto Exit; 541 }
551 } 542 decoder->bytes_left_in_chunk = decoder->bytes_left_in_chunk * 16 + v;
552 decoder->bytes_left_in_chunk = decoder->bytes_left_in_chunk * 16 + v; 543 ++decoder->_hex_count;
553 ++decoder->_hex_count; 544 }
554 } 545 decoder->_hex_count = 0;
555 decoder->_hex_count = 0; 546 decoder->_state = CHUNKED_IN_CHUNK_EXT;
556 decoder->_state = CHUNKED_IN_CHUNK_EXT; 547 /* fallthru */
557 /* fallthru */ 548 case CHUNKED_IN_CHUNK_EXT:
558 case CHUNKED_IN_CHUNK_EXT: 549 /* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */
559 /* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */ 550 for (;; ++src) {
560 for (;; ++src) { 551 if (src == bufsz)
561 if (src == bufsz) 552 goto Exit;
562 goto Exit; 553 if (buf[src] == '\012')
563 if (buf[src] == '\012') 554 break;
564 break; 555 }
565 } 556 ++src;
566 ++src; 557 if (decoder->bytes_left_in_chunk == 0) {
567 if (decoder->bytes_left_in_chunk == 0) { 558 if (decoder->consume_trailer) {
568 if (decoder->consume_trailer) { 559 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
569 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD; 560 break;
570 break; 561 } else {
571 } else { 562 goto Complete;
572 goto Complete; 563 }
573 } 564 }
574 } 565 decoder->_state = CHUNKED_IN_CHUNK_DATA;
575 decoder->_state = CHUNKED_IN_CHUNK_DATA; 566 /* fallthru */
576 /* fallthru */ 567 case CHUNKED_IN_CHUNK_DATA: {
577 case CHUNKED_IN_CHUNK_DATA: { 568 size_t avail = bufsz - src;
578 size_t avail = bufsz - src; 569 if (avail < decoder->bytes_left_in_chunk) {
579 if (avail < decoder->bytes_left_in_chunk) { 570 if (dst != src)
580 if (dst != src) 571 memmove(buf + dst, buf + src, avail);
581 memmove(buf + dst, buf + src, avail); 572 src += avail;
582 src += avail; 573 dst += avail;
583 dst += avail; 574 decoder->bytes_left_in_chunk -= avail;
584 decoder->bytes_left_in_chunk -= avail; 575 goto Exit;
585 goto Exit; 576 }
586 } 577 if (dst != src)
587 if (dst != src) 578 memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk);
588 memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk); 579 src += decoder->bytes_left_in_chunk;
589 src += decoder->bytes_left_in_chunk; 580 dst += decoder->bytes_left_in_chunk;
590 dst += decoder->bytes_left_in_chunk; 581 decoder->bytes_left_in_chunk = 0;
591 decoder->bytes_left_in_chunk = 0; 582 decoder->_state = CHUNKED_IN_CHUNK_CRLF;
592 decoder->_state = CHUNKED_IN_CHUNK_CRLF; 583 }
593 } 584 /* fallthru */
594 /* fallthru */ 585 case CHUNKED_IN_CHUNK_CRLF:
595 case CHUNKED_IN_CHUNK_CRLF: 586 for (;; ++src) {
596 for (;; ++src) { 587 if (src == bufsz)
597 if (src == bufsz) 588 goto Exit;
598 goto Exit; 589 if (buf[src] != '\015')
599 if (buf[src] != '\015') 590 break;
600 break; 591 }
601 } 592 if (buf[src] != '\012') {
602 if (buf[src] != '\012') { 593 ret = -1;
603 ret = -1; 594 goto Exit;
604 goto Exit; 595 }
605 } 596 ++src;
606 ++src; 597 decoder->_state = CHUNKED_IN_CHUNK_SIZE;
607 decoder->_state = CHUNKED_IN_CHUNK_SIZE; 598 break;
608 break; 599 case CHUNKED_IN_TRAILERS_LINE_HEAD:
609 case CHUNKED_IN_TRAILERS_LINE_HEAD: 600 for (;; ++src) {
610 for (;; ++src) { 601 if (src == bufsz)
611 if (src == bufsz) 602 goto Exit;
612 goto Exit; 603 if (buf[src] != '\015')
613 if (buf[src] != '\015') 604 break;
614 break; 605 }
615 } 606 if (buf[src++] == '\012')
616 if (buf[src++] == '\012') 607 goto Complete;
617 goto Complete; 608 decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE;
618 decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE; 609 /* fallthru */
619 /* fallthru */ 610 case CHUNKED_IN_TRAILERS_LINE_MIDDLE:
620 case CHUNKED_IN_TRAILERS_LINE_MIDDLE: 611 for (;; ++src) {
621 for (;; ++src) { 612 if (src == bufsz)
622 if (src == bufsz) 613 goto Exit;
623 goto Exit; 614 if (buf[src] == '\012')
624 if (buf[src] == '\012') 615 break;
625 break; 616 }
626 } 617 ++src;
627 ++src; 618 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
628 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD; 619 break;
629 break; 620 default:
630 default: 621 assert(!"decoder is corrupt");
631 assert(!"decoder is corrupt"); 622 }
632 } 623 }
633 }
634 624
635Complete: 625Complete:
636 ret = bufsz - src; 626 ret = bufsz - src;
637Exit: 627Exit:
638 if (dst != src) 628 if (dst != src)
639 memmove(buf + dst, buf + src, bufsz - src); 629 memmove(buf + dst, buf + src, bufsz - src);
640 *_bufsz = dst; 630 *_bufsz = dst;
641 return ret; 631 return ret;
642} 632}
643 633
644int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder) 634int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder) { return decoder->_state == CHUNKED_IN_CHUNK_DATA; }
645{
646 return decoder->_state == CHUNKED_IN_CHUNK_DATA;
647}
648 635
649#undef CHECK_EOF 636#undef CHECK_EOF
650#undef EXPECT_CHAR 637#undef EXPECT_CHAR
diff --git a/plugins/popen.c b/plugins/popen.c
index 54e63bc5..2b9824bc 100644
--- a/plugins/popen.c
+++ b/plugins/popen.c
@@ -1,42 +1,42 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins popen 3 * Monitoring Plugins popen
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* A safe alternative to popen 10 * A safe alternative to popen
11* 11 *
12* Provides spopen and spclose 12 * Provides spopen and spclose
13* 13 *
14* FILE * spopen(const char *); 14 * FILE * spopen(const char *);
15* int spclose(FILE *); 15 * int spclose(FILE *);
16* 16 *
17* Code taken with little modification from "Advanced Programming for the Unix 17 * Code taken with little modification from "Advanced Programming for the Unix
18* Environment" by W. Richard Stevens 18 * Environment" by W. Richard Stevens
19* 19 *
20* This is considered safe in that no shell is spawned, and the environment 20 * This is considered safe in that no shell is spawned, and the environment
21* and path passed to the exec'd program are essentially empty. (popen create 21 * and path passed to the exec'd program are essentially empty. (popen create
22* a shell and passes the environment to it). 22 * a shell and passes the environment to it).
23* 23 *
24* 24 *
25* This program is free software: you can redistribute it and/or modify 25 * This program is free software: you can redistribute it and/or modify
26* it under the terms of the GNU General Public License as published by 26 * it under the terms of the GNU General Public License as published by
27* the Free Software Foundation, either version 3 of the License, or 27 * the Free Software Foundation, either version 3 of the License, or
28* (at your option) any later version. 28 * (at your option) any later version.
29* 29 *
30* This program is distributed in the hope that it will be useful, 30 * This program is distributed in the hope that it will be useful,
31* but WITHOUT ANY WARRANTY; without even the implied warranty of 31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33* GNU General Public License for more details. 33 * GNU General Public License for more details.
34* 34 *
35* You should have received a copy of the GNU General Public License 35 * You should have received a copy of the GNU General Public License
36* along with this program. If not, see <http://www.gnu.org/licenses/>. 36 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37* 37 *
38* 38 *
39*****************************************************************************/ 39 *****************************************************************************/
40 40
41#include "./common.h" 41#include "./common.h"
42#include "./utils.h" 42#include "./utils.h"
@@ -47,63 +47,52 @@ extern pid_t *childpid;
47extern int *child_stderr_array; 47extern int *child_stderr_array;
48extern FILE *child_process; 48extern FILE *child_process;
49 49
50FILE *spopen (const char *); 50FILE *spopen(const char * /*cmdstring*/);
51int spclose (FILE *); 51int spclose(FILE * /*fp*/);
52#ifdef REDHAT_SPOPEN_ERROR 52#ifdef REDHAT_SPOPEN_ERROR
53void popen_sigchld_handler (int); 53void popen_sigchld_handler(int);
54#endif 54#endif
55void popen_timeout_alarm_handler (int); 55void popen_timeout_alarm_handler(int /*signo*/);
56 56
57#include <stdarg.h> /* ANSI C header file */ 57#include <stdarg.h> /* ANSI C header file */
58#include <fcntl.h> 58#include <fcntl.h>
59 59
60#include <limits.h> 60#include <limits.h>
61#include <sys/resource.h> 61#include <sys/resource.h>
62 62
63#ifdef HAVE_SYS_WAIT_H 63#ifdef HAVE_SYS_WAIT_H
64#include <sys/wait.h> 64# include <sys/wait.h>
65#endif 65#endif
66 66
67#ifndef WEXITSTATUS 67#ifndef WEXITSTATUS
68# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 68# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
69#endif 69#endif
70 70
71#ifndef WIFEXITED 71#ifndef WIFEXITED
72# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 72# define WIFEXITED(stat_val) (((stat_val)&255) == 0)
73#endif 73#endif
74 74
75/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */ 75/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
76#if defined(SIG_IGN) && !defined(SIG_ERR) 76#if defined(SIG_IGN) && !defined(SIG_ERR)
77#define SIG_ERR ((Sigfunc *)-1) 77# define SIG_ERR ((Sigfunc *)-1)
78#endif 78#endif
79 79
80 80char *pname = NULL; /* caller can set this from argv[0] */
81char *pname = NULL; /* caller can set this from argv[0] */
82 81
83#ifdef REDHAT_SPOPEN_ERROR 82#ifdef REDHAT_SPOPEN_ERROR
84static volatile int childtermd = 0; 83static volatile int childtermd = 0;
85#endif 84#endif
86 85
87FILE * 86FILE *spopen(const char *cmdstring) {
88spopen (const char *cmdstring) 87#ifdef RLIMIT_CORE
89{
90 char *env[2];
91 char *cmd = NULL;
92 char **argv = NULL;
93 char *str, *tmp;
94 int argc;
95
96 int i = 0, pfd[2], pfderr[2];
97 pid_t pid;
98
99#ifdef RLIMIT_CORE
100 /* do not leave core files */ 88 /* do not leave core files */
101 struct rlimit limit; 89 struct rlimit limit;
102 getrlimit (RLIMIT_CORE, &limit); 90 getrlimit(RLIMIT_CORE, &limit);
103 limit.rlim_cur = 0; 91 limit.rlim_cur = 0;
104 setrlimit (RLIMIT_CORE, &limit); 92 setrlimit(RLIMIT_CORE, &limit);
105#endif 93#endif
106 94
95 char *env[2];
107 env[0] = strdup("LC_ALL=C"); 96 env[0] = strdup("LC_ALL=C");
108 env[1] = NULL; 97 env[1] = NULL;
109 98
@@ -111,184 +100,182 @@ spopen (const char *cmdstring)
111 if (cmdstring == NULL) 100 if (cmdstring == NULL)
112 return (NULL); 101 return (NULL);
113 102
103 char *cmd = NULL;
114 /* make copy of command string so strtok() doesn't silently modify it */ 104 /* make copy of command string so strtok() doesn't silently modify it */
115 /* (the calling program may want to access it later) */ 105 /* (the calling program may want to access it later) */
116 cmd = malloc (strlen (cmdstring) + 1); 106 cmd = malloc(strlen(cmdstring) + 1);
117 if (cmd == NULL) 107 if (cmd == NULL)
118 return NULL; 108 return NULL;
119 strcpy (cmd, cmdstring); 109 strcpy(cmd, cmdstring);
120 110
121 /* This is not a shell, so we don't handle "???" */ 111 /* This is not a shell, so we don't handle "???" */
122 if (strstr (cmdstring, "\"")) 112 if (strstr(cmdstring, "\""))
123 return NULL; 113 return NULL;
124 114
125 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ 115 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
126 if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''")) 116 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''"))
127 return NULL; 117 return NULL;
128 118
119 int argc;
120 char **argv = NULL;
129 /* there cannot be more args than characters */ 121 /* there cannot be more args than characters */
130 argc = strlen (cmdstring) + 1; /* add 1 for NULL termination */ 122 argc = strlen(cmdstring) + 1; /* add 1 for NULL termination */
131 argv = malloc (sizeof(char*)*argc); 123 argv = malloc(sizeof(char *) * argc);
132 124
133 if (argv == NULL) { 125 if (argv == NULL) {
134 printf ("%s\n", _("Could not malloc argv array in popen()")); 126 printf("%s\n", _("Could not malloc argv array in popen()"));
135 return NULL; 127 return NULL;
136 } 128 }
137 129
130 int i = 0;
131 char *str;
138 /* loop to get arguments to command */ 132 /* loop to get arguments to command */
139 while (cmd) { 133 while (cmd) {
140 str = cmd; 134 str = cmd;
141 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 135 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
142 136
143 if (i >= argc - 2) { 137 if (i >= argc - 2) {
144 printf ("%s\n",_("CRITICAL - You need more args!!!")); 138 printf("%s\n", _("CRITICAL - You need more args!!!"));
145 return (NULL); 139 return (NULL);
146 } 140 }
147 141
148 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */ 142 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */
149 str++; 143 str++;
150 if (!strstr (str, "'")) 144 if (!strstr(str, "'"))
151 return NULL; /* balanced? */ 145 return NULL; /* balanced? */
152 cmd = 1 + strstr (str, "'"); 146 cmd = 1 + strstr(str, "'");
153 str[strcspn (str, "'")] = 0; 147 str[strcspn(str, "'")] = 0;
154 } 148 } else if (strcspn(str, "'") < strcspn(str, " \t\r\n")) {
155 else if (strcspn(str,"'") < strcspn (str, " \t\r\n")) { 149 /* handle --option='foo bar' strings */
156 /* handle --option='foo bar' strings */ 150 char *tmp = str + strcspn(str, "'") + 1;
157 tmp = str + strcspn(str, "'") + 1; 151 if (!strstr(tmp, "'"))
158 if (!strstr (tmp, "'")) 152 return NULL; /* balanced? */
159 return NULL; /* balanced? */ 153 tmp += strcspn(tmp, "'") + 1;
160 tmp += strcspn(tmp,"'") + 1;
161 *tmp = 0; 154 *tmp = 0;
162 cmd = tmp + 1; 155 cmd = tmp + 1;
163 } else { 156 } else {
164 if (strpbrk (str, " \t\r\n")) { 157 if (strpbrk(str, " \t\r\n")) {
165 cmd = 1 + strpbrk (str, " \t\r\n"); 158 cmd = 1 + strpbrk(str, " \t\r\n");
166 str[strcspn (str, " \t\r\n")] = 0; 159 str[strcspn(str, " \t\r\n")] = 0;
167 } 160 } else {
168 else {
169 cmd = NULL; 161 cmd = NULL;
170 } 162 }
171 } 163 }
172 164
173 if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n")) 165 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n"))
174 cmd = NULL; 166 cmd = NULL;
175 167
176 argv[i++] = str; 168 argv[i++] = str;
177
178 } 169 }
179 argv[i] = NULL; 170 argv[i] = NULL;
180 171
181 long maxfd = mp_open_max(); 172 long maxfd = mp_open_max();
182 173
183 if (childpid == NULL) { /* first time through */ 174 if (childpid == NULL) { /* first time through */
184 if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL) 175 if ((childpid = calloc((size_t)maxfd, sizeof(pid_t))) == NULL)
185 return (NULL); 176 return (NULL);
186 } 177 }
187 178
188 if (child_stderr_array == NULL) { /* first time through */ 179 if (child_stderr_array == NULL) { /* first time through */
189 if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL) 180 if ((child_stderr_array = calloc((size_t)maxfd, sizeof(int))) == NULL)
190 return (NULL); 181 return (NULL);
191 } 182 }
192 183
193 if (pipe (pfd) < 0) 184 int pfd[2];
194 return (NULL); /* errno set by pipe() */ 185 if (pipe(pfd) < 0)
186 return (NULL); /* errno set by pipe() */
195 187
196 if (pipe (pfderr) < 0) 188 int pfderr[2];
197 return (NULL); /* errno set by pipe() */ 189 if (pipe(pfderr) < 0)
190 return (NULL); /* errno set by pipe() */
198 191
199#ifdef REDHAT_SPOPEN_ERROR 192#ifdef REDHAT_SPOPEN_ERROR
200 if (signal (SIGCHLD, popen_sigchld_handler) == SIG_ERR) { 193 if (signal(SIGCHLD, popen_sigchld_handler) == SIG_ERR) {
201 usage4 (_("Cannot catch SIGCHLD")); 194 usage4(_("Cannot catch SIGCHLD"));
202 } 195 }
203#endif 196#endif
204 197
205 if ((pid = fork ()) < 0) 198 pid_t pid;
206 return (NULL); /* errno set by fork() */ 199 if ((pid = fork()) < 0)
207 else if (pid == 0) { /* child */ 200 return (NULL); /* errno set by fork() */
208 close (pfd[0]); 201
202 if (pid == 0) { /* child */
203 close(pfd[0]);
209 if (pfd[1] != STDOUT_FILENO) { 204 if (pfd[1] != STDOUT_FILENO) {
210 dup2 (pfd[1], STDOUT_FILENO); 205 dup2(pfd[1], STDOUT_FILENO);
211 close (pfd[1]); 206 close(pfd[1]);
212 } 207 }
213 close (pfderr[0]); 208 close(pfderr[0]);
214 if (pfderr[1] != STDERR_FILENO) { 209 if (pfderr[1] != STDERR_FILENO) {
215 dup2 (pfderr[1], STDERR_FILENO); 210 dup2(pfderr[1], STDERR_FILENO);
216 close (pfderr[1]); 211 close(pfderr[1]);
217 } 212 }
218 /* close all descriptors in childpid[] */ 213 /* close all descriptors in childpid[] */
219 for (i = 0; i < maxfd; i++) 214 for (i = 0; i < maxfd; i++)
220 if (childpid[i] > 0) 215 if (childpid[i] > 0)
221 close (i); 216 close(i);
222 217
223 execve (argv[0], argv, env); 218 execve(argv[0], argv, env);
224 _exit (0); 219 _exit(0);
225 } 220 }
226 221
227 close (pfd[1]); /* parent */ 222 close(pfd[1]); /* parent */
228 if ((child_process = fdopen (pfd[0], "r")) == NULL) 223 if ((child_process = fdopen(pfd[0], "r")) == NULL)
229 return (NULL); 224 return (NULL);
230 close (pfderr[1]); 225 close(pfderr[1]);
231 226
232 childpid[fileno (child_process)] = pid; /* remember child pid for this fd */ 227 childpid[fileno(child_process)] = pid; /* remember child pid for this fd */
233 child_stderr_array[fileno (child_process)] = pfderr[0]; /* remember STDERR */ 228 child_stderr_array[fileno(child_process)] = pfderr[0]; /* remember STDERR */
234 return (child_process); 229 return (child_process);
235} 230}
236 231
237int 232int spclose(FILE *fp) {
238spclose (FILE * fp)
239{
240 int fd, status;
241 pid_t pid;
242
243 if (childpid == NULL) 233 if (childpid == NULL)
244 return (1); /* popen() has never been called */ 234 return (1); /* popen() has never been called */
245 235
246 fd = fileno (fp); 236 pid_t pid;
237 int fd = fileno(fp);
247 if ((pid = childpid[fd]) == 0) 238 if ((pid = childpid[fd]) == 0)
248 return (1); /* fp wasn't opened by popen() */ 239 return (1); /* fp wasn't opened by popen() */
249 240
250 childpid[fd] = 0; 241 childpid[fd] = 0;
251 if (fclose (fp) == EOF) 242 if (fclose(fp) == EOF)
252 return (1); 243 return (1);
253 244
254#ifdef REDHAT_SPOPEN_ERROR 245#ifdef REDHAT_SPOPEN_ERROR
255 while (!childtermd); /* wait until SIGCHLD */ 246 while (!childtermd)
247 ; /* wait until SIGCHLD */
256#endif 248#endif
257 249
258 while (waitpid (pid, &status, 0) < 0) 250 int status;
251 while (waitpid(pid, &status, 0) < 0)
259 if (errno != EINTR) 252 if (errno != EINTR)
260 return (1); /* error other than EINTR from waitpid() */ 253 return (1); /* error other than EINTR from waitpid() */
261 254
262 if (WIFEXITED (status)) 255 if (WIFEXITED(status))
263 return (WEXITSTATUS (status)); /* return child's termination status */ 256 return (WEXITSTATUS(status)); /* return child's termination status */
264 257
265 return (1); 258 return (1);
266} 259}
267 260
268#ifdef REDHAT_SPOPEN_ERROR 261#ifdef REDHAT_SPOPEN_ERROR
269void 262void popen_sigchld_handler(int signo) {
270popen_sigchld_handler (int signo)
271{
272 if (signo == SIGCHLD) 263 if (signo == SIGCHLD)
273 childtermd = 1; 264 childtermd = 1;
274} 265}
275#endif 266#endif
276 267
277void 268void popen_timeout_alarm_handler(int signo) {
278popen_timeout_alarm_handler (int signo)
279{
280 int fh;
281 if (signo == SIGALRM) { 269 if (signo == SIGALRM) {
282 if (child_process != NULL) { 270 if (child_process != NULL) {
283 fh=fileno (child_process); 271 int fh = fileno(child_process);
284 if(fh >= 0){ 272 if (fh >= 0) {
285 kill (childpid[fh], SIGKILL); 273 kill(childpid[fh], SIGKILL);
286 } 274 }
287 printf (_("CRITICAL - Plugin timed out after %d seconds\n"), 275 printf(_("CRITICAL - Plugin timed out after %d seconds\n"), timeout_interval);
288 timeout_interval);
289 } else { 276 } else {
290 printf ("%s\n", _("CRITICAL - popen timeout received, but no child process")); 277 printf("%s\n", _("CRITICAL - popen timeout received, but no child process"));
291 } 278 }
292 exit (STATE_CRITICAL); 279 exit(STATE_CRITICAL);
293 } 280 }
294} 281}
diff --git a/plugins/runcmd.c b/plugins/runcmd.c
index ed49bb99..2e53dc0b 100644
--- a/plugins/runcmd.c
+++ b/plugins/runcmd.c
@@ -1,63 +1,63 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring run command utilities 3 * Monitoring run command utilities
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2006 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* 7 *
8* Description : 8 * Description :
9* 9 *
10* A simple interface to executing programs from other programs, using an 10 * A simple interface to executing programs from other programs, using an
11* optimized and safe popen()-like implementation. It is considered safe 11 * optimized and safe popen()-like implementation. It is considered safe
12* in that no shell needs to be spawned and the environment passed to the 12 * in that no shell needs to be spawned and the environment passed to the
13* execve()'d program is essentially empty. 13 * execve()'d program is essentially empty.
14* 14 *
15* The code in this file is a derivative of popen.c which in turn was taken 15 * The code in this file is a derivative of popen.c which in turn was taken
16* from "Advanced Programming for the Unix Environment" by W. Richard Stevens. 16 * from "Advanced Programming for the Unix Environment" by W. Richard Stevens.
17* 17 *
18* Care has been taken to make sure the functions are async-safe. The one 18 * Care has been taken to make sure the functions are async-safe. The one
19* function which isn't is np_runcmd_init() which it doesn't make sense to 19 * function which isn't is np_runcmd_init() which it doesn't make sense to
20* call twice anyway, so the api as a whole should be considered async-safe. 20 * call twice anyway, so the api as a whole should be considered async-safe.
21* 21 *
22* 22 *
23* This program is free software: you can redistribute it and/or modify 23 * This program is free software: you can redistribute it and/or modify
24* it under the terms of the GNU General Public License as published by 24 * it under the terms of the GNU General Public License as published by
25* the Free Software Foundation, either version 3 of the License, or 25 * the Free Software Foundation, either version 3 of the License, or
26* (at your option) any later version. 26 * (at your option) any later version.
27* 27 *
28* This program is distributed in the hope that it will be useful, 28 * This program is distributed in the hope that it will be useful,
29* but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31* GNU General Public License for more details. 31 * GNU General Public License for more details.
32* 32 *
33* You should have received a copy of the GNU General Public License 33 * You should have received a copy of the GNU General Public License
34* along with this program. If not, see <http://www.gnu.org/licenses/>. 34 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35* 35 *
36* 36 *
37*****************************************************************************/ 37 *****************************************************************************/
38 38
39#define NAGIOSPLUG_API_C 1 39#define NAGIOSPLUG_API_C 1
40 40
41/** includes **/ 41/** includes **/
42#include "runcmd.h" 42#include "runcmd.h"
43#ifdef HAVE_SYS_WAIT_H 43#ifdef HAVE_SYS_WAIT_H
44# include <sys/wait.h> 44# include <sys/wait.h>
45#endif 45#endif
46 46
47#include "./utils.h" 47#include "./utils.h"
48 48
49/** macros **/ 49/** macros **/
50#ifndef WEXITSTATUS 50#ifndef WEXITSTATUS
51# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 51# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
52#endif 52#endif
53 53
54#ifndef WIFEXITED 54#ifndef WIFEXITED
55# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 55# define WIFEXITED(stat_val) (((stat_val)&255) == 0)
56#endif 56#endif
57 57
58/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */ 58/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
59#if defined(SIG_IGN) && !defined(SIG_ERR) 59#if defined(SIG_IGN) && !defined(SIG_ERR)
60# define SIG_ERR ((Sigfunc *)-1) 60# define SIG_ERR ((Sigfunc *)-1)
61#endif 61#endif
62 62
63#include "../lib/maxfd.h" 63#include "../lib/maxfd.h"
@@ -72,33 +72,26 @@
72static pid_t *np_pids = NULL; 72static pid_t *np_pids = NULL;
73 73
74/** prototypes **/ 74/** prototypes **/
75static int np_runcmd_open(const char *, int *, int *) 75static int np_runcmd_open(const char *, int *, int *) __attribute__((__nonnull__(1, 2, 3)));
76 __attribute__((__nonnull__(1, 2, 3)));
77 76
78static int np_fetch_output(int, output *, int) 77static int np_fetch_output(int, output *, int) __attribute__((__nonnull__(2)));
79 __attribute__((__nonnull__(2)));
80 78
81static int np_runcmd_close(int); 79static int np_runcmd_close(int);
82 80
83/* prototype imported from utils.h */ 81/* prototype imported from utils.h */
84extern void die (int, const char *, ...) 82extern void die(int, const char *, ...) __attribute__((__noreturn__, __format__(__printf__, 2, 3)));
85 __attribute__((__noreturn__,__format__(__printf__, 2, 3)));
86
87 83
88/* this function is NOT async-safe. It is exported so multithreaded 84/* this function is NOT async-safe. It is exported so multithreaded
89 * plugins (or other apps) can call it prior to running any commands 85 * plugins (or other apps) can call it prior to running any commands
90 * through this api and thus achieve async-safeness throughout the api */ 86 * through this api and thus achieve async-safeness throughout the api */
91void np_runcmd_init(void) 87void np_runcmd_init(void) {
92{ 88 long maxfd = mp_open_max();
93 long maxfd = mp_open_max(); 89 if (!np_pids)
94 if(!np_pids) np_pids = calloc(maxfd, sizeof(pid_t)); 90 np_pids = calloc(maxfd, sizeof(pid_t));
95} 91}
96 92
97
98/* Start running a command */ 93/* Start running a command */
99static int 94static int np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr) {
100np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
101{
102 char *env[2]; 95 char *env[2];
103 char *cmd = NULL; 96 char *cmd = NULL;
104 char **argv = NULL; 97 char **argv = NULL;
@@ -112,7 +105,8 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
112 105
113 int i = 0; 106 int i = 0;
114 107
115 if(!np_pids) NP_RUNCMD_INIT; 108 if (!np_pids)
109 NP_RUNCMD_INIT;
116 110
117 env[0] = strdup("LC_ALL=C"); 111 env[0] = strdup("LC_ALL=C");
118 env[1] = NULL; 112 env[1] = NULL;
@@ -120,15 +114,17 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
120 /* make copy of command string so strtok() doesn't silently modify it */ 114 /* make copy of command string so strtok() doesn't silently modify it */
121 /* (the calling program may want to access it later) */ 115 /* (the calling program may want to access it later) */
122 cmdlen = strlen(cmdstring); 116 cmdlen = strlen(cmdstring);
123 if((cmd = malloc(cmdlen + 1)) == NULL) return -1; 117 if ((cmd = malloc(cmdlen + 1)) == NULL)
118 return -1;
124 memcpy(cmd, cmdstring, cmdlen); 119 memcpy(cmd, cmdstring, cmdlen);
125 cmd[cmdlen] = '\0'; 120 cmd[cmdlen] = '\0';
126 121
127 /* This is not a shell, so we don't handle "???" */ 122 /* This is not a shell, so we don't handle "???" */
128 if (strstr (cmdstring, "\"")) return -1; 123 if (strstr(cmdstring, "\""))
124 return -1;
129 125
130 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ 126 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
131 if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''")) 127 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''"))
132 return -1; 128 return -1;
133 129
134 /* each arg must be whitespace-separated, so args can be a maximum 130 /* each arg must be whitespace-separated, so args can be a maximum
@@ -137,32 +133,31 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
137 argv = calloc(sizeof(char *), argc); 133 argv = calloc(sizeof(char *), argc);
138 134
139 if (argv == NULL) { 135 if (argv == NULL) {
140 printf ("%s\n", _("Could not malloc argv array in popen()")); 136 printf("%s\n", _("Could not malloc argv array in popen()"));
141 return -1; 137 return -1;
142 } 138 }
143 139
144 /* get command arguments (stupidly, but fairly quickly) */ 140 /* get command arguments (stupidly, but fairly quickly) */
145 while (cmd) { 141 while (cmd) {
146 str = cmd; 142 str = cmd;
147 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 143 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
148 144
149 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */ 145 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */
150 str++; 146 str++;
151 if (!strstr (str, "'")) return -1; /* balanced? */ 147 if (!strstr(str, "'"))
152 cmd = 1 + strstr (str, "'"); 148 return -1; /* balanced? */
153 str[strcspn (str, "'")] = 0; 149 cmd = 1 + strstr(str, "'");
154 } 150 str[strcspn(str, "'")] = 0;
155 else { 151 } else {
156 if (strpbrk (str, " \t\r\n")) { 152 if (strpbrk(str, " \t\r\n")) {
157 cmd = 1 + strpbrk (str, " \t\r\n"); 153 cmd = 1 + strpbrk(str, " \t\r\n");
158 str[strcspn (str, " \t\r\n")] = 0; 154 str[strcspn(str, " \t\r\n")] = 0;
159 } 155 } else {
160 else {
161 cmd = NULL; 156 cmd = NULL;
162 } 157 }
163 } 158 }
164 159
165 if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n")) 160 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n"))
166 cmd = NULL; 161 cmd = NULL;
167 162
168 argv[i++] = str; 163 argv[i++] = str;
@@ -173,33 +168,33 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
173 168
174 /* child runs exceve() and _exit. */ 169 /* child runs exceve() and _exit. */
175 if (pid == 0) { 170 if (pid == 0) {
176#ifdef RLIMIT_CORE 171#ifdef RLIMIT_CORE
177 /* the program we execve shouldn't leave core files */ 172 /* the program we execve shouldn't leave core files */
178 getrlimit (RLIMIT_CORE, &limit); 173 getrlimit(RLIMIT_CORE, &limit);
179 limit.rlim_cur = 0; 174 limit.rlim_cur = 0;
180 setrlimit (RLIMIT_CORE, &limit); 175 setrlimit(RLIMIT_CORE, &limit);
181#endif 176#endif
182 close (pfd[0]); 177 close(pfd[0]);
183 if (pfd[1] != STDOUT_FILENO) { 178 if (pfd[1] != STDOUT_FILENO) {
184 dup2 (pfd[1], STDOUT_FILENO); 179 dup2(pfd[1], STDOUT_FILENO);
185 close (pfd[1]); 180 close(pfd[1]);
186 } 181 }
187 close (pfderr[0]); 182 close(pfderr[0]);
188 if (pfderr[1] != STDERR_FILENO) { 183 if (pfderr[1] != STDERR_FILENO) {
189 dup2 (pfderr[1], STDERR_FILENO); 184 dup2(pfderr[1], STDERR_FILENO);
190 close (pfderr[1]); 185 close(pfderr[1]);
191 } 186 }
192 187
193 /* close all descriptors in np_pids[] 188 /* close all descriptors in np_pids[]
194 * This is executed in a separate address space (pure child), 189 * This is executed in a separate address space (pure child),
195 * so we don't have to worry about async safety */ 190 * so we don't have to worry about async safety */
196 long maxfd = mp_open_max(); 191 long maxfd = mp_open_max();
197 for (i = 0; i < maxfd; i++) 192 for (i = 0; i < maxfd; i++)
198 if(np_pids[i] > 0) 193 if (np_pids[i] > 0)
199 close (i); 194 close(i);
200 195
201 execve (argv[0], argv, env); 196 execve(argv[0], argv, env);
202 _exit (STATE_UNKNOWN); 197 _exit(STATE_UNKNOWN);
203 } 198 }
204 199
205 /* parent picks up execution here */ 200 /* parent picks up execution here */
@@ -213,49 +208,44 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
213 return pfd[0]; 208 return pfd[0];
214} 209}
215 210
216 211static int np_runcmd_close(int fd) {
217static int
218np_runcmd_close(int fd)
219{
220 int status; 212 int status;
221 pid_t pid; 213 pid_t pid;
222 214
223 /* make sure this fd was opened by popen() */ 215 /* make sure this fd was opened by popen() */
224 long maxfd = mp_open_max(); 216 long maxfd = mp_open_max();
225 if(fd < 0 || fd > maxfd || !np_pids || (pid = np_pids[fd]) == 0) 217 if (fd < 0 || fd > maxfd || !np_pids || (pid = np_pids[fd]) == 0)
226 return -1; 218 return -1;
227 219
228 np_pids[fd] = 0; 220 np_pids[fd] = 0;
229 if (close (fd) == -1) return -1; 221 if (close(fd) == -1)
222 return -1;
230 223
231 /* EINTR is ok (sort of), everything else is bad */ 224 /* EINTR is ok (sort of), everything else is bad */
232 while (waitpid (pid, &status, 0) < 0) 225 while (waitpid(pid, &status, 0) < 0)
233 if (errno != EINTR) return -1; 226 if (errno != EINTR)
227 return -1;
234 228
235 /* return child's termination status */ 229 /* return child's termination status */
236 return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1; 230 return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1;
237} 231}
238 232
239 233void runcmd_timeout_alarm_handler(int signo) {
240void
241runcmd_timeout_alarm_handler (int signo)
242{
243 234
244 if (signo == SIGALRM) 235 if (signo == SIGALRM)
245 puts(_("CRITICAL - Plugin timed out while executing system call")); 236 puts(_("CRITICAL - Plugin timed out while executing system call"));
246 237
247 long maxfd = mp_open_max(); 238 long maxfd = mp_open_max();
248 if(np_pids) for(long int i = 0; i < maxfd; i++) { 239 if (np_pids)
249 if(np_pids[i] != 0) kill(np_pids[i], SIGKILL); 240 for (long int i = 0; i < maxfd; i++) {
250 } 241 if (np_pids[i] != 0)
242 kill(np_pids[i], SIGKILL);
243 }
251 244
252 exit (STATE_CRITICAL); 245 exit(STATE_CRITICAL);
253} 246}
254 247
255 248static int np_fetch_output(int fd, output *op, int flags) {
256static int
257np_fetch_output(int fd, output *op, int flags)
258{
259 size_t len = 0, i = 0, lineno = 0; 249 size_t len = 0, i = 0, lineno = 0;
260 size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */ 250 size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */
261 char *buf = NULL; 251 char *buf = NULL;
@@ -264,7 +254,7 @@ np_fetch_output(int fd, output *op, int flags)
264 254
265 op->buf = NULL; 255 op->buf = NULL;
266 op->buflen = 0; 256 op->buflen = 0;
267 while((ret = read(fd, tmpbuf, sizeof(tmpbuf))) > 0) { 257 while ((ret = read(fd, tmpbuf, sizeof(tmpbuf))) > 0) {
268 len = (size_t)ret; 258 len = (size_t)ret;
269 op->buf = realloc(op->buf, op->buflen + len + 1); 259 op->buf = realloc(op->buf, op->buflen + len + 1);
270 memcpy(op->buf + op->buflen, tmpbuf, len); 260 memcpy(op->buf + op->buflen, tmpbuf, len);
@@ -272,33 +262,33 @@ np_fetch_output(int fd, output *op, int flags)
272 i++; 262 i++;
273 } 263 }
274 264
275 if(ret < 0) { 265 if (ret < 0) {
276 printf("read() returned %d: %s\n", ret, strerror(errno)); 266 printf("read() returned %d: %s\n", ret, strerror(errno));
277 return ret; 267 return ret;
278 } 268 }
279 269
280 /* some plugins may want to keep output unbroken, and some commands 270 /* some plugins may want to keep output unbroken, and some commands
281 * will yield no output, so return here for those */ 271 * will yield no output, so return here for those */
282 if(flags & RUNCMD_NO_ARRAYS || !op->buf || !op->buflen) 272 if (flags & RUNCMD_NO_ARRAYS || !op->buf || !op->buflen)
283 return op->buflen; 273 return op->buflen;
284 274
285 /* and some may want both */ 275 /* and some may want both */
286 if(flags & RUNCMD_NO_ASSOC) { 276 if (flags & RUNCMD_NO_ASSOC) {
287 buf = malloc(op->buflen); 277 buf = malloc(op->buflen);
288 memcpy(buf, op->buf, op->buflen); 278 memcpy(buf, op->buf, op->buflen);
289 } 279 } else
290 else buf = op->buf; 280 buf = op->buf;
291 281
292 op->line = NULL; 282 op->line = NULL;
293 op->lens = NULL; 283 op->lens = NULL;
294 i = 0; 284 i = 0;
295 while(i < op->buflen) { 285 while (i < op->buflen) {
296 /* make sure we have enough memory */ 286 /* make sure we have enough memory */
297 if(lineno >= ary_size) { 287 if (lineno >= ary_size) {
298 /* ary_size must never be zero */ 288 /* ary_size must never be zero */
299 do { 289 do {
300 ary_size = op->buflen >> --rsf; 290 ary_size = op->buflen >> --rsf;
301 } while(!ary_size); 291 } while (!ary_size);
302 292
303 op->line = realloc(op->line, ary_size * sizeof(char *)); 293 op->line = realloc(op->line, ary_size * sizeof(char *));
304 op->lens = realloc(op->lens, ary_size * sizeof(size_t)); 294 op->lens = realloc(op->lens, ary_size * sizeof(size_t));
@@ -308,7 +298,8 @@ np_fetch_output(int fd, output *op, int flags)
308 op->line[lineno] = &buf[i]; 298 op->line[lineno] = &buf[i];
309 299
310 /* hop to next newline or end of buffer */ 300 /* hop to next newline or end of buffer */
311 while(buf[i] != '\n' && i < op->buflen) i++; 301 while (buf[i] != '\n' && i < op->buflen)
302 i++;
312 buf[i] = '\0'; 303 buf[i] = '\0';
313 304
314 /* calculate the string length using pointer difference */ 305 /* calculate the string length using pointer difference */
@@ -321,21 +312,22 @@ np_fetch_output(int fd, output *op, int flags)
321 return lineno; 312 return lineno;
322} 313}
323 314
324 315int np_runcmd(const char *cmd, output *out, output *err, int flags) {
325int
326np_runcmd(const char *cmd, output *out, output *err, int flags)
327{
328 int fd, pfd_out[2], pfd_err[2]; 316 int fd, pfd_out[2], pfd_err[2];
329 317
330 /* initialize the structs */ 318 /* initialize the structs */
331 if(out) memset(out, 0, sizeof(output)); 319 if (out)
332 if(err) memset(err, 0, sizeof(output)); 320 memset(out, 0, sizeof(output));
333 321 if (err)
334 if((fd = np_runcmd_open(cmd, pfd_out, pfd_err)) == -1) 322 memset(err, 0, sizeof(output));
335 die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); 323
336 324 if ((fd = np_runcmd_open(cmd, pfd_out, pfd_err)) == -1)
337 if(out) out->lines = np_fetch_output(pfd_out[0], out, flags); 325 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
338 if(err) err->lines = np_fetch_output(pfd_err[0], err, flags); 326
327 if (out)
328 out->lines = np_fetch_output(pfd_out[0], out, flags);
329 if (err)
330 err->lines = np_fetch_output(pfd_err[0], err, flags);
339 331
340 return np_runcmd_close(fd); 332 return np_runcmd_close(fd);
341} 333}
diff --git a/plugins/sslutils.c b/plugins/sslutils.c
index 6bc0ba81..3c928413 100644
--- a/plugins/sslutils.c
+++ b/plugins/sslutils.c
@@ -1,46 +1,42 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins SSL utilities 3 * Monitoring Plugins SSL utilities
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2010 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains common functions for plugins that require SSL. 10 * This file contains common functions for plugins that require SSL.
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29#define MAX_CN_LENGTH 256 29#define MAX_CN_LENGTH 256
30#include "common.h" 30#include "common.h"
31#include "netutils.h" 31#include "netutils.h"
32 32
33#ifdef HAVE_SSL 33#ifdef HAVE_SSL
34static SSL_CTX *ctx=NULL; 34static SSL_CTX *ctx = NULL;
35static SSL *s=NULL; 35static SSL *s = NULL;
36 36
37int np_net_ssl_init(int sd) { 37int np_net_ssl_init(int sd) { return np_net_ssl_init_with_hostname(sd, NULL); }
38 return np_net_ssl_init_with_hostname(sd, NULL);
39}
40 38
41int np_net_ssl_init_with_hostname(int sd, char *host_name) { 39int np_net_ssl_init_with_hostname(int sd, char *host_name) { return np_net_ssl_init_with_hostname_and_version(sd, host_name, 0); }
42 return np_net_ssl_init_with_hostname_and_version(sd, host_name, 0);
43}
44 40
45int np_net_ssl_init_with_hostname_and_version(int sd, char *host_name, int version) { 41int np_net_ssl_init_with_hostname_and_version(int sd, char *host_name, int version) {
46 return np_net_ssl_init_with_hostname_version_and_cert(sd, host_name, version, NULL, NULL); 42 return np_net_ssl_init_with_hostname_version_and_cert(sd, host_name, version, NULL, NULL);
@@ -59,145 +55,141 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int
59 printf("%s\n", _("UNKNOWN - SSL protocol version 2 is not supported by your SSL library.")); 55 printf("%s\n", _("UNKNOWN - SSL protocol version 2 is not supported by your SSL library."));
60 return STATE_UNKNOWN; 56 return STATE_UNKNOWN;
61 case MP_SSLv3: /* SSLv3 protocol */ 57 case MP_SSLv3: /* SSLv3 protocol */
62#if defined(OPENSSL_NO_SSL3) 58# if defined(OPENSSL_NO_SSL3)
63 printf("%s\n", _("UNKNOWN - SSL protocol version 3 is not supported by your SSL library.")); 59 printf("%s\n", _("UNKNOWN - SSL protocol version 3 is not supported by your SSL library."));
64 return STATE_UNKNOWN; 60 return STATE_UNKNOWN;
65#else 61# else
66 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION); 62 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
67 SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION); 63 SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION);
68 break; 64 break;
69#endif 65# endif
70 case MP_TLSv1: /* TLSv1 protocol */ 66 case MP_TLSv1: /* TLSv1 protocol */
71#if defined(OPENSSL_NO_TLS1) 67# if defined(OPENSSL_NO_TLS1)
72 printf("%s\n", _("UNKNOWN - TLS protocol version 1 is not supported by your SSL library.")); 68 printf("%s\n", _("UNKNOWN - TLS protocol version 1 is not supported by your SSL library."));
73 return STATE_UNKNOWN; 69 return STATE_UNKNOWN;
74#else 70# else
75 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION); 71 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
76 SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION); 72 SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION);
77 break; 73 break;
78#endif 74# endif
79 case MP_TLSv1_1: /* TLSv1.1 protocol */ 75 case MP_TLSv1_1: /* TLSv1.1 protocol */
80#if !defined(SSL_OP_NO_TLSv1_1) 76# if !defined(SSL_OP_NO_TLSv1_1)
81 printf("%s\n", _("UNKNOWN - TLS protocol version 1.1 is not supported by your SSL library.")); 77 printf("%s\n", _("UNKNOWN - TLS protocol version 1.1 is not supported by your SSL library."));
82 return STATE_UNKNOWN; 78 return STATE_UNKNOWN;
83#else 79# else
84 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION); 80 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
85 SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION); 81 SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION);
86 break; 82 break;
87#endif 83# endif
88 case MP_TLSv1_2: /* TLSv1.2 protocol */ 84 case MP_TLSv1_2: /* TLSv1.2 protocol */
89#if !defined(SSL_OP_NO_TLSv1_2) 85# if !defined(SSL_OP_NO_TLSv1_2)
90 printf("%s\n", _("UNKNOWN - TLS protocol version 1.2 is not supported by your SSL library.")); 86 printf("%s\n", _("UNKNOWN - TLS protocol version 1.2 is not supported by your SSL library."));
91 return STATE_UNKNOWN; 87 return STATE_UNKNOWN;
92#else 88# else
93 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); 89 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
94 SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); 90 SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
95 break; 91 break;
96#endif 92# endif
97 case MP_TLSv1_2_OR_NEWER: 93 case MP_TLSv1_2_OR_NEWER:
98#if !defined(SSL_OP_NO_TLSv1_1) 94# if !defined(SSL_OP_NO_TLSv1_1)
99 printf("%s\n", _("UNKNOWN - Disabling TLSv1.1 is not supported by your SSL library.")); 95 printf("%s\n", _("UNKNOWN - Disabling TLSv1.1 is not supported by your SSL library."));
100 return STATE_UNKNOWN; 96 return STATE_UNKNOWN;
101#else 97# else
102 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); 98 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
103 break; 99 break;
104#endif 100# endif
105 case MP_TLSv1_1_OR_NEWER: 101 case MP_TLSv1_1_OR_NEWER:
106#if !defined(SSL_OP_NO_TLSv1) 102# if !defined(SSL_OP_NO_TLSv1)
107 printf("%s\n", _("UNKNOWN - Disabling TLSv1 is not supported by your SSL library.")); 103 printf("%s\n", _("UNKNOWN - Disabling TLSv1 is not supported by your SSL library."));
108 return STATE_UNKNOWN; 104 return STATE_UNKNOWN;
109#else 105# else
110 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION); 106 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
111 break; 107 break;
112#endif 108# endif
113 case MP_TLSv1_OR_NEWER: 109 case MP_TLSv1_OR_NEWER:
114#if defined(SSL_OP_NO_SSLv3) 110# if defined(SSL_OP_NO_SSLv3)
115 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION); 111 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
116 break; 112 break;
117#endif 113# endif
118 case MP_SSLv3_OR_NEWER: 114 case MP_SSLv3_OR_NEWER:
119#if defined(SSL_OP_NO_SSLv2) 115# if defined(SSL_OP_NO_SSLv2)
120 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION); 116 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
121 break; 117 break;
122#endif 118# endif
123 } 119 }
124 120
125 if (cert && privkey) { 121 if (cert && privkey) {
126#ifdef USE_OPENSSL 122# ifdef USE_OPENSSL
127 if (!SSL_CTX_use_certificate_chain_file(ctx, cert)) { 123 if (!SSL_CTX_use_certificate_chain_file(ctx, cert)) {
128#elif USE_GNUTLS 124# elif USE_GNUTLS
129 if (!SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)) { 125 if (!SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)) {
130#else 126# else
131#error Unported for unknown SSL library 127# error Unported for unknown SSL library
132#endif 128# endif
133 printf ("%s\n", _("CRITICAL - Unable to open certificate chain file!\n")); 129 printf("%s\n", _("CRITICAL - Unable to open certificate chain file!\n"));
134 return STATE_CRITICAL; 130 return STATE_CRITICAL;
135 } 131 }
136 SSL_CTX_use_PrivateKey_file(ctx, privkey, SSL_FILETYPE_PEM); 132 SSL_CTX_use_PrivateKey_file(ctx, privkey, SSL_FILETYPE_PEM);
137#ifdef USE_OPENSSL 133# ifdef USE_OPENSSL
138 if (!SSL_CTX_check_private_key(ctx)) { 134 if (!SSL_CTX_check_private_key(ctx)) {
139 printf ("%s\n", _("CRITICAL - Private key does not seem to match certificate!\n")); 135 printf("%s\n", _("CRITICAL - Private key does not seem to match certificate!\n"));
140 return STATE_CRITICAL; 136 return STATE_CRITICAL;
141 } 137 }
142#endif 138# endif
143 } 139 }
144#ifdef SSL_OP_NO_TICKET 140# ifdef SSL_OP_NO_TICKET
145 options |= SSL_OP_NO_TICKET; 141 options |= SSL_OP_NO_TICKET;
146#endif 142# endif
147 SSL_CTX_set_options(ctx, options); 143 SSL_CTX_set_options(ctx, options);
148 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 144 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
149 if ((s = SSL_new(ctx)) != NULL) { 145 if ((s = SSL_new(ctx)) != NULL) {
150#ifdef SSL_set_tlsext_host_name 146# ifdef SSL_set_tlsext_host_name
151 if (host_name != NULL) 147 if (host_name != NULL)
152 SSL_set_tlsext_host_name(s, host_name); 148 SSL_set_tlsext_host_name(s, host_name);
153#endif 149# endif
154 SSL_set_fd(s, sd); 150 SSL_set_fd(s, sd);
155 if (SSL_connect(s) == 1) { 151 if (SSL_connect(s) == 1) {
156 return OK; 152 return OK;
157 } else { 153 } else {
158 printf("%s\n", _("CRITICAL - Cannot make SSL connection.")); 154 printf("%s\n", _("CRITICAL - Cannot make SSL connection."));
159# ifdef USE_OPENSSL /* XXX look into ERR_error_string */ 155# ifdef USE_OPENSSL /* XXX look into ERR_error_string */
160 ERR_print_errors_fp(stdout); 156 ERR_print_errors_fp(stdout);
161# endif /* USE_OPENSSL */ 157# endif /* USE_OPENSSL */
162 } 158 }
163 } else { 159 } else {
164 printf("%s\n", _("CRITICAL - Cannot initiate SSL handshake.")); 160 printf("%s\n", _("CRITICAL - Cannot initiate SSL handshake."));
165 } 161 }
166 return STATE_CRITICAL; 162 return STATE_CRITICAL;
167} 163}
168 164
169void np_net_ssl_cleanup() { 165void np_net_ssl_cleanup() {
170 if (s) { 166 if (s) {
171#ifdef SSL_set_tlsext_host_name 167# ifdef SSL_set_tlsext_host_name
172 SSL_set_tlsext_host_name(s, NULL); 168 SSL_set_tlsext_host_name(s, NULL);
173#endif 169# endif
174 SSL_shutdown(s); 170 SSL_shutdown(s);
175 SSL_free(s); 171 SSL_free(s);
176 if (ctx) { 172 if (ctx) {
177 SSL_CTX_free(ctx); 173 SSL_CTX_free(ctx);
178 ctx=NULL; 174 ctx = NULL;
179 } 175 }
180 s=NULL; 176 s = NULL;
181 } 177 }
182} 178}
183 179
184int np_net_ssl_write(const void *buf, int num) { 180int np_net_ssl_write(const void *buf, int num) { return SSL_write(s, buf, num); }
185 return SSL_write(s, buf, num);
186}
187 181
188int np_net_ssl_read(void *buf, int num) { 182int np_net_ssl_read(void *buf, int num) { return SSL_read(s, buf, num); }
189 return SSL_read(s, buf, num);
190}
191 183
192int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit){ 184int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit) {
193# ifdef USE_OPENSSL 185# ifdef USE_OPENSSL
194 X509_NAME *subj=NULL; 186 X509_NAME *subj = NULL;
195 char timestamp[50] = ""; 187 char timestamp[50] = "";
196 char cn[MAX_CN_LENGTH]= ""; 188 char cn[MAX_CN_LENGTH] = "";
197 char *tz; 189 char *tz;
198 190
199 int cnlen =-1; 191 int cnlen = -1;
200 int status=STATE_UNKNOWN; 192 int status = STATE_UNKNOWN;
201 193
202 ASN1_STRING *tm; 194 ASN1_STRING *tm;
203 int offset; 195 int offset;
@@ -208,15 +200,15 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
208 time_t tm_t; 200 time_t tm_t;
209 201
210 if (!certificate) { 202 if (!certificate) {
211 printf("%s\n",_("CRITICAL - Cannot retrieve server certificate.")); 203 printf("%s\n", _("CRITICAL - Cannot retrieve server certificate."));
212 return STATE_CRITICAL; 204 return STATE_CRITICAL;
213 } 205 }
214 206
215 /* Extract CN from certificate subject */ 207 /* Extract CN from certificate subject */
216 subj=X509_get_subject_name(certificate); 208 subj = X509_get_subject_name(certificate);
217 209
218 if (!subj) { 210 if (!subj) {
219 printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject.")); 211 printf("%s\n", _("CRITICAL - Cannot retrieve certificate subject."));
220 return STATE_CRITICAL; 212 return STATE_CRITICAL;
221 } 213 }
222 cnlen = X509_NAME_get_text_by_NID(subj, NID_commonName, cn, sizeof(cn)); 214 cnlen = X509_NAME_get_text_by_NID(subj, NID_commonName, cn, sizeof(cn));
@@ -242,23 +234,16 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
242 printf("%s\n", _("CRITICAL - Wrong time format in certificate.")); 234 printf("%s\n", _("CRITICAL - Wrong time format in certificate."));
243 return STATE_CRITICAL; 235 return STATE_CRITICAL;
244 } else { 236 } else {
245 stamp.tm_year = 237 stamp.tm_year = (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 + (tm->data[2] - '0') * 10 + (tm->data[3] - '0');
246 (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
247 (tm->data[2] - '0') * 10 + (tm->data[3] - '0');
248 stamp.tm_year -= 1900; 238 stamp.tm_year -= 1900;
249 offset = 2; 239 offset = 2;
250 } 240 }
251 } 241 }
252 stamp.tm_mon = 242 stamp.tm_mon = (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
253 (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1; 243 stamp.tm_mday = (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
254 stamp.tm_mday = 244 stamp.tm_hour = (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
255 (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0'); 245 stamp.tm_min = (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
256 stamp.tm_hour = 246 stamp.tm_sec = (tm->data[10 + offset] - '0') * 10 + (tm->data[11 + offset] - '0');
257 (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
258 stamp.tm_min =
259 (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
260 stamp.tm_sec =
261 (tm->data[10 + offset] - '0') * 10 + (tm->data[11 + offset] - '0');
262 stamp.tm_isdst = -1; 247 stamp.tm_isdst = -1;
263 248
264 tm_t = timegm(&stamp); 249 tm_t = timegm(&stamp);
@@ -275,30 +260,30 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
275 tzset(); 260 tzset();
276 261
277 if (days_left > 0 && days_left <= days_till_exp_warn) { 262 if (days_left > 0 && days_left <= days_till_exp_warn) {
278 printf (_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", cn, days_left, timestamp); 263 printf(_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", cn,
264 days_left, timestamp);
279 if (days_left > days_till_exp_crit) 265 if (days_left > days_till_exp_crit)
280 status = STATE_WARNING; 266 status = STATE_WARNING;
281 else 267 else
282 status = STATE_CRITICAL; 268 status = STATE_CRITICAL;
283 } else if (days_left == 0 && time_left > 0) { 269 } else if (days_left == 0 && time_left > 0) {
284 if (time_left >= 3600) 270 if (time_left >= 3600)
285 time_remaining = (int) time_left / 3600; 271 time_remaining = (int)time_left / 3600;
286 else 272 else
287 time_remaining = (int) time_left / 60; 273 time_remaining = (int)time_left / 60;
288 274
289 printf (_("%s - Certificate '%s' expires in %u %s (%s)\n"), 275 printf(_("%s - Certificate '%s' expires in %u %s (%s)\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", cn,
290 (days_left>days_till_exp_crit) ? "WARNING" : "CRITICAL", cn, time_remaining, 276 time_remaining, time_left >= 3600 ? "hours" : "minutes", timestamp);
291 time_left >= 3600 ? "hours" : "minutes", timestamp);
292 277
293 if ( days_left > days_till_exp_crit) 278 if (days_left > days_till_exp_crit)
294 status = STATE_WARNING; 279 status = STATE_WARNING;
295 else 280 else
296 status = STATE_CRITICAL; 281 status = STATE_CRITICAL;
297 } else if (time_left < 0) { 282 } else if (time_left < 0) {
298 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), cn, timestamp); 283 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), cn, timestamp);
299 status=STATE_CRITICAL; 284 status = STATE_CRITICAL;
300 } else if (days_left == 0) { 285 } else if (days_left == 0) {
301 printf (_("%s - Certificate '%s' just expired (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", cn, timestamp); 286 printf(_("%s - Certificate '%s' just expired (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", cn, timestamp);
302 if (days_left > days_till_exp_crit) 287 if (days_left > days_till_exp_crit)
303 status = STATE_WARNING; 288 status = STATE_WARNING;
304 else 289 else
@@ -309,22 +294,21 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
309 } 294 }
310 X509_free(certificate); 295 X509_free(certificate);
311 return status; 296 return status;
312# else /* ifndef USE_OPENSSL */ 297# else /* ifndef USE_OPENSSL */
313 printf("%s\n", _("WARNING - Plugin does not support checking certificates.")); 298 printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
314 return STATE_WARNING; 299 return STATE_WARNING;
315# endif /* USE_OPENSSL */ 300# endif /* USE_OPENSSL */
316} 301}
317 302
318int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){ 303int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit) {
319# ifdef USE_OPENSSL 304# ifdef USE_OPENSSL
320 X509 *certificate = NULL; 305 X509 *certificate = NULL;
321 certificate=SSL_get_peer_certificate(s); 306 certificate = SSL_get_peer_certificate(s);
322 return(np_net_ssl_check_certificate(certificate, days_till_exp_warn, days_till_exp_crit)); 307 return (np_net_ssl_check_certificate(certificate, days_till_exp_warn, days_till_exp_crit));
323# else /* ifndef USE_OPENSSL */ 308# else /* ifndef USE_OPENSSL */
324 printf("%s\n", _("WARNING - Plugin does not support checking certificates.")); 309 printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
325 return STATE_WARNING; 310 return STATE_WARNING;
326# endif /* USE_OPENSSL */ 311# endif /* USE_OPENSSL */
327} 312}
328 313
329
330#endif /* HAVE_SSL */ 314#endif /* HAVE_SSL */
diff --git a/plugins/urlize.c b/plugins/urlize.c
index 6fda72d1..1aa4e425 100644
--- a/plugins/urlize.c
+++ b/plugins/urlize.c
@@ -1,51 +1,49 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring urlize plugin 3 * Monitoring urlize plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the urlize plugin 10 * This file contains the urlize plugin
11* 11 *
12* This plugin wraps the text output of another command (plugin) in HTML <A> 12 * This plugin wraps the text output of another command (plugin) in HTML <A>
13* tags. This plugin returns the status of the invoked plugin. 13 * tags. This plugin returns the status of the invoked plugin.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "urlize"; 32const char *progname = "urlize";
33const char *copyright = "2000-2006"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
37#include "utils.h" 37#include "utils.h"
38#include "popen.h" 38#include "popen.h"
39 39
40#define PERF_CHARACTER "|" 40#define PERF_CHARACTER "|"
41#define NEWLINE_CHARACTER '\n' 41#define NEWLINE_CHARACTER '\n'
42 42
43void print_help (void); 43void print_help(void);
44void print_usage (void); 44void print_usage(void);
45 45
46int 46int main(int argc, char **argv) {
47main (int argc, char **argv)
48{
49 int found = 0, result = STATE_UNKNOWN; 47 int found = 0, result = STATE_UNKNOWN;
50 char *url = NULL; 48 char *url = NULL;
51 char *cmd; 49 char *cmd;
@@ -56,79 +54,72 @@ main (int argc, char **argv)
56 int c; 54 int c;
57 int option = 0; 55 int option = 0;
58 static struct option longopts[] = { 56 static struct option longopts[] = {
59 {"help", no_argument, 0, 'h'}, 57 {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"url", required_argument, 0, 'u'}, {0, 0, 0, 0}};
60 {"version", no_argument, 0, 'V'},
61 {"url", required_argument, 0, 'u'},
62 {0, 0, 0, 0}
63 };
64 58
65 setlocale (LC_ALL, ""); 59 setlocale(LC_ALL, "");
66 bindtextdomain (PACKAGE, LOCALEDIR); 60 bindtextdomain(PACKAGE, LOCALEDIR);
67 textdomain (PACKAGE); 61 textdomain(PACKAGE);
68 62
69 /* Need at least 2 args */ 63 /* Need at least 2 args */
70 if (argc < 3) { 64 if (argc < 3) {
71 print_help(); 65 print_help();
72 exit (STATE_UNKNOWN); 66 exit(STATE_UNKNOWN);
73 } 67 }
74 68
75 while (1) { 69 while (1) {
76 c = getopt_long (argc, argv, "+hVu:", longopts, &option); 70 c = getopt_long(argc, argv, "+hVu:", longopts, &option);
77 71
78 if (c == -1 || c == EOF) 72 if (c == -1 || c == EOF)
79 break; 73 break;
80 74
81 switch (c) { 75 switch (c) {
82 case 'h': /* help */ 76 case 'h': /* help */
83 print_help (); 77 print_help();
84 exit (EXIT_SUCCESS); 78 exit(EXIT_SUCCESS);
85 break; 79 break;
86 case 'V': /* version */ 80 case 'V': /* version */
87 print_revision (progname, NP_VERSION); 81 print_revision(progname, NP_VERSION);
88 exit (EXIT_SUCCESS); 82 exit(EXIT_SUCCESS);
89 break; 83 break;
90 case 'u': 84 case 'u':
91 url = strdup (argv[optind]); 85 url = strdup(argv[optind]);
92 break; 86 break;
93 case '?': 87 case '?':
94 default: 88 default:
95 usage5 (); 89 usage5();
96 } 90 }
97 } 91 }
98 92
99 if (url == NULL) 93 if (url == NULL)
100 url = strdup (argv[optind++]); 94 url = strdup(argv[optind++]);
101 95
102 cmd = strdup (argv[optind++]); 96 cmd = strdup(argv[optind++]);
103 for (c = optind; c < argc; c++) { 97 for (c = optind; c < argc; c++) {
104 xasprintf (&cmd, "%s %s", cmd, argv[c]); 98 xasprintf(&cmd, "%s %s", cmd, argv[c]);
105 } 99 }
106 100
107 child_process = spopen (cmd); 101 child_process = spopen(cmd);
108 if (child_process == NULL) { 102 if (child_process == NULL) {
109 printf (_("Could not open pipe: %s\n"), cmd); 103 printf(_("Could not open pipe: %s\n"), cmd);
110 exit (STATE_UNKNOWN); 104 exit(STATE_UNKNOWN);
111 } 105 }
112 106
113 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 107 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
114 if (child_stderr == NULL) { 108 if (child_stderr == NULL) {
115 printf (_("Could not open stderr for %s\n"), cmd); 109 printf(_("Could not open stderr for %s\n"), cmd);
116 } 110 }
117 111
118 bzero(tstr, sizeof(tstr)); 112 bzero(tstr, sizeof(tstr));
119 buf = malloc(MAX_INPUT_BUFFER); 113 buf = malloc(MAX_INPUT_BUFFER);
120 printf ("<A href=\"%s\">", argv[1]); 114 printf("<A href=\"%s\">", argv[1]);
121 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) { 115 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) {
122 found++; 116 found++;
123 /* Collect the string in temp str so we can tokenize */ 117 /* Collect the string in temp str so we can tokenize */
124 strcat(tstr, buf); 118 strcat(tstr, buf);
125 } 119 }
126 120
127 if (!found) 121 if (!found)
128 die (STATE_UNKNOWN, 122 die(STATE_UNKNOWN, _("%s UNKNOWN - No data received from host\nCMD: %s</A>\n"), argv[0], cmd);
129 _("%s UNKNOWN - No data received from host\nCMD: %s</A>\n"),
130 argv[0], cmd);
131
132 123
133 /* chop the newline character */ 124 /* chop the newline character */
134 if ((nstr = strchr(tstr, NEWLINE_CHARACTER)) != NULL) 125 if ((nstr = strchr(tstr, NEWLINE_CHARACTER)) != NULL)
@@ -136,63 +127,55 @@ main (int argc, char **argv)
136 127
137 /* tokenize the string for Perfdata if there is some */ 128 /* tokenize the string for Perfdata if there is some */
138 nstr = strtok(tstr, PERF_CHARACTER); 129 nstr = strtok(tstr, PERF_CHARACTER);
139 printf ("%s", nstr); 130 printf("%s", nstr);
140 printf ("</A>"); 131 printf("</A>");
141 nstr = strtok(NULL, PERF_CHARACTER); 132 nstr = strtok(NULL, PERF_CHARACTER);
142 if (nstr != NULL) 133 if (nstr != NULL)
143 printf (" | %s", nstr); 134 printf(" | %s", nstr);
144 135
145 /* close the pipe */ 136 /* close the pipe */
146 result = spclose (child_process); 137 result = spclose(child_process);
147 138
148 /* WARNING if output found on stderr */ 139 /* WARNING if output found on stderr */
149 if (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) 140 if (fgets(buf, MAX_INPUT_BUFFER - 1, child_stderr))
150 result = max_state (result, STATE_WARNING); 141 result = max_state(result, STATE_WARNING);
151 142
152 /* close stderr */ 143 /* close stderr */
153 (void) fclose (child_stderr); 144 (void)fclose(child_stderr);
154 145
155 return result; 146 return result;
156} 147}
157 148
149void print_help(void) {
150 print_revision(progname, NP_VERSION);
158 151
152 printf("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
153 printf(COPYRIGHT, copyright, email);
159 154
160void 155 printf("%s\n", _("This plugin wraps the text output of another command (plugin) in HTML <A>"));
161print_help (void) 156 printf("%s\n", _("tags, thus displaying the child plugin's output as a clickable link in compatible"));
162{ 157 printf("%s\n", _("monitoring status screen. This plugin returns the status of the invoked plugin."));
163 print_revision (progname, NP_VERSION);
164
165 printf ("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
166 printf (COPYRIGHT, copyright, email);
167
168 printf ("%s\n", _("This plugin wraps the text output of another command (plugin) in HTML <A>"));
169 printf ("%s\n", _("tags, thus displaying the child plugin's output as a clickable link in compatible"));
170 printf ("%s\n", _("monitoring status screen. This plugin returns the status of the invoked plugin."));
171 158
172 printf ("\n\n"); 159 printf("\n\n");
173 160
174 print_usage (); 161 print_usage();
175 162
176 printf (UT_HELP_VRSN); 163 printf(UT_HELP_VRSN);
177 164
178 printf ("\n"); 165 printf("\n");
179 printf ("%s\n", _("Examples:")); 166 printf("%s\n", _("Examples:"));
180 printf ("%s\n", _("Pay close attention to quoting to ensure that the shell passes the expected")); 167 printf("%s\n", _("Pay close attention to quoting to ensure that the shell passes the expected"));
181 printf ("%s\n\n", _("data to the plugin. For example, in:")); 168 printf("%s\n\n", _("data to the plugin. For example, in:"));
182 printf (" %s\n\n", _("urlize http://example.com/ check_http -H example.com -r 'two words'")); 169 printf(" %s\n\n", _("urlize http://example.com/ check_http -H example.com -r 'two words'"));
183 printf (" %s\n", _("the shell will remove the single quotes and urlize will see:")); 170 printf(" %s\n", _("the shell will remove the single quotes and urlize will see:"));
184 printf (" %s\n\n", _("urlize http://example.com/ check_http -H example.com -r two words")); 171 printf(" %s\n\n", _("urlize http://example.com/ check_http -H example.com -r two words"));
185 printf (" %s\n\n", _("You probably want:")); 172 printf(" %s\n\n", _("You probably want:"));
186 printf (" %s\n", _("urlize http://example.com/ \"check_http -H example.com -r 'two words'\"")); 173 printf(" %s\n", _("urlize http://example.com/ \"check_http -H example.com -r 'two words'\""));
187 174
188 printf (UT_SUPPORT); 175 printf(UT_SUPPORT);
189} 176}
190 177
191 178void print_usage(void) {
192 179 printf("%s\n", _("Usage:"));
193void 180 printf("%s <url> <plugin> <arg1> ... <argN>\n", progname);
194print_usage (void)
195{
196 printf ("%s\n", _("Usage:"));
197 printf ("%s <url> <plugin> <arg1> ... <argN>\n", progname);
198} 181}
diff --git a/plugins/utils.c b/plugins/utils.c
index 77d6a6f9..f11db731 100644
--- a/plugins/utils.c
+++ b/plugins/utils.c
@@ -1,26 +1,26 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Library of useful functions for plugins 3 * Library of useful functions for plugins
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net) 6 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
7* Copyright (c) 2002-2007 Monitoring Plugins Development Team 7 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
8* 8 *
9* This program is free software: you can redistribute it and/or modify 9 * This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 3 of the License, or 11 * the Free Software Foundation, either version 3 of the License, or
12* (at your option) any later version. 12 * (at your option) any later version.
13* 13 *
14* This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details. 17 * GNU General Public License for more details.
18* 18 *
19* You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21* 21 *
22* 22 *
23*****************************************************************************/ 23 *****************************************************************************/
24 24
25#include "common.h" 25#include "common.h"
26#include "./utils.h" 26#include "./utils.h"
@@ -34,7 +34,7 @@
34 34
35#include <arpa/inet.h> 35#include <arpa/inet.h>
36 36
37extern void print_usage (void); 37extern void print_usage(void);
38extern const char *progname; 38extern const char *progname;
39 39
40#define STRLEN 64 40#define STRLEN 64
@@ -50,9 +50,7 @@ time_t start_time, end_time;
50 * Note that numerically the above does not hold 50 * Note that numerically the above does not hold
51 ****************************************************************************/ 51 ****************************************************************************/
52 52
53int 53int max_state(int a, int b) {
54max_state (int a, int b)
55{
56 if (a == STATE_CRITICAL || b == STATE_CRITICAL) 54 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
57 return STATE_CRITICAL; 55 return STATE_CRITICAL;
58 else if (a == STATE_WARNING || b == STATE_WARNING) 56 else if (a == STATE_WARNING || b == STATE_WARNING)
@@ -64,7 +62,7 @@ max_state (int a, int b)
64 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT) 62 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
65 return STATE_DEPENDENT; 63 return STATE_DEPENDENT;
66 else 64 else
67 return max (a, b); 65 return max(a, b);
68} 66}
69 67
70/* ************************************************************************** 68/* **************************************************************************
@@ -77,9 +75,7 @@ max_state (int a, int b)
77 * non-OK state. 75 * non-OK state.
78 ****************************************************************************/ 76 ****************************************************************************/
79 77
80int 78int max_state_alt(int a, int b) {
81max_state_alt (int a, int b)
82{
83 if (a == STATE_CRITICAL || b == STATE_CRITICAL) 79 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
84 return STATE_CRITICAL; 80 return STATE_CRITICAL;
85 else if (a == STATE_WARNING || b == STATE_WARNING) 81 else if (a == STATE_WARNING || b == STATE_WARNING)
@@ -91,124 +87,112 @@ max_state_alt (int a, int b)
91 else if (a == STATE_OK || b == STATE_OK) 87 else if (a == STATE_OK || b == STATE_OK)
92 return STATE_OK; 88 return STATE_OK;
93 else 89 else
94 return max (a, b); 90 return max(a, b);
95} 91}
96 92
97void usage (const char *msg) 93void usage(const char *msg) {
98{ 94 printf("%s\n", msg);
99 printf ("%s\n", msg); 95 print_usage();
100 print_usage (); 96 exit(STATE_UNKNOWN);
101 exit (STATE_UNKNOWN);
102} 97}
103 98
104void usage_va (const char *fmt, ...) 99void usage_va(const char *fmt, ...) {
105{
106 va_list ap; 100 va_list ap;
107 printf("%s: ", progname); 101 printf("%s: ", progname);
108 va_start(ap, fmt); 102 va_start(ap, fmt);
109 vprintf(fmt, ap); 103 vprintf(fmt, ap);
110 va_end(ap); 104 va_end(ap);
111 printf("\n"); 105 printf("\n");
112 exit (STATE_UNKNOWN); 106 exit(STATE_UNKNOWN);
113} 107}
114 108
115void usage2(const char *msg, const char *arg) 109void usage2(const char *msg, const char *arg) {
116{ 110 printf("%s: %s - %s\n", progname, msg, arg ? arg : "(null)");
117 printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" ); 111 print_usage();
118 print_usage (); 112 exit(STATE_UNKNOWN);
119 exit (STATE_UNKNOWN);
120} 113}
121 114
122void 115void usage3(const char *msg, int arg) {
123usage3 (const char *msg, int arg) 116 printf("%s: %s - %c\n", progname, msg, arg);
124{
125 printf ("%s: %s - %c\n", progname, msg, arg);
126 print_usage(); 117 print_usage();
127 exit (STATE_UNKNOWN); 118 exit(STATE_UNKNOWN);
128} 119}
129 120
130void 121void usage4(const char *msg) {
131usage4 (const char *msg) 122 printf("%s: %s\n", progname, msg);
132{
133 printf ("%s: %s\n", progname, msg);
134 print_usage(); 123 print_usage();
135 exit (STATE_UNKNOWN); 124 exit(STATE_UNKNOWN);
136} 125}
137 126
138void 127void usage5(void) {
139usage5 (void)
140{
141 print_usage(); 128 print_usage();
142 exit (STATE_UNKNOWN); 129 exit(STATE_UNKNOWN);
143} 130}
144 131
145void 132void print_revision(const char *command_name, const char *revision) {
146print_revision (const char *command_name, const char *revision) 133 printf("%s v%s (%s %s)\n", command_name, revision, PACKAGE, VERSION);
147{
148 printf ("%s v%s (%s %s)\n",
149 command_name, revision, PACKAGE, VERSION);
150} 134}
151 135
152bool is_numeric (char *number) { 136bool is_numeric(char *number) {
153 char tmp[1]; 137 char tmp[1];
154 float x; 138 float x;
155 139
156 if (!number) 140 if (!number)
157 return false; 141 return false;
158 else if (sscanf (number, "%f%c", &x, tmp) == 1) 142 else if (sscanf(number, "%f%c", &x, tmp) == 1)
159 return true; 143 return true;
160 else 144 else
161 return false; 145 return false;
162} 146}
163 147
164bool is_positive (char *number) { 148bool is_positive(char *number) {
165 if (is_numeric (number) && atof (number) > 0.0) 149 if (is_numeric(number) && atof(number) > 0.0)
166 return true; 150 return true;
167 else 151 else
168 return false; 152 return false;
169} 153}
170 154
171bool is_negative (char *number) { 155bool is_negative(char *number) {
172 if (is_numeric (number) && atof (number) < 0.0) 156 if (is_numeric(number) && atof(number) < 0.0)
173 return true; 157 return true;
174 else 158 else
175 return false; 159 return false;
176} 160}
177 161
178bool is_nonnegative (char *number) { 162bool is_nonnegative(char *number) {
179 if (is_numeric (number) && atof (number) >= 0.0) 163 if (is_numeric(number) && atof(number) >= 0.0)
180 return true; 164 return true;
181 else 165 else
182 return false; 166 return false;
183} 167}
184 168
185bool is_percentage (char *number) { 169bool is_percentage(char *number) {
186 int x; 170 int x;
187 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100) 171 if (is_numeric(number) && (x = atof(number)) >= 0 && x <= 100)
188 return true; 172 return true;
189 else 173 else
190 return false; 174 return false;
191} 175}
192 176
193bool is_percentage_expression (const char str[]) { 177bool is_percentage_expression(const char str[]) {
194 if (!str) { 178 if (!str) {
195 return false; 179 return false;
196 } 180 }
197 181
198 size_t len = strlen(str); 182 size_t len = strlen(str);
199 183
200 if (str[len-1] != '%') { 184 if (str[len - 1] != '%') {
201 return false; 185 return false;
202 } 186 }
203 187
204 char *foo = calloc(sizeof(char), len + 1); 188 char *foo = calloc(sizeof(char), len + 1);
205 189
206 if (!foo) { 190 if (!foo) {
207 die (STATE_UNKNOWN, _("calloc failed \n")); 191 die(STATE_UNKNOWN, _("calloc failed \n"));
208 } 192 }
209 193
210 strcpy(foo, str); 194 strcpy(foo, str);
211 foo[len-1] = '\0'; 195 foo[len - 1] = '\0';
212 196
213 bool result = is_numeric(foo); 197 bool result = is_numeric(foo);
214 198
@@ -217,13 +201,13 @@ bool is_percentage_expression (const char str[]) {
217 return result; 201 return result;
218} 202}
219 203
220bool is_integer (char *number) { 204bool is_integer(char *number) {
221 long int n; 205 long int n;
222 206
223 if (!number || (strspn (number, "-0123456789 ") != strlen (number))) 207 if (!number || (strspn(number, "-0123456789 ") != strlen(number)))
224 return false; 208 return false;
225 209
226 n = strtol (number, NULL, 10); 210 n = strtol(number, NULL, 10);
227 211
228 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX) 212 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
229 return true; 213 return true;
@@ -231,22 +215,22 @@ bool is_integer (char *number) {
231 return false; 215 return false;
232} 216}
233 217
234bool is_intpos (char *number) { 218bool is_intpos(char *number) {
235 if (is_integer (number) && atoi (number) > 0) 219 if (is_integer(number) && atoi(number) > 0)
236 return true; 220 return true;
237 else 221 else
238 return false; 222 return false;
239} 223}
240 224
241bool is_intneg (char *number) { 225bool is_intneg(char *number) {
242 if (is_integer (number) && atoi (number) < 0) 226 if (is_integer(number) && atoi(number) < 0)
243 return true; 227 return true;
244 else 228 else
245 return false; 229 return false;
246} 230}
247 231
248bool is_intnonneg (char *number) { 232bool is_intnonneg(char *number) {
249 if (is_integer (number) && atoi (number) >= 0) 233 if (is_integer(number) && atoi(number) >= 0)
250 return true; 234 return true;
251 else 235 else
252 return false; 236 return false;
@@ -259,7 +243,7 @@ bool is_intnonneg (char *number) {
259 */ 243 */
260bool is_int64(char *number, int64_t *target) { 244bool is_int64(char *number, int64_t *target) {
261 errno = 0; 245 errno = 0;
262 char *endptr = { 0 }; 246 char *endptr = {0};
263 247
264 int64_t tmp = strtoll(number, &endptr, 10); 248 int64_t tmp = strtoll(number, &endptr, 10);
265 if (errno != 0) { 249 if (errno != 0) {
@@ -287,7 +271,7 @@ bool is_int64(char *number, int64_t *target) {
287 */ 271 */
288bool is_uint64(char *number, uint64_t *target) { 272bool is_uint64(char *number, uint64_t *target) {
289 errno = 0; 273 errno = 0;
290 char *endptr = { 0 }; 274 char *endptr = {0};
291 unsigned long long tmp = strtoull(number, &endptr, 10); 275 unsigned long long tmp = strtoull(number, &endptr, 10);
292 276
293 if (errno != 0) { 277 if (errno != 0) {
@@ -309,66 +293,50 @@ bool is_uint64(char *number, uint64_t *target) {
309 return true; 293 return true;
310} 294}
311 295
312bool is_intpercent (char *number) { 296bool is_intpercent(char *number) {
313 int i; 297 int i;
314 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100) 298 if (is_integer(number) && (i = atoi(number)) >= 0 && i <= 100)
315 return true; 299 return true;
316 else 300 else
317 return false; 301 return false;
318} 302}
319 303
320bool is_option (char *str) { 304bool is_option(char *str) {
321 if (!str) 305 if (!str)
322 return false; 306 return false;
323 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2) 307 else if (strspn(str, "-") == 1 || strspn(str, "-") == 2)
324 return true; 308 return true;
325 else 309 else
326 return false; 310 return false;
327} 311}
328 312
329#ifdef NEED_GETTIMEOFDAY 313#ifdef NEED_GETTIMEOFDAY
330int 314int gettimeofday(struct timeval *tv, struct timezone *tz) {
331gettimeofday (struct timeval *tv, struct timezone *tz)
332{
333 tv->tv_usec = 0; 315 tv->tv_usec = 0;
334 tv->tv_sec = (long) time ((time_t) 0); 316 tv->tv_sec = (long)time((time_t)0);
335} 317}
336#endif 318#endif
337 319
338 320double delta_time(struct timeval tv) {
339
340double
341delta_time (struct timeval tv)
342{
343 struct timeval now; 321 struct timeval now;
344 322
345 gettimeofday (&now, NULL); 323 gettimeofday(&now, NULL);
346 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000); 324 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
347} 325}
348 326
349 327long deltime(struct timeval tv) {
350
351long
352deltime (struct timeval tv)
353{
354 struct timeval now; 328 struct timeval now;
355 gettimeofday (&now, NULL); 329 gettimeofday(&now, NULL);
356 return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec; 330 return (now.tv_sec - tv.tv_sec) * 1000000 + now.tv_usec - tv.tv_usec;
357} 331}
358 332
359 333void strip(char *buffer) {
360
361
362void
363strip (char *buffer)
364{
365 size_t x; 334 size_t x;
366 int i; 335 int i;
367 336
368 for (x = strlen (buffer); x >= 1; x--) { 337 for (x = strlen(buffer); x >= 1; x--) {
369 i = x - 1; 338 i = x - 1;
370 if (buffer[i] == ' ' || 339 if (buffer[i] == ' ' || buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
371 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
372 buffer[i] = '\0'; 340 buffer[i] = '\0';
373 else 341 else
374 break; 342 break;
@@ -376,7 +344,6 @@ strip (char *buffer)
376 return; 344 return;
377} 345}
378 346
379
380/****************************************************************************** 347/******************************************************************************
381 * 348 *
382 * Copies one string to another. Any previously existing data in 349 * Copies one string to another. Any previously existing data in
@@ -389,19 +356,15 @@ strip (char *buffer)
389 * 356 *
390 *****************************************************************************/ 357 *****************************************************************************/
391 358
392char * 359char *strscpy(char *dest, const char *src) {
393strscpy (char *dest, const char *src)
394{
395 if (src == NULL) 360 if (src == NULL)
396 return NULL; 361 return NULL;
397 362
398 xasprintf (&dest, "%s", src); 363 xasprintf(&dest, "%s", src);
399 364
400 return dest; 365 return dest;
401} 366}
402 367
403
404
405/****************************************************************************** 368/******************************************************************************
406 * 369 *
407 * Returns a pointer to the next line of a multiline string buffer 370 * Returns a pointer to the next line of a multiline string buffer
@@ -418,7 +381,7 @@ strscpy (char *dest, const char *src)
418 * This 381 * This
419 * is 382 * is
420 * a 383 * a
421 * 384 *
422 * multiline string buffer 385 * multiline string buffer
423 * ============================== 386 * ==============================
424 * 387 *
@@ -431,7 +394,7 @@ strscpy (char *dest, const char *src)
431 * printf("%d %s",i++,firstword(ptr)); 394 * printf("%d %s",i++,firstword(ptr));
432 * ptr = strnl(ptr); 395 * ptr = strnl(ptr);
433 * } 396 * }
434 * 397 *
435 * Produces the following: 398 * Produces the following:
436 * 399 *
437 * 1 This 400 * 1 This
@@ -452,25 +415,22 @@ strscpy (char *dest, const char *src)
452 * 415 *
453 *****************************************************************************/ 416 *****************************************************************************/
454 417
455char * 418char *strnl(char *str) {
456strnl (char *str)
457{
458 size_t len; 419 size_t len;
459 if (str == NULL) 420 if (str == NULL)
460 return NULL; 421 return NULL;
461 str = strpbrk (str, "\r\n"); 422 str = strpbrk(str, "\r\n");
462 if (str == NULL) 423 if (str == NULL)
463 return NULL; 424 return NULL;
464 len = strspn (str, "\r\n"); 425 len = strspn(str, "\r\n");
465 if (str[len] == '\0') 426 if (str[len] == '\0')
466 return NULL; 427 return NULL;
467 str += len; 428 str += len;
468 if (strlen (str) == 0) 429 if (strlen(str) == 0)
469 return NULL; 430 return NULL;
470 return str; 431 return str;
471} 432}
472 433
473
474/****************************************************************************** 434/******************************************************************************
475 * 435 *
476 * Like strscpy, except only the portion of the source string up to 436 * Like strscpy, except only the portion of the source string up to
@@ -487,29 +447,25 @@ strnl (char *str)
487 * 447 *
488 *****************************************************************************/ 448 *****************************************************************************/
489 449
490char * 450char *strpcpy(char *dest, const char *src, const char *str) {
491strpcpy (char *dest, const char *src, const char *str)
492{
493 size_t len; 451 size_t len;
494 452
495 if (src) 453 if (src)
496 len = strcspn (src, str); 454 len = strcspn(src, str);
497 else 455 else
498 return NULL; 456 return NULL;
499 457
500 if (dest == NULL || strlen (dest) < len) 458 if (dest == NULL || strlen(dest) < len)
501 dest = realloc (dest, len + 1); 459 dest = realloc(dest, len + 1);
502 if (dest == NULL) 460 if (dest == NULL)
503 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n")); 461 die(STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
504 462
505 strncpy (dest, src, len); 463 strncpy(dest, src, len);
506 dest[len] = '\0'; 464 dest[len] = '\0';
507 465
508 return dest; 466 return dest;
509} 467}
510 468
511
512
513/****************************************************************************** 469/******************************************************************************
514 * 470 *
515 * Like strscat, except only the portion of the source string up to 471 * Like strscat, except only the portion of the source string up to
@@ -518,62 +474,54 @@ strpcpy (char *dest, const char *src, const char *str)
518 * str = strpcpy(str,"This is a line of text with no trailing newline","x"); 474 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
519 * str = strpcat(str,"This is a line of text with no trailing newline","x"); 475 * str = strpcat(str,"This is a line of text with no trailing newline","x");
520 * printf("%s\n",str); 476 * printf("%s\n",str);
521 * 477 *
522 *This is a line of texThis is a line of tex 478 *This is a line of texThis is a line of tex
523 * 479 *
524 *****************************************************************************/ 480 *****************************************************************************/
525 481
526char * 482char *strpcat(char *dest, const char *src, const char *str) {
527strpcat (char *dest, const char *src, const char *str)
528{
529 size_t len, l2; 483 size_t len, l2;
530 484
531 if (dest) 485 if (dest)
532 len = strlen (dest); 486 len = strlen(dest);
533 else 487 else
534 len = 0; 488 len = 0;
535 489
536 if (src) { 490 if (src) {
537 l2 = strcspn (src, str); 491 l2 = strcspn(src, str);
538 } 492 } else {
539 else {
540 return dest; 493 return dest;
541 } 494 }
542 495
543 dest = realloc (dest, len + l2 + 1); 496 dest = realloc(dest, len + l2 + 1);
544 if (dest == NULL) 497 if (dest == NULL)
545 die (STATE_UNKNOWN, _("failed malloc in strscat\n")); 498 die(STATE_UNKNOWN, _("failed malloc in strscat\n"));
546 499
547 strncpy (dest + len, src, l2); 500 strncpy(dest + len, src, l2);
548 dest[len + l2] = '\0'; 501 dest[len + l2] = '\0';
549 502
550 return dest; 503 return dest;
551} 504}
552 505
553
554/****************************************************************************** 506/******************************************************************************
555 * 507 *
556 * asprintf, but die on failure 508 * asprintf, but die on failure
557 * 509 *
558 ******************************************************************************/ 510 ******************************************************************************/
559 511
560int 512int xvasprintf(char **strp, const char *fmt, va_list ap) {
561xvasprintf (char **strp, const char *fmt, va_list ap) 513 int result = vasprintf(strp, fmt, ap);
562{
563 int result = vasprintf (strp, fmt, ap);
564 if (result == -1 || *strp == NULL) 514 if (result == -1 || *strp == NULL)
565 die (STATE_UNKNOWN, _("failed malloc in xvasprintf\n")); 515 die(STATE_UNKNOWN, _("failed malloc in xvasprintf\n"));
566 return result; 516 return result;
567} 517}
568 518
569int 519int xasprintf(char **strp, const char *fmt, ...) {
570xasprintf (char **strp, const char *fmt, ...)
571{
572 va_list ap; 520 va_list ap;
573 int result; 521 int result;
574 va_start (ap, fmt); 522 va_start(ap, fmt);
575 result = xvasprintf (strp, fmt, ap); 523 result = xvasprintf(strp, fmt, ap);
576 va_end (ap); 524 va_end(ap);
577 return result; 525 return result;
578} 526}
579 527
@@ -583,247 +531,192 @@ xasprintf (char **strp, const char *fmt, ...)
583 * 531 *
584 ******************************************************************************/ 532 ******************************************************************************/
585 533
586char *perfdata (const char *label, 534char *perfdata(const char *label, long int val, const char *uom, int warnp, long int warn, int critp, long int crit, int minp,
587 long int val, 535 long int minv, int maxp, long int maxv) {
588 const char *uom,
589 int warnp,
590 long int warn,
591 int critp,
592 long int crit,
593 int minp,
594 long int minv,
595 int maxp,
596 long int maxv)
597{
598 char *data = NULL; 536 char *data = NULL;
599 537
600 if (strpbrk (label, "'= ")) 538 if (strpbrk(label, "'= "))
601 xasprintf (&data, "'%s'=%ld%s;", label, val, uom); 539 xasprintf(&data, "'%s'=%ld%s;", label, val, uom);
602 else 540 else
603 xasprintf (&data, "%s=%ld%s;", label, val, uom); 541 xasprintf(&data, "%s=%ld%s;", label, val, uom);
604 542
605 if (warnp) 543 if (warnp)
606 xasprintf (&data, "%s%ld;", data, warn); 544 xasprintf(&data, "%s%ld;", data, warn);
607 else 545 else
608 xasprintf (&data, "%s;", data); 546 xasprintf(&data, "%s;", data);
609 547
610 if (critp) 548 if (critp)
611 xasprintf (&data, "%s%ld;", data, crit); 549 xasprintf(&data, "%s%ld;", data, crit);
612 else 550 else
613 xasprintf (&data, "%s;", data); 551 xasprintf(&data, "%s;", data);
614 552
615 if (minp) 553 if (minp)
616 xasprintf (&data, "%s%ld;", data, minv); 554 xasprintf(&data, "%s%ld;", data, minv);
617 else 555 else
618 xasprintf (&data, "%s;", data); 556 xasprintf(&data, "%s;", data);
619 557
620 if (maxp) 558 if (maxp)
621 xasprintf (&data, "%s%ld", data, maxv); 559 xasprintf(&data, "%s%ld", data, maxv);
622 560
623 return data; 561 return data;
624} 562}
625 563
626 564char *perfdata_uint64(const char *label, uint64_t val, const char *uom, int warnp, /* Warning present */
627char *perfdata_uint64 (const char *label, 565 uint64_t warn, int critp, /* Critical present */
628 uint64_t val, 566 uint64_t crit, int minp, /* Minimum present */
629 const char *uom, 567 uint64_t minv, int maxp, /* Maximum present */
630 int warnp, /* Warning present */ 568 uint64_t maxv) {
631 uint64_t warn,
632 int critp, /* Critical present */
633 uint64_t crit,
634 int minp, /* Minimum present */
635 uint64_t minv,
636 int maxp, /* Maximum present */
637 uint64_t maxv)
638{
639 char *data = NULL; 569 char *data = NULL;
640 570
641 if (strpbrk (label, "'= ")) 571 if (strpbrk(label, "'= "))
642 xasprintf (&data, "'%s'=%" PRIu64 "%s;", label, val, uom); 572 xasprintf(&data, "'%s'=%" PRIu64 "%s;", label, val, uom);
643 else 573 else
644 xasprintf (&data, "%s=%" PRIu64 "%s;", label, val, uom); 574 xasprintf(&data, "%s=%" PRIu64 "%s;", label, val, uom);
645 575
646 if (warnp) 576 if (warnp)
647 xasprintf (&data, "%s%" PRIu64 ";", data, warn); 577 xasprintf(&data, "%s%" PRIu64 ";", data, warn);
648 else 578 else
649 xasprintf (&data, "%s;", data); 579 xasprintf(&data, "%s;", data);
650 580
651 if (critp) 581 if (critp)
652 xasprintf (&data, "%s%" PRIu64 ";", data, crit); 582 xasprintf(&data, "%s%" PRIu64 ";", data, crit);
653 else 583 else
654 xasprintf (&data, "%s;", data); 584 xasprintf(&data, "%s;", data);
655 585
656 if (minp) 586 if (minp)
657 xasprintf (&data, "%s%" PRIu64 ";", data, minv); 587 xasprintf(&data, "%s%" PRIu64 ";", data, minv);
658 else 588 else
659 xasprintf (&data, "%s;", data); 589 xasprintf(&data, "%s;", data);
660 590
661 if (maxp) 591 if (maxp)
662 xasprintf (&data, "%s%" PRIu64, data, maxv); 592 xasprintf(&data, "%s%" PRIu64, data, maxv);
663 593
664 return data; 594 return data;
665} 595}
666 596
667 597char *perfdata_int64(const char *label, int64_t val, const char *uom, int warnp, /* Warning present */
668char *perfdata_int64 (const char *label, 598 int64_t warn, int critp, /* Critical present */
669 int64_t val, 599 int64_t crit, int minp, /* Minimum present */
670 const char *uom, 600 int64_t minv, int maxp, /* Maximum present */
671 int warnp, /* Warning present */ 601 int64_t maxv) {
672 int64_t warn,
673 int critp, /* Critical present */
674 int64_t crit,
675 int minp, /* Minimum present */
676 int64_t minv,
677 int maxp, /* Maximum present */
678 int64_t maxv)
679{
680 char *data = NULL; 602 char *data = NULL;
681 603
682 if (strpbrk (label, "'= ")) 604 if (strpbrk(label, "'= "))
683 xasprintf (&data, "'%s'=%" PRId64 "%s;", label, val, uom); 605 xasprintf(&data, "'%s'=%" PRId64 "%s;", label, val, uom);
684 else 606 else
685 xasprintf (&data, "%s=%" PRId64 "%s;", label, val, uom); 607 xasprintf(&data, "%s=%" PRId64 "%s;", label, val, uom);
686 608
687 if (warnp) 609 if (warnp)
688 xasprintf (&data, "%s%" PRId64 ";", data, warn); 610 xasprintf(&data, "%s%" PRId64 ";", data, warn);
689 else 611 else
690 xasprintf (&data, "%s;", data); 612 xasprintf(&data, "%s;", data);
691 613
692 if (critp) 614 if (critp)
693 xasprintf (&data, "%s%" PRId64 ";", data, crit); 615 xasprintf(&data, "%s%" PRId64 ";", data, crit);
694 else 616 else
695 xasprintf (&data, "%s;", data); 617 xasprintf(&data, "%s;", data);
696 618
697 if (minp) 619 if (minp)
698 xasprintf (&data, "%s%" PRId64 ";", data, minv); 620 xasprintf(&data, "%s%" PRId64 ";", data, minv);
699 else 621 else
700 xasprintf (&data, "%s;", data); 622 xasprintf(&data, "%s;", data);
701 623
702 if (maxp) 624 if (maxp)
703 xasprintf (&data, "%s%" PRId64, data, maxv); 625 xasprintf(&data, "%s%" PRId64, data, maxv);
704 626
705 return data; 627 return data;
706} 628}
707 629
708 630char *fperfdata(const char *label, double val, const char *uom, int warnp, double warn, int critp, double crit, int minp, double minv,
709char *fperfdata (const char *label, 631 int maxp, double maxv) {
710 double val,
711 const char *uom,
712 int warnp,
713 double warn,
714 int critp,
715 double crit,
716 int minp,
717 double minv,
718 int maxp,
719 double maxv)
720{
721 char *data = NULL; 632 char *data = NULL;
722 633
723 if (strpbrk (label, "'= ")) 634 if (strpbrk(label, "'= "))
724 xasprintf (&data, "'%s'=", label); 635 xasprintf(&data, "'%s'=", label);
725 else 636 else
726 xasprintf (&data, "%s=", label); 637 xasprintf(&data, "%s=", label);
727 638
728 xasprintf (&data, "%s%f", data, val); 639 xasprintf(&data, "%s%f", data, val);
729 xasprintf (&data, "%s%s;", data, uom); 640 xasprintf(&data, "%s%s;", data, uom);
730 641
731 if (warnp) 642 if (warnp)
732 xasprintf (&data, "%s%f", data, warn); 643 xasprintf(&data, "%s%f", data, warn);
733 644
734 xasprintf (&data, "%s;", data); 645 xasprintf(&data, "%s;", data);
735 646
736 if (critp) 647 if (critp)
737 xasprintf (&data, "%s%f", data, crit); 648 xasprintf(&data, "%s%f", data, crit);
738 649
739 xasprintf (&data, "%s;", data); 650 xasprintf(&data, "%s;", data);
740 651
741 if (minp) 652 if (minp)
742 xasprintf (&data, "%s%f", data, minv); 653 xasprintf(&data, "%s%f", data, minv);
743 654
744 if (maxp) { 655 if (maxp) {
745 xasprintf (&data, "%s;", data); 656 xasprintf(&data, "%s;", data);
746 xasprintf (&data, "%s%f", data, maxv); 657 xasprintf(&data, "%s%f", data, maxv);
747 } 658 }
748 659
749 return data; 660 return data;
750} 661}
751 662
752char *sperfdata (const char *label, 663char *sperfdata(const char *label, double val, const char *uom, char *warn, char *crit, int minp, double minv, int maxp, double maxv) {
753 double val,
754 const char *uom,
755 char *warn,
756 char *crit,
757 int minp,
758 double minv,
759 int maxp,
760 double maxv)
761{
762 char *data = NULL; 664 char *data = NULL;
763 if (strpbrk (label, "'= ")) 665 if (strpbrk(label, "'= "))
764 xasprintf (&data, "'%s'=", label); 666 xasprintf(&data, "'%s'=", label);
765 else 667 else
766 xasprintf (&data, "%s=", label); 668 xasprintf(&data, "%s=", label);
767 669
768 xasprintf (&data, "%s%f", data, val); 670 xasprintf(&data, "%s%f", data, val);
769 xasprintf (&data, "%s%s;", data, uom); 671 xasprintf(&data, "%s%s;", data, uom);
770 672
771 if (warn!=NULL) 673 if (warn != NULL)
772 xasprintf (&data, "%s%s", data, warn); 674 xasprintf(&data, "%s%s", data, warn);
773 675
774 xasprintf (&data, "%s;", data); 676 xasprintf(&data, "%s;", data);
775 677
776 if (crit!=NULL) 678 if (crit != NULL)
777 xasprintf (&data, "%s%s", data, crit); 679 xasprintf(&data, "%s%s", data, crit);
778 680
779 xasprintf (&data, "%s;", data); 681 xasprintf(&data, "%s;", data);
780 682
781 if (minp) 683 if (minp)
782 xasprintf (&data, "%s%f", data, minv); 684 xasprintf(&data, "%s%f", data, minv);
783 685
784 if (maxp) { 686 if (maxp) {
785 xasprintf (&data, "%s;", data); 687 xasprintf(&data, "%s;", data);
786 xasprintf (&data, "%s%f", data, maxv); 688 xasprintf(&data, "%s%f", data, maxv);
787 } 689 }
788 690
789 return data; 691 return data;
790} 692}
791 693
792char *sperfdata_int (const char *label, 694char *sperfdata_int(const char *label, int val, const char *uom, char *warn, char *crit, int minp, int minv, int maxp, int maxv) {
793 int val,
794 const char *uom,
795 char *warn,
796 char *crit,
797 int minp,
798 int minv,
799 int maxp,
800 int maxv)
801{
802 char *data = NULL; 695 char *data = NULL;
803 if (strpbrk (label, "'= ")) 696 if (strpbrk(label, "'= "))
804 xasprintf (&data, "'%s'=", label); 697 xasprintf(&data, "'%s'=", label);
805 else 698 else
806 xasprintf (&data, "%s=", label); 699 xasprintf(&data, "%s=", label);
807 700
808 xasprintf (&data, "%s%d", data, val); 701 xasprintf(&data, "%s%d", data, val);
809 xasprintf (&data, "%s%s;", data, uom); 702 xasprintf(&data, "%s%s;", data, uom);
810 703
811 if (warn!=NULL) 704 if (warn != NULL)
812 xasprintf (&data, "%s%s", data, warn); 705 xasprintf(&data, "%s%s", data, warn);
813 706
814 xasprintf (&data, "%s;", data); 707 xasprintf(&data, "%s;", data);
815 708
816 if (crit!=NULL) 709 if (crit != NULL)
817 xasprintf (&data, "%s%s", data, crit); 710 xasprintf(&data, "%s%s", data, crit);
818 711
819 xasprintf (&data, "%s;", data); 712 xasprintf(&data, "%s;", data);
820 713
821 if (minp) 714 if (minp)
822 xasprintf (&data, "%s%d", data, minv); 715 xasprintf(&data, "%s%d", data, minv);
823 716
824 if (maxp) { 717 if (maxp) {
825 xasprintf (&data, "%s;", data); 718 xasprintf(&data, "%s;", data);
826 xasprintf (&data, "%s%d", data, maxv); 719 xasprintf(&data, "%s%d", data, maxv);
827 } 720 }
828 721
829 return data; 722 return data;