X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=plugins%2Fcheck_snmp.c;h=38ce940bfdcc454a87859267d8fbdfa9509ae4ec;hb=35df6c697d3a5988f4306bb86e6fe1901ed99069;hp=220be234c6dc0cfddbdfc8292dd554f89367317c;hpb=a396d2177806ac4ee9f524a139b19ad29c76ca91;p=nagiosplug.git diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c index 220be23..38ce940 100644 --- a/plugins/check_snmp.c +++ b/plugins/check_snmp.c @@ -1,19 +1,7 @@ /****************************************************************************** - * - * CHECK_SNMP.C * * Program: SNMP plugin for Nagios * License: GPL - * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) - * - * Last Modified: $Date$ - * - * Description: - * - * This plugin uses the 'snmpget' command included with the UCD-SNMP - * package. If you don't have the package installed you will need to - * download it from http://ucd-snmp.ucdavis.edu before you can use - * this plugin. * * License Information: * @@ -30,15 +18,88 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * *./plugins/check_snmp 127.0.0.1 -c public -o .1.3.6.1.4.1.2021.9.1.2.1 + * *****************************************************************************/ +#define PROGNAME "check_snmp" +#define REVISION "$Revision$" +#define COPYRIGHT "1999-2002" +#define AUTHOR "Ethan Galstad" +#define EMAIL "nagios@nagios.org" +#define SUMMARY "Check status of remote machines using SNMP.\n" + +#define OPTIONS "\ +-H -o [-w warn_range] [-c crit_range] \n\ + [-C community] [-s string] [-r regex] [-R regexi] [-t timeout]\n\ + [-l label] [-u units] [-p port-number] [-d delimiter]\n\ + [-D output-delimiter]" + +#define LONGOPTIONS "\ + -H, --hostname=HOST\n\ + Name or IP address of the device you wish to query\n\ + -o, --oid=OID(s)\n\ + Object identifier(s) whose value you wish to query\n\ + -w, --warning=INTEGER_RANGE(s)\n\ + Range(s) which will not result in a WARNING status\n\ + -c, --critical=INTEGER_RANGE(s)\n\ + Range(s) which will not result in a CRITICAL status\n\ + -C, --community=STRING\n\ + Optional community string for SNMP communication\n\ + (default is \"%s\")\n\ + -u, --units=STRING\n\ + Units label(s) for output data (e.g., 'sec.').\n\ + -p, --port=STRING\n\ + UDP port number target is listening on. Default is \"%s\"\n\ + -d, --delimiter=STRING\n\ + Delimiter to use when parsing returned data. Default is \"%s\"\n\ + Any data on the right hand side of the delimiter is considered\n\ + to be the data that should be used in the evaluation.\n\ + -t, --timeout=INTEGER\n\ + Seconds to wait before plugin times out (see also nagios server timeout).\n\ + Default is %d seconds\n\ + -D, --output-delimiter=STRING\n\ + Separates output on multiple OID requests\n\ + -s, --string=STRING\n\ + Return OK state (for that OID) if STRING is an exact match\n\ + -r, --ereg=REGEX\n\ + Return OK state (for that OID) if extended regular expression REGEX matches\n\ + -R, --eregi=REGEX\n\ + Return OK state (for that OID) if case-insensitive extended REGEX matches\n\ + -l, --label=STRING\n\ + Prefix label for output from plugin (default -s 'SNMP')\n" + +#define NOTES "\ +- This plugin uses the 'snmpget' command included with the UCD-SNMP package.\n\ + If you don't have the package installed, you will need to download it from\n\ + http://ucd-snmp.ucdavis.edu before you can use this plugin.\n\ +- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with\n\ + internal spaces must be quoted)\n\ +- Ranges are inclusive and are indicated with colons. When specified as\n\ + 'min:max' a STATE_OK will be returned if the result is within the indicated\n\ + range or is equal to the upper or lower bound. A non-OK state will be\n\ + returned if the result is outside the specified range.\n\ +- If spcified in the order 'max:min' a non-OK state will be returned if the\n\ + result is within the (inclusive) range.\n\ +- Upper or lower bounds may be omitted to skip checking the respective limit.\n\ +- Bare integers are interpreted as upper limits.\n\ +- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'\n\ +- Note that only one string and one regex may be checked at present\n\ +- All evaluation methods other than PR, STR, and SUBSTR expect that the value\n\ + returned from the SNMP query is an unsigned integer.\n" + +#define DESCRIPTION "\ +This plugin gets system information on a remote server via snmp.\n" + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_PORT "161" +#define DEFAULT_TIMEOUT 10 + #include "common.h" #include "utils.h" #include "popen.h" -#define PROGNAME check_snmp - #define mark(a) ((a)!=0?"*":"") #define CHECK_UNDEF 0 @@ -69,9 +130,9 @@ #define DEFAULT_OUTPUT_DELIMITER " " void print_usage (void); -void print_help (char *); +void print_help (void); int process_arguments (int, char **); -int call_getopt (int, char **); +int validate_arguments (void); int check_num (int); char *clarify_message (char *); int lu_getll (unsigned long *, char *); @@ -94,7 +155,7 @@ int errcode, excode; char *server_address = NULL; char *community = NULL; -char oid[MAX_INPUT_BUFFER] = ""; +char *oid = NULL; char *label = NULL; char *units = NULL; char *port = NULL; @@ -105,6 +166,7 @@ int nlabels = 0; int labels_size = 8; int nunits = 0; int unitv_size = 8; +int verbose = FALSE; unsigned long lower_warn_lim[MAX_OIDS]; unsigned long upper_warn_lim[MAX_OIDS]; unsigned long lower_crit_lim[MAX_OIDS]; @@ -144,10 +206,10 @@ main (int argc, char **argv) usage ("Incorrect arguments supplied\n"); /* create the command line to execute */ - asprintf - (&command_line, - "%s -p %s -m ALL -v 1 %s -c %s %s", - PATH_TO_SNMPGET, port, server_address, community, oid); + asprintf (&command_line, "%s -p %s -m ALL -v 1 %s -c %s %s", + PATH_TO_SNMPGET, port, server_address, community, oid); + if (verbose) + printf ("%s\n", command_line); /* run the command */ child_process = spopen (command_line); @@ -161,8 +223,12 @@ main (int argc, char **argv) printf ("Could not open stderr for %s\n", command_line); } + asprintf (&output, ""); while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) - output = strscat (output, input_buffer); + asprintf (&output, "%s%s", output, input_buffer); + + if (verbose) + printf ("%s\n", output); ptr = output; @@ -207,6 +273,14 @@ main (int argc, char **argv) show = response; p2 = show; + iresult = STATE_DEPENDENT; + + if (eval_method[i] & CRIT_PRESENT) { + iresult = STATE_CRITICAL; + } else if (eval_method[i] & WARN_PRESENT) { + iresult = STATE_WARNING; + } + if (eval_method[i] & CRIT_GT || eval_method[i] & CRIT_LT || eval_method[i] & CRIT_GE || @@ -252,27 +326,22 @@ main (int argc, char **argv) #endif } - else { - if (response) - iresult = STATE_OK; - else if (eval_method[i] & CRIT_PRESENT) - iresult = STATE_CRITICAL; - else - iresult = STATE_WARNING; - } + if (response && iresult == STATE_DEPENDENT) + iresult = STATE_OK; + else if (eval_method[i] & CRIT_PRESENT) + iresult = STATE_CRITICAL; + else + iresult = STATE_WARNING; result = max_state (result, iresult); if (nlabels > 1 && i < nlabels && labels[i] != NULL) - asprintf - (&outbuff, - "%s%s%s %s%s%s", - outbuff, - (i == 0) ? " " : output_delim, - labels[i], mark (iresult), show, mark (iresult)); + asprintf (&outbuff, "%s%s%s %s%s%s", outbuff, + (i == 0) ? " " : output_delim, + labels[i], mark (iresult), show, mark (iresult)); else - asprintf (&outbuff, "%s%s%s%s%s", outbuff, - (i == 0) ? " " : output_delim, mark (iresult), show, mark (iresult)); + asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim, + mark (iresult), show, mark (iresult)); if (nunits > 0 && i < nunits) asprintf (&outbuff, "%s %s", outbuff, unitv[i]); @@ -309,66 +378,15 @@ main (int argc, char **argv) /* process command-line arguments */ int process_arguments (int argc, char **argv) -{ - int c; - - if (argc < 2) - return ERROR; - - for (c = 1; c < argc; c++) { - if (strcmp ("-to", argv[c]) == 0) - strcpy (argv[c], "-t"); - if (strcmp ("-wv", argv[c]) == 0) - strcpy (argv[c], "-w"); - if (strcmp ("-cv", argv[c]) == 0) - strcpy (argv[c], "-c"); - } - - c = 0; - while (c += (call_getopt (argc - c, &argv[c]))) { - if (argc <= c) - break; - if (server_address == NULL) - server_address = strscpy (NULL, argv[c]); - } - - if (community == NULL) - community = strscpy (NULL, "public"); - - if (delimiter == NULL) - delimiter = strscpy (NULL, DEFAULT_DELIMITER); - - if (output_delim == NULL) - output_delim = strscpy (NULL, DEFAULT_OUTPUT_DELIMITER); - - if (label == NULL) - label = strscpy (NULL, "SNMP"); - - if (units == NULL) - units = strscpy (NULL, ""); - - if (port == NULL) - port = strscpy(NULL,"161"); - - return c; -} - -int -call_getopt (int argc, char **argv) { char *ptr; - int c, i = 1; + int c = 1; int j = 0, jj = 0; #ifdef HAVE_GETOPT_H int option_index = 0; static struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"timeout", required_argument, 0, 't'}, - {"critical", required_argument, 0, 'c'}, - {"warning", required_argument, 0, 'w'}, - {"hostname", required_argument, 0, 'H'}, + STD_LONG_OPTS, {"community", required_argument, 0, 'C'}, {"oid", required_argument, 0, 'o'}, {"object", required_argument, 0, 'o'}, @@ -385,57 +403,67 @@ call_getopt (int argc, char **argv) }; #endif + if (argc < 2) + return ERROR; + + /* reverse compatibility for very old non-POSIX usage forms */ + for (c = 1; c < argc; c++) { + if (strcmp ("-to", argv[c]) == 0) + strcpy (argv[c], "-t"); + if (strcmp ("-wv", argv[c]) == 0) + strcpy (argv[c], "-w"); + if (strcmp ("-cv", argv[c]) == 0) + strcpy (argv[c], "-c"); + } + + /* initialize some args */ + asprintf (&oid, ""); + while (1) { #ifdef HAVE_GETOPT_H c = - getopt_long (argc, argv, "+?hVt:c:w:H:C:o:d:D:s:R:r:l:u:p:", + getopt_long (argc, argv, "+?hVt:c:w:H:C:o:e:E:d:D:s:R:r:l:u:p:", long_options, &option_index); #else - c = getopt (argc, argv, "+?hVt:c:w:H:C:o:d:D:s:R:r:l:u:p:"); + c = getopt (argc, argv, "+?hVt:c:w:H:C:o:e:E:d:D:s:R:r:l:u:p:"); #endif if (c == -1 || c == EOF) break; - i++; switch (c) { - case 't': - case 'c': - case 'w': - case 'H': - case 'C': - case 'o': - case 'd': - case 'D': - case 's': - case 'R': - case 'r': - case 'l': - case 'u': - case 'p': - i++; - } - - switch (c) { - case '?': /* help */ - printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg); - print_usage (); - exit (STATE_UNKNOWN); - case 'h': /* help */ - print_help (my_basename (argv[0])); + case '?': /* usage */ + usage2 ("Unknown argument", optarg); + case 'h': /* help */ + print_help (); exit (STATE_OK); - case 'V': /* version */ - print_revision (my_basename (argv[0]), "$Revision$"); + case 'V': /* version */ + print_revision (PROGNAME, REVISION); exit (STATE_OK); - case 't': /* timeout period */ - if (!is_integer (optarg)) { - printf ("%s: Timeout Interval must be an integer!\n\n", - my_basename (argv[0])); - print_usage (); - exit (STATE_UNKNOWN); - } + case 'v': /* verbose */ + verbose = TRUE; + break; + case 't': /* timeout period */ + if (!is_integer (optarg)) + usage2 ("Timeout Interval must be an integer", optarg); timeout_interval = atoi (optarg); break; + case 'e': /* PRELIMINARY - may change */ + eval_method[j] |= WARN_PRESENT; + for (ptr = optarg; (ptr = index (ptr, ',')); ptr++) + ptr[0] = ' '; /* relpace comma with space */ + for (ptr = optarg; (ptr = index (ptr, ' ')); ptr++) + eval_method[++j] |= WARN_PRESENT; + asprintf (&oid, "%s %s", oid, optarg); + break; + case 'E': /* PRELIMINARY - may change */ + eval_method[j] |= WARN_PRESENT; + for (ptr = optarg; (ptr = index (ptr, ',')); ptr++) + ptr[0] = ' '; /* relpace comma with space */ + for (ptr = optarg; (ptr = index (ptr, ' ')); ptr++) + eval_method[++j] |= CRIT_PRESENT; + asprintf (&oid, "%s %s", oid, optarg); + break; case 'c': /* critical time threshold */ if (strspn (optarg, "0123456789:,") < strlen (optarg)) { printf ("Invalid critical threshold: %s\n", optarg); @@ -472,11 +500,11 @@ call_getopt (int argc, char **argv) break; case 'o': /* object identifier */ for (ptr = optarg; (ptr = index (ptr, ',')); ptr++) - ptr[0] = ' '; - strncpy (oid, optarg, sizeof (oid) - 1); - oid[sizeof (oid) - 1] = 0; - for (ptr = optarg, j = 1; (ptr = index (ptr, ' ')); ptr++) - j++; + ptr[0] = ' '; /* relpace comma with space */ + for (ptr = optarg; (ptr = index (ptr, ' ')); ptr++) { + j++; /* count OIDs */ + } + asprintf (&oid, "%s %s", oid, optarg); break; case 'd': /* delimiter */ delimiter = strscpy (delimiter, optarg); @@ -578,81 +606,85 @@ call_getopt (int argc, char **argv) } } - return i; + + if (server_address == NULL) + asprintf (&server_address, argv[optind]); + + return validate_arguments (); } +/****************************************************************************** + +@@- + +validate_arguments + +&PROTO_validate_arguments; + +Given a database name, this function returns TRUE if the string +is a valid PostgreSQL database name, and returns false if it is +not. + +Valid PostgreSQL database names are less than &NAMEDATALEN; +characters long and consist of letters, numbers, and underscores. The +first character cannot be a number, however. + + +-@@ +******************************************************************************/ + +int +validate_arguments () +{ + + if (community == NULL) + asprintf (&community, DEFAULT_COMMUNITY); + + if (delimiter == NULL) + asprintf (&delimiter, DEFAULT_DELIMITER); + + if (output_delim == NULL) + asprintf (&output_delim, DEFAULT_OUTPUT_DELIMITER); + + if (label == NULL) + asprintf (&label, "SNMP"); + + if (units == NULL) + asprintf (&units, ""); + + if (port == NULL) + asprintf (&port, DEFAULT_PORT); + + return OK; +} + + + void -print_usage (void) +print_help (void) { + print_revision (PROGNAME, REVISION); + printf + ("Copyright (c) %s %s <%s>\n\n%s\n", + COPYRIGHT, AUTHOR, EMAIL, SUMMARY); + print_usage (); printf - ("Usage: check_snmp -H -o [-w warn_range] [-c crit_range] \n" - " [-C community] [-s string] [-r regex] [-R regexi] [-t timeout]\n" - " [-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n" - " check_snmp --help\n" " check_snmp --version\n"); + ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n" NOTES "\n", + DEFAULT_COMMUNITY, DEFAULT_PORT, DEFAULT_DELIMITER, DEFAULT_TIMEOUT); + support (); } void -print_help (char *cmd) +print_usage (void) { - printf ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n" - "License: GPL\n\n"); - print_usage (); printf - ("\nOptions:\n" - " -h, --help\n" - " Print detailed help screen\n" - " -V, --version\n" - " Print version information\n" - " -H, --hostname=HOST\n" - " Name or IP address of the device you wish to query\n" - " -o, --oid=OID(s)\n" - " Object identifier(s) whose value you wish to query\n" - " -w, --warning=INTEGER_RANGE(s)\n" - " Range(s) which will not result in a WARNING status\n" - " -c, --critical=INTEGER_RANGE(s)\n" - " Range(s) which will not result in a CRITICAL status\n" - " -C, --community=STRING\n" - " Optional community string for SNMP communication\n" - " (default is \"public\")\n" - " -u, --units=STRING\n" - " Units label(s) for output data (e.g., 'sec.').\n" - " -p, --port=STRING\n" - " UDP port number target is listening on.\n" - " -d, --delimiter=STRING\n" - " Delimiter to use when parsing returned data. Default is \"%s\"\n" - " Any data on the right hand side of the delimiter is considered\n" - " to be the data that should be used in the evaluation.\n" - " -t, --timeout=INTEGER\n" - " Seconds to wait before plugin times out (see also nagios server timeout)\n" - " -D, --output-delimiter=STRING\n" - " Separates output on multiple OID requests\n" - " -s, --string=STRING\n" - " Return OK state (for that OID) if STRING is an exact match\n" - " -r, --ereg=REGEX\n" - " Return OK state (for that OID) if extended regular expression REGEX matches\n" - " -R, --eregi=REGEX\n" - " Return OK state (for that OID) if case-insensitive extended REGEX matches\n" - " -l, --label=STRING\n" - " Prefix label for output from plugin (default -s 'SNMP')\n\n" - "- This plugin uses the 'snmpget' command included with the UCD-SNMP package.\n" - " If you don't have the package installed, you will need to download it from\n" - " http://ucd-snmp.ucdavis.edu before you can use this plugin.\n" - "- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with\n" - " internal spaces must be quoted)\n" - "- Ranges are inclusive and are indicated with colons. When specified as\n" - " 'min:max' a STATE_OK will be returned if the result is within the indicated\n" - " range or is equal to the upper or lower bound. A non-OK state will be\n" - " returned if the result is outside the specified range.\n" - "- If spcified in the order 'max:min' a non-OK state will be returned if the\n" - " result is within the (inclusive) range.\n" - "- Upper or lower bounds may be omitted to skip checking the respective limit.\n" - "- Bare integers are interpreted as upper limits.\n" - "- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'\n" - "- Note that only one string and one regex may be checked at present\n" - "- All evaluation methods other than PR, STR, and SUBSTR expect that the value\n" - " returned from the SNMP query is an unsigned integer.\n\n", - DEFAULT_DELIMITER); + ("Usage:\n" " %s %s\n" + " %s (-h | --help) for detailed help\n" + " %s (-V | --version) for version information\n", + PROGNAME, OPTIONS, PROGNAME, PROGNAME); } + + char * clarify_message (char *msg)