diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/check_snmp.c | 289 |
1 files changed, 174 insertions, 115 deletions
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c index 35d21479..38ce940b 100644 --- a/plugins/check_snmp.c +++ b/plugins/check_snmp.c | |||
@@ -1,19 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * CHECK_SNMP.C | ||
4 | * | ||
5 | * Program: SNMP plugin for Nagios | 3 | * Program: SNMP plugin for Nagios |
6 | * License: GPL | 4 | * License: GPL |
7 | * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) | ||
8 | * | ||
9 | * Last Modified: $Date$ | ||
10 | * | ||
11 | * Description: | ||
12 | * | ||
13 | * This plugin uses the 'snmpget' command included with the UCD-SNMP | ||
14 | * package. If you don't have the package installed you will need to | ||
15 | * download it from http://ucd-snmp.ucdavis.edu before you can use | ||
16 | * this plugin. | ||
17 | * | 5 | * |
18 | * License Information: | 6 | * License Information: |
19 | * | 7 | * |
@@ -30,15 +18,88 @@ | |||
30 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
31 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
32 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | * | ||
33 | *./plugins/check_snmp 127.0.0.1 -c public -o .1.3.6.1.4.1.2021.9.1.2.1 | 22 | *./plugins/check_snmp 127.0.0.1 -c public -o .1.3.6.1.4.1.2021.9.1.2.1 |
23 | * | ||
34 | *****************************************************************************/ | 24 | *****************************************************************************/ |
35 | 25 | ||
26 | #define PROGNAME "check_snmp" | ||
27 | #define REVISION "$Revision$" | ||
28 | #define COPYRIGHT "1999-2002" | ||
29 | #define AUTHOR "Ethan Galstad" | ||
30 | #define EMAIL "nagios@nagios.org" | ||
31 | #define SUMMARY "Check status of remote machines using SNMP.\n" | ||
32 | |||
33 | #define OPTIONS "\ | ||
34 | -H <ip_address> -o <OID> [-w warn_range] [-c crit_range] \n\ | ||
35 | [-C community] [-s string] [-r regex] [-R regexi] [-t timeout]\n\ | ||
36 | [-l label] [-u units] [-p port-number] [-d delimiter]\n\ | ||
37 | [-D output-delimiter]" | ||
38 | |||
39 | #define LONGOPTIONS "\ | ||
40 | -H, --hostname=HOST\n\ | ||
41 | Name or IP address of the device you wish to query\n\ | ||
42 | -o, --oid=OID(s)\n\ | ||
43 | Object identifier(s) whose value you wish to query\n\ | ||
44 | -w, --warning=INTEGER_RANGE(s)\n\ | ||
45 | Range(s) which will not result in a WARNING status\n\ | ||
46 | -c, --critical=INTEGER_RANGE(s)\n\ | ||
47 | Range(s) which will not result in a CRITICAL status\n\ | ||
48 | -C, --community=STRING\n\ | ||
49 | Optional community string for SNMP communication\n\ | ||
50 | (default is \"%s\")\n\ | ||
51 | -u, --units=STRING\n\ | ||
52 | Units label(s) for output data (e.g., 'sec.').\n\ | ||
53 | -p, --port=STRING\n\ | ||
54 | UDP port number target is listening on. Default is \"%s\"\n\ | ||
55 | -d, --delimiter=STRING\n\ | ||
56 | Delimiter to use when parsing returned data. Default is \"%s\"\n\ | ||
57 | Any data on the right hand side of the delimiter is considered\n\ | ||
58 | to be the data that should be used in the evaluation.\n\ | ||
59 | -t, --timeout=INTEGER\n\ | ||
60 | Seconds to wait before plugin times out (see also nagios server timeout).\n\ | ||
61 | Default is %d seconds\n\ | ||
62 | -D, --output-delimiter=STRING\n\ | ||
63 | Separates output on multiple OID requests\n\ | ||
64 | -s, --string=STRING\n\ | ||
65 | Return OK state (for that OID) if STRING is an exact match\n\ | ||
66 | -r, --ereg=REGEX\n\ | ||
67 | Return OK state (for that OID) if extended regular expression REGEX matches\n\ | ||
68 | -R, --eregi=REGEX\n\ | ||
69 | Return OK state (for that OID) if case-insensitive extended REGEX matches\n\ | ||
70 | -l, --label=STRING\n\ | ||
71 | Prefix label for output from plugin (default -s 'SNMP')\n" | ||
72 | |||
73 | #define NOTES "\ | ||
74 | - This plugin uses the 'snmpget' command included with the UCD-SNMP package.\n\ | ||
75 | If you don't have the package installed, you will need to download it from\n\ | ||
76 | http://ucd-snmp.ucdavis.edu before you can use this plugin.\n\ | ||
77 | - Multiple OIDs may be indicated by a comma- or space-delimited list (lists with\n\ | ||
78 | internal spaces must be quoted)\n\ | ||
79 | - Ranges are inclusive and are indicated with colons. When specified as\n\ | ||
80 | 'min:max' a STATE_OK will be returned if the result is within the indicated\n\ | ||
81 | range or is equal to the upper or lower bound. A non-OK state will be\n\ | ||
82 | returned if the result is outside the specified range.\n\ | ||
83 | - If spcified in the order 'max:min' a non-OK state will be returned if the\n\ | ||
84 | result is within the (inclusive) range.\n\ | ||
85 | - Upper or lower bounds may be omitted to skip checking the respective limit.\n\ | ||
86 | - Bare integers are interpreted as upper limits.\n\ | ||
87 | - When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'\n\ | ||
88 | - Note that only one string and one regex may be checked at present\n\ | ||
89 | - All evaluation methods other than PR, STR, and SUBSTR expect that the value\n\ | ||
90 | returned from the SNMP query is an unsigned integer.\n" | ||
91 | |||
92 | #define DESCRIPTION "\ | ||
93 | This plugin gets system information on a remote server via snmp.\n" | ||
94 | |||
95 | #define DEFAULT_COMMUNITY "public" | ||
96 | #define DEFAULT_PORT "161" | ||
97 | #define DEFAULT_TIMEOUT 10 | ||
98 | |||
36 | #include "common.h" | 99 | #include "common.h" |
37 | #include "utils.h" | 100 | #include "utils.h" |
38 | #include "popen.h" | 101 | #include "popen.h" |
39 | 102 | ||
40 | #define PROGNAME check_snmp | ||
41 | |||
42 | #define mark(a) ((a)!=0?"*":"") | 103 | #define mark(a) ((a)!=0?"*":"") |
43 | 104 | ||
44 | #define CHECK_UNDEF 0 | 105 | #define CHECK_UNDEF 0 |
@@ -69,9 +130,9 @@ | |||
69 | #define DEFAULT_OUTPUT_DELIMITER " " | 130 | #define DEFAULT_OUTPUT_DELIMITER " " |
70 | 131 | ||
71 | void print_usage (void); | 132 | void print_usage (void); |
72 | void print_help (char *); | 133 | void print_help (void); |
73 | int process_arguments (int, char **); | 134 | int process_arguments (int, char **); |
74 | int call_getopt (int, char **); | 135 | int validate_arguments (void); |
75 | int check_num (int); | 136 | int check_num (int); |
76 | char *clarify_message (char *); | 137 | char *clarify_message (char *); |
77 | int lu_getll (unsigned long *, char *); | 138 | int lu_getll (unsigned long *, char *); |
@@ -212,6 +273,14 @@ main (int argc, char **argv) | |||
212 | show = response; | 273 | show = response; |
213 | p2 = show; | 274 | p2 = show; |
214 | 275 | ||
276 | iresult = STATE_DEPENDENT; | ||
277 | |||
278 | if (eval_method[i] & CRIT_PRESENT) { | ||
279 | iresult = STATE_CRITICAL; | ||
280 | } else if (eval_method[i] & WARN_PRESENT) { | ||
281 | iresult = STATE_WARNING; | ||
282 | } | ||
283 | |||
215 | if (eval_method[i] & CRIT_GT || | 284 | if (eval_method[i] & CRIT_GT || |
216 | eval_method[i] & CRIT_LT || | 285 | eval_method[i] & CRIT_LT || |
217 | eval_method[i] & CRIT_GE || | 286 | eval_method[i] & CRIT_GE || |
@@ -257,14 +326,12 @@ main (int argc, char **argv) | |||
257 | #endif | 326 | #endif |
258 | } | 327 | } |
259 | 328 | ||
260 | else { | 329 | if (response && iresult == STATE_DEPENDENT) |
261 | if (response) | 330 | iresult = STATE_OK; |
262 | iresult = STATE_OK; | 331 | else if (eval_method[i] & CRIT_PRESENT) |
263 | else if (eval_method[i] & CRIT_PRESENT) | 332 | iresult = STATE_CRITICAL; |
264 | iresult = STATE_CRITICAL; | 333 | else |
265 | else | 334 | iresult = STATE_WARNING; |
266 | iresult = STATE_WARNING; | ||
267 | } | ||
268 | 335 | ||
269 | result = max_state (result, iresult); | 336 | result = max_state (result, iresult); |
270 | 337 | ||
@@ -313,7 +380,7 @@ int | |||
313 | process_arguments (int argc, char **argv) | 380 | process_arguments (int argc, char **argv) |
314 | { | 381 | { |
315 | char *ptr; | 382 | char *ptr; |
316 | int c, i = 1; | 383 | int c = 1; |
317 | int j = 0, jj = 0; | 384 | int j = 0, jj = 0; |
318 | 385 | ||
319 | #ifdef HAVE_GETOPT_H | 386 | #ifdef HAVE_GETOPT_H |
@@ -355,38 +422,48 @@ process_arguments (int argc, char **argv) | |||
355 | while (1) { | 422 | while (1) { |
356 | #ifdef HAVE_GETOPT_H | 423 | #ifdef HAVE_GETOPT_H |
357 | c = | 424 | c = |
358 | getopt_long (argc, argv, "+?hVt:c:w:H:C:o:d:D:s:R:r:l:u:p:", | 425 | getopt_long (argc, argv, "+?hVt:c:w:H:C:o:e:E:d:D:s:R:r:l:u:p:", |
359 | long_options, &option_index); | 426 | long_options, &option_index); |
360 | #else | 427 | #else |
361 | c = getopt (argc, argv, "+?hVt:c:w:H:C:o:d:D:s:R:r:l:u:p:"); | 428 | c = getopt (argc, argv, "+?hVt:c:w:H:C:o:e:E:d:D:s:R:r:l:u:p:"); |
362 | #endif | 429 | #endif |
363 | 430 | ||
364 | if (c == -1 || c == EOF) | 431 | if (c == -1 || c == EOF) |
365 | break; | 432 | break; |
366 | 433 | ||
367 | switch (c) { | 434 | switch (c) { |
368 | case '?': /* help */ | 435 | case '?': /* usage */ |
369 | printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg); | 436 | usage2 ("Unknown argument", optarg); |
370 | print_usage (); | 437 | case 'h': /* help */ |
371 | exit (STATE_UNKNOWN); | 438 | print_help (); |
372 | case 'h': /* help */ | ||
373 | print_help (my_basename (argv[0])); | ||
374 | exit (STATE_OK); | 439 | exit (STATE_OK); |
375 | case 'V': /* version */ | 440 | case 'V': /* version */ |
376 | print_revision (my_basename (argv[0]), "$Revision$"); | 441 | print_revision (PROGNAME, REVISION); |
377 | exit (STATE_OK); | 442 | exit (STATE_OK); |
378 | case 'v': /* verbose */ | 443 | case 'v': /* verbose */ |
379 | verbose = TRUE; | 444 | verbose = TRUE; |
380 | break; | 445 | break; |
381 | case 't': /* timeout period */ | 446 | case 't': /* timeout period */ |
382 | if (!is_integer (optarg)) { | 447 | if (!is_integer (optarg)) |
383 | printf ("%s: Timeout Interval must be an integer!\n\n", | 448 | usage2 ("Timeout Interval must be an integer", optarg); |
384 | my_basename (argv[0])); | ||
385 | print_usage (); | ||
386 | exit (STATE_UNKNOWN); | ||
387 | } | ||
388 | timeout_interval = atoi (optarg); | 449 | timeout_interval = atoi (optarg); |
389 | break; | 450 | break; |
451 | case 'e': /* PRELIMINARY - may change */ | ||
452 | eval_method[j] |= WARN_PRESENT; | ||
453 | for (ptr = optarg; (ptr = index (ptr, ',')); ptr++) | ||
454 | ptr[0] = ' '; /* relpace comma with space */ | ||
455 | for (ptr = optarg; (ptr = index (ptr, ' ')); ptr++) | ||
456 | eval_method[++j] |= WARN_PRESENT; | ||
457 | asprintf (&oid, "%s %s", oid, optarg); | ||
458 | break; | ||
459 | case 'E': /* PRELIMINARY - may change */ | ||
460 | eval_method[j] |= WARN_PRESENT; | ||
461 | for (ptr = optarg; (ptr = index (ptr, ',')); ptr++) | ||
462 | ptr[0] = ' '; /* relpace comma with space */ | ||
463 | for (ptr = optarg; (ptr = index (ptr, ' ')); ptr++) | ||
464 | eval_method[++j] |= CRIT_PRESENT; | ||
465 | asprintf (&oid, "%s %s", oid, optarg); | ||
466 | break; | ||
390 | case 'c': /* critical time threshold */ | 467 | case 'c': /* critical time threshold */ |
391 | if (strspn (optarg, "0123456789:,") < strlen (optarg)) { | 468 | if (strspn (optarg, "0123456789:,") < strlen (optarg)) { |
392 | printf ("Invalid critical threshold: %s\n", optarg); | 469 | printf ("Invalid critical threshold: %s\n", optarg); |
@@ -424,8 +501,9 @@ process_arguments (int argc, char **argv) | |||
424 | case 'o': /* object identifier */ | 501 | case 'o': /* object identifier */ |
425 | for (ptr = optarg; (ptr = index (ptr, ',')); ptr++) | 502 | for (ptr = optarg; (ptr = index (ptr, ',')); ptr++) |
426 | ptr[0] = ' '; /* relpace comma with space */ | 503 | ptr[0] = ' '; /* relpace comma with space */ |
427 | for (ptr = optarg, j = 1; (ptr = index (ptr, ' ')); ptr++) | 504 | for (ptr = optarg; (ptr = index (ptr, ' ')); ptr++) { |
428 | j++; /* count OIDs */ | 505 | j++; /* count OIDs */ |
506 | } | ||
429 | asprintf (&oid, "%s %s", oid, optarg); | 507 | asprintf (&oid, "%s %s", oid, optarg); |
430 | break; | 508 | break; |
431 | case 'd': /* delimiter */ | 509 | case 'd': /* delimiter */ |
@@ -529,103 +607,84 @@ process_arguments (int argc, char **argv) | |||
529 | } | 607 | } |
530 | } | 608 | } |
531 | 609 | ||
532 | c = optind; | ||
533 | if (server_address == NULL) | 610 | if (server_address == NULL) |
534 | server_address = strscpy (NULL, argv[c++]); | 611 | asprintf (&server_address, argv[optind]); |
612 | |||
613 | return validate_arguments (); | ||
614 | } | ||
615 | |||
616 | /****************************************************************************** | ||
617 | |||
618 | @@- | ||
619 | <sect3> | ||
620 | <title>validate_arguments</title> | ||
621 | |||
622 | <para>&PROTO_validate_arguments;</para> | ||
623 | |||
624 | <para>Given a database name, this function returns TRUE if the string | ||
625 | is a valid PostgreSQL database name, and returns false if it is | ||
626 | not.</para> | ||
627 | |||
628 | <para>Valid PostgreSQL database names are less than &NAMEDATALEN; | ||
629 | characters long and consist of letters, numbers, and underscores. The | ||
630 | first character cannot be a number, however.</para> | ||
631 | |||
632 | </sect3> | ||
633 | -@@ | ||
634 | ******************************************************************************/ | ||
635 | |||
636 | int | ||
637 | validate_arguments () | ||
638 | { | ||
535 | 639 | ||
536 | if (community == NULL) | 640 | if (community == NULL) |
537 | community = strscpy (NULL, "public"); | 641 | asprintf (&community, DEFAULT_COMMUNITY); |
538 | 642 | ||
539 | if (delimiter == NULL) | 643 | if (delimiter == NULL) |
540 | delimiter = strscpy (NULL, DEFAULT_DELIMITER); | 644 | asprintf (&delimiter, DEFAULT_DELIMITER); |
541 | 645 | ||
542 | if (output_delim == NULL) | 646 | if (output_delim == NULL) |
543 | output_delim = strscpy (NULL, DEFAULT_OUTPUT_DELIMITER); | 647 | asprintf (&output_delim, DEFAULT_OUTPUT_DELIMITER); |
544 | 648 | ||
545 | if (label == NULL) | 649 | if (label == NULL) |
546 | label = strscpy (NULL, "SNMP"); | 650 | asprintf (&label, "SNMP"); |
547 | 651 | ||
548 | if (units == NULL) | 652 | if (units == NULL) |
549 | units = strscpy (NULL, ""); | 653 | asprintf (&units, ""); |
550 | 654 | ||
551 | if (port == NULL) | 655 | if (port == NULL) |
552 | port = strscpy(NULL,"161"); | 656 | asprintf (&port, DEFAULT_PORT); |
553 | 657 | ||
554 | return i; | 658 | return OK; |
555 | } | 659 | } |
660 | |||
661 | |||
556 | 662 | ||
557 | void | 663 | void |
558 | print_usage (void) | 664 | print_help (void) |
559 | { | 665 | { |
666 | print_revision (PROGNAME, REVISION); | ||
667 | printf | ||
668 | ("Copyright (c) %s %s <%s>\n\n%s\n", | ||
669 | COPYRIGHT, AUTHOR, EMAIL, SUMMARY); | ||
670 | print_usage (); | ||
560 | printf | 671 | printf |
561 | ("Usage: check_snmp -H <ip_address> -o <OID> [-w warn_range] [-c crit_range] \n" | 672 | ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n" NOTES "\n", |
562 | " [-C community] [-s string] [-r regex] [-R regexi] [-t timeout]\n" | 673 | DEFAULT_COMMUNITY, DEFAULT_PORT, DEFAULT_DELIMITER, DEFAULT_TIMEOUT); |
563 | " [-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n" | 674 | support (); |
564 | " check_snmp --help\n" " check_snmp --version\n"); | ||
565 | } | 675 | } |
566 | 676 | ||
567 | void | 677 | void |
568 | print_help (char *cmd) | 678 | print_usage (void) |
569 | { | 679 | { |
570 | printf ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n" | ||
571 | "License: GPL\n\n"); | ||
572 | print_usage (); | ||
573 | printf | 680 | printf |
574 | ("\nOptions:\n" | 681 | ("Usage:\n" " %s %s\n" |
575 | " -h, --help\n" | 682 | " %s (-h | --help) for detailed help\n" |
576 | " Print detailed help screen\n" | 683 | " %s (-V | --version) for version information\n", |
577 | " -V, --version\n" | 684 | PROGNAME, OPTIONS, PROGNAME, PROGNAME); |
578 | " Print version information\n" | ||
579 | " -H, --hostname=HOST\n" | ||
580 | " Name or IP address of the device you wish to query\n" | ||
581 | " -o, --oid=OID(s)\n" | ||
582 | " Object identifier(s) whose value you wish to query\n" | ||
583 | " -w, --warning=INTEGER_RANGE(s)\n" | ||
584 | " Range(s) which will not result in a WARNING status\n" | ||
585 | " -c, --critical=INTEGER_RANGE(s)\n" | ||
586 | " Range(s) which will not result in a CRITICAL status\n" | ||
587 | " -C, --community=STRING\n" | ||
588 | " Optional community string for SNMP communication\n" | ||
589 | " (default is \"public\")\n" | ||
590 | " -u, --units=STRING\n" | ||
591 | " Units label(s) for output data (e.g., 'sec.').\n" | ||
592 | " -p, --port=STRING\n" | ||
593 | " UDP port number target is listening on.\n" | ||
594 | " -d, --delimiter=STRING\n" | ||
595 | " Delimiter to use when parsing returned data. Default is \"%s\"\n" | ||
596 | " Any data on the right hand side of the delimiter is considered\n" | ||
597 | " to be the data that should be used in the evaluation.\n" | ||
598 | " -t, --timeout=INTEGER\n" | ||
599 | " Seconds to wait before plugin times out (see also nagios server timeout)\n" | ||
600 | " -D, --output-delimiter=STRING\n" | ||
601 | " Separates output on multiple OID requests\n" | ||
602 | " -s, --string=STRING\n" | ||
603 | " Return OK state (for that OID) if STRING is an exact match\n" | ||
604 | " -r, --ereg=REGEX\n" | ||
605 | " Return OK state (for that OID) if extended regular expression REGEX matches\n" | ||
606 | " -R, --eregi=REGEX\n" | ||
607 | " Return OK state (for that OID) if case-insensitive extended REGEX matches\n" | ||
608 | " -l, --label=STRING\n" | ||
609 | " Prefix label for output from plugin (default -s 'SNMP')\n\n" | ||
610 | "- This plugin uses the 'snmpget' command included with the UCD-SNMP package.\n" | ||
611 | " If you don't have the package installed, you will need to download it from\n" | ||
612 | " http://ucd-snmp.ucdavis.edu before you can use this plugin.\n" | ||
613 | "- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with\n" | ||
614 | " internal spaces must be quoted)\n" | ||
615 | "- Ranges are inclusive and are indicated with colons. When specified as\n" | ||
616 | " 'min:max' a STATE_OK will be returned if the result is within the indicated\n" | ||
617 | " range or is equal to the upper or lower bound. A non-OK state will be\n" | ||
618 | " returned if the result is outside the specified range.\n" | ||
619 | "- If spcified in the order 'max:min' a non-OK state will be returned if the\n" | ||
620 | " result is within the (inclusive) range.\n" | ||
621 | "- Upper or lower bounds may be omitted to skip checking the respective limit.\n" | ||
622 | "- Bare integers are interpreted as upper limits.\n" | ||
623 | "- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'\n" | ||
624 | "- Note that only one string and one regex may be checked at present\n" | ||
625 | "- All evaluation methods other than PR, STR, and SUBSTR expect that the value\n" | ||
626 | " returned from the SNMP query is an unsigned integer.\n\n", | ||
627 | DEFAULT_DELIMITER); | ||
628 | } | 685 | } |
686 | |||
687 | |||
629 | 688 | ||
630 | char * | 689 | char * |
631 | clarify_message (char *msg) | 690 | clarify_message (char *msg) |