summaryrefslogtreecommitdiffstats
path: root/plugins/check_snmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_snmp.c')
-rw-r--r--plugins/check_snmp.c153
1 files changed, 122 insertions, 31 deletions
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index e8a21a40..d3968a27 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] = "";
@@ -113,6 +114,7 @@ char *authproto = NULL;
113char *privproto = NULL; 114char *privproto = NULL;
114char *authpasswd = NULL; 115char *authpasswd = NULL;
115char *privpasswd = NULL; 116char *privpasswd = NULL;
117int nulloid = STATE_UNKNOWN;
116char **oids = NULL; 118char **oids = NULL;
117size_t oids_size = 0; 119size_t oids_size = 0;
118char *label; 120char *label;
@@ -153,6 +155,8 @@ double *previous_value;
153size_t previous_size = OID_COUNT_STEP; 155size_t previous_size = OID_COUNT_STEP;
154int perf_labels = 1; 156int perf_labels = 1;
155char* ip_version = ""; 157char* ip_version = "";
158double multiplier = 1.0;
159char *fmtstr = "";
156 160
157static char *fix_snmp_range(char *th) 161static char *fix_snmp_range(char *th)
158{ 162{
@@ -315,7 +319,7 @@ main (int argc, char **argv)
315 for (i = 0; i < numcontext; i++) { 319 for (i = 0; i < numcontext; i++) {
316 command_line[10 + i] = contextargs[i]; 320 command_line[10 + i] = contextargs[i];
317 } 321 }
318 322
319 for (i = 0; i < numauthpriv; i++) { 323 for (i = 0; i < numauthpriv; i++) {
320 command_line[10 + numcontext + i] = authpriv[i]; 324 command_line[10 + numcontext + i] = authpriv[i];
321 } 325 }
@@ -329,7 +333,7 @@ main (int argc, char **argv)
329 333
330 for (i = 0; i < numoids; i++) { 334 for (i = 0; i < numoids; i++) {
331 command_line[10 + numcontext + numauthpriv + 1 + i] = oids[i]; 335 command_line[10 + numcontext + numauthpriv + 1 + i] = oids[i];
332 xasprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]); 336 xasprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);
333 } 337 }
334 338
335 command_line[10 + numcontext + numauthpriv + 1 + numoids] = NULL; 339 command_line[10 + numcontext + numauthpriv + 1 + numoids] = NULL;
@@ -375,7 +379,7 @@ main (int argc, char **argv)
375 } 379 }
376 } 380 }
377 381
378 for (line=0, i=0; line < chld_out.lines; line++, i++) { 382 for (line=0, i=0; line < chld_out.lines && i < numoids ; line++, i++) {
379 if(calculate_rate) 383 if(calculate_rate)
380 conv = "%.10g"; 384 conv = "%.10g";
381 else 385 else
@@ -397,15 +401,15 @@ main (int argc, char **argv)
397 is_counter=0; 401 is_counter=0;
398 /* We strip out the datatype indicator for PHBs */ 402 /* We strip out the datatype indicator for PHBs */
399 if (strstr (response, "Gauge: ")) { 403 if (strstr (response, "Gauge: ")) {
400 show = strstr (response, "Gauge: ") + 7; 404 show = multiply (strstr (response, "Gauge: ") + 7);
401 } 405 }
402 else if (strstr (response, "Gauge32: ")) { 406 else if (strstr (response, "Gauge32: ")) {
403 show = strstr (response, "Gauge32: ") + 9; 407 show = multiply (strstr (response, "Gauge32: ") + 9);
404 } 408 }
405 else if (strstr (response, "Counter32: ")) { 409 else if (strstr (response, "Counter32: ")) {
406 show = strstr (response, "Counter32: ") + 11; 410 show = strstr (response, "Counter32: ") + 11;
407 is_counter=1; 411 is_counter=1;
408 if(!calculate_rate) 412 if(!calculate_rate)
409 strcpy(type, "c"); 413 strcpy(type, "c");
410 } 414 }
411 else if (strstr (response, "Counter64: ")) { 415 else if (strstr (response, "Counter64: ")) {
@@ -415,7 +419,10 @@ main (int argc, char **argv)
415 strcpy(type, "c"); 419 strcpy(type, "c");
416 } 420 }
417 else if (strstr (response, "INTEGER: ")) { 421 else if (strstr (response, "INTEGER: ")) {
418 show = strstr (response, "INTEGER: ") + 9; 422 show = multiply (strstr (response, "INTEGER: ") + 9);
423 if (fmtstr != "") {
424 conv = fmtstr;
425 }
419 } 426 }
420 else if (strstr (response, "OID: ")) { 427 else if (strstr (response, "OID: ")) {
421 show = strstr (response, "OID: ") + 5; 428 show = strstr (response, "OID: ") + 5;
@@ -468,9 +475,20 @@ main (int argc, char **argv)
468 /* Process this block for numeric comparisons */ 475 /* Process this block for numeric comparisons */
469 /* Make some special values,like Timeticks numeric only if a threshold is defined */ 476 /* Make some special values,like Timeticks numeric only if a threshold is defined */
470 if (thlds[i]->warning || thlds[i]->critical || calculate_rate) { 477 if (thlds[i]->warning || thlds[i]->critical || calculate_rate) {
478 if (verbose > 2) {
479 print_thresholds(" thresholds", thlds[i]);
480 }
471 ptr = strpbrk (show, "-0123456789"); 481 ptr = strpbrk (show, "-0123456789");
472 if (ptr == NULL) 482 if (ptr == NULL){
473 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show); 483 if (nulloid == 3)
484 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show);
485 else if (nulloid == 0)
486 die (STATE_OK,_("No valid data returned (%s)\n"), show);
487 else if (nulloid == 1)
488 die (STATE_WARNING,_("No valid data returned (%s)\n"), show);
489 else if (nulloid == 2)
490 die (STATE_CRITICAL,_("No valid data returned (%s)\n"), show);
491 }
474 while (i >= response_size) { 492 while (i >= response_size) {
475 response_size += OID_COUNT_STEP; 493 response_size += OID_COUNT_STEP;
476 response_value = realloc(response_value, response_size * sizeof(*response_value)); 494 response_value = realloc(response_value, response_size * sizeof(*response_value));
@@ -576,20 +594,23 @@ main (int argc, char **argv)
576 len = sizeof(perfstr)-strlen(perfstr)-1; 594 len = sizeof(perfstr)-strlen(perfstr)-1;
577 strncat(perfstr, show, len>ptr-show ? ptr-show : len); 595 strncat(perfstr, show, len>ptr-show ? ptr-show : len);
578 596
597 if (type)
598 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
599
579 if (warning_thresholds) { 600 if (warning_thresholds) {
580 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 601 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
581 strncat(perfstr, warning_thresholds, sizeof(perfstr)-strlen(perfstr)-1); 602 if(thlds[i]->warning && thlds[i]->warning->text)
603 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr)-strlen(perfstr)-1);
582 } 604 }
583 605
584 if (critical_thresholds) { 606 if (critical_thresholds) {
585 if (!warning_thresholds) 607 if (!warning_thresholds)
586 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 608 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
587 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 609 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
588 strncat(perfstr, critical_thresholds, sizeof(perfstr)-strlen(perfstr)-1); 610 if(thlds[i]->critical && thlds[i]->critical->text)
611 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr)-strlen(perfstr)-1);
589 } 612 }
590 613
591 if (type)
592 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
593 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); 614 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
594 } 615 }
595 } 616 }
@@ -601,7 +622,7 @@ main (int argc, char **argv)
601 state_string=malloc(string_length); 622 state_string=malloc(string_length);
602 if(state_string==NULL) 623 if(state_string==NULL)
603 die(STATE_UNKNOWN, _("Cannot malloc")); 624 die(STATE_UNKNOWN, _("Cannot malloc"));
604 625
605 current_length=0; 626 current_length=0;
606 for(i=0; i<total_oids; i++) { 627 for(i=0; i<total_oids; i++) {
607 xasprintf(&temp_string,"%.0f",response_value[i]); 628 xasprintf(&temp_string,"%.0f",response_value[i]);
@@ -623,7 +644,7 @@ main (int argc, char **argv)
623 state_string[--current_length]='\0'; 644 state_string[--current_length]='\0';
624 if (verbose > 2) 645 if (verbose > 2)
625 printf("State string=%s\n",state_string); 646 printf("State string=%s\n",state_string);
626 647
627 /* 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 */
628 np_state_write_string(current_time, state_string ); 649 np_state_write_string(current_time, state_string );
629 if(previous_state==NULL) { 650 if(previous_state==NULL) {
@@ -655,6 +676,7 @@ process_arguments (int argc, char **argv)
655 {"oid", required_argument, 0, 'o'}, 676 {"oid", required_argument, 0, 'o'},
656 {"object", required_argument, 0, 'o'}, 677 {"object", required_argument, 0, 'o'},
657 {"delimiter", required_argument, 0, 'd'}, 678 {"delimiter", required_argument, 0, 'd'},
679 {"nulloid", required_argument, 0, 'z'},
658 {"output-delimiter", required_argument, 0, 'D'}, 680 {"output-delimiter", required_argument, 0, 'D'},
659 {"string", required_argument, 0, 's'}, 681 {"string", required_argument, 0, 's'},
660 {"timeout", required_argument, 0, 't'}, 682 {"timeout", required_argument, 0, 't'},
@@ -682,6 +704,8 @@ process_arguments (int argc, char **argv)
682 {"perf-oids", no_argument, 0, 'O'}, 704 {"perf-oids", no_argument, 0, 'O'},
683 {"ipv4", no_argument, 0, '4'}, 705 {"ipv4", no_argument, 0, '4'},
684 {"ipv6", no_argument, 0, '6'}, 706 {"ipv6", no_argument, 0, '6'},
707 {"multiplier", required_argument, 0, 'M'},
708 {"fmtstr", required_argument, 0, 'f'},
685 {0, 0, 0, 0} 709 {0, 0, 0, 0}
686 }; 710 };
687 711
@@ -699,7 +723,7 @@ process_arguments (int argc, char **argv)
699 } 723 }
700 724
701 while (1) { 725 while (1) {
702 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:", 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:",
703 longopts, &option); 727 longopts, &option);
704 728
705 if (c == -1 || c == EOF) 729 if (c == -1 || c == EOF)
@@ -810,6 +834,12 @@ process_arguments (int argc, char **argv)
810 eval_method[j+1] |= CRIT_PRESENT; 834 eval_method[j+1] |= CRIT_PRESENT;
811 } 835 }
812 break; 836 break;
837 case 'z': /* Null OID Return Check */
838 if (!is_integer (optarg))
839 usage2 (_("Exit status must be a positive integer"), optarg);
840 else
841 nulloid = atoi(optarg);
842 break;
813 case 's': /* string or substring */ 843 case 's': /* string or substring */
814 strncpy (string_value, optarg, sizeof (string_value) - 1); 844 strncpy (string_value, optarg, sizeof (string_value) - 1);
815 string_value[sizeof (string_value) - 1] = 0; 845 string_value[sizeof (string_value) - 1] = 0;
@@ -931,6 +961,16 @@ process_arguments (int argc, char **argv)
931 if(verbose>2) 961 if(verbose>2)
932 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n"); 962 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n");
933 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;
934 } 974 }
935 } 975 }
936 976
@@ -1000,7 +1040,7 @@ validate_arguments ()
1000 contextargs[0] = strdup ("-n"); 1040 contextargs[0] = strdup ("-n");
1001 contextargs[1] = strdup (context); 1041 contextargs[1] = strdup (context);
1002 } 1042 }
1003 1043
1004 if (seclevel == NULL) 1044 if (seclevel == NULL)
1005 xasprintf(&seclevel, "noAuthNoPriv"); 1045 xasprintf(&seclevel, "noAuthNoPriv");
1006 1046
@@ -1121,6 +1161,44 @@ nextarg (char *str)
1121 1161
1122 1162
1123 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
1124void 1202void
1125print_help (void) 1203print_help (void)
1126{ 1204{
@@ -1160,7 +1238,7 @@ print_help (void)
1160 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY); 1238 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
1161 printf (" %s\n", "-U, --secname=USERNAME"); 1239 printf (" %s\n", "-U, --secname=USERNAME");
1162 printf (" %s\n", _("SNMPv3 username")); 1240 printf (" %s\n", _("SNMPv3 username"));
1163 printf (" %s\n", "-A, --authpassword=PASSWORD"); 1241 printf (" %s\n", "-A, --authpasswd=PASSWORD");
1164 printf (" %s\n", _("SNMPv3 authentication password")); 1242 printf (" %s\n", _("SNMPv3 authentication password"));
1165 printf (" %s\n", "-X, --privpasswd=PASSWORD"); 1243 printf (" %s\n", "-X, --privpasswd=PASSWORD");
1166 printf (" %s\n", _("SNMPv3 privacy password")); 1244 printf (" %s\n", _("SNMPv3 privacy password"));
@@ -1175,6 +1253,14 @@ print_help (void)
1175 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER); 1253 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
1176 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered")); 1254 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
1177 printf (" %s\n", _("to be the data that should be used in the evaluation.")); 1255 printf (" %s\n", _("to be the data that should be used in the evaluation."));
1256 printf (" %s\n", "-z, --nulloid=#");
1257 printf (" %s\n", _("If the check returns a 0 length string or NULL value"));
1258 printf (" %s\n", _("This option allows you to choose what status you want it to exit"));
1259 printf (" %s\n", _("Excluding this option renders the default exit of 3(STATE_UNKNOWN)"));
1260 printf (" %s\n", _("0 = OK"));
1261 printf (" %s\n", _("1 = WARNING"));
1262 printf (" %s\n", _("2 = CRITICAL"));
1263 printf (" %s\n", _("3 = UNKNOWN"));
1178 1264
1179 /* Tests Against Integers */ 1265 /* Tests Against Integers */
1180 printf (" %s\n", "-w, --warning=THRESHOLD(s)"); 1266 printf (" %s\n", "-w, --warning=THRESHOLD(s)");
@@ -1205,6 +1291,10 @@ print_help (void)
1205 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.')."));
1206 printf (" %s\n", "-D, --output-delimiter=STRING"); 1292 printf (" %s\n", "-D, --output-delimiter=STRING");
1207 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)"));
1208 1298
1209 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1299 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1210 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"));
@@ -1257,4 +1347,5 @@ print_usage (void)
1257 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");
1258 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");
1259 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");
1260} 1351}