summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorKristian Schuster <116557017+KriSchu@users.noreply.github.com>2023-02-19 22:49:18 (GMT)
committerKristian Schuster <116557017+KriSchu@users.noreply.github.com>2023-02-19 22:49:18 (GMT)
commita0d42777217296c0a7bdb1e1be8d8f6de1b24dd7 (patch)
tree8effe94c57b2f9796ba36090b07551baa8f1e1cb /plugins
parentca3d59cd6918c9e2739e783b721d4c1122640fd3 (diff)
parentc07206f2ccc2356aa74bc6813a94c2190017d44e (diff)
downloadmonitoring-plugins-a0d42777217296c0a7bdb1e1be8d8f6de1b24dd7.tar.gz
Merge remote-tracking branch 'origin/master' into feature_check_disk_add_ignore_missing_option
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am4
-rw-r--r--plugins/check_apt.c72
-rw-r--r--plugins/check_curl.c31
-rw-r--r--plugins/check_disk.c4
-rw-r--r--plugins/check_fping.c2
-rw-r--r--plugins/check_http.c318
-rw-r--r--plugins/check_pgsql.c48
-rw-r--r--plugins/check_snmp.c107
-rw-r--r--plugins/sslutils.c34
-rw-r--r--plugins/t/check_curl.t39
-rw-r--r--plugins/t/check_http.t2
-rwxr-xr-xplugins/tests/check_curl.t21
-rwxr-xr-xplugins/tests/check_http.t85
-rwxr-xr-xplugins/tests/check_snmp.t22
-rw-r--r--plugins/tests/check_snmp_agent.pl8
-rw-r--r--plugins/utils.c4
16 files changed, 548 insertions, 253 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 3fde54d..ab59eb7 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -51,10 +51,10 @@ noinst_LIBRARIES = libnpcommon.a
51libnpcommon_a_SOURCES = utils.c netutils.c sslutils.c runcmd.c \ 51libnpcommon_a_SOURCES = utils.c netutils.c sslutils.c runcmd.c \
52 popen.c utils.h netutils.h popen.h common.h runcmd.c runcmd.h 52 popen.c utils.h netutils.h popen.h common.h runcmd.c runcmd.h
53 53
54BASEOBJS = libnpcommon.a ../lib/libmonitoringplug.a ../gl/libgnu.a 54BASEOBJS = libnpcommon.a ../lib/libmonitoringplug.a ../gl/libgnu.a $(LIB_CRYPTO)
55NETOBJS = $(BASEOBJS) $(EXTRA_NETOBLS) 55NETOBJS = $(BASEOBJS) $(EXTRA_NETOBLS)
56NETLIBS = $(NETOBJS) $(SOCKETLIBS) 56NETLIBS = $(NETOBJS) $(SOCKETLIBS)
57SSLOBJS = $(BASEOBJS) $(NETLIBS) $(SSLLIBS) 57SSLOBJS = $(BASEOBJS) $(NETLIBS) $(SSLLIBS) $(LIB_CRYPTO)
58 58
59TESTS_ENVIRONMENT = perl -I $(top_builddir) -I $(top_srcdir) 59TESTS_ENVIRONMENT = perl -I $(top_builddir) -I $(top_srcdir)
60 60
diff --git a/plugins/check_apt.c b/plugins/check_apt.c
index d7be575..fa982ae 100644
--- a/plugins/check_apt.c
+++ b/plugins/check_apt.c
@@ -1,32 +1,32 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2*
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-2008 Monitoring Plugins Development Team
7* 7*
8* Original author: Sean Finney 8* Original author: Sean Finney
9* 9*
10* Description: 10* Description:
11* 11*
12* This file contains the check_apt plugin 12* This file contains the check_apt plugin
13* 13*
14* Check for available updates in apt package management systems 14* Check for available updates in apt package management systems
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
32const char *progname = "check_apt"; 32const char *progname = "check_apt";
@@ -76,9 +76,9 @@ int cmpstringp(const void *p1, const void *p2);
76 76
77/* configuration variables */ 77/* configuration variables */
78static int verbose = 0; /* -v */ 78static int verbose = 0; /* -v */
79static int list = 0; /* list packages available for upgrade */ 79static bool list = false; /* list packages available for upgrade */
80static int do_update = 0; /* whether to call apt-get update */ 80static bool do_update = false; /* whether to call apt-get update */
81static int only_critical = 0; /* whether to warn about non-critical updates */ 81static bool only_critical = false; /* whether to warn about non-critical updates */
82static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */ 82static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */
83static char *upgrade_opts = NULL; /* options to override defaults for upgrade */ 83static char *upgrade_opts = NULL; /* options to override defaults for upgrade */
84static char *update_opts = NULL; /* options to override defaults for update */ 84static char *update_opts = NULL; /* options to override defaults for update */
@@ -119,7 +119,7 @@ int main (int argc, char **argv) {
119 119
120 if(sec_count > 0){ 120 if(sec_count > 0){
121 result = max_state(result, STATE_CRITICAL); 121 result = max_state(result, STATE_CRITICAL);
122 } else if(packages_available >= packages_warning && only_critical == 0){ 122 } else if(packages_available >= packages_warning && only_critical == false){
123 result = max_state(result, STATE_WARNING); 123 result = max_state(result, STATE_WARNING);
124 } else if(result > STATE_UNKNOWN){ 124 } else if(result > STATE_UNKNOWN){
125 result = STATE_UNKNOWN; 125 result = STATE_UNKNOWN;
@@ -144,7 +144,7 @@ int main (int argc, char **argv) {
144 144
145 for(i = 0; i < sec_count; i++) 145 for(i = 0; i < sec_count; i++)
146 printf("%s (security)\n", secpackages_list[i]); 146 printf("%s (security)\n", secpackages_list[i]);
147 if (only_critical == 0) { 147 if (only_critical == false) {
148 for(i = 0; i < packages_available - sec_count; i++) 148 for(i = 0; i < packages_available - sec_count; i++)
149 printf("%s\n", packages_list[i]); 149 printf("%s\n", packages_list[i]);
150 } 150 }
@@ -166,7 +166,7 @@ int process_arguments (int argc, char **argv) {
166 {"upgrade", optional_argument, 0, 'U'}, 166 {"upgrade", optional_argument, 0, 'U'},
167 {"no-upgrade", no_argument, 0, 'n'}, 167 {"no-upgrade", no_argument, 0, 'n'},
168 {"dist-upgrade", optional_argument, 0, 'd'}, 168 {"dist-upgrade", optional_argument, 0, 'd'},
169 {"list", no_argument, 0, 'l'}, 169 {"list", no_argument, false, 'l'},
170 {"include", required_argument, 0, 'i'}, 170 {"include", required_argument, 0, 'i'},
171 {"exclude", required_argument, 0, 'e'}, 171 {"exclude", required_argument, 0, 'e'},
172 {"critical", required_argument, 0, 'c'}, 172 {"critical", required_argument, 0, 'c'},
@@ -212,14 +212,14 @@ int process_arguments (int argc, char **argv) {
212 upgrade=NO_UPGRADE; 212 upgrade=NO_UPGRADE;
213 break; 213 break;
214 case 'u': 214 case 'u':
215 do_update=1; 215 do_update=true;
216 if(optarg!=NULL){ 216 if(optarg!=NULL){
217 update_opts=strdup(optarg); 217 update_opts=strdup(optarg);
218 if(update_opts==NULL) die(STATE_UNKNOWN, "strdup failed"); 218 if(update_opts==NULL) die(STATE_UNKNOWN, "strdup failed");
219 } 219 }
220 break; 220 break;
221 case 'l': 221 case 'l':
222 list=1; 222 list=true;
223 break; 223 break;
224 case 'i': 224 case 'i':
225 do_include=add_to_regexp(do_include, optarg); 225 do_include=add_to_regexp(do_include, optarg);
@@ -231,7 +231,7 @@ int process_arguments (int argc, char **argv) {
231 do_critical=add_to_regexp(do_critical, optarg); 231 do_critical=add_to_regexp(do_critical, optarg);
232 break; 232 break;
233 case 'o': 233 case 'o':
234 only_critical=1; 234 only_critical=true;
235 break; 235 break;
236 case INPUT_FILE_OPT: 236 case INPUT_FILE_OPT:
237 input_filename = optarg; 237 input_filename = optarg;
@@ -269,7 +269,7 @@ int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkg
269 die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf); 269 die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf);
270 } 270 }
271 } 271 }
272 272
273 if(do_exclude!=NULL){ 273 if(do_exclude!=NULL){
274 regres=regcomp(&ereg, do_exclude, REG_EXTENDED); 274 regres=regcomp(&ereg, do_exclude, REG_EXTENDED);
275 if(regres!=0) { 275 if(regres!=0) {
@@ -278,7 +278,7 @@ int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkg
278 progname, rerrbuf); 278 progname, rerrbuf);
279 } 279 }
280 } 280 }
281 281
282 const char *crit_ptr = (do_critical != NULL) ? do_critical : SECURITY_RE; 282 const char *crit_ptr = (do_critical != NULL) ? do_critical : SECURITY_RE;
283 regres=regcomp(&sreg, crit_ptr, REG_EXTENDED); 283 regres=regcomp(&sreg, crit_ptr, REG_EXTENDED);
284 if(regres!=0) { 284 if(regres!=0) {
@@ -295,7 +295,7 @@ int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkg
295 /* run the upgrade */ 295 /* run the upgrade */
296 result = np_runcmd(cmdline, &chld_out, &chld_err, 0); 296 result = np_runcmd(cmdline, &chld_out, &chld_err, 0);
297 } 297 }
298 298
299 /* apt-get upgrade only changes exit status if there is an 299 /* apt-get upgrade only changes exit status if there is an
300 * internal error when run in dry-run mode. therefore we will 300 * internal error when run in dry-run mode. therefore we will
301 * treat such an error as UNKNOWN */ 301 * treat such an error as UNKNOWN */
@@ -371,7 +371,7 @@ int run_update(void){
371 struct output chld_out, chld_err; 371 struct output chld_out, chld_err;
372 char *cmdline; 372 char *cmdline;
373 373
374 /* run the upgrade */ 374 /* run the update */
375 cmdline = construct_cmdline(NO_UPGRADE, update_opts); 375 cmdline = construct_cmdline(NO_UPGRADE, update_opts);
376 result = np_runcmd(cmdline, &chld_out, &chld_err, 0); 376 result = np_runcmd(cmdline, &chld_out, &chld_err, 0);
377 /* apt-get update changes exit status if it can't fetch packages. 377 /* apt-get update changes exit status if it can't fetch packages.
@@ -501,16 +501,6 @@ print_help (void)
501 501
502 printf(UT_PLUG_TIMEOUT, timeout_interval); 502 printf(UT_PLUG_TIMEOUT, timeout_interval);
503 503
504 printf (" %s\n", "-U, --upgrade=OPTS");
505 printf (" %s\n", _("[Default] Perform an upgrade. If an optional OPTS argument is provided,"));
506 printf (" %s\n", _("apt-get will be run with these command line options instead of the"));
507 printf (" %s", _("default "));
508 printf ("(%s).\n", UPGRADE_DEFAULT_OPTS);
509 printf (" %s\n", _("Note that you may be required to have root privileges if you do not use"));
510 printf (" %s\n", _("the default options."));
511 printf (" %s\n", "-d, --dist-upgrade=OPTS");
512 printf (" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS"));
513 printf (" %s\n", _("can be provided to override the default options."));
514 printf (" %s\n", "-n, --no-upgrade"); 504 printf (" %s\n", "-n, --no-upgrade");
515 printf (" %s\n", _("Do not run the upgrade. Probably not useful (without -u at least).")); 505 printf (" %s\n", _("Do not run the upgrade. Probably not useful (without -u at least)."));
516 printf (" %s\n", "-l, --list"); 506 printf (" %s\n", "-l, --list");
@@ -530,7 +520,7 @@ print_help (void)
530 printf (" %s\n", _("this REGEXP, the plugin will return CRITICAL status. Can be specified")); 520 printf (" %s\n", _("this REGEXP, the plugin will return CRITICAL status. Can be specified"));
531 printf (" %s\n", _("multiple times like above. Default is a regexp matching security")); 521 printf (" %s\n", _("multiple times like above. Default is a regexp matching security"));
532 printf (" %s\n", _("upgrades for Debian and Ubuntu:")); 522 printf (" %s\n", _("upgrades for Debian and Ubuntu:"));
533 printf (" \t\%s\n", SECURITY_RE); 523 printf (" \t%s\n", SECURITY_RE);
534 printf (" %s\n", _("Note that the package must first match the include list before its")); 524 printf (" %s\n", _("Note that the package must first match the include list before its"));
535 printf (" %s\n", _("information is compared against the critical list.")); 525 printf (" %s\n", _("information is compared against the critical list."));
536 printf (" %s\n", "-o, --only-critical"); 526 printf (" %s\n", "-o, --only-critical");
@@ -538,7 +528,7 @@ print_help (void)
538 printf (" %s\n", _("of upgrades will be printed, but any non-critical upgrades will not cause")); 528 printf (" %s\n", _("of upgrades will be printed, but any non-critical upgrades will not cause"));
539 printf (" %s\n", _("the plugin to return WARNING status.")); 529 printf (" %s\n", _("the plugin to return WARNING status."));
540 printf (" %s\n", "-w, --packages-warning"); 530 printf (" %s\n", "-w, --packages-warning");
541 printf (" %s\n", _("Minumum number of packages available for upgrade to return WARNING status.")); 531 printf (" %s\n", _("Minimum number of packages available for upgrade to return WARNING status."));
542 printf (" %s\n\n", _("Default is 1 package.")); 532 printf (" %s\n\n", _("Default is 1 package."));
543 533
544 printf ("%s\n\n", _("The following options require root privileges and should be used with care:")); 534 printf ("%s\n\n", _("The following options require root privileges and should be used with care:"));
@@ -547,6 +537,16 @@ print_help (void)
547 printf (" %s\n", _("the default options. Note: you may also need to adjust the global")); 537 printf (" %s\n", _("the default options. Note: you may also need to adjust the global"));
548 printf (" %s\n", _("timeout (with -t) to prevent the plugin from timing out if apt-get")); 538 printf (" %s\n", _("timeout (with -t) to prevent the plugin from timing out if apt-get"));
549 printf (" %s\n", _("upgrade is expected to take longer than the default timeout.")); 539 printf (" %s\n", _("upgrade is expected to take longer than the default timeout."));
540 printf (" %s\n", "-U, --upgrade=OPTS");
541 printf (" %s\n", _("Perform an upgrade. If an optional OPTS argument is provided,"));
542 printf (" %s\n", _("apt-get will be run with these command line options instead of the"));
543 printf (" %s", _("default "));
544 printf ("(%s).\n", UPGRADE_DEFAULT_OPTS);
545 printf (" %s\n", _("Note that you may be required to have root privileges if you do not use"));
546 printf (" %s\n", _("the default options, which will only run a simulation and NOT perform the upgrade"));
547 printf (" %s\n", "-d, --dist-upgrade=OPTS");
548 printf (" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS"));
549 printf (" %s\n", _("can be provided to override the default options."));
550 550
551 printf(UT_SUPPORT); 551 printf(UT_SUPPORT);
552} 552}
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index a69854a..c6593df 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -476,6 +476,18 @@ check_http (void)
476 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache); 476 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache);
477 } 477 }
478 478
479 // If server_address is an IPv6 address it must be surround by square brackets
480 struct in6_addr tmp_in_addr;
481 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) {
482 char *new_server_address = malloc(strlen(server_address) + 3);
483 if (new_server_address == NULL) {
484 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
485 }
486 snprintf(new_server_address, strlen(server_address)+3, "[%s]", server_address);
487 free(server_address);
488 server_address = new_server_address;
489 }
490
479 /* compose URL: use the address we want to connect to, set Host: header later */ 491 /* compose URL: use the address we want to connect to, set Host: header later */
480 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", 492 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s",
481 use_ssl ? "https" : "http", 493 use_ssl ? "https" : "http",
@@ -999,10 +1011,12 @@ GOT_FIRST_CERT:
999 result = max_state_alt(get_status(total_time, thlds), result); 1011 result = max_state_alt(get_status(total_time, thlds), result);
1000 1012
1001 /* Cut-off trailing characters */ 1013 /* Cut-off trailing characters */
1002 if(msg[strlen(msg)-2] == ',') 1014 if (strlen(msg) >= 2) {
1003 msg[strlen(msg)-2] = '\0'; 1015 if(msg[strlen(msg)-2] == ',')
1004 else 1016 msg[strlen(msg)-2] = '\0';
1005 msg[strlen(msg)-3] = '\0'; 1017 else
1018 msg[strlen(msg)-3] = '\0';
1019 }
1006 1020
1007 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */ 1021 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */
1008 die (result, "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s", 1022 die (result, "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s",
@@ -1666,7 +1680,7 @@ process_arguments (int argc, char **argv)
1666 curl_http_version = CURL_HTTP_VERSION_NONE; 1680 curl_http_version = CURL_HTTP_VERSION_NONE;
1667#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */ 1681#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */
1668 } else { 1682 } else {
1669 fprintf (stderr, "unkown http-version parameter: %s\n", optarg); 1683 fprintf (stderr, "unknown http-version parameter: %s\n", optarg);
1670 exit (STATE_WARNING); 1684 exit (STATE_WARNING);
1671 } 1685 }
1672 break; 1686 break;
@@ -2010,9 +2024,12 @@ curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *s
2010 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream; 2024 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2011 2025
2012 while (buf->bufsize < buf->buflen + size * nmemb + 1) { 2026 while (buf->bufsize < buf->buflen + size * nmemb + 1) {
2013 buf->bufsize *= buf->bufsize * 2; 2027 buf->bufsize = buf->bufsize * 2;
2014 buf->buf = (char *)realloc (buf->buf, buf->bufsize); 2028 buf->buf = (char *)realloc (buf->buf, buf->bufsize);
2015 if (buf->buf == NULL) return -1; 2029 if (buf->buf == NULL) {
2030 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno));
2031 return -1;
2032 }
2016 } 2033 }
2017 2034
2018 memcpy (buf->buf + buf->buflen, buffer, size * nmemb); 2035 memcpy (buf->buf + buf->buflen, buffer, size * nmemb);
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index c1cfb13..d32841d 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -1017,7 +1017,7 @@ void
1017print_usage (void) 1017print_usage (void)
1018{ 1018{
1019 printf ("%s\n", _("Usage:")); 1019 printf ("%s\n", _("Usage:"));
1020 printf (" %s -w limit -c limit [-W limit] [-K limit] {-p path | -x device}\n", progname); 1020 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);
1021 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); 1021 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n");
1022 printf ("[-t timeout] [-u unit] [-v] [-X type] [-N type]\n"); 1022 printf ("[-t timeout] [-u unit] [-v] [-X type] [-N type]\n");
1023} 1023}
@@ -1128,7 +1128,7 @@ get_path_stats (struct parameter_list *p, struct fs_usage *fsp) {
1128 p->dfree_units = p->available*fsp->fsu_blocksize/mult; 1128 p->dfree_units = p->available*fsp->fsu_blocksize/mult;
1129 p->dtotal_units = p->total*fsp->fsu_blocksize/mult; 1129 p->dtotal_units = p->total*fsp->fsu_blocksize/mult;
1130 /* Free file nodes. Not sure the workaround is required, but in case...*/ 1130 /* Free file nodes. Not sure the workaround is required, but in case...*/
1131 p->inodes_free = fsp->fsu_favail > fsp->fsu_ffree ? 0 : fsp->fsu_favail; 1131 p->inodes_free = fsp->fsu_ffree;
1132 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */ 1132 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
1133 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree; 1133 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
1134 if (freespace_ignore_reserved) { 1134 if (freespace_ignore_reserved) {
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index be9362a..db43316 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -492,7 +492,7 @@ void print_help (void) {
492 printf (" %s\n", "-c, --critical=THRESHOLD"); 492 printf (" %s\n", "-c, --critical=THRESHOLD");
493 printf (" %s\n", _("critical threshold pair")); 493 printf (" %s\n", _("critical threshold pair"));
494 printf (" %s\n", "-a, --alive"); 494 printf (" %s\n", "-a, --alive");
495 printf (" %s\n", _("Return OK after first successfull reply")); 495 printf (" %s\n", _("Return OK after first successful reply"));
496 printf (" %s\n", "-b, --bytes=INTEGER"); 496 printf (" %s\n", "-b, --bytes=INTEGER");
497 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE); 497 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE);
498 printf (" %s\n", "-n, --number=INTEGER"); 498 printf (" %s\n", "-n, --number=INTEGER");
diff --git a/plugins/check_http.c b/plugins/check_http.c
index ff39c59..8dda046 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -31,13 +31,14 @@
31* 31*
32*****************************************************************************/ 32*****************************************************************************/
33 33
34/* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */
35
36const char *progname = "check_http"; 34const char *progname = "check_http";
37const char *copyright = "1999-2013"; 35const char *copyright = "1999-2022";
38const char *email = "devel@monitoring-plugins.org"; 36const char *email = "devel@monitoring-plugins.org";
39 37
38// Do NOT sort those headers, it will break the build
39// TODO: Fix this
40#include "common.h" 40#include "common.h"
41#include "base64.h"
41#include "netutils.h" 42#include "netutils.h"
42#include "utils.h" 43#include "utils.h"
43#include "base64.h" 44#include "base64.h"
@@ -57,8 +58,8 @@ enum {
57}; 58};
58 59
59#ifdef HAVE_SSL 60#ifdef HAVE_SSL
60int check_cert = FALSE; 61bool check_cert = false;
61int continue_after_check_cert = FALSE; 62bool continue_after_check_cert = false;
62int ssl_version = 0; 63int ssl_version = 0;
63int days_till_exp_warn, days_till_exp_crit; 64int days_till_exp_warn, days_till_exp_crit;
64char *randbuff; 65char *randbuff;
@@ -69,7 +70,7 @@ X509 *server_cert;
69# define my_recv(buf, len) read(sd, buf, len) 70# define my_recv(buf, len) read(sd, buf, len)
70# define my_send(buf, len) send(sd, buf, len, 0) 71# define my_send(buf, len) send(sd, buf, len, 0)
71#endif /* HAVE_SSL */ 72#endif /* HAVE_SSL */
72int no_body = FALSE; 73bool no_body = false;
73int maximum_age = -1; 74int maximum_age = -1;
74 75
75enum { 76enum {
@@ -91,7 +92,7 @@ struct timeval tv_temp;
91#define HTTP_URL "/" 92#define HTTP_URL "/"
92#define CRLF "\r\n" 93#define CRLF "\r\n"
93 94
94int specify_port = FALSE; 95bool specify_port = false;
95int server_port = HTTP_PORT; 96int server_port = HTTP_PORT;
96int virtual_port = 0; 97int virtual_port = 0;
97char server_port_text[6] = ""; 98char server_port_text[6] = "";
@@ -106,23 +107,21 @@ int server_expect_yn = 0;
106char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; 107char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
107char header_expect[MAX_INPUT_BUFFER] = ""; 108char header_expect[MAX_INPUT_BUFFER] = "";
108char string_expect[MAX_INPUT_BUFFER] = ""; 109char string_expect[MAX_INPUT_BUFFER] = "";
109char output_header_search[30] = "";
110char output_string_search[30] = "";
111char *warning_thresholds = NULL; 110char *warning_thresholds = NULL;
112char *critical_thresholds = NULL; 111char *critical_thresholds = NULL;
113thresholds *thlds; 112thresholds *thlds;
114char user_auth[MAX_INPUT_BUFFER] = ""; 113char user_auth[MAX_INPUT_BUFFER] = "";
115char proxy_auth[MAX_INPUT_BUFFER] = ""; 114char proxy_auth[MAX_INPUT_BUFFER] = "";
116int display_html = FALSE; 115bool display_html = false;
117char **http_opt_headers; 116char **http_opt_headers;
118int http_opt_headers_count = 0; 117int http_opt_headers_count = 0;
119int onredirect = STATE_OK; 118int onredirect = STATE_OK;
120int followsticky = STICKY_NONE; 119int followsticky = STICKY_NONE;
121int use_ssl = FALSE; 120bool use_ssl = false;
122int use_sni = FALSE; 121bool use_sni = false;
123int verbose = FALSE; 122bool verbose = false;
124int show_extended_perfdata = FALSE; 123bool show_extended_perfdata = false;
125int show_body = FALSE; 124bool show_body = false;
126int sd; 125int sd;
127int min_page_len = 0; 126int min_page_len = 0;
128int max_page_len = 0; 127int max_page_len = 0;
@@ -136,10 +135,11 @@ char buffer[MAX_INPUT_BUFFER];
136char *client_cert = NULL; 135char *client_cert = NULL;
137char *client_privkey = NULL; 136char *client_privkey = NULL;
138 137
139int process_arguments (int, char **); 138// Forward function declarations
139bool process_arguments (int, char **);
140int check_http (void); 140int check_http (void);
141void redir (char *pos, char *status_line); 141void redir (char *pos, char *status_line);
142int server_type_check(const char *type); 142bool server_type_check(const char *type);
143int server_port_check(int ssl_flag); 143int server_port_check(int ssl_flag);
144char *perfd_time (double microsec); 144char *perfd_time (double microsec);
145char *perfd_time_connect (double microsec); 145char *perfd_time_connect (double microsec);
@@ -150,6 +150,7 @@ char *perfd_time_transfer (double microsec);
150char *perfd_size (int page_len); 150char *perfd_size (int page_len);
151void print_help (void); 151void print_help (void);
152void print_usage (void); 152void print_usage (void);
153char *unchunk_content(const char *content);
153 154
154int 155int
155main (int argc, char **argv) 156main (int argc, char **argv)
@@ -169,10 +170,10 @@ main (int argc, char **argv)
169 /* Parse extra opts if any */ 170 /* Parse extra opts if any */
170 argv=np_extra_opts (&argc, argv, progname); 171 argv=np_extra_opts (&argc, argv, progname);
171 172
172 if (process_arguments (argc, argv) == ERROR) 173 if (process_arguments (argc, argv) == false)
173 usage4 (_("Could not parse arguments")); 174 usage4 (_("Could not parse arguments"));
174 175
175 if (display_html == TRUE) 176 if (display_html == true)
176 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", 177 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
177 use_ssl ? "https" : "http", host_name ? host_name : server_address, 178 use_ssl ? "https" : "http", host_name ? host_name : server_address,
178 server_port, server_url); 179 server_port, server_url);
@@ -195,9 +196,11 @@ test_file (char *path)
195 usage2 (_("file does not exist or is not readable"), path); 196 usage2 (_("file does not exist or is not readable"), path);
196} 197}
197 198
198/* process command-line arguments */ 199/*
199int 200 * process command-line arguments
200process_arguments (int argc, char **argv) 201 * returns true on succes, false otherwise
202 */
203bool process_arguments (int argc, char **argv)
201{ 204{
202 int c = 1; 205 int c = 1;
203 char *p; 206 char *p;
@@ -252,7 +255,7 @@ process_arguments (int argc, char **argv)
252 }; 255 };
253 256
254 if (argc < 2) 257 if (argc < 2)
255 return ERROR; 258 return false;
256 259
257 for (c = 1; c < argc; c++) { 260 for (c = 1; c < argc; c++) {
258 if (strcmp ("-to", argv[c]) == 0) 261 if (strcmp ("-to", argv[c]) == 0)
@@ -308,10 +311,10 @@ process_arguments (int argc, char **argv)
308 /* xasprintf (&http_opt_headers, "%s", optarg); */ 311 /* xasprintf (&http_opt_headers, "%s", optarg); */
309 break; 312 break;
310 case 'L': /* show html link */ 313 case 'L': /* show html link */
311 display_html = TRUE; 314 display_html = true;
312 break; 315 break;
313 case 'n': /* do not show html link */ 316 case 'n': /* do not show html link */
314 display_html = FALSE; 317 display_html = false;
315 break; 318 break;
316 case 'C': /* Check SSL cert validity */ 319 case 'C': /* Check SSL cert validity */
317#ifdef HAVE_SSL 320#ifdef HAVE_SSL
@@ -332,12 +335,12 @@ process_arguments (int argc, char **argv)
332 usage2 (_("Invalid certificate expiration period"), optarg); 335 usage2 (_("Invalid certificate expiration period"), optarg);
333 days_till_exp_warn = atoi (optarg); 336 days_till_exp_warn = atoi (optarg);
334 } 337 }
335 check_cert = TRUE; 338 check_cert = true;
336 goto enable_ssl; 339 goto enable_ssl;
337#endif 340#endif
338 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */ 341 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */
339#ifdef HAVE_SSL 342#ifdef HAVE_SSL
340 continue_after_check_cert = TRUE; 343 continue_after_check_cert = true;
341 break; 344 break;
342#endif 345#endif
343 case 'J': /* use client certificate */ 346 case 'J': /* use client certificate */
@@ -357,7 +360,7 @@ process_arguments (int argc, char **argv)
357 enable_ssl: 360 enable_ssl:
358 /* ssl_version initialized to 0 as a default. Only set if it's non-zero. This helps when we include multiple 361 /* ssl_version initialized to 0 as a default. Only set if it's non-zero. This helps when we include multiple
359 parameters, like -S and -C combinations */ 362 parameters, like -S and -C combinations */
360 use_ssl = TRUE; 363 use_ssl = true;
361 if (c=='S' && optarg != NULL) { 364 if (c=='S' && optarg != NULL) {
362 int got_plus = strchr(optarg, '+') != NULL; 365 int got_plus = strchr(optarg, '+') != NULL;
363 366
@@ -374,7 +377,7 @@ process_arguments (int argc, char **argv)
374 else 377 else
375 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)")); 378 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)"));
376 } 379 }
377 if (specify_port == FALSE) 380 if (specify_port == false)
378 server_port = HTTPS_PORT; 381 server_port = HTTPS_PORT;
379#else 382#else
380 /* -C -J and -K fall through to here without SSL */ 383 /* -C -J and -K fall through to here without SSL */
@@ -382,7 +385,7 @@ process_arguments (int argc, char **argv)
382#endif 385#endif
383 break; 386 break;
384 case SNI_OPTION: 387 case SNI_OPTION:
385 use_sni = TRUE; 388 use_sni = true;
386 break; 389 break;
387 case MAX_REDIRS_OPTION: 390 case MAX_REDIRS_OPTION:
388 if (!is_intnonneg (optarg)) 391 if (!is_intnonneg (optarg))
@@ -420,7 +423,7 @@ process_arguments (int argc, char **argv)
420 host_name_length = strlen (host_name) - strlen (p) - 1; 423 host_name_length = strlen (host_name) - strlen (p) - 1;
421 free (host_name); 424 free (host_name);
422 host_name = strndup (optarg, host_name_length); 425 host_name = strndup (optarg, host_name_length);
423 if (specify_port == FALSE) 426 if (specify_port == false)
424 server_port = virtual_port; 427 server_port = virtual_port;
425 } 428 }
426 } else if ((p = strchr (host_name, ':')) != NULL 429 } else if ((p = strchr (host_name, ':')) != NULL
@@ -430,7 +433,7 @@ process_arguments (int argc, char **argv)
430 host_name_length = strlen (host_name) - strlen (p) - 1; 433 host_name_length = strlen (host_name) - strlen (p) - 1;
431 free (host_name); 434 free (host_name);
432 host_name = strndup (optarg, host_name_length); 435 host_name = strndup (optarg, host_name_length);
433 if (specify_port == FALSE) 436 if (specify_port == false)
434 server_port = virtual_port; 437 server_port = virtual_port;
435 } 438 }
436 break; 439 break;
@@ -446,7 +449,7 @@ process_arguments (int argc, char **argv)
446 usage2 (_("Invalid port number"), optarg); 449 usage2 (_("Invalid port number"), optarg);
447 else { 450 else {
448 server_port = atoi (optarg); 451 server_port = atoi (optarg);
449 specify_port = TRUE; 452 specify_port = true;
450 } 453 }
451 break; 454 break;
452 case 'a': /* authorization info */ 455 case 'a': /* authorization info */
@@ -502,7 +505,7 @@ process_arguments (int argc, char **argv)
502 if (errcode != 0) { 505 if (errcode != 0) {
503 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 506 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
504 printf (_("Could Not Compile Regular Expression: %s"), errbuf); 507 printf (_("Could Not Compile Regular Expression: %s"), errbuf);
505 return ERROR; 508 return false;
506 } 509 }
507 break; 510 break;
508 case INVERT_REGEX: 511 case INVERT_REGEX:
@@ -519,7 +522,7 @@ process_arguments (int argc, char **argv)
519#endif 522#endif
520 break; 523 break;
521 case 'v': /* verbose */ 524 case 'v': /* verbose */
522 verbose = TRUE; 525 verbose = true;
523 break; 526 break;
524 case 'm': /* min_page_length */ 527 case 'm': /* min_page_length */
525 { 528 {
@@ -544,7 +547,7 @@ process_arguments (int argc, char **argv)
544 break; 547 break;
545 } 548 }
546 case 'N': /* no-body */ 549 case 'N': /* no-body */
547 no_body = TRUE; 550 no_body = true;
548 break; 551 break;
549 case 'M': /* max-age */ 552 case 'M': /* max-age */
550 { 553 {
@@ -565,10 +568,10 @@ process_arguments (int argc, char **argv)
565 } 568 }
566 break; 569 break;
567 case 'E': /* show extended perfdata */ 570 case 'E': /* show extended perfdata */
568 show_extended_perfdata = TRUE; 571 show_extended_perfdata = true;
569 break; 572 break;
570 case 'B': /* print body content after status line */ 573 case 'B': /* print body content after status line */
571 show_body = TRUE; 574 show_body = true;
572 break; 575 break;
573 } 576 }
574 } 577 }
@@ -605,7 +608,7 @@ process_arguments (int argc, char **argv)
605 if (virtual_port == 0) 608 if (virtual_port == 0)
606 virtual_port = server_port; 609 virtual_port = server_port;
607 610
608 return TRUE; 611 return true;
609} 612}
610 613
611 614
@@ -945,7 +948,7 @@ check_http (void)
945 /* @20100414, public[at]frank4dd.com, http://www.frank4dd.com/howto */ 948 /* @20100414, public[at]frank4dd.com, http://www.frank4dd.com/howto */
946 949
947 if ( server_address != NULL && strcmp(http_method, "CONNECT") == 0 950 if ( server_address != NULL && strcmp(http_method, "CONNECT") == 0
948 && host_name != NULL && use_ssl == TRUE) { 951 && host_name != NULL && use_ssl == true) {
949 952
950 if (verbose) printf ("Entering CONNECT tunnel mode with proxy %s:%d to dst %s:%d\n", server_address, server_port, host_name, HTTPS_PORT); 953 if (verbose) printf ("Entering CONNECT tunnel mode with proxy %s:%d to dst %s:%d\n", server_address, server_port, host_name, HTTPS_PORT);
951 asprintf (&buf, "%s %s:%d HTTP/1.1\r\n%s\r\n", http_method, host_name, HTTPS_PORT, user_agent); 954 asprintf (&buf, "%s %s:%d HTTP/1.1\r\n%s\r\n", http_method, host_name, HTTPS_PORT, user_agent);
@@ -979,7 +982,7 @@ check_http (void)
979 } 982 }
980#ifdef HAVE_SSL 983#ifdef HAVE_SSL
981 elapsed_time_connect = (double)microsec_connect / 1.0e6; 984 elapsed_time_connect = (double)microsec_connect / 1.0e6;
982 if (use_ssl == TRUE) { 985 if (use_ssl == true) {
983 gettimeofday (&tv_temp, NULL); 986 gettimeofday (&tv_temp, NULL);
984 result = np_net_ssl_init_with_hostname_version_and_cert(sd, (use_sni ? host_name : NULL), ssl_version, client_cert, client_privkey); 987 result = np_net_ssl_init_with_hostname_version_and_cert(sd, (use_sni ? host_name : NULL), ssl_version, client_cert, client_privkey);
985 if (verbose) printf ("SSL initialized\n"); 988 if (verbose) printf ("SSL initialized\n");
@@ -987,9 +990,9 @@ check_http (void)
987 die (STATE_CRITICAL, NULL); 990 die (STATE_CRITICAL, NULL);
988 microsec_ssl = deltime (tv_temp); 991 microsec_ssl = deltime (tv_temp);
989 elapsed_time_ssl = (double)microsec_ssl / 1.0e6; 992 elapsed_time_ssl = (double)microsec_ssl / 1.0e6;
990 if (check_cert == TRUE) { 993 if (check_cert == true) {
991 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); 994 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
992 if (continue_after_check_cert == FALSE) { 995 if (continue_after_check_cert == false) {
993 if (sd) close(sd); 996 if (sd) close(sd);
994 np_net_ssl_cleanup(); 997 np_net_ssl_cleanup();
995 return result; 998 return result;
@@ -999,7 +1002,7 @@ check_http (void)
999#endif /* HAVE_SSL */ 1002#endif /* HAVE_SSL */
1000 1003
1001 if ( server_address != NULL && strcmp(http_method, "CONNECT") == 0 1004 if ( server_address != NULL && strcmp(http_method, "CONNECT") == 0
1002 && host_name != NULL && use_ssl == TRUE) 1005 && host_name != NULL && use_ssl == true)
1003 asprintf (&buf, "%s %s %s\r\n%s\r\n", http_method_proxy, server_url, host_name ? "HTTP/1.1" : "HTTP/1.0", user_agent); 1006 asprintf (&buf, "%s %s %s\r\n%s\r\n", http_method_proxy, server_url, host_name ? "HTTP/1.1" : "HTTP/1.0", user_agent);
1004 else 1007 else
1005 asprintf (&buf, "%s %s %s\r\n%s\r\n", http_method, server_url, host_name ? "HTTP/1.1" : "HTTP/1.0", user_agent); 1008 asprintf (&buf, "%s %s %s\r\n%s\r\n", http_method, server_url, host_name ? "HTTP/1.1" : "HTTP/1.0", user_agent);
@@ -1027,10 +1030,10 @@ check_http (void)
1027 * 14.23). Some server applications/configurations cause trouble if the 1030 * 14.23). Some server applications/configurations cause trouble if the
1028 * (default) port is explicitly specified in the "Host:" header line. 1031 * (default) port is explicitly specified in the "Host:" header line.
1029 */ 1032 */
1030 if ((use_ssl == FALSE && virtual_port == HTTP_PORT) || 1033 if ((use_ssl == false && virtual_port == HTTP_PORT) ||
1031 (use_ssl == TRUE && virtual_port == HTTPS_PORT) || 1034 (use_ssl == true && virtual_port == HTTPS_PORT) ||
1032 (server_address != NULL && strcmp(http_method, "CONNECT") == 0 1035 (server_address != NULL && strcmp(http_method, "CONNECT") == 0
1033 && host_name != NULL && use_ssl == TRUE)) 1036 && host_name != NULL && use_ssl == true))
1034 xasprintf (&buf, "%sHost: %s\r\n", buf, host_name); 1037 xasprintf (&buf, "%sHost: %s\r\n", buf, host_name);
1035 else 1038 else
1036 xasprintf (&buf, "%sHost: %s:%d\r\n", buf, host_name, virtual_port); 1039 xasprintf (&buf, "%sHost: %s:%d\r\n", buf, host_name, virtual_port);
@@ -1070,9 +1073,8 @@ check_http (void)
1070 } 1073 }
1071 1074
1072 xasprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, (int)strlen (http_post_data)); 1075 xasprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, (int)strlen (http_post_data));
1073 xasprintf (&buf, "%s%s%s", buf, http_post_data, CRLF); 1076 xasprintf (&buf, "%s%s", buf, http_post_data);
1074 } 1077 } else {
1075 else {
1076 /* or just a newline so the server knows we're done with the request */ 1078 /* or just a newline so the server knows we're done with the request */
1077 xasprintf (&buf, "%s%s", buf, CRLF); 1079 xasprintf (&buf, "%s%s", buf, CRLF);
1078 } 1080 }
@@ -1096,9 +1098,14 @@ check_http (void)
1096 *pos = ' '; 1098 *pos = ' ';
1097 } 1099 }
1098 buffer[i] = '\0'; 1100 buffer[i] = '\0';
1099 xasprintf (&full_page_new, "%s%s", full_page, buffer); 1101
1100 free (full_page); 1102 if ((full_page_new = realloc(full_page, pagesize + i + 1)) == NULL)
1103 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate memory for full_page\n"));
1104
1105 memmove(&full_page_new[pagesize], buffer, i + 1);
1106
1101 full_page = full_page_new; 1107 full_page = full_page_new;
1108
1102 pagesize += i; 1109 pagesize += i;
1103 1110
1104 if (no_body && document_headers_done (full_page)) { 1111 if (no_body && document_headers_done (full_page)) {
@@ -1110,25 +1117,7 @@ check_http (void)
1110 elapsed_time_transfer = (double)microsec_transfer / 1.0e6; 1117 elapsed_time_transfer = (double)microsec_transfer / 1.0e6;
1111 1118
1112 if (i < 0 && errno != ECONNRESET) { 1119 if (i < 0 && errno != ECONNRESET) {
1113#ifdef HAVE_SSL 1120 die(STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
1114 /*
1115 if (use_ssl) {
1116 sslerr=SSL_get_error(ssl, i);
1117 if ( sslerr == SSL_ERROR_SSL ) {
1118 die (STATE_WARNING, _("HTTP WARNING - Client Certificate Required\n"));
1119 } else {
1120 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
1121 }
1122 }
1123 else {
1124 */
1125#endif
1126 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
1127#ifdef HAVE_SSL
1128 /* XXX
1129 }
1130 */
1131#endif
1132 } 1121 }
1133 1122
1134 /* return a CRITICAL status if we couldn't read any data */ 1123 /* return a CRITICAL status if we couldn't read any data */
@@ -1253,32 +1242,73 @@ check_http (void)
1253 } 1242 }
1254 1243
1255 /* Page and Header content checks go here */ 1244 /* Page and Header content checks go here */
1256 if (strlen (header_expect)) { 1245 if (strlen(header_expect) > 0) {
1257 if (!strstr (header, header_expect)) { 1246 if (strstr(header, header_expect) == NULL) {
1258 strncpy(&output_header_search[0],header_expect,sizeof(output_header_search)); 1247 // We did not find the header, the rest is for building the output and setting the state
1259 if(output_header_search[sizeof(output_header_search)-1]!='\0') { 1248 char output_header_search[30] = "";
1260 bcopy("...",&output_header_search[sizeof(output_header_search)-4],4); 1249
1250 strncpy(&output_header_search[0], header_expect,
1251 sizeof(output_header_search));
1252
1253 if (output_header_search[sizeof(output_header_search) - 1] != '\0') {
1254 bcopy("...",
1255 &output_header_search[sizeof(output_header_search) - 4],
1256 4);
1261 } 1257 }
1262 xasprintf (&msg, _("%sheader '%s' not found on '%s://%s:%d%s', "), msg, output_header_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); 1258
1259 xasprintf (&msg,
1260 _("%sheader '%s' not found on '%s://%s:%d%s', "),
1261 msg,
1262 output_header_search, use_ssl ? "https" : "http",
1263 host_name ? host_name : server_address, server_port,
1264 server_url);
1265
1263 result = STATE_CRITICAL; 1266 result = STATE_CRITICAL;
1264 } 1267 }
1265 } 1268 }
1266 1269
1270 // At this point we should test if the content is chunked and unchunk it, so
1271 // it can be searched (and possibly printed)
1272 const char *chunked_header_regex_string = "Transfer-Encoding: *chunked *";
1273 regex_t chunked_header_regex;
1274
1275 if (regcomp(&chunked_header_regex, chunked_header_regex_string, REG_ICASE)) {
1276 die(STATE_UNKNOWN, "HTTP %s: %s\n", state_text(STATE_UNKNOWN), "Failed to compile chunked_header_regex regex");
1277 }
1278
1279 regmatch_t chre_pmatch[1]; // We actually do not care about this, since we only want to know IF it was found
1280
1281 if (regexec(&chunked_header_regex, header, 1, chre_pmatch, 0) == 0) {
1282 if (verbose) {
1283 printf("Found chunked content\n");
1284 }
1285 // We actually found the chunked header
1286 char *tmp = unchunk_content(page);
1287 if (tmp == NULL) {
1288 die(STATE_UNKNOWN, "HTTP %s: %s\n", state_text(STATE_UNKNOWN), "Failed to unchunk message body");
1289 }
1290 page = tmp;
1291 }
1267 1292
1268 if (strlen (string_expect)) { 1293 if (strlen(string_expect) > 0) {
1269 if (!strstr (page, string_expect)) { 1294 if (!strstr(page, string_expect)) {
1270 strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); 1295 // We found the string the body, the rest is for building the output
1271 if(output_string_search[sizeof(output_string_search)-1]!='\0') { 1296 char output_string_search[30] = "";
1272 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); 1297 strncpy(&output_string_search[0], string_expect,
1298 sizeof(output_string_search));
1299 if (output_string_search[sizeof(output_string_search) - 1] != '\0') {
1300 bcopy("...", &output_string_search[sizeof(output_string_search) - 4],
1301 4);
1273 } 1302 }
1274 xasprintf (&msg, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); 1303 xasprintf (&msg, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1275 result = STATE_CRITICAL; 1304 result = STATE_CRITICAL;
1276 } 1305 }
1277 } 1306 }
1278 1307
1279 if (strlen (regexp)) { 1308 if (strlen(regexp) > 0) {
1280 errcode = regexec (&preg, page, REGS, pmatch, 0); 1309 errcode = regexec(&preg, page, REGS, pmatch, 0);
1281 if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) { 1310 if ((errcode == 0 && invert_regex == 0) ||
1311 (errcode == REG_NOMATCH && invert_regex == 1)) {
1282 /* OK - No-op to avoid changing the logic around it */ 1312 /* OK - No-op to avoid changing the logic around it */
1283 result = max_state_alt(STATE_OK, result); 1313 result = max_state_alt(STATE_OK, result);
1284 } 1314 }
@@ -1330,7 +1360,7 @@ check_http (void)
1330 perfd_time (elapsed_time), 1360 perfd_time (elapsed_time),
1331 perfd_size (page_len), 1361 perfd_size (page_len),
1332 perfd_time_connect (elapsed_time_connect), 1362 perfd_time_connect (elapsed_time_connect),
1333 use_ssl == TRUE ? perfd_time_ssl (elapsed_time_ssl) : "", 1363 use_ssl == true ? perfd_time_ssl (elapsed_time_ssl) : "",
1334 perfd_time_headers (elapsed_time_headers), 1364 perfd_time_headers (elapsed_time_headers),
1335 perfd_time_firstbyte (elapsed_time_firstbyte), 1365 perfd_time_firstbyte (elapsed_time_firstbyte),
1336 perfd_time_transfer (elapsed_time_transfer)); 1366 perfd_time_transfer (elapsed_time_transfer));
@@ -1352,7 +1382,95 @@ check_http (void)
1352 return STATE_UNKNOWN; 1382 return STATE_UNKNOWN;
1353} 1383}
1354 1384
1385/* Receivces a pointer to the beginning of the body of a HTTP message
1386 * which is chunked and returns a pointer to a freshly allocated memory
1387 * region containing the unchunked body or NULL if something failed.
1388 * The result must be freed by the caller.
1389 */
1390char *unchunk_content(const char *content) {
1391 // https://en.wikipedia.org/wiki/Chunked_transfer_encoding
1392 // https://www.rfc-editor.org/rfc/rfc7230#section-4.1
1393 char *result = NULL;
1394 size_t content_length = strlen(content);
1395 char *start_of_chunk;
1396 char* end_of_chunk;
1397 long size_of_chunk;
1398 const char *pointer = content;
1399 char *endptr;
1400 long length_of_chunk = 0;
1401 size_t overall_size = 0;
1402
1403 while (true) {
1404 size_of_chunk = strtol(pointer, &endptr, 16);
1405 if (size_of_chunk == LONG_MIN || size_of_chunk == LONG_MAX) {
1406 // Apparently underflow or overflow, should not happen
1407 if (verbose) {
1408 printf("Got an underflow or overflow from strtol at: %u\n", __LINE__);
1409 }
1410 return NULL;
1411 }
1412 if (endptr == pointer) {
1413 // Apparently this was not a number
1414 if (verbose) {
1415 printf("Chunked content did not start with a number at all (Line: %u)\n", __LINE__);
1416 }
1417 return NULL;
1418 }
1419
1420 // So, we got the length of the chunk
1421 if (*endptr == ';') {
1422 // Chunk extension starts here
1423 while (*endptr != '\r') {
1424 endptr++;
1425 }
1426 }
1427
1428 start_of_chunk = endptr + 2;
1429 end_of_chunk = start_of_chunk + size_of_chunk;
1430 length_of_chunk = (long)(end_of_chunk - start_of_chunk);
1431 pointer = end_of_chunk + 2; //Next number should be here
1432
1433 if (length_of_chunk == 0) {
1434 // Chunk length is 0, so this is the last one
1435 break;
1436 }
1437
1438 overall_size += length_of_chunk;
1355 1439
1440 if (result == NULL) {
1441 // Size of the chunk plus the ending NULL byte
1442 result = (char *)malloc(length_of_chunk +1);
1443 if (result == NULL) {
1444 if (verbose) {
1445 printf("Failed to allocate memory for unchunked body\n");
1446 }
1447 return NULL;
1448 }
1449 } else {
1450 // Enlarge memory to the new size plus the ending NULL byte
1451 void *tmp = realloc(result, overall_size +1);
1452 if (tmp == NULL) {
1453 if (verbose) {
1454 printf("Failed to allocate memory for unchunked body\n");
1455 }
1456 return NULL;
1457 } else {
1458 result = tmp;
1459 }
1460 }
1461
1462 memcpy(result + (overall_size - size_of_chunk), start_of_chunk, size_of_chunk);
1463 }
1464
1465 if (overall_size == 0 && result == NULL) {
1466 // We might just have received the end chunk without previous content, so result is never allocated
1467 result = calloc(1, sizeof(char));
1468 // No error handling here, we can only return NULL anyway
1469 } else {
1470 result[overall_size] = '\0';
1471 }
1472 return result;
1473}
1356 1474
1357/* per RFC 2396 */ 1475/* per RFC 2396 */
1358#define URI_HTTP "%5[HTPShtps]" 1476#define URI_HTTP "%5[HTPShtps]"
@@ -1525,13 +1643,13 @@ redir (char *pos, char *status_line)
1525} 1643}
1526 1644
1527 1645
1528int 1646bool
1529server_type_check (const char *type) 1647server_type_check (const char *type)
1530{ 1648{
1531 if (strcmp (type, "https")) 1649 if (strcmp (type, "https"))
1532 return FALSE; 1650 return false;
1533 else 1651 else
1534 return TRUE; 1652 return true;
1535} 1653}
1536 1654
1537int 1655int
@@ -1546,42 +1664,42 @@ server_port_check (int ssl_flag)
1546char *perfd_time (double elapsed_time) 1664char *perfd_time (double elapsed_time)
1547{ 1665{
1548 return fperfdata ("time", elapsed_time, "s", 1666 return fperfdata ("time", elapsed_time, "s",
1549 thlds->warning?TRUE:FALSE, thlds->warning?thlds->warning->end:0, 1667 thlds->warning?true:false, thlds->warning?thlds->warning->end:0,
1550 thlds->critical?TRUE:FALSE, thlds->critical?thlds->critical->end:0, 1668 thlds->critical?true:false, thlds->critical?thlds->critical->end:0,
1551 TRUE, 0, TRUE, socket_timeout); 1669 true, 0, true, socket_timeout);
1552} 1670}
1553 1671
1554char *perfd_time_connect (double elapsed_time_connect) 1672char *perfd_time_connect (double elapsed_time_connect)
1555{ 1673{
1556 return fperfdata ("time_connect", elapsed_time_connect, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1674 return fperfdata ("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1557} 1675}
1558 1676
1559char *perfd_time_ssl (double elapsed_time_ssl) 1677char *perfd_time_ssl (double elapsed_time_ssl)
1560{ 1678{
1561 return fperfdata ("time_ssl", elapsed_time_ssl, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1679 return fperfdata ("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1562} 1680}
1563 1681
1564char *perfd_time_headers (double elapsed_time_headers) 1682char *perfd_time_headers (double elapsed_time_headers)
1565{ 1683{
1566 return fperfdata ("time_headers", elapsed_time_headers, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1684 return fperfdata ("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1567} 1685}
1568 1686
1569char *perfd_time_firstbyte (double elapsed_time_firstbyte) 1687char *perfd_time_firstbyte (double elapsed_time_firstbyte)
1570{ 1688{
1571 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1689 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1572} 1690}
1573 1691
1574char *perfd_time_transfer (double elapsed_time_transfer) 1692char *perfd_time_transfer (double elapsed_time_transfer)
1575{ 1693{
1576 return fperfdata ("time_transfer", elapsed_time_transfer, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1694 return fperfdata ("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1577} 1695}
1578 1696
1579char *perfd_size (int page_len) 1697char *perfd_size (int page_len)
1580{ 1698{
1581 return perfdata ("size", page_len, "B", 1699 return perfdata ("size", page_len, "B",
1582 (min_page_len>0?TRUE:FALSE), min_page_len, 1700 (min_page_len>0?true:false), min_page_len,
1583 (min_page_len>0?TRUE:FALSE), 0, 1701 (min_page_len>0?true:false), 0,
1584 TRUE, 0, FALSE, 0); 1702 true, 0, false, 0);
1585} 1703}
1586 1704
1587void 1705void
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index c893386..c26cd43 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -69,7 +69,6 @@ int process_arguments (int, char **);
69int validate_arguments (void); 69int validate_arguments (void);
70void print_usage (void); 70void print_usage (void);
71void print_help (void); 71void print_help (void);
72int is_pg_dbname (char *);
73int is_pg_logname (char *); 72int is_pg_logname (char *);
74int do_query (PGconn *, char *); 73int do_query (PGconn *, char *);
75 74
@@ -347,10 +346,10 @@ process_arguments (int argc, char **argv)
347 pgport = optarg; 346 pgport = optarg;
348 break; 347 break;
349 case 'd': /* database name */ 348 case 'd': /* database name */
350 if (!is_pg_dbname (optarg)) /* checks length and valid chars */ 349 if (strlen(optarg) >= NAMEDATALEN) {
351 usage2 (_("Database name is not valid"), optarg); 350 usage2 (_("Database name exceeds the maximum length"), optarg);
352 else /* we know length, and know optarg is terminated, so us strcpy */ 351 }
353 snprintf(dbName, NAMEDATALEN, "%s", optarg); 352 snprintf(dbName, NAMEDATALEN, "%s", optarg);
354 break; 353 break;
355 case 'l': /* login name */ 354 case 'l': /* login name */
356 if (!is_pg_logname (optarg)) 355 if (!is_pg_logname (optarg))
@@ -414,45 +413,6 @@ validate_arguments ()
414 return OK; 413 return OK;
415} 414}
416 415
417
418/******************************************************************************
419
420@@-
421<sect3>
422<title>is_pg_dbname</title>
423
424<para>&PROTO_is_pg_dbname;</para>
425
426<para>Given a database name, this function returns TRUE if the string
427is a valid PostgreSQL database name, and returns false if it is
428not.</para>
429
430<para>Valid PostgreSQL database names are less than &NAMEDATALEN;
431characters long and consist of letters, numbers, and underscores. The
432first character cannot be a number, however.</para>
433
434</sect3>
435-@@
436******************************************************************************/
437
438
439
440int
441is_pg_dbname (char *dbname)
442{
443 char txt[NAMEDATALEN];
444 char tmp[NAMEDATALEN];
445 if (strlen (dbname) > NAMEDATALEN - 1)
446 return (FALSE);
447 strncpy (txt, dbname, NAMEDATALEN - 1);
448 txt[NAMEDATALEN - 1] = 0;
449 if (sscanf (txt, "%[_a-zA-Z]%[^_a-zA-Z0-9-]", tmp, tmp) == 1)
450 return (TRUE);
451 if (sscanf (txt, "%[_a-zA-Z]%[_a-zA-Z0-9-]%[^_a-zA-Z0-9-]", tmp, tmp, tmp) ==
452 2) return (TRUE);
453 return (FALSE);
454}
455
456/** 416/**
457 417
458the tango program should eventually create an entity here based on the 418the tango program should eventually create an entity here based on the
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index 2601ccd..d3968a2 100644
--- a/plugins/check_snmp.c
+++ b/plugins/check_snmp.c
@@ -1,31 +1,31 @@
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-2007 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";
@@ -90,6 +90,7 @@ char *thisarg (char *str);
90char *nextarg (char *str); 90char *nextarg (char *str);
91void print_usage (void); 91void print_usage (void);
92void print_help (void); 92void print_help (void);
93char *multiply (char *str);
93 94
94#include "regex.h" 95#include "regex.h"
95char regex_expect[MAX_INPUT_BUFFER] = ""; 96char regex_expect[MAX_INPUT_BUFFER] = "";
@@ -154,6 +155,8 @@ double *previous_value;
154size_t previous_size = OID_COUNT_STEP; 155size_t previous_size = OID_COUNT_STEP;
155int perf_labels = 1; 156int perf_labels = 1;
156char* ip_version = ""; 157char* ip_version = "";
158double multiplier = 1.0;
159char *fmtstr = "";
157 160
158static char *fix_snmp_range(char *th) 161static char *fix_snmp_range(char *th)
159{ 162{
@@ -316,7 +319,7 @@ main (int argc, char **argv)
316 for (i = 0; i < numcontext; i++) { 319 for (i = 0; i < numcontext; i++) {
317 command_line[10 + i] = contextargs[i]; 320 command_line[10 + i] = contextargs[i];
318 } 321 }
319 322
320 for (i = 0; i < numauthpriv; i++) { 323 for (i = 0; i < numauthpriv; i++) {
321 command_line[10 + numcontext + i] = authpriv[i]; 324 command_line[10 + numcontext + i] = authpriv[i];
322 } 325 }
@@ -330,7 +333,7 @@ main (int argc, char **argv)
330 333
331 for (i = 0; i < numoids; i++) { 334 for (i = 0; i < numoids; i++) {
332 command_line[10 + numcontext + numauthpriv + 1 + i] = oids[i]; 335 command_line[10 + numcontext + numauthpriv + 1 + i] = oids[i];
333 xasprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]); 336 xasprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);
334 } 337 }
335 338
336 command_line[10 + numcontext + numauthpriv + 1 + numoids] = NULL; 339 command_line[10 + numcontext + numauthpriv + 1 + numoids] = NULL;
@@ -398,15 +401,15 @@ main (int argc, char **argv)
398 is_counter=0; 401 is_counter=0;
399 /* We strip out the datatype indicator for PHBs */ 402 /* We strip out the datatype indicator for PHBs */
400 if (strstr (response, "Gauge: ")) { 403 if (strstr (response, "Gauge: ")) {
401 show = strstr (response, "Gauge: ") + 7; 404 show = multiply (strstr (response, "Gauge: ") + 7);
402 } 405 }
403 else if (strstr (response, "Gauge32: ")) { 406 else if (strstr (response, "Gauge32: ")) {
404 show = strstr (response, "Gauge32: ") + 9; 407 show = multiply (strstr (response, "Gauge32: ") + 9);
405 } 408 }
406 else if (strstr (response, "Counter32: ")) { 409 else if (strstr (response, "Counter32: ")) {
407 show = strstr (response, "Counter32: ") + 11; 410 show = strstr (response, "Counter32: ") + 11;
408 is_counter=1; 411 is_counter=1;
409 if(!calculate_rate) 412 if(!calculate_rate)
410 strcpy(type, "c"); 413 strcpy(type, "c");
411 } 414 }
412 else if (strstr (response, "Counter64: ")) { 415 else if (strstr (response, "Counter64: ")) {
@@ -416,7 +419,10 @@ main (int argc, char **argv)
416 strcpy(type, "c"); 419 strcpy(type, "c");
417 } 420 }
418 else if (strstr (response, "INTEGER: ")) { 421 else if (strstr (response, "INTEGER: ")) {
419 show = strstr (response, "INTEGER: ") + 9; 422 show = multiply (strstr (response, "INTEGER: ") + 9);
423 if (fmtstr != "") {
424 conv = fmtstr;
425 }
420 } 426 }
421 else if (strstr (response, "OID: ")) { 427 else if (strstr (response, "OID: ")) {
422 show = strstr (response, "OID: ") + 5; 428 show = strstr (response, "OID: ") + 5;
@@ -616,7 +622,7 @@ main (int argc, char **argv)
616 state_string=malloc(string_length); 622 state_string=malloc(string_length);
617 if(state_string==NULL) 623 if(state_string==NULL)
618 die(STATE_UNKNOWN, _("Cannot malloc")); 624 die(STATE_UNKNOWN, _("Cannot malloc"));
619 625
620 current_length=0; 626 current_length=0;
621 for(i=0; i<total_oids; i++) { 627 for(i=0; i<total_oids; i++) {
622 xasprintf(&temp_string,"%.0f",response_value[i]); 628 xasprintf(&temp_string,"%.0f",response_value[i]);
@@ -638,7 +644,7 @@ main (int argc, char **argv)
638 state_string[--current_length]='\0'; 644 state_string[--current_length]='\0';
639 if (verbose > 2) 645 if (verbose > 2)
640 printf("State string=%s\n",state_string); 646 printf("State string=%s\n",state_string);
641 647
642 /* This is not strictly the same as time now, but any subtle variations will cancel out */ 648 /* This is not strictly the same as time now, but any subtle variations will cancel out */
643 np_state_write_string(current_time, state_string ); 649 np_state_write_string(current_time, state_string );
644 if(previous_state==NULL) { 650 if(previous_state==NULL) {
@@ -698,6 +704,8 @@ process_arguments (int argc, char **argv)
698 {"perf-oids", no_argument, 0, 'O'}, 704 {"perf-oids", no_argument, 0, 'O'},
699 {"ipv4", no_argument, 0, '4'}, 705 {"ipv4", no_argument, 0, '4'},
700 {"ipv6", no_argument, 0, '6'}, 706 {"ipv6", no_argument, 0, '6'},
707 {"multiplier", required_argument, 0, 'M'},
708 {"fmtstr", required_argument, 0, 'f'},
701 {0, 0, 0, 0} 709 {0, 0, 0, 0}
702 }; 710 };
703 711
@@ -715,7 +723,7 @@ process_arguments (int argc, char **argv)
715 } 723 }
716 724
717 while (1) { 725 while (1) {
718 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:z:", 726 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:",
719 longopts, &option); 727 longopts, &option);
720 728
721 if (c == -1 || c == EOF) 729 if (c == -1 || c == EOF)
@@ -953,6 +961,16 @@ process_arguments (int argc, char **argv)
953 if(verbose>2) 961 if(verbose>2)
954 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n"); 962 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n");
955 break; 963 break;
964 case 'M':
965 if ( strspn( optarg, "0123456789.," ) == strlen( optarg ) ) {
966 multiplier=strtod(optarg,NULL);
967 }
968 break;
969 case 'f':
970 if (multiplier != 1.0) {
971 fmtstr=optarg;
972 }
973 break;
956 } 974 }
957 } 975 }
958 976
@@ -1022,7 +1040,7 @@ validate_arguments ()
1022 contextargs[0] = strdup ("-n"); 1040 contextargs[0] = strdup ("-n");
1023 contextargs[1] = strdup (context); 1041 contextargs[1] = strdup (context);
1024 } 1042 }
1025 1043
1026 if (seclevel == NULL) 1044 if (seclevel == NULL)
1027 xasprintf(&seclevel, "noAuthNoPriv"); 1045 xasprintf(&seclevel, "noAuthNoPriv");
1028 1046
@@ -1143,6 +1161,44 @@ nextarg (char *str)
1143 1161
1144 1162
1145 1163
1164/* multiply result (values 0 < n < 1 work as divider) */
1165char *
1166multiply (char *str)
1167{
1168 char *endptr;
1169 double val;
1170 char *conv = "%f";
1171
1172 if(verbose>2)
1173 printf(" multiply input: %s\n", str);
1174
1175 val = strtod (str, &endptr);
1176 if ((val == 0.0) && (endptr == str)) {
1177 if(multiplier != 1) {
1178 die(STATE_UNKNOWN, _("multiplier set (%.1f), but input is not a number: %s"), multiplier, str);
1179 }
1180 return str;
1181 }
1182
1183 if(verbose>2)
1184 printf(" multiply extracted double: %f\n", val);
1185 val *= multiplier;
1186 if (fmtstr != "") {
1187 conv = fmtstr;
1188 }
1189 if (val == (int)val) {
1190 sprintf(str, "%.0f", val);
1191 } else {
1192 if(verbose>2)
1193 printf(" multiply using format: %s\n", conv);
1194 sprintf(str, conv, val);
1195 }
1196 if(verbose>2)
1197 printf(" multiply result: %s\n", str);
1198 return str;
1199}
1200
1201
1146void 1202void
1147print_help (void) 1203print_help (void)
1148{ 1204{
@@ -1235,6 +1291,10 @@ print_help (void)
1235 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.').")); 1291 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
1236 printf (" %s\n", "-D, --output-delimiter=STRING"); 1292 printf (" %s\n", "-D, --output-delimiter=STRING");
1237 printf (" %s\n", _("Separates output on multiple OID requests")); 1293 printf (" %s\n", _("Separates output on multiple OID requests"));
1294 printf (" %s\n", "-M, --multiplier=FLOAT");
1295 printf (" %s\n", _("Multiplies current value, 0 < n < 1 works as divider, defaults to 1"));
1296 printf (" %s\n", "-f, --fmtstr=STRING");
1297 printf (" %s\n", _("C-style format string for float values (see option -M)"));
1238 1298
1239 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1299 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1240 printf (" %s\n", _("NOTE the final timeout value is calculated using this formula: timeout_interval * retries + 5")); 1300 printf (" %s\n", _("NOTE the final timeout value is calculated using this formula: timeout_interval * retries + 5"));
@@ -1287,4 +1347,5 @@ print_usage (void)
1287 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n"); 1347 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1288 printf ("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n"); 1348 printf ("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
1289 printf ("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd] [-4|6]\n"); 1349 printf ("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd] [-4|6]\n");
1350 printf ("[-M multiplier [-f format]]\n");
1290} 1351}
diff --git a/plugins/sslutils.c b/plugins/sslutils.c
index 286273f..666a012 100644
--- a/plugins/sslutils.c
+++ b/plugins/sslutils.c
@@ -134,7 +134,16 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int
134 return STATE_CRITICAL; 134 return STATE_CRITICAL;
135 } 135 }
136 if (cert && privkey) { 136 if (cert && privkey) {
137 SSL_CTX_use_certificate_chain_file(c, cert); 137#ifdef USE_OPENSSL
138 if (!SSL_CTX_use_certificate_chain_file(c, cert)) {
139#elif USE_GNUTLS
140 if (!SSL_CTX_use_certificate_file(c, cert, SSL_FILETYPE_PEM)) {
141#else
142#error Unported for unknown SSL library
143#endif
144 printf ("%s\n", _("CRITICAL - Unable to open certificate chain file!\n"));
145 return STATE_CRITICAL;
146 }
138 SSL_CTX_use_PrivateKey_file(c, privkey, SSL_FILETYPE_PEM); 147 SSL_CTX_use_PrivateKey_file(c, privkey, SSL_FILETYPE_PEM);
139#ifdef USE_OPENSSL 148#ifdef USE_OPENSSL
140 if (!SSL_CTX_check_private_key(c)) { 149 if (!SSL_CTX_check_private_key(c)) {
@@ -191,17 +200,6 @@ int np_net_ssl_read(void *buf, int num) {
191 return SSL_read(s, buf, num); 200 return SSL_read(s, buf, num);
192} 201}
193 202
194int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
195# ifdef USE_OPENSSL
196 X509 *certificate = NULL;
197 certificate=SSL_get_peer_certificate(s);
198 return(np_net_ssl_check_certificate(certificate, days_till_exp_warn, days_till_exp_crit));
199# else /* ifndef USE_OPENSSL */
200 printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
201 return STATE_WARNING;
202# endif /* USE_OPENSSL */
203}
204
205int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit){ 203int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit){
206# ifdef USE_OPENSSL 204# ifdef USE_OPENSSL
207 X509_NAME *subj=NULL; 205 X509_NAME *subj=NULL;
@@ -328,4 +326,16 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
328# endif /* USE_OPENSSL */ 326# endif /* USE_OPENSSL */
329} 327}
330 328
329int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
330# ifdef USE_OPENSSL
331 X509 *certificate = NULL;
332 certificate=SSL_get_peer_certificate(s);
333 return(np_net_ssl_check_certificate(certificate, days_till_exp_warn, days_till_exp_crit));
334# else /* ifndef USE_OPENSSL */
335 printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
336 return STATE_WARNING;
337# endif /* USE_OPENSSL */
338}
339
340
331#endif /* HAVE_SSL */ 341#endif /* HAVE_SSL */
diff --git a/plugins/t/check_curl.t b/plugins/t/check_curl.t
index 693f4b2..eae98cc 100644
--- a/plugins/t/check_curl.t
+++ b/plugins/t/check_curl.t
@@ -1,15 +1,22 @@
1#! /usr/bin/perl -w -I .. 1#! /usr/bin/perl -w -I ..
2# 2#
3# HyperText Transfer Protocol (HTTP) Test via check_http 3# HyperText Transfer Protocol (HTTP) Test via check_curl
4# 4#
5# 5#
6 6
7use strict; 7use strict;
8use Test::More; 8use Test::More;
9use POSIX qw/mktime strftime/; 9use POSIX qw/mktime strftime/;
10use NPTest;
11 10
12plan tests => 57; 11use vars qw($tests $has_ipv6);
12
13BEGIN {
14 use NPTest;
15 $has_ipv6 = NPTest::has_ipv6();
16 $tests = $has_ipv6 ? 59 : 57;
17 plan tests => $tests;
18}
19
13 20
14my $successOutput = '/OK.*HTTP.*second/'; 21my $successOutput = '/OK.*HTTP.*second/';
15 22
@@ -18,6 +25,7 @@ my $plugin = 'check_http';
18$plugin = 'check_curl' if $0 =~ m/check_curl/mx; 25$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
19 26
20my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost"); 27my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost");
28my $host_tcp_http_ipv6 = getTestParameter("NP_HOST_TCP_HTTP_IPV6", "An IPv6 address providing a HTTP Service (a web server)", "::1");
21my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost"); 29my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost");
22my $host_tls_cert = getTestParameter("NP_HOST_TLS_CERT", "the common name of the certificate.", "localhost"); 30my $host_tls_cert = getTestParameter("NP_HOST_TLS_CERT", "the common name of the certificate.", "localhost");
23my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1"); 31my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
@@ -31,26 +39,35 @@ my $faketime = -x '/usr/bin/faketime' ? 1 : 0;
31 39
32 40
33$res = NPTest->testCmd( 41$res = NPTest->testCmd(
34 "./$plugin $host_tcp_http -wt 300 -ct 600" 42 "./$plugin $host_tcp_http -wt 300 -ct 600"
35 ); 43 );
36cmp_ok( $res->return_code, '==', 0, "Webserver $host_tcp_http responded" ); 44cmp_ok( $res->return_code, '==', 0, "Webserver $host_tcp_http responded" );
37like( $res->output, $successOutput, "Output OK" ); 45like( $res->output, $successOutput, "Output OK" );
38 46
47if ($has_ipv6) {
48 # Test for IPv6 formatting
49 $res = NPTest->testCmd(
50 "./$plugin -I $host_tcp_http_ipv6 -wt 300 -ct 600"
51 );
52 cmp_ok( $res->return_code, '==', 0, "IPv6 URL formatting is working" );
53 like( $res->output, $successOutput, "Output OK" );
54}
55
39$res = NPTest->testCmd( 56$res = NPTest->testCmd(
40 "./$plugin $host_tcp_http -wt 300 -ct 600 -v -v -v -k 'bob:there' -k 'carl:frown'" 57 "./$plugin $host_tcp_http -wt 300 -ct 600 -v -v -v -k 'bob:there' -k 'carl:frown'"
41 ); 58 );
42like( $res->output, '/bob:there\r\ncarl:frown\r\n/', "Got headers with multiple -k options" ); 59like( $res->output, '/bob:there\r\ncarl:frown\r\n/', "Got headers with multiple -k options" );
43 60
44$res = NPTest->testCmd( 61$res = NPTest->testCmd(
45 "./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3" 62 "./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3"
46 ); 63 );
47cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" ); 64cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" );
48# was CRITICAL only, but both check_curl and check_http print HTTP CRITICAL (puzzle?!) 65# was CRITICAL only, but both check_curl and check_http print HTTP CRITICAL (puzzle?!)
49like( $res->output, "/HTTP CRITICAL - Invalid HTTP response received from host on port 80: cURL returned 28 - Connection timed out after/", "Output OK"); 66like( $res->output, "/HTTP CRITICAL - Invalid HTTP response received from host on port 80: cURL returned 28 - Connection timed out after/", "Output OK");
50 67
51$res = NPTest->testCmd( 68$res = NPTest->testCmd(
52 "./$plugin $hostname_invalid -wt 1 -ct 2" 69 "./$plugin $hostname_invalid -wt 1 -ct 2"
53 ); 70 );
54cmp_ok( $res->return_code, '==', 2, "Webserver $hostname_invalid not valid" ); 71cmp_ok( $res->return_code, '==', 2, "Webserver $hostname_invalid not valid" );
55# The first part of the message comes from the OS catalogue, so cannot check this. 72# The first part of the message comes from the OS catalogue, so cannot check this.
56# On Debian, it is Name or service not known, on Darwin, it is No address associated with nodename 73# On Debian, it is Name or service not known, on Darwin, it is No address associated with nodename
diff --git a/plugins/t/check_http.t b/plugins/t/check_http.t
index 0c86622..1ca52f6 100644
--- a/plugins/t/check_http.t
+++ b/plugins/t/check_http.t
@@ -103,7 +103,7 @@ SKIP: {
103 cmp_ok( $res->return_code, "==", 0, "And also when not found"); 103 cmp_ok( $res->return_code, "==", 0, "And also when not found");
104} 104}
105SKIP: { 105SKIP: {
106 skip "No internet access", 23 if $internet_access eq "no"; 106 skip "No internet access", 22 if $internet_access eq "no";
107 107
108 $res = NPTest->testCmd( 108 $res = NPTest->testCmd(
109 "./$plugin --ssl $host_tls_http" 109 "./$plugin --ssl $host_tls_http"
diff --git a/plugins/tests/check_curl.t b/plugins/tests/check_curl.t
index aa72ef6..72f2b7c 100755
--- a/plugins/tests/check_curl.t
+++ b/plugins/tests/check_curl.t
@@ -21,7 +21,7 @@ use FindBin qw($Bin);
21 21
22$ENV{'LC_TIME'} = "C"; 22$ENV{'LC_TIME'} = "C";
23 23
24my $common_tests = 72; 24my $common_tests = 73;
25my $ssl_only_tests = 8; 25my $ssl_only_tests = 8;
26# Check that all dependent modules are available 26# Check that all dependent modules are available
27eval "use HTTP::Daemon 6.01;"; 27eval "use HTTP::Daemon 6.01;";
@@ -200,6 +200,14 @@ sub run_server {
200 $c->send_basic_header; 200 $c->send_basic_header;
201 $c->send_crlf; 201 $c->send_crlf;
202 $c->send_response(HTTP::Response->new( 200, 'OK', undef, $r->header ('Host'))); 202 $c->send_response(HTTP::Response->new( 200, 'OK', undef, $r->header ('Host')));
203 } elsif ($r->url->path eq "/chunked") {
204 my $chunks = ["chunked", "encoding", "test\n"];
205 $c->send_response(HTTP::Response->new( 200, 'OK', undef, sub {
206 my $chunk = shift @{$chunks};
207 return unless $chunk;
208 sleep(1);
209 return($chunk);
210 }));
203 } else { 211 } else {
204 $c->send_error(HTTP::Status->RC_FORBIDDEN); 212 $c->send_error(HTTP::Status->RC_FORBIDDEN);
205 } 213 }
@@ -472,7 +480,8 @@ sub run_common_tests {
472 local $SIG{ALRM} = sub { die "alarm\n" }; 480 local $SIG{ALRM} = sub { die "alarm\n" };
473 alarm(2); 481 alarm(2);
474 $result = NPTest->testCmd( $cmd ); 482 $result = NPTest->testCmd( $cmd );
475 alarm(0); }; 483 };
484 alarm(0);
476 isnt( $@, "alarm\n", $cmd ); 485 isnt( $@, "alarm\n", $cmd );
477 is( $result->return_code, 0, $cmd ); 486 is( $result->return_code, 0, $cmd );
478 487
@@ -482,7 +491,8 @@ sub run_common_tests {
482 local $SIG{ALRM} = sub { die "alarm\n" }; 491 local $SIG{ALRM} = sub { die "alarm\n" };
483 alarm(2); 492 alarm(2);
484 $result = NPTest->testCmd( $cmd ); 493 $result = NPTest->testCmd( $cmd );
485 alarm(0); }; 494 };
495 alarm(0);
486 isnt( $@, "alarm\n", $cmd ); 496 isnt( $@, "alarm\n", $cmd );
487 isnt( $result->return_code, 0, $cmd ); 497 isnt( $result->return_code, 0, $cmd );
488 498
@@ -508,4 +518,9 @@ sub run_common_tests {
508 }; 518 };
509 is( $@, "", $cmd ); 519 is( $@, "", $cmd );
510 520
521 $cmd = "$command -u /chunked -s 'chunkedencodingtest' -d 'Transfer-Encoding: chunked'";
522 eval {
523 $result = NPTest->testCmd( $cmd, 5 );
524 };
525 is( $@, "", $cmd );
511} 526}
diff --git a/plugins/tests/check_http.t b/plugins/tests/check_http.t
index ea11b2a..6078b27 100755
--- a/plugins/tests/check_http.t
+++ b/plugins/tests/check_http.t
@@ -9,12 +9,14 @@ use strict;
9use Test::More; 9use Test::More;
10use NPTest; 10use NPTest;
11use FindBin qw($Bin); 11use FindBin qw($Bin);
12use IO::Socket::INET;
12 13
13$ENV{'LC_TIME'} = "C"; 14$ENV{'LC_TIME'} = "C";
14 15
15my $common_tests = 70; 16my $common_tests = 71;
16my $virtual_port_tests = 8; 17my $virtual_port_tests = 8;
17my $ssl_only_tests = 12; 18my $ssl_only_tests = 12;
19my $chunked_encoding_special_tests = 1;
18# Check that all dependent modules are available 20# Check that all dependent modules are available
19eval "use HTTP::Daemon 6.01;"; 21eval "use HTTP::Daemon 6.01;";
20plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@; 22plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@;
@@ -30,7 +32,7 @@ if ($@) {
30 plan skip_all => "Missing required module for test: $@"; 32 plan skip_all => "Missing required module for test: $@";
31} else { 33} else {
32 if (-x "./$plugin") { 34 if (-x "./$plugin") {
33 plan tests => $common_tests * 2 + $ssl_only_tests + $virtual_port_tests; 35 plan tests => $common_tests * 2 + $ssl_only_tests + $virtual_port_tests + $chunked_encoding_special_tests;
34 } else { 36 } else {
35 plan skip_all => "No $plugin compiled"; 37 plan skip_all => "No $plugin compiled";
36 } 38 }
@@ -51,6 +53,7 @@ my $port_http = 50000 + int(rand(1000));
51my $port_https = $port_http + 1; 53my $port_https = $port_http + 1;
52my $port_https_expired = $port_http + 2; 54my $port_https_expired = $port_http + 2;
53my $port_https_clientcert = $port_http + 3; 55my $port_https_clientcert = $port_http + 3;
56my $port_hacked_http = $port_http + 4;
54 57
55# This array keeps sockets around for implementing timeouts 58# This array keeps sockets around for implementing timeouts
56my @persist; 59my @persist;
@@ -72,6 +75,28 @@ if (!$pid) {
72} 75}
73push @pids, $pid; 76push @pids, $pid;
74 77
78# Fork the hacked HTTP server
79undef $pid;
80$pid = fork;
81defined $pid or die "Failed to fork";
82if (!$pid) {
83 # this is the fork
84 undef @pids;
85 my $socket = new IO::Socket::INET (
86 LocalHost => '0.0.0.0',
87 LocalPort => $port_hacked_http,
88 Proto => 'tcp',
89 Listen => 5,
90 Reuse => 1
91 );
92 die "cannot create socket $!n" unless $socket;
93 my $local_sock = $socket->sockport();
94 print "server waiting for client connection on port $local_sock\n";
95 run_hacked_http_server ( $socket );
96 die "hacked http server stopped";
97}
98push @pids, $pid;
99
75if (exists $servers->{https}) { 100if (exists $servers->{https}) {
76 # Fork a normal HTTPS server 101 # Fork a normal HTTPS server
77 $pid = fork; 102 $pid = fork;
@@ -190,6 +215,14 @@ sub run_server {
190 $c->send_basic_header; 215 $c->send_basic_header;
191 $c->send_crlf; 216 $c->send_crlf;
192 $c->send_response(HTTP::Response->new( 200, 'OK', undef, $r->header ('Host'))); 217 $c->send_response(HTTP::Response->new( 200, 'OK', undef, $r->header ('Host')));
218 } elsif ($r->url->path eq "/chunked") {
219 my $chunks = ["chunked", "encoding", "test\n"];
220 $c->send_response(HTTP::Response->new( 200, 'OK', undef, sub {
221 my $chunk = shift @{$chunks};
222 return unless $chunk;
223 sleep(1);
224 return($chunk);
225 }));
193 } else { 226 } else {
194 $c->send_error(HTTP::Status->RC_FORBIDDEN); 227 $c->send_error(HTTP::Status->RC_FORBIDDEN);
195 } 228 }
@@ -199,6 +232,37 @@ sub run_server {
199 } 232 }
200} 233}
201 234
235sub run_hacked_http_server {
236 my $socket = shift;
237
238 # auto-flush on socket
239 $| = 1;
240
241
242 while(1)
243 {
244 # waiting for a new client connection
245 my $client_socket = $socket->accept();
246
247 # get information about a newly connected client
248 my $client_address = $client_socket->peerhost();
249 my $client_portn = $client_socket->peerport();
250 print "connection from $client_address:$client_portn";
251
252 # read up to 1024 characters from the connected client
253 my $data = "";
254 $client_socket->recv($data, 1024);
255 print "received data: $data";
256
257 # write response data to the connected client
258 $data = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n";
259 $client_socket->send($data);
260
261 # notify client that response has been sent
262 shutdown($client_socket, 1);
263 }
264}
265
202END { 266END {
203 foreach my $pid (@pids) { 267 foreach my $pid (@pids) {
204 if ($pid) { print "Killing $pid\n"; kill "INT", $pid } 268 if ($pid) { print "Killing $pid\n"; kill "INT", $pid }
@@ -214,6 +278,7 @@ if ($ARGV[0] && $ARGV[0] eq "-d") {
214my $result; 278my $result;
215my $command = "./$plugin -H 127.0.0.1"; 279my $command = "./$plugin -H 127.0.0.1";
216 280
281run_chunked_encoding_special_test( {command => "$command -p $port_hacked_http"});
217run_common_tests( { command => "$command -p $port_http" } ); 282run_common_tests( { command => "$command -p $port_http" } );
218SKIP: { 283SKIP: {
219 skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https}; 284 skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https};
@@ -497,4 +562,20 @@ sub run_common_tests {
497 }; 562 };
498 is( $@, "", $cmd ); 563 is( $@, "", $cmd );
499 564
565 $cmd = "$command -u /chunked -s 'chunkedencodingtest' -d 'Transfer-Encoding: chunked'";
566 eval {
567 $result = NPTest->testCmd( $cmd, 5 );
568 };
569 is( $@, "", $cmd );
570}
571
572sub run_chunked_encoding_special_test {
573 my ($opts) = @_;
574 my $command = $opts->{command};
575
576 $cmd = "$command -u / -s 'ChunkedEncodingSpecialTest'";
577 eval {
578 $result = NPTest->testCmd( $cmd, 5 );
579 };
580 is( $@, "", $cmd );
500} 581}
diff --git a/plugins/tests/check_snmp.t b/plugins/tests/check_snmp.t
index 0a77fa8..bc03ec6 100755
--- a/plugins/tests/check_snmp.t
+++ b/plugins/tests/check_snmp.t
@@ -9,7 +9,7 @@ use NPTest;
9use FindBin qw($Bin); 9use FindBin qw($Bin);
10use POSIX qw/strftime/; 10use POSIX qw/strftime/;
11 11
12my $tests = 73; 12my $tests = 81;
13# Check that all dependent modules are available 13# Check that all dependent modules are available
14eval { 14eval {
15 require NetSNMP::OID; 15 require NetSNMP::OID;
@@ -57,9 +57,9 @@ if ($pid) {
57 exec("snmpd -c tests/conf/snmpd.conf -C -f -r udp:$port_snmp"); 57 exec("snmpd -c tests/conf/snmpd.conf -C -f -r udp:$port_snmp");
58} 58}
59 59
60END { 60END {
61 foreach my $pid (@pids) { 61 foreach my $pid (@pids) {
62 if ($pid) { print "Killing $pid\n"; kill "INT", $pid } 62 if ($pid) { print "Killing $pid\n"; kill "INT", $pid }
63 } 63 }
64}; 64};
65 65
@@ -268,3 +268,19 @@ like($res->output, '/SNMP WARNING - \d+ \*-4\* | iso.3.6.1.4.1.8072.3.2.67.10=\d
268$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10,.1.3.6.1.4.1.8072.3.2.67.17 -w 1,2 -c 1" ); 268$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10,.1.3.6.1.4.1.8072.3.2.67.17 -w 1,2 -c 1" );
269is($res->return_code, 2, "Multiple OIDs with some thresholds" ); 269is($res->return_code, 2, "Multiple OIDs with some thresholds" );
270like($res->output, '/SNMP CRITICAL - \*\d+\* \*-4\* | iso.3.6.1.4.1.8072.3.2.67.10=\d+c;1;2 iso.3.6.1.4.1.8072.3.2.67.17=-4;;/', "Multiple OIDs with thresholds output" ); 270like($res->output, '/SNMP CRITICAL - \*\d+\* \*-4\* | iso.3.6.1.4.1.8072.3.2.67.10=\d+c;1;2 iso.3.6.1.4.1.8072.3.2.67.17=-4;;/', "Multiple OIDs with thresholds output" );
271
272$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.19");
273is($res->return_code, 0, "Test plain .1.3.6.1.4.1.8072.3.2.67.6 RC" );
274is($res->output,'SNMP OK - 42 | iso.3.6.1.4.1.8072.3.2.67.19=42 ', "Test plain value of .1.3.6.1.4.1.8072.3.2.67.1" );
275
276$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.19 -M .1");
277is($res->return_code, 0, "Test multiply RC" );
278is($res->output,'SNMP OK - 4.200000 | iso.3.6.1.4.1.8072.3.2.67.19=4.200000 ' , "Test multiply .1 output" );
279
280$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.19 --multiplier=.1 -f '%.2f' ");
281is($res->return_code, 0, "Test multiply RC + format" );
282is($res->output, 'SNMP OK - 4.20 | iso.3.6.1.4.1.8072.3.2.67.19=4.20 ', "Test multiply .1 output + format" );
283
284$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.19 --multiplier=.1 -f '%.2f' -w 1");
285is($res->return_code, 1, "Test multiply RC + format + thresholds" );
286is($res->output, 'SNMP WARNING - *4.20* | iso.3.6.1.4.1.8072.3.2.67.19=4.20;1 ', "Test multiply .1 output + format + thresholds" );
diff --git a/plugins/tests/check_snmp_agent.pl b/plugins/tests/check_snmp_agent.pl
index 0e41d57..38912e9 100644
--- a/plugins/tests/check_snmp_agent.pl
+++ b/plugins/tests/check_snmp_agent.pl
@@ -32,11 +32,11 @@ my $multilin5 = 'And now have fun with with this: "C:\\"
32because we\'re not done yet!'; 32because we\'re not done yet!';
33 33
34# Next are arrays of indexes (Type, initial value and increments) 34# Next are arrays of indexes (Type, initial value and increments)
35# 0..16 <---- please update comment when adding/removing fields 35# 0..19 <---- please update comment when adding/removing fields
36my @fields = (ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_UNSIGNED, ASN_UNSIGNED, ASN_COUNTER, ASN_COUNTER64, ASN_UNSIGNED, ASN_COUNTER, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_INTEGER, ASN_OCTET_STR, ASN_OCTET_STR ); 36my @fields = (ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_UNSIGNED, ASN_UNSIGNED, ASN_COUNTER, ASN_COUNTER64, ASN_UNSIGNED, ASN_COUNTER, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_INTEGER, ASN_OCTET_STR, ASN_OCTET_STR, ASN_INTEGER );
37my @values = ($multiline, $multilin2, $multilin3, $multilin4, $multilin5, 4294965296, 1000, 4294965296, uint64("18446744073709351616"), int(rand(2**32)), 64000, "stringtests", "3.5", "87.4startswithnumberbutshouldbestring", '555"I said"', 'CUSTOM CHECK OK: foo is 12345', -2, '-4', '-6.6' ); 37my @values = ($multiline, $multilin2, $multilin3, $multilin4, $multilin5, 4294965296, 1000, 4294965296, uint64("18446744073709351616"), int(rand(2**32)), 64000, "stringtests", "3.5", "87.4startswithnumberbutshouldbestring", '555"I said"', 'CUSTOM CHECK OK: foo is 12345', -2, '-4', '-6.6', 42 );
38# undef increments are randomized 38# undef increments are randomized
39my @incrts = (undef, undef, undef, undef, undef, 1000, -500, 1000, 100000, undef, 666, undef, undef, undef, undef, undef, -1, undef, undef ); 39my @incrts = (undef, undef, undef, undef, undef, 1000, -500, 1000, 100000, undef, 666, undef, undef, undef, undef, undef, -1, undef, undef, 0 );
40 40
41# Number of elements in our OID 41# Number of elements in our OID
42my $oidelts; 42my $oidelts;
diff --git a/plugins/utils.c b/plugins/utils.c
index f75cf03..b4214c6 100644
--- a/plugins/utils.c
+++ b/plugins/utils.c
@@ -615,9 +615,9 @@ char *perfdata_uint64 (const char *label,
615 char *data = NULL; 615 char *data = NULL;
616 616
617 if (strpbrk (label, "'= ")) 617 if (strpbrk (label, "'= "))
618 xasprintf (&data, "'%s'=%" PRId64 "%s;", label, val, uom); 618 xasprintf (&data, "'%s'=%" PRIu64 "%s;", label, val, uom);
619 else 619 else
620 xasprintf (&data, "%s=%" PRId64 "%s;", label, val, uom); 620 xasprintf (&data, "%s=%" PRIu64 "%s;", label, val, uom);
621 621
622 if (warnp) 622 if (warnp)
623 xasprintf (&data, "%s%" PRIu64 ";", data, warn); 623 xasprintf (&data, "%s%" PRIu64 ";", data, warn);