Fix whitespaces in check_snmp
[monitoring-plugins.git] / plugins / check_snmp.c
blob94b75b9f66c67482586c3b06127e5e3347a6106b
1 /*****************************************************************************
2 *
3 * Nagios check_snmp plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2007 Nagios Plugins Development Team
7 *
8 * Description:
9 *
10 * This file contains the check_snmp plugin
12 * Check status of remote machines and obtain system information via SNMP
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
17 * the Free Software Foundation, either version 3 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
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/>.
29 *****************************************************************************/
31 const char *progname = "check_snmp";
32 const char *copyright = "1999-2007";
33 const char *email = "nagiosplug-devel@lists.sourceforge.net";
35 #include "common.h"
36 #include "utils.h"
37 #include "utils_cmd.h"
39 #define DEFAULT_COMMUNITY "public"
40 #define DEFAULT_PORT "161"
41 #define DEFAULT_MIBLIST "ALL"
42 #define DEFAULT_PROTOCOL "1"
43 #define DEFAULT_TIMEOUT 1
44 #define DEFAULT_RETRIES 5
45 #define DEFAULT_AUTH_PROTOCOL "MD5"
46 #define DEFAULT_PRIV_PROTOCOL "DES"
47 #define DEFAULT_DELIMITER "="
48 #define DEFAULT_OUTPUT_DELIMITER " "
50 #define mark(a) ((a)!=0?"*":"")
52 #define CHECK_UNDEF 0
53 #define CRIT_PRESENT 1
54 #define CRIT_STRING 2
55 #define CRIT_REGEX 4
56 #define CRIT_GT 8
57 #define CRIT_LT 16
58 #define CRIT_GE 32
59 #define CRIT_LE 64
60 #define CRIT_EQ 128
61 #define CRIT_NE 256
62 #define CRIT_RANGE 512
63 #define WARN_PRESENT 1024
64 #define WARN_STRING 2048
65 #define WARN_REGEX 4096
66 #define WARN_GT 8192
67 #define WARN_LT 16384
68 #define WARN_GE 32768
69 #define WARN_LE 65536
70 #define WARN_EQ 131072
71 #define WARN_NE 262144
72 #define WARN_RANGE 524288
74 #define MAX_OIDS 8
75 #define MAX_DELIM_LENGTH 8
77 int process_arguments (int, char **);
78 int validate_arguments (void);
79 char *clarify_message (char *);
80 int check_num (int);
81 int llu_getll (unsigned long long *, char *);
82 int llu_getul (unsigned long long *, char *);
83 char *thisarg (char *str);
84 char *nextarg (char *str);
85 void print_usage (void);
86 void print_help (void);
88 #include "regex.h"
89 char regex_expect[MAX_INPUT_BUFFER] = "";
90 regex_t preg;
91 regmatch_t pmatch[10];
92 char timestamp[10] = "";
93 char errbuf[MAX_INPUT_BUFFER] = "";
94 char perfstr[MAX_INPUT_BUFFER] = "| ";
95 int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
96 int eflags = 0;
97 int errcode, excode;
99 char *server_address = NULL;
100 char *community = NULL;
101 char **authpriv = NULL;
102 char *proto = NULL;
103 char *seclevel = NULL;
104 char *secname = NULL;
105 char *authproto = NULL;
106 char *privproto = NULL;
107 char *authpasswd = NULL;
108 char *privpasswd = NULL;
109 char **oids = NULL;
110 char *label;
111 char *units;
112 char *port;
113 char *snmpcmd;
114 char string_value[MAX_INPUT_BUFFER] = "";
115 char **labels = NULL;
116 char **unitv = NULL;
117 size_t nlabels = 0;
118 size_t labels_size = 8;
119 size_t nunits = 0;
120 size_t unitv_size = 8;
121 int numoids = 0;
122 int numauthpriv = 0;
123 int verbose = FALSE;
124 int usesnmpgetnext = FALSE;
125 unsigned long long lower_warn_lim[MAX_OIDS];
126 unsigned long long upper_warn_lim[MAX_OIDS];
127 unsigned long long lower_crit_lim[MAX_OIDS];
128 unsigned long long upper_crit_lim[MAX_OIDS];
129 unsigned long long response_value[MAX_OIDS];
130 int check_warning_value = FALSE;
131 int check_critical_value = FALSE;
132 int retries = 0;
133 unsigned long long eval_method[MAX_OIDS];
134 char *delimiter;
135 char *output_delim;
136 char *miblist = NULL;
137 int needmibs = FALSE;
141 main (int argc, char **argv)
143 int i = 0;
144 int iresult = STATE_UNKNOWN;
145 int result = STATE_UNKNOWN;
146 int return_code = 0;
147 int external_error = 0;
148 char **command_line = NULL;
149 char *cl_hidden_auth = NULL;
150 char *oidname = NULL;
151 char *response = NULL;
152 char *outbuff;
153 char *ptr = NULL;
154 char *show = NULL;
155 char type[8] = "";
156 output chld_out, chld_err;
158 setlocale (LC_ALL, "");
159 bindtextdomain (PACKAGE, LOCALEDIR);
160 textdomain (PACKAGE);
162 labels = malloc (labels_size);
163 unitv = malloc (unitv_size);
164 for (i = 0; i < MAX_OIDS; i++)
165 eval_method[i] = CHECK_UNDEF;
166 i = 0;
168 label = strdup ("SNMP");
169 units = strdup ("");
170 port = strdup (DEFAULT_PORT);
171 outbuff = strdup ("");
172 delimiter = strdup (" = ");
173 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
174 /* miblist = strdup (DEFAULT_MIBLIST); */
175 timeout_interval = DEFAULT_TIMEOUT;
176 retries = DEFAULT_RETRIES;
178 /* Parse extra opts if any */
179 argv=np_extra_opts (&argc, argv, progname);
181 if (process_arguments (argc, argv) == ERROR)
182 usage4 (_("Could not parse arguments"));
184 /* Create the command array to execute */
185 if(usesnmpgetnext == TRUE) {
186 snmpcmd = strdup (PATH_TO_SNMPGETNEXT);
187 }else{
188 snmpcmd = strdup (PATH_TO_SNMPGET);
191 /* 9 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */
192 command_line = calloc (9 + numauthpriv + 1 + numoids + 1, sizeof (char *));
193 command_line[0] = snmpcmd;
194 command_line[1] = strdup ("-t");
195 asprintf (&command_line[2], "%d", timeout_interval);
196 command_line[3] = strdup ("-r");
197 asprintf (&command_line[4], "%d", retries);
198 command_line[5] = strdup ("-m");
199 command_line[6] = strdup (miblist);
200 command_line[7] = "-v";
201 command_line[8] = strdup (proto);
203 for (i = 0; i < numauthpriv; i++) {
204 command_line[9 + i] = authpriv[i];
207 asprintf (&command_line[9 + numauthpriv], "%s:%s", server_address, port);
209 /* This is just for display purposes, so it can remain a string */
210 asprintf(&cl_hidden_auth, "%s -t %d -r %d -m %s -v %s %s %s:%s",
211 snmpcmd, timeout_interval, retries, miblist, proto, "[authpriv]",
212 server_address, port);
214 for (i = 0; i < numoids; i++) {
215 command_line[9 + numauthpriv + 1 + i] = oids[i];
216 asprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);
219 command_line[9 + numauthpriv + 1 + numoids] = NULL;
221 if (verbose)
222 printf ("%s\n", cl_hidden_auth);
224 /* Run the command */
225 return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0);
227 /* Due to net-snmp sometimes showing stderr messages with poorly formed MIBs,
228 only return state unknown if return code is non zero or there is no stdout.
229 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
231 if (return_code != 0)
232 external_error=1;
233 if (chld_out.lines == 0)
234 external_error=1;
235 if (external_error) {
236 if (chld_err.lines > 0) {
237 printf (_("External command error: %s\n"), chld_err.line[0]);
238 for (i = 1; i < chld_err.lines; i++) {
239 printf ("%s\n", chld_err.line[i]);
241 } else {
242 printf(_("External command error with no output (return code: %d)\n"), return_code);
244 exit (STATE_UNKNOWN);
247 if (verbose) {
248 for (i = 0; i < chld_out.lines; i++) {
249 printf ("%s\n", chld_out.line[i]);
253 for (i = 0; i < chld_out.lines; i++) {
254 ptr = chld_out.line[i];
255 oidname = strpcpy (oidname, ptr, delimiter);
256 response = strstr (ptr, delimiter);
258 /* We strip out the datatype indicator for PHBs */
260 /* Clean up type array - Sol10 does not necessarily zero it out */
261 bzero(type, sizeof(type));
263 if (strstr (response, "Gauge: "))
264 show = strstr (response, "Gauge: ") + 7;
265 else if (strstr (response, "Gauge32: "))
266 show = strstr (response, "Gauge32: ") + 9;
267 else if (strstr (response, "Counter32: ")) {
268 show = strstr (response, "Counter32: ") + 11;
269 strcpy(type, "c");
271 else if (strstr (response, "Counter64: ")) {
272 show = strstr (response, "Counter64: ") + 11;
273 strcpy(type, "c");
275 else if (strstr (response, "INTEGER: "))
276 show = strstr (response, "INTEGER: ") + 9;
277 else if (strstr (response, "STRING: "))
278 show = strstr (response, "STRING: ") + 8;
279 else
280 show = response;
282 iresult = STATE_DEPENDENT;
284 /* Process this block for integer comparisons */
285 if (eval_method[i] & CRIT_GT ||
286 eval_method[i] & CRIT_LT ||
287 eval_method[i] & CRIT_GE ||
288 eval_method[i] & CRIT_LE ||
289 eval_method[i] & CRIT_EQ ||
290 eval_method[i] & CRIT_NE ||
291 eval_method[i] & WARN_GT ||
292 eval_method[i] & WARN_LT ||
293 eval_method[i] & WARN_GE ||
294 eval_method[i] & WARN_LE ||
295 eval_method[i] & WARN_EQ ||
296 eval_method[i] & WARN_NE) {
297 ptr = strpbrk (show, "0123456789");
298 if (ptr == NULL)
299 die (STATE_UNKNOWN,_("No valid data returned"));
300 response_value[i] = strtoul (ptr, NULL, 10);
301 iresult = check_num (i);
302 asprintf (&show, "%llu", response_value[i]);
305 /* Process this block for string matching */
306 else if (eval_method[i] & CRIT_STRING) {
307 if (strcmp (show, string_value))
308 iresult = STATE_CRITICAL;
309 else
310 iresult = STATE_OK;
313 /* Process this block for regex matching */
314 else if (eval_method[i] & CRIT_REGEX) {
315 excode = regexec (&preg, response, 10, pmatch, eflags);
316 if (excode == 0) {
317 iresult = STATE_OK;
319 else if (excode != REG_NOMATCH) {
320 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
321 printf (_("Execute Error: %s\n"), errbuf);
322 exit (STATE_CRITICAL);
324 else {
325 iresult = STATE_CRITICAL;
329 /* Process this block for existence-nonexistence checks */
330 else {
331 if (eval_method[i] & CRIT_PRESENT)
332 iresult = STATE_CRITICAL;
333 else if (eval_method[i] & WARN_PRESENT)
334 iresult = STATE_WARNING;
335 else if (response && iresult == STATE_DEPENDENT)
336 iresult = STATE_OK;
339 /* Result is the worst outcome of all the OIDs tested */
340 result = max_state (result, iresult);
342 /* Prepend a label for this OID if there is one */
343 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
344 asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
345 (i == 0) ? " " : output_delim,
346 labels[i], mark (iresult), show, mark (iresult));
347 else
348 asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
349 mark (iresult), show, mark (iresult));
351 /* Append a unit string for this OID if there is one */
352 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
353 asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
355 if (is_numeric(show)) {
356 strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
357 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
358 strncat(perfstr, show, sizeof(perfstr)-strlen(perfstr)-1);
360 if (type)
361 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
362 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
366 /* if (nunits == 1 || i == 1) */
367 /* printf ("%s %s -%s %s\n", label, state_text (result), outbuff, units); */
368 /* else */
369 printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
371 return result;
376 /* process command-line arguments */
378 process_arguments (int argc, char **argv)
380 char *ptr;
381 int c = 1;
382 int j = 0, jj = 0, ii = 0;
384 int option = 0;
385 static struct option longopts[] = {
386 STD_LONG_OPTS,
387 {"community", required_argument, 0, 'C'},
388 {"oid", required_argument, 0, 'o'},
389 {"object", required_argument, 0, 'o'},
390 {"delimiter", required_argument, 0, 'd'},
391 {"output-delimiter", required_argument, 0, 'D'},
392 {"string", required_argument, 0, 's'},
393 {"timeout", required_argument, 0, 't'},
394 {"regex", required_argument, 0, 'r'},
395 {"ereg", required_argument, 0, 'r'},
396 {"eregi", required_argument, 0, 'R'},
397 {"label", required_argument, 0, 'l'},
398 {"units", required_argument, 0, 'u'},
399 {"port", required_argument, 0, 'p'},
400 {"retries", required_argument, 0, 'e'},
401 {"miblist", required_argument, 0, 'm'},
402 {"protocol", required_argument, 0, 'P'},
403 {"seclevel", required_argument, 0, 'L'},
404 {"secname", required_argument, 0, 'U'},
405 {"authproto", required_argument, 0, 'a'},
406 {"privproto", required_argument, 0, 'x'},
407 {"authpasswd", required_argument, 0, 'A'},
408 {"privpasswd", required_argument, 0, 'X'},
409 {"next", no_argument, 0, 'n'},
410 {0, 0, 0, 0}
413 if (argc < 2)
414 return ERROR;
416 /* reverse compatibility for very old non-POSIX usage forms */
417 for (c = 1; c < argc; c++) {
418 if (strcmp ("-to", argv[c]) == 0)
419 strcpy (argv[c], "-t");
420 if (strcmp ("-wv", argv[c]) == 0)
421 strcpy (argv[c], "-w");
422 if (strcmp ("-cv", argv[c]) == 0)
423 strcpy (argv[c], "-c");
426 while (1) {
427 c = getopt_long (argc, argv, "nhvVt:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:L:U:a:x:A:X:",
428 longopts, &option);
430 if (c == -1 || c == EOF)
431 break;
433 switch (c) {
434 case '?': /* usage */
435 usage5 ();
436 case 'h': /* help */
437 print_help ();
438 exit (STATE_OK);
439 case 'V': /* version */
440 print_revision (progname, NP_VERSION);
441 exit (STATE_OK);
442 case 'v': /* verbose */
443 verbose = TRUE;
444 break;
446 /* Connection info */
447 case 'C': /* group or community */
448 community = optarg;
449 break;
450 case 'H': /* Host or server */
451 server_address = optarg;
452 break;
453 case 'p': /* TCP port number */
454 port = optarg;
455 break;
456 case 'm': /* List of MIBS */
457 miblist = optarg;
458 break;
459 case 'n': /* usesnmpgetnext */
460 usesnmpgetnext = TRUE;
461 break;
462 case 'P': /* SNMP protocol version */
463 proto = optarg;
464 break;
465 case 'L': /* security level */
466 seclevel = optarg;
467 break;
468 case 'U': /* security username */
469 secname = optarg;
470 break;
471 case 'a': /* auth protocol */
472 authproto = optarg;
473 break;
474 case 'x': /* priv protocol */
475 privproto = optarg;
476 break;
477 case 'A': /* auth passwd */
478 authpasswd = optarg;
479 break;
480 case 'X': /* priv passwd */
481 privpasswd = optarg;
482 break;
483 case 't': /* timeout period */
484 if (!is_integer (optarg))
485 usage2 (_("Timeout interval must be a positive integer"), optarg);
486 else
487 timeout_interval = atoi (optarg);
488 break;
490 /* Test parameters */
491 case 'c': /* critical time threshold */
492 if (strspn (optarg, "0123456789:,") < strlen (optarg))
493 usage2 (_("Invalid critical threshold"), optarg);
494 for (ptr = optarg; ptr && jj < MAX_OIDS; jj++) {
495 if (llu_getll (&lower_crit_lim[jj], ptr) == 1)
496 eval_method[jj] |= CRIT_LT;
497 if (llu_getul (&upper_crit_lim[jj], ptr) == 1)
498 eval_method[jj] |= CRIT_GT;
499 (ptr = index (ptr, ',')) ? ptr++ : ptr;
501 break;
502 case 'w': /* warning time threshold */
503 if (strspn (optarg, "0123456789:,") < strlen (optarg))
504 usage2 (_("Invalid warning threshold"), optarg);
505 for (ptr = optarg; ptr && ii < MAX_OIDS; ii++) {
506 if (llu_getll (&lower_warn_lim[ii], ptr) == 1)
507 eval_method[ii] |= WARN_LT;
508 if (llu_getul (&upper_warn_lim[ii], ptr) == 1)
509 eval_method[ii] |= WARN_GT;
510 (ptr = index (ptr, ',')) ? ptr++ : ptr;
512 break;
513 case 'e': /* PRELIMINARY - may change */
514 case 'E': /* PRELIMINARY - may change */
515 if (!is_integer (optarg))
516 usage2 (_("Retries interval must be a positive integer"), optarg);
517 else
518 retries = atoi(optarg);
519 break;
520 case 'o': /* object identifier */
521 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
523 * we have something other than digits, periods and comas,
524 * so we have a mib variable, rather than just an SNMP OID,
525 * so we have to actually read the mib files
527 needmibs = TRUE;
529 oids = calloc(MAX_OIDS, sizeof (char *));
530 for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
531 oids[j] = strdup(ptr);
533 numoids = j;
534 if (c == 'E' || c == 'e') {
535 jj++;
536 ii++;
538 if (c == 'E')
539 eval_method[j+1] |= WARN_PRESENT;
540 else if (c == 'e')
541 eval_method[j+1] |= CRIT_PRESENT;
542 break;
543 case 's': /* string or substring */
544 strncpy (string_value, optarg, sizeof (string_value) - 1);
545 string_value[sizeof (string_value) - 1] = 0;
546 eval_method[jj++] = CRIT_STRING;
547 ii++;
548 break;
549 case 'R': /* regex */
550 cflags = REG_ICASE;
551 case 'r': /* regex */
552 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
553 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
554 regex_expect[sizeof (regex_expect) - 1] = 0;
555 errcode = regcomp (&preg, regex_expect, cflags);
556 if (errcode != 0) {
557 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
558 printf (_("Could Not Compile Regular Expression"));
559 return ERROR;
561 eval_method[jj++] = CRIT_REGEX;
562 ii++;
563 break;
565 /* Format */
566 case 'd': /* delimiter */
567 delimiter = strscpy (delimiter, optarg);
568 break;
569 case 'D': /* output-delimiter */
570 output_delim = strscpy (output_delim, optarg);
571 break;
572 case 'l': /* label */
573 label = optarg;
574 nlabels++;
575 if (nlabels >= labels_size) {
576 labels_size += 8;
577 labels = realloc (labels, labels_size);
578 if (labels == NULL)
579 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
581 labels[nlabels - 1] = optarg;
582 ptr = thisarg (optarg);
583 labels[nlabels - 1] = ptr;
584 if (strstr (ptr, "'") == ptr)
585 labels[nlabels - 1] = ptr + 1;
586 while (ptr && (ptr = nextarg (ptr))) {
587 if (nlabels >= labels_size) {
588 labels_size += 8;
589 labels = realloc (labels, labels_size);
590 if (labels == NULL)
591 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
593 labels++;
594 ptr = thisarg (ptr);
595 if (strstr (ptr, "'") == ptr)
596 labels[nlabels - 1] = ptr + 1;
597 else
598 labels[nlabels - 1] = ptr;
600 break;
601 case 'u': /* units */
602 units = optarg;
603 nunits++;
604 if (nunits >= unitv_size) {
605 unitv_size += 8;
606 unitv = realloc (unitv, unitv_size);
607 if (unitv == NULL)
608 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
610 unitv[nunits - 1] = optarg;
611 ptr = thisarg (optarg);
612 unitv[nunits - 1] = ptr;
613 if (strstr (ptr, "'") == ptr)
614 unitv[nunits - 1] = ptr + 1;
615 while (ptr && (ptr = nextarg (ptr))) {
616 if (nunits >= unitv_size) {
617 unitv_size += 8;
618 unitv = realloc (unitv, unitv_size);
619 if (units == NULL)
620 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
622 nunits++;
623 ptr = thisarg (ptr);
624 if (strstr (ptr, "'") == ptr)
625 unitv[nunits - 1] = ptr + 1;
626 else
627 unitv[nunits - 1] = ptr;
629 break;
634 if (server_address == NULL)
635 server_address = argv[optind];
637 if (community == NULL)
638 community = strdup (DEFAULT_COMMUNITY);
640 return validate_arguments ();
644 /******************************************************************************
647 <sect3>
648 <title>validate_arguments</title>
650 <para>&PROTO_validate_arguments;</para>
652 <para>Checks to see if the default miblist needs to be loaded. Also verifies
653 the authentication and authorization combinations based on protocol version
654 selected.</para>
656 <para></para>
658 </sect3>
660 ******************************************************************************/
665 validate_arguments ()
667 /* check whether to load locally installed MIBS (CPU/disk intensive) */
668 if (miblist == NULL) {
669 if ( needmibs == TRUE ) {
670 miblist = strdup (DEFAULT_MIBLIST);
671 }else{
672 miblist = "''"; /* don't read any mib files for numeric oids */
676 /* Check server_address is given */
677 if (server_address == NULL)
678 die(STATE_UNKNOWN, _("No host specified\n"));
680 /* Check oid is given */
681 if (numoids == 0)
682 die(STATE_UNKNOWN, _("No OIDs specified\n"));
684 if (proto == NULL)
685 asprintf(&proto, DEFAULT_PROTOCOL);
687 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */
688 numauthpriv = 2;
689 authpriv = calloc (numauthpriv, sizeof (char *));
690 authpriv[0] = strdup ("-c");
691 authpriv[1] = strdup (community);
693 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
694 if (seclevel == NULL)
695 asprintf(&seclevel, "noAuthNoPriv");
697 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
698 numauthpriv = 2;
699 authpriv = calloc (numauthpriv, sizeof (char *));
700 authpriv[0] = strdup ("-l");
701 authpriv[1] = strdup ("noAuthNoPriv");
702 } else {
703 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
704 usage2 (_("Invalid seclevel"), seclevel);
707 if (authproto == NULL )
708 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
710 if (secname == NULL)
711 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
713 if (authpasswd == NULL)
714 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
716 if ( strcmp(seclevel, "authNoPriv") == 0 ) {
717 numauthpriv = 8;
718 authpriv = calloc (numauthpriv, sizeof (char *));
719 authpriv[0] = strdup ("-l");
720 authpriv[1] = strdup ("authNoPriv");
721 authpriv[2] = strdup ("-a");
722 authpriv[3] = strdup (authproto);
723 authpriv[4] = strdup ("-u");
724 authpriv[5] = strdup (secname);
725 authpriv[6] = strdup ("-A");
726 authpriv[7] = strdup (authpasswd);
727 } else if ( strcmp(seclevel, "authPriv") == 0 ) {
728 if (privproto == NULL )
729 asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
731 if (privpasswd == NULL)
732 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
734 numauthpriv = 12;
735 authpriv = calloc (numauthpriv, sizeof (char *));
736 authpriv[0] = strdup ("-l");
737 authpriv[1] = strdup ("authPriv");
738 authpriv[2] = strdup ("-a");
739 authpriv[3] = strdup (authproto);
740 authpriv[4] = strdup ("-u");
741 authpriv[5] = strdup (secname);
742 authpriv[6] = strdup ("-A");
743 authpriv[7] = strdup (authpasswd);
744 authpriv[8] = strdup ("-x");
745 authpriv[9] = strdup (privproto);
746 authpriv[10] = strdup ("-X");
747 authpriv[11] = strdup (privpasswd);
752 else {
753 usage2 (_("Invalid SNMP version"), proto);
756 return OK;
761 char *
762 clarify_message (char *msg)
764 int i = 0;
765 int foo;
766 char tmpmsg_c[MAX_INPUT_BUFFER];
767 char *tmpmsg = (char *) &tmpmsg_c;
768 tmpmsg = strcpy (tmpmsg, msg);
769 if (!strncmp (tmpmsg, " Hex:", 5)) {
770 tmpmsg = strtok (tmpmsg, ":");
771 while ((tmpmsg = strtok (NULL, " "))) {
772 foo = strtol (tmpmsg, NULL, 16);
773 /* Translate chars that are not the same value in the printers
774 * character set.
776 switch (foo) {
777 case 208:
779 foo = 197;
780 break;
782 case 216:
784 foo = 196;
785 break;
788 msg[i] = foo;
789 i++;
791 msg[i] = 0;
793 return (msg);
799 check_num (int i)
801 int result;
802 result = STATE_OK;
803 if (eval_method[i] & WARN_GT && eval_method[i] & WARN_LT &&
804 lower_warn_lim[i] > upper_warn_lim[i]) {
805 if (response_value[i] <= lower_warn_lim[i] &&
806 response_value[i] >= upper_warn_lim[i]) {
807 result = STATE_WARNING;
810 else if
811 ((eval_method[i] & WARN_GT && response_value[i] > upper_warn_lim[i]) ||
812 (eval_method[i] & WARN_GE && response_value[i] >= upper_warn_lim[i]) ||
813 (eval_method[i] & WARN_LT && response_value[i] < lower_warn_lim[i]) ||
814 (eval_method[i] & WARN_LE && response_value[i] <= lower_warn_lim[i]) ||
815 (eval_method[i] & WARN_EQ && response_value[i] == upper_warn_lim[i]) ||
816 (eval_method[i] & WARN_NE && response_value[i] != upper_warn_lim[i])) {
817 result = STATE_WARNING;
820 if (eval_method[i] & CRIT_GT && eval_method[i] & CRIT_LT &&
821 lower_crit_lim[i] > upper_crit_lim[i]) {
822 if (response_value[i] <= lower_crit_lim[i] &&
823 response_value[i] >= upper_crit_lim[i]) {
824 result = STATE_CRITICAL;
827 else if
828 ((eval_method[i] & CRIT_GT && response_value[i] > upper_crit_lim[i]) ||
829 (eval_method[i] & CRIT_GE && response_value[i] >= upper_crit_lim[i]) ||
830 (eval_method[i] & CRIT_LT && response_value[i] < lower_crit_lim[i]) ||
831 (eval_method[i] & CRIT_LE && response_value[i] <= lower_crit_lim[i]) ||
832 (eval_method[i] & CRIT_EQ && response_value[i] == upper_crit_lim[i]) ||
833 (eval_method[i] & CRIT_NE && response_value[i] != upper_crit_lim[i])) {
834 result = STATE_CRITICAL;
837 return result;
843 llu_getll (unsigned long long *ll, char *str)
845 char tmp[100];
846 if (strchr (str, ':') == NULL)
847 return 0;
848 if (strchr (str, ',') != NULL && (strchr (str, ',') < strchr (str, ':')))
849 return 0;
850 if (sscanf (str, "%llu%[:]", ll, tmp) == 2)
851 return 1;
852 return 0;
858 llu_getul (unsigned long long *ul, char *str)
860 char tmp[100];
861 if (sscanf (str, "%llu%[^,]", ul, tmp) == 1)
862 return 1;
863 if (sscanf (str, ":%llu%[^,]", ul, tmp) == 1)
864 return 1;
865 if (sscanf (str, "%*u:%llu%[^,]", ul, tmp) == 1)
866 return 1;
867 return 0;
872 /* trim leading whitespace
873 if there is a leading quote, make sure it balances */
875 char *
876 thisarg (char *str)
878 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
879 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
880 if (strlen (str) == 1 || !strstr (str + 1, "'"))
881 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
883 return str;
888 /* if there's a leading quote, advance to the trailing quote
889 set the trailing quote to '\x0'
890 if the string continues, advance beyond the comma */
892 char *
893 nextarg (char *str)
895 if (strstr (str, "'") == str) {
896 str[0] = 0;
897 if (strlen (str) > 1) {
898 str = strstr (str + 1, "'");
899 return (++str);
901 else {
902 return NULL;
905 if (strstr (str, ",") == str) {
906 str[0] = 0;
907 if (strlen (str) > 1) {
908 return (++str);
910 else {
911 return NULL;
914 if ((str = strstr (str, ",")) && strlen (str) > 1) {
915 str[0] = 0;
916 return (++str);
918 return NULL;
923 void
924 print_help (void)
926 print_revision (progname, NP_VERSION);
928 printf (COPYRIGHT, copyright, email);
930 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
932 printf ("\n\n");
934 print_usage ();
936 printf (_(UT_HELP_VRSN));
937 printf (_(UT_EXTRA_OPTS));
939 printf (_(UT_HOST_PORT), 'p', DEFAULT_PORT);
941 /* SNMP and Authentication Protocol */
942 printf (" %s\n", "-n, --next");
943 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
944 printf (" %s\n", "-P, --protocol=[1|2c|3]");
945 printf (" %s\n", _("SNMP protocol version"));
946 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
947 printf (" %s\n", _("SNMPv3 securityLevel"));
948 printf (" %s\n", "-a, --authproto=[MD5|SHA]");
949 printf (" %s\n", _("SNMPv3 auth proto"));
950 printf (" %s\n", "-x, --privproto=[DES|AES]");
951 printf (" %s\n", _("SNMPv3 priv proto (default DES)"));
953 /* Authentication Tokens*/
954 printf (" %s\n", "-C, --community=STRING");
955 printf (" %s ", _("Optional community string for SNMP communication"));
956 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
957 printf (" %s\n", "-U, --secname=USERNAME");
958 printf (" %s\n", _("SNMPv3 username"));
959 printf (" %s\n", "-A, --authpassword=PASSWORD");
960 printf (" %s\n", _("SNMPv3 authentication password"));
961 printf (" %s\n", "-X, --privpasswd=PASSWORD");
962 printf (" %s\n", _("SNMPv3 privacy password"));
964 /* OID Stuff */
965 printf (" %s\n", "-o, --oid=OID(s)");
966 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
967 printf (" %s\n", "-m, --miblist=STRING");
968 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
969 printf (" %s\n", _("for symbolic OIDs.)"));
970 printf (" %s\n", "-d, --delimiter=STRING");
971 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
972 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
973 printf (" %s\n", _("to be the data that should be used in the evaluation."));
975 /* Tests Against Integers */
976 printf (" %s\n", "-w, --warning=INTEGER_RANGE(s)");
977 printf (" %s\n", _("Range(s) which will not result in a WARNING status"));
978 printf (" %s\n", "-c, --critical=INTEGER_RANGE(s)");
979 printf (" %s\n", _("Range(s) which will not result in a CRITICAL status"));
981 /* Tests Against Strings */
982 printf (" %s\n", "-s, --string=STRING");
983 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
984 printf (" %s\n", "-r, --ereg=REGEX");
985 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
986 printf (" %s\n", "-R, --eregi=REGEX");
987 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
988 printf (" %s\n", "-l, --label=STRING");
989 printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
991 /* Output Formatting */
992 printf (" %s\n", "-u, --units=STRING");
993 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
994 printf (" %s\n", "-D, --output-delimiter=STRING");
995 printf (" %s\n", _("Separates output on multiple OID requests"));
997 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
998 printf (" %s\n", "-e, --retries=INTEGER");
999 printf (" %s\n", _("Number of retries to be used in the requests"));
1001 printf (_(UT_VERBOSE));
1003 printf ("\n");
1004 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
1005 printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
1006 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
1008 printf ("\n");
1009 printf ("%s\n", _("Notes:"));
1010 printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
1011 printf (" %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
1013 printf (" %s\n", _("- Ranges are inclusive and are indicated with colons. When specified as"));
1014 printf (" %s\n", _("'min:max' a STATE_OK will be returned if the result is within the indicated"));
1015 printf (" %s\n", _("range or is equal to the upper or lower bound. A non-OK state will be"));
1016 printf (" %s\n", _("returned if the result is outside the specified range."));
1018 printf (" %s\n", _("- If specified in the order 'max:min' a non-OK state will be returned if the"));
1019 printf (" %s\n", _("result is within the (inclusive) range."));
1021 printf (" %s\n", _("- Upper or lower bounds may be omitted to skip checking the respective limit."));
1022 printf (" %s\n", _("- Bare integers are interpreted as upper limits."));
1023 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
1024 printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
1025 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
1026 printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
1027 #ifdef NP_EXTRA_OPTS
1028 printf (" -%s", _(UT_EXTRA_OPTS_NOTES));
1029 #endif
1031 printf (_(UT_SUPPORT));
1036 void
1037 print_usage (void)
1039 printf (_("Usage:"));
1040 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
1041 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
1042 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1043 printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
1044 printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");