summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am2
-rw-r--r--plugins/check_snmp.c173
-rwxr-xr-xplugins/tests/check_snmp.t39
-rw-r--r--plugins/tests/check_snmp_agent.pl6
4 files changed, 199 insertions, 21 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 4570fb7a..36a28b0b 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -39,7 +39,7 @@ EXTRA_PROGRAMS = check_mysql check_radius check_pgsql check_snmp check_hpjd \
39 check_nagios check_by_ssh check_dns check_nt check_ide_smart \ 39 check_nagios check_by_ssh check_dns check_nt check_ide_smart \
40 check_procs check_mysql_query check_apt 40 check_procs check_mysql_query check_apt
41 41
42EXTRA_DIST = t utils.c netutils.c sslutils.c popen.c utils.h netutils.h \ 42EXTRA_DIST = t tests utils.c netutils.c sslutils.c popen.c utils.h netutils.h \
43 popen.h common.h runcmd.c runcmd.h 43 popen.h common.h runcmd.c runcmd.h
44 44
45PLUGINHDRS = common.h 45PLUGINHDRS = common.h
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index 2bc6024f..bf210222 100644
--- a/plugins/check_snmp.c
+++ b/plugins/check_snmp.c
@@ -59,6 +59,10 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
59 59
60#define MAX_OIDS 8 60#define MAX_OIDS 8
61 61
62/* Longopts only arguments */
63#define L_CALCULATE_RATE CHAR_MAX+1
64#define L_RATE_MULTIPLIER CHAR_MAX+2
65
62/* Gobble to string - stop incrementing c when c[0] match one of the 66/* Gobble to string - stop incrementing c when c[0] match one of the
63 * characters in s */ 67 * characters in s */
64#define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; } 68#define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; }
@@ -131,12 +135,16 @@ char *delimiter;
131char *output_delim; 135char *output_delim;
132char *miblist = NULL; 136char *miblist = NULL;
133int needmibs = FALSE; 137int needmibs = FALSE;
138int calculate_rate = 0;
139int rate_multiplier = 1;
140state_data *previous_state;
141double previous_value[MAX_OIDS];
134 142
135 143
136int 144int
137main (int argc, char **argv) 145main (int argc, char **argv)
138{ 146{
139 int i, len, line; 147 int i, len, line, total_oids;
140 unsigned int bk_count = 0, dq_count = 0; 148 unsigned int bk_count = 0, dq_count = 0;
141 int iresult = STATE_UNKNOWN; 149 int iresult = STATE_UNKNOWN;
142 int result = STATE_UNKNOWN; 150 int result = STATE_UNKNOWN;
@@ -154,6 +162,17 @@ main (int argc, char **argv)
154 char *th_crit=NULL; 162 char *th_crit=NULL;
155 char type[8] = ""; 163 char type[8] = "";
156 output chld_out, chld_err; 164 output chld_out, chld_err;
165 char *previous_string=NULL;
166 char *ap=NULL;
167 char *state_string=NULL;
168 size_t response_length, current_length, string_length;
169 char *temp_string=NULL;
170 int is_numeric=0;
171 time_t current_time;
172 double temp_double;
173 time_t duration;
174 char *conv = "12345678";
175 int is_counter=0;
157 176
158 setlocale (LC_ALL, ""); 177 setlocale (LC_ALL, "");
159 bindtextdomain (PACKAGE, LOCALEDIR); 178 bindtextdomain (PACKAGE, LOCALEDIR);
@@ -173,12 +192,33 @@ main (int argc, char **argv)
173 timeout_interval = DEFAULT_TIMEOUT; 192 timeout_interval = DEFAULT_TIMEOUT;
174 retries = DEFAULT_RETRIES; 193 retries = DEFAULT_RETRIES;
175 194
195 np_init( (char *) progname, argc, argv );
196
176 /* Parse extra opts if any */ 197 /* Parse extra opts if any */
177 argv=np_extra_opts (&argc, argv, progname); 198 argv=np_extra_opts (&argc, argv, progname);
178 199
200 np_set_args(argc, argv);
201
179 if (process_arguments (argc, argv) == ERROR) 202 if (process_arguments (argc, argv) == ERROR)
180 usage4 (_("Could not parse arguments")); 203 usage4 (_("Could not parse arguments"));
181 204
205 if(calculate_rate) {
206 if (!strcmp(label, "SNMP"))
207 label = strdup("SNMP RATE");
208 time(&current_time);
209 i=0;
210 previous_state = np_state_read();
211 if(previous_state!=NULL) {
212 /* Split colon separated values */
213 previous_string = strdup((char *) previous_state->data);
214 while((ap = strsep(&previous_string, ":")) != NULL) {
215 if(verbose>2)
216 printf("State for %d=%s\n", i, ap);
217 previous_value[i++]=strtod(ap,NULL);
218 }
219 }
220 }
221
182 /* Populate the thresholds */ 222 /* Populate the thresholds */
183 th_warn=warning_thresholds; 223 th_warn=warning_thresholds;
184 th_crit=critical_thresholds; 224 th_crit=critical_thresholds;
@@ -271,7 +311,10 @@ main (int argc, char **argv)
271 } 311 }
272 312
273 for (line=0, i=0; line < chld_out.lines; line++, i++) { 313 for (line=0, i=0; line < chld_out.lines; line++, i++) {
274 const char *conv = "%.0f"; 314 if(calculate_rate)
315 conv = "%.10g";
316 else
317 conv = "%.0f";
275 318
276 ptr = chld_out.line[line]; 319 ptr = chld_out.line[line];
277 oidname = strpcpy (oidname, ptr, delimiter); 320 oidname = strpcpy (oidname, ptr, delimiter);
@@ -286,21 +329,34 @@ main (int argc, char **argv)
286 /* Clean up type array - Sol10 does not necessarily zero it out */ 329 /* Clean up type array - Sol10 does not necessarily zero it out */
287 bzero(type, sizeof(type)); 330 bzero(type, sizeof(type));
288 331
332 is_counter=0;
289 /* We strip out the datatype indicator for PHBs */ 333 /* We strip out the datatype indicator for PHBs */
290 if (strstr (response, "Gauge: ")) 334 if (strstr (response, "Gauge: ")) {
291 show = strstr (response, "Gauge: ") + 7; 335 show = strstr (response, "Gauge: ") + 7;
292 else if (strstr (response, "Gauge32: ")) 336 is_numeric++;
337 }
338 else if (strstr (response, "Gauge32: ")) {
293 show = strstr (response, "Gauge32: ") + 9; 339 show = strstr (response, "Gauge32: ") + 9;
340 is_numeric++;
341 }
294 else if (strstr (response, "Counter32: ")) { 342 else if (strstr (response, "Counter32: ")) {
295 show = strstr (response, "Counter32: ") + 11; 343 show = strstr (response, "Counter32: ") + 11;
296 strcpy(type, "c"); 344 is_numeric++;
345 is_counter=1;
346 if(!calculate_rate)
347 strcpy(type, "c");
297 } 348 }
298 else if (strstr (response, "Counter64: ")) { 349 else if (strstr (response, "Counter64: ")) {
299 show = strstr (response, "Counter64: ") + 11; 350 show = strstr (response, "Counter64: ") + 11;
300 strcpy(type, "c"); 351 is_numeric++;
352 is_counter=1;
353 if(!calculate_rate)
354 strcpy(type, "c");
301 } 355 }
302 else if (strstr (response, "INTEGER: ")) 356 else if (strstr (response, "INTEGER: ")) {
303 show = strstr (response, "INTEGER: ") + 9; 357 show = strstr (response, "INTEGER: ") + 9;
358 is_numeric++;
359 }
304 else if (strstr (response, "STRING: ")) { 360 else if (strstr (response, "STRING: ")) {
305 show = strstr (response, "STRING: ") + 8; 361 show = strstr (response, "STRING: ") + 8;
306 conv = "%.10g"; 362 conv = "%.10g";
@@ -345,14 +401,33 @@ main (int argc, char **argv)
345 401
346 iresult = STATE_DEPENDENT; 402 iresult = STATE_DEPENDENT;
347 403
348 /* Process this block for integer comparisons */ 404 /* Process this block for numeric comparisons */
349 if (thlds[i]->warning || thlds[i]->critical) { 405 if (is_numeric) {
350 ptr = strpbrk (show, "0123456789"); 406 ptr = strpbrk (show, "0123456789");
351 if (ptr == NULL) 407 if (ptr == NULL)
352 die (STATE_UNKNOWN,_("No valid data returned")); 408 die (STATE_UNKNOWN,_("No valid data returned"));
353 response_value[i] = strtod (ptr, NULL); 409 response_value[i] = strtod (ptr, NULL);
354 iresult = get_status(response_value[i], thlds[i]); 410
355 asprintf (&show, conv, response_value[i]); 411 if(calculate_rate) {
412 if (previous_state!=NULL) {
413 duration = current_time-previous_state->time;
414 if(duration<=0)
415 die(STATE_UNKNOWN,_("Time duration between plugin calls is invalid"));
416 temp_double = (response_value[i]-previous_value[i])/duration;
417 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */
418 if(is_counter) {
419 if(temp_double<(double)0.0)
420 temp_double+=(double)4294967296.0; /* 2^32 */
421 if(temp_double<(double)0.0)
422 temp_double+=(double)18446744069414584320.0; /* 2^64-2^32 */;
423 }
424 iresult = get_status(temp_double, thlds[i]);
425 asprintf (&show, conv, temp_double);
426 }
427 } else {
428 iresult = get_status(response_value[i], thlds[i]);
429 asprintf (&show, conv, response_value[i]);
430 }
356 } 431 }
357 432
358 /* Process this block for string matching */ 433 /* Process this block for string matching */
@@ -380,6 +455,7 @@ main (int argc, char **argv)
380 } 455 }
381 456
382 /* Process this block for existence-nonexistence checks */ 457 /* Process this block for existence-nonexistence checks */
458 /* TV: Should this be outside of this else block? */
383 else { 459 else {
384 if (eval_method[i] & CRIT_PRESENT) 460 if (eval_method[i] & CRIT_PRESENT)
385 iresult = STATE_CRITICAL; 461 iresult = STATE_CRITICAL;
@@ -393,7 +469,7 @@ main (int argc, char **argv)
393 result = max_state (result, iresult); 469 result = max_state (result, iresult);
394 470
395 /* Prepend a label for this OID if there is one */ 471 /* Prepend a label for this OID if there is one */
396 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) 472 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
397 asprintf (&outbuff, "%s%s%s %s%s%s", outbuff, 473 asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
398 (i == 0) ? " " : output_delim, 474 (i == 0) ? " " : output_delim,
399 labels[i], mark (iresult), show, mark (iresult)); 475 labels[i], mark (iresult), show, mark (iresult));
@@ -409,7 +485,13 @@ main (int argc, char **argv)
409 ptr = NULL; 485 ptr = NULL;
410 strtod(show, &ptr); 486 strtod(show, &ptr);
411 if (ptr > show) { 487 if (ptr > show) {
412 strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1); 488 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
489 temp_string=labels[i];
490 else
491 temp_string=oidname;
492 if(calculate_rate)
493 asprintf(&temp_string,"%s-rate",temp_string);
494 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1);
413 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1); 495 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
414 len = sizeof(perfstr)-strlen(perfstr)-1; 496 len = sizeof(perfstr)-strlen(perfstr)-1;
415 strncat(perfstr, show, len>ptr-show ? ptr-show : len); 497 strncat(perfstr, show, len>ptr-show ? ptr-show : len);
@@ -419,6 +501,44 @@ main (int argc, char **argv)
419 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); 501 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
420 } 502 }
421 } 503 }
504 total_oids=i;
505
506 /* Save state data, as all data collected now */
507 if(calculate_rate) {
508 string_length=1024;
509 state_string=malloc(string_length);
510 if(state_string==NULL)
511 die(STATE_UNKNOWN, _("Cannot malloc"));
512
513 current_length=0;
514 for(i=0; i<total_oids; i++) {
515 asprintf(&temp_string,"%.0f",response_value[i]);
516 if(temp_string==NULL)
517 die(STATE_UNKNOWN,_("Cannot asprintf()"));
518 response_length = strlen(temp_string);
519 if(current_length+response_length>string_length) {
520 string_length=current_length+1024;
521 state_string=realloc(state_string,string_length);
522 if(state_string==NULL)
523 die(STATE_UNKNOWN, _("Cannot realloc()"));
524 }
525 strcpy(&state_string[current_length],temp_string);
526 current_length=current_length+response_length;
527 state_string[current_length]=':';
528 current_length++;
529 free(temp_string);
530 }
531 state_string[--current_length]='\0';
532 if (verbose > 2)
533 printf("State string=%s\n",state_string);
534
535 /* This is not strictly the same as time now, but any subtle variations will cancel out */
536 np_state_write_string(current_time, state_string );
537 if(previous_state==NULL) {
538 /* Or should this be highest state? */
539 die( STATE_OK, _("No previous data to calculate rate - assume okay" ) );
540 }
541 }
422 542
423 printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr); 543 printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr);
424 if (mult_resp) printf ("%s", mult_resp); 544 if (mult_resp) printf ("%s", mult_resp);
@@ -462,6 +582,8 @@ process_arguments (int argc, char **argv)
462 {"authpasswd", required_argument, 0, 'A'}, 582 {"authpasswd", required_argument, 0, 'A'},
463 {"privpasswd", required_argument, 0, 'X'}, 583 {"privpasswd", required_argument, 0, 'X'},
464 {"next", no_argument, 0, 'n'}, 584 {"next", no_argument, 0, 'n'},
585 {"rate", no_argument, 0, L_CALCULATE_RATE},
586 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER},
465 {0, 0, 0, 0} 587 {0, 0, 0, 0}
466 }; 588 };
467 589
@@ -609,7 +731,6 @@ process_arguments (int argc, char **argv)
609 output_delim = strscpy (output_delim, optarg); 731 output_delim = strscpy (output_delim, optarg);
610 break; 732 break;
611 case 'l': /* label */ 733 case 'l': /* label */
612 label = optarg;
613 nlabels++; 734 nlabels++;
614 if (nlabels >= labels_size) { 735 if (nlabels >= labels_size) {
615 labels_size += 8; 736 labels_size += 8;
@@ -666,7 +787,15 @@ process_arguments (int argc, char **argv)
666 unitv[nunits - 1] = ptr; 787 unitv[nunits - 1] = ptr;
667 } 788 }
668 break; 789 break;
669 790 case L_CALCULATE_RATE:
791 if(calculate_rate==0)
792 np_enable_state(NULL, 1);
793 calculate_rate = 1;
794 break;
795 case L_RATE_MULTIPLIER:
796 if(!is_integer(optarg)||(rate_multiplier=atoi(optarg)<=0))
797 usage2(_("Rate multiplier must be a positive integer"),optarg);
798 break;
670 } 799 }
671 } 800 }
672 801
@@ -905,6 +1034,8 @@ print_help (void)
905 printf (" %s\n", _("Warning threshold range(s)")); 1034 printf (" %s\n", _("Warning threshold range(s)"));
906 printf (" %s\n", "-c, --critical=THRESHOLD(s)"); 1035 printf (" %s\n", "-c, --critical=THRESHOLD(s)");
907 printf (" %s\n", _("Critical threshold range(s)")); 1036 printf (" %s\n", _("Critical threshold range(s)"));
1037 printf (" %s\n", "--rate");
1038 printf (" %s\n", _("Enable rate calculation. See 'Rate Calculation' below"));
908 1039
909 /* Tests Against Strings */ 1040 /* Tests Against Strings */
910 printf (" %s\n", "-s, --string=STRING"); 1041 printf (" %s\n", "-s, --string=STRING");
@@ -914,7 +1045,7 @@ print_help (void)
914 printf (" %s\n", "-R, --eregi=REGEX"); 1045 printf (" %s\n", "-R, --eregi=REGEX");
915 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches")); 1046 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
916 printf (" %s\n", "-l, --label=STRING"); 1047 printf (" %s\n", "-l, --label=STRING");
917 printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')")); 1048 printf (" %s\n", _("Prefix label for output from plugin (default -l 'SNMP')"));
918 1049
919 /* Output Formatting */ 1050 /* Output Formatting */
920 printf (" %s\n", "-u, --units=STRING"); 1051 printf (" %s\n", "-u, --units=STRING");
@@ -945,6 +1076,16 @@ print_help (void)
945 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value")); 1076 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
946 printf (" %s\n", _("returned from the SNMP query is an unsigned integer.")); 1077 printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
947 1078
1079 printf("\n");
1080 printf("%s\n", _("Rate Calculation:"));
1081 printf(" %s\n", _("In many places, SNMP returns counters that are only meaningful when"));
1082 printf(" %s\n", _("calculating the counter difference since the last check. check_snmp"));
1083 printf(" %s\n", _("saves the last state information in a file so that the rate can be"));
1084 printf(" %s\n", _("calculated. Use the --rate option to save state information. On the"));
1085 printf(" %s\n", _("first run, there will be no prior state - this will return with OK."));
1086 printf(" %s\n", _("The state is uniquely determined by the arguments to the plugin, so"));
1087 printf(" %s\n", _("changing the arguments will create a new state file."));
1088
948 printf (UT_SUPPORT); 1089 printf (UT_SUPPORT);
949} 1090}
950 1091
diff --git a/plugins/tests/check_snmp.t b/plugins/tests/check_snmp.t
index b5f3f89e..17420792 100755
--- a/plugins/tests/check_snmp.t
+++ b/plugins/tests/check_snmp.t
@@ -51,7 +51,7 @@ if ($ARGV[0] && $ARGV[0] eq "-d") {
51 } 51 }
52} 52}
53 53
54my $tests = 9; 54my $tests = 21;
55if (-x "./check_snmp") { 55if (-x "./check_snmp") {
56 plan tests => $tests; 56 plan tests => $tests;
57} else { 57} else {
@@ -106,3 +106,40 @@ like($res->output, '/'.quotemeta('SNMP OK - And now have fun with with this: \"C
106"And now have fun with with this: \"C:\\\\\" 106"And now have fun with with this: \"C:\\\\\"
107because we\'re not done yet!"').'/m', "Attempt to confuse parser No.3"); 107because we\'re not done yet!"').'/m', "Attempt to confuse parser No.3");
108 108
109system("rm /usr/local/nagios/var/check_snmp/*");
110$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 --rate -w 600" );
111is($res->return_code, 0, "Returns OK");
112is($res->output, "No previous data to calculate rate - assume okay");
113
114# Need to sleep, otherwise duration=0
115sleep 1;
116
117$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 --rate -w 600" );
118is($res->return_code, 1, "WARNING - due to going above rate calculation" );
119is($res->output, "SNMP RATE WARNING - *666* | iso.3.6.1.4.1.8072.3.2.67.10-rate=666 ");
120
121$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 --rate -w 600" );
122is($res->return_code, 3, "UNKNOWN - basically the divide by zero error" );
123is($res->output, "Time duration between plugin calls is invalid");
124
125
126$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 --rate -l inoctets" );
127is($res->return_code, 0, "OK for first call" );
128is($res->output, "No previous data to calculate rate - assume okay" );
129
130# Need to sleep, otherwise duration=0
131sleep 1;
132
133$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 --rate -l inoctets" );
134is($res->return_code, 0, "OK as no thresholds" );
135is($res->output, "SNMP RATE OK - inoctets 666 | inoctets-rate=666 ", "Check label");
136
137sleep 2;
138
139$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 --rate -l inoctets" );
140is($res->return_code, 0, "OK as no thresholds" );
141is($res->output, "SNMP RATE OK - inoctets 333 | inoctets-rate=333 ", "Check rate decreases due to longer interval");
142
143
144
145
diff --git a/plugins/tests/check_snmp_agent.pl b/plugins/tests/check_snmp_agent.pl
index 302ba6e7..425caeb3 100644
--- a/plugins/tests/check_snmp_agent.pl
+++ b/plugins/tests/check_snmp_agent.pl
@@ -33,9 +33,9 @@ ends with with this: C:\\';
33my $multilin5 = 'And now have fun with with this: "C:\\" 33my $multilin5 = 'And now have fun with with this: "C:\\"
34because we\'re not done yet!'; 34because we\'re not done yet!';
35 35
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); 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);
37my @values = ($multiline, $multilin2, $multilin3, $multilin4, $multilin5, 4294965296, 1000, 4294965296, uint64("18446744073709351616"), int(rand(2**32))); 37my @values = ($multiline, $multilin2, $multilin3, $multilin4, $multilin5, 4294965296, 1000, 4294965296, uint64("18446744073709351616"), int(rand(2**32)), 64000);
38my @incrts = (undef, undef, undef, undef, undef, 1000, -500, 1000, 100000, undef); 38my @incrts = (undef, undef, undef, undef, undef, 1000, -500, 1000, 100000, undef, 666);
39 39
40# Number of elements in our OID 40# Number of elements in our OID
41my $oidelts; 41my $oidelts;