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
11 *
12 * Check status of remote machines and obtain system information via SNMP
13 *
14 *
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.
19 *
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.
24 *
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/>.
27 *
28 *
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 WARN_PRESENT 8
57 #define WARN_STRING 16
58 #define WARN_REGEX 32
60 #define MAX_OIDS 8
62 int process_arguments (int, char **);
63 int validate_arguments (void);
64 char *thisarg (char *str);
65 char *nextarg (char *str);
66 void print_usage (void);
67 void print_help (void);
69 #include "regex.h"
70 char regex_expect[MAX_INPUT_BUFFER] = "";
71 regex_t preg;
72 regmatch_t pmatch[10];
73 char errbuf[MAX_INPUT_BUFFER] = "";
74 char perfstr[MAX_INPUT_BUFFER] = "| ";
75 int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
76 int eflags = 0;
77 int errcode, excode;
79 char *server_address = NULL;
80 char *community = NULL;
81 char **authpriv = NULL;
82 char *proto = NULL;
83 char *seclevel = NULL;
84 char *secname = NULL;
85 char *authproto = NULL;
86 char *privproto = NULL;
87 char *authpasswd = NULL;
88 char *privpasswd = NULL;
89 char **oids = NULL;
90 char *label;
91 char *units;
92 char *port;
93 char *snmpcmd;
94 char string_value[MAX_INPUT_BUFFER] = "";
95 char **labels = NULL;
96 char **unitv = NULL;
97 size_t nlabels = 0;
98 size_t labels_size = 8;
99 size_t nunits = 0;
100 size_t unitv_size = 8;
101 int numoids = 0;
102 int numauthpriv = 0;
103 int verbose = 0;
104 int usesnmpgetnext = FALSE;
105 char *warning_thresholds = NULL;
106 char *critical_thresholds = NULL;
107 thresholds *thlds[MAX_OIDS];
108 double response_value[MAX_OIDS];
109 int retries = 0;
110 int eval_method[MAX_OIDS];
111 char *delimiter;
112 char *output_delim;
113 char *miblist = NULL;
114 int needmibs = FALSE;
117 int
118 main (int argc, char **argv)
119 {
120 int i, len;
121 int iresult = STATE_UNKNOWN;
122 int result = STATE_UNKNOWN;
123 int return_code = 0;
124 int external_error = 0;
125 char **command_line = NULL;
126 char *cl_hidden_auth = NULL;
127 char *oidname = NULL;
128 char *response = NULL;
129 char *outbuff;
130 char *ptr = NULL;
131 char *show = NULL;
132 char *th_warn=NULL;
133 char *th_crit=NULL;
134 char type[8] = "";
135 output chld_out, chld_err;
137 setlocale (LC_ALL, "");
138 bindtextdomain (PACKAGE, LOCALEDIR);
139 textdomain (PACKAGE);
141 labels = malloc (labels_size);
142 unitv = malloc (unitv_size);
143 for (i = 0; i < MAX_OIDS; i++)
144 eval_method[i] = CHECK_UNDEF;
146 label = strdup ("SNMP");
147 units = strdup ("");
148 port = strdup (DEFAULT_PORT);
149 outbuff = strdup ("");
150 delimiter = strdup (" = ");
151 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
152 timeout_interval = DEFAULT_TIMEOUT;
153 retries = DEFAULT_RETRIES;
155 /* Parse extra opts if any */
156 argv=np_extra_opts (&argc, argv, progname);
158 if (process_arguments (argc, argv) == ERROR)
159 usage4 (_("Could not parse arguments"));
161 /* Populate the thresholds */
162 th_warn=warning_thresholds;
163 th_crit=critical_thresholds;
164 for (i=0; i<numoids; i++) {
165 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
166 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
167 /* Skip empty thresholds, while avoiding segfault */
168 set_thresholds(&thlds[i],
169 w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
170 c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
171 if (w) {
172 th_warn=strchr(th_warn, ',');
173 if (th_warn) th_warn++;
174 free(w);
175 }
176 if (c) {
177 th_crit=strchr(th_crit, ',');
178 if (th_crit) th_crit++;
179 free(c);
180 }
181 }
183 /* Create the command array to execute */
184 if(usesnmpgetnext == TRUE) {
185 snmpcmd = strdup (PATH_TO_SNMPGETNEXT);
186 }else{
187 snmpcmd = strdup (PATH_TO_SNMPGET);
188 }
190 /* 9 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */
191 command_line = calloc (9 + numauthpriv + 1 + numoids + 1, sizeof (char *));
192 command_line[0] = snmpcmd;
193 command_line[1] = strdup ("-t");
194 asprintf (&command_line[2], "%d", timeout_interval);
195 command_line[3] = strdup ("-r");
196 asprintf (&command_line[4], "%d", retries);
197 command_line[5] = strdup ("-m");
198 command_line[6] = strdup (miblist);
199 command_line[7] = "-v";
200 command_line[8] = strdup (proto);
202 for (i = 0; i < numauthpriv; i++) {
203 command_line[9 + i] = authpriv[i];
204 }
206 asprintf (&command_line[9 + numauthpriv], "%s:%s", server_address, port);
208 /* This is just for display purposes, so it can remain a string */
209 asprintf(&cl_hidden_auth, "%s -t %d -r %d -m %s -v %s %s %s:%s",
210 snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto, "[authpriv]",
211 server_address, port);
213 for (i = 0; i < numoids; i++) {
214 command_line[9 + numauthpriv + 1 + i] = oids[i];
215 asprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);
216 }
218 command_line[9 + numauthpriv + 1 + numoids] = NULL;
220 if (verbose)
221 printf ("%s\n", cl_hidden_auth);
223 /* Run the command */
224 return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0);
226 /* Due to net-snmp sometimes showing stderr messages with poorly formed MIBs,
227 only return state unknown if return code is non zero or there is no stdout.
228 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
229 */
230 if (return_code != 0)
231 external_error=1;
232 if (chld_out.lines == 0)
233 external_error=1;
234 if (external_error) {
235 if (chld_err.lines > 0) {
236 printf (_("External command error: %s\n"), chld_err.line[0]);
237 for (i = 1; i < chld_err.lines; i++) {
238 printf ("%s\n", chld_err.line[i]);
239 }
240 } else {
241 printf(_("External command error with no output (return code: %d)\n"), return_code);
242 }
243 exit (STATE_UNKNOWN);
244 }
246 if (verbose) {
247 for (i = 0; i < chld_out.lines; i++) {
248 printf ("%s\n", chld_out.line[i]);
249 }
250 }
252 for (i = 0; i < chld_out.lines; i++) {
253 const char *conv = "%.0f";
255 ptr = chld_out.line[i];
256 oidname = strpcpy (oidname, ptr, delimiter);
257 response = strstr (ptr, delimiter);
258 if (response == NULL)
259 break;
261 if (verbose > 2) {
262 printf("Processing line %i\n oidname: %s\n response: %s\n", i+1, oidname, response);
263 }
265 /* Clean up type array - Sol10 does not necessarily zero it out */
266 bzero(type, sizeof(type));
268 /* We strip out the datatype indicator for PHBs */
269 if (strstr (response, "Gauge: "))
270 show = strstr (response, "Gauge: ") + 7;
271 else if (strstr (response, "Gauge32: "))
272 show = strstr (response, "Gauge32: ") + 9;
273 else if (strstr (response, "Counter32: ")) {
274 show = strstr (response, "Counter32: ") + 11;
275 strcpy(type, "c");
276 }
277 else if (strstr (response, "Counter64: ")) {
278 show = strstr (response, "Counter64: ") + 11;
279 strcpy(type, "c");
280 }
281 else if (strstr (response, "INTEGER: "))
282 show = strstr (response, "INTEGER: ") + 9;
283 else if (strstr (response, "STRING: ")) {
284 show = strstr (response, "STRING: ") + 8;
285 conv = "%.10g";
286 }
287 else if (strstr (response, "Timeticks: "))
288 show = strstr (response, "Timeticks: ");
289 else
290 show = response;
292 iresult = STATE_DEPENDENT;
294 /* Process this block for integer comparisons */
295 if (thlds[i]->warning || thlds[i]->critical) {
296 ptr = strpbrk (show, "0123456789");
297 if (ptr == NULL)
298 die (STATE_UNKNOWN,_("No valid data returned"));
299 response_value[i] = strtod (ptr, NULL);
300 iresult = get_status(response_value[i], thlds[i]);
301 asprintf (&show, conv, response_value[i]);
302 }
304 /* Process this block for string matching */
305 else if (eval_method[i] & CRIT_STRING) {
306 if (strcmp (show, string_value))
307 iresult = STATE_CRITICAL;
308 else
309 iresult = STATE_OK;
310 }
312 /* Process this block for regex matching */
313 else if (eval_method[i] & CRIT_REGEX) {
314 excode = regexec (&preg, response, 10, pmatch, eflags);
315 if (excode == 0) {
316 iresult = STATE_OK;
317 }
318 else if (excode != REG_NOMATCH) {
319 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
320 printf (_("Execute Error: %s\n"), errbuf);
321 exit (STATE_CRITICAL);
322 }
323 else {
324 iresult = STATE_CRITICAL;
325 }
326 }
328 /* Process this block for existence-nonexistence checks */
329 else {
330 if (eval_method[i] & CRIT_PRESENT)
331 iresult = STATE_CRITICAL;
332 else if (eval_method[i] & WARN_PRESENT)
333 iresult = STATE_WARNING;
334 else if (response && iresult == STATE_DEPENDENT)
335 iresult = STATE_OK;
336 }
338 /* Result is the worst outcome of all the OIDs tested */
339 result = max_state (result, iresult);
341 /* Prepend a label for this OID if there is one */
342 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
343 asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
344 (i == 0) ? " " : output_delim,
345 labels[i], mark (iresult), show, mark (iresult));
346 else
347 asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
348 mark (iresult), show, mark (iresult));
350 /* Append a unit string for this OID if there is one */
351 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
352 asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
354 /* Write perfdata with whatever can be parsed by strtod, if possible */
355 ptr = NULL;
356 strtod(show, &ptr);
357 if (ptr > show) {
358 strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
359 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
360 len = sizeof(perfstr)-strlen(perfstr)-1;
361 strncat(perfstr, show, len>ptr-show ? ptr-show : len);
363 if (type)
364 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
365 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
366 }
367 }
369 printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
371 return result;
372 }
376 /* process command-line arguments */
377 int
378 process_arguments (int argc, char **argv)
379 {
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}
411 };
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");
424 }
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++;
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 threshold */
492 critical_thresholds = optarg;
493 break;
494 case 'w': /* warning threshold */
495 warning_thresholds = optarg;
496 break;
497 case 'e': /* PRELIMINARY - may change */
498 case 'E': /* PRELIMINARY - may change */
499 if (!is_integer (optarg))
500 usage2 (_("Retries interval must be a positive integer"), optarg);
501 else
502 retries = atoi(optarg);
503 break;
504 case 'o': /* object identifier */
505 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
506 /*
507 * we have something other than digits, periods and comas,
508 * so we have a mib variable, rather than just an SNMP OID,
509 * so we have to actually read the mib files
510 */
511 needmibs = TRUE;
512 }
513 if (!oids) oids = calloc(MAX_OIDS, sizeof (char *));
514 for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
515 oids[j] = strdup(ptr);
516 }
517 numoids = j;
518 if (c == 'E' || c == 'e') {
519 jj++;
520 ii++;
521 }
522 if (c == 'E')
523 eval_method[j+1] |= WARN_PRESENT;
524 else if (c == 'e')
525 eval_method[j+1] |= CRIT_PRESENT;
526 break;
527 case 's': /* string or substring */
528 strncpy (string_value, optarg, sizeof (string_value) - 1);
529 string_value[sizeof (string_value) - 1] = 0;
530 eval_method[jj++] = CRIT_STRING;
531 ii++;
532 break;
533 case 'R': /* regex */
534 cflags = REG_ICASE;
535 case 'r': /* regex */
536 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
537 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
538 regex_expect[sizeof (regex_expect) - 1] = 0;
539 errcode = regcomp (&preg, regex_expect, cflags);
540 if (errcode != 0) {
541 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
542 printf (_("Could Not Compile Regular Expression"));
543 return ERROR;
544 }
545 eval_method[jj++] = CRIT_REGEX;
546 ii++;
547 break;
549 /* Format */
550 case 'd': /* delimiter */
551 delimiter = strscpy (delimiter, optarg);
552 break;
553 case 'D': /* output-delimiter */
554 output_delim = strscpy (output_delim, optarg);
555 break;
556 case 'l': /* label */
557 label = optarg;
558 nlabels++;
559 if (nlabels >= labels_size) {
560 labels_size += 8;
561 labels = realloc (labels, labels_size);
562 if (labels == NULL)
563 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
564 }
565 labels[nlabels - 1] = optarg;
566 ptr = thisarg (optarg);
567 labels[nlabels - 1] = ptr;
568 if (strstr (ptr, "'") == ptr)
569 labels[nlabels - 1] = ptr + 1;
570 while (ptr && (ptr = nextarg (ptr))) {
571 if (nlabels >= labels_size) {
572 labels_size += 8;
573 labels = realloc (labels, labels_size);
574 if (labels == NULL)
575 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
576 }
577 labels++;
578 ptr = thisarg (ptr);
579 if (strstr (ptr, "'") == ptr)
580 labels[nlabels - 1] = ptr + 1;
581 else
582 labels[nlabels - 1] = ptr;
583 }
584 break;
585 case 'u': /* units */
586 units = optarg;
587 nunits++;
588 if (nunits >= unitv_size) {
589 unitv_size += 8;
590 unitv = realloc (unitv, unitv_size);
591 if (unitv == NULL)
592 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
593 }
594 unitv[nunits - 1] = optarg;
595 ptr = thisarg (optarg);
596 unitv[nunits - 1] = ptr;
597 if (strstr (ptr, "'") == ptr)
598 unitv[nunits - 1] = ptr + 1;
599 while (ptr && (ptr = nextarg (ptr))) {
600 if (nunits >= unitv_size) {
601 unitv_size += 8;
602 unitv = realloc (unitv, unitv_size);
603 if (units == NULL)
604 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
605 }
606 nunits++;
607 ptr = thisarg (ptr);
608 if (strstr (ptr, "'") == ptr)
609 unitv[nunits - 1] = ptr + 1;
610 else
611 unitv[nunits - 1] = ptr;
612 }
613 break;
615 }
616 }
618 if (server_address == NULL)
619 server_address = argv[optind];
621 if (community == NULL)
622 community = strdup (DEFAULT_COMMUNITY);
624 return validate_arguments ();
625 }
628 /******************************************************************************
630 @@-
631 <sect3>
632 <title>validate_arguments</title>
634 <para>&PROTO_validate_arguments;</para>
636 <para>Checks to see if the default miblist needs to be loaded. Also verifies
637 the authentication and authorization combinations based on protocol version
638 selected.</para>
640 <para></para>
642 </sect3>
643 -@@
644 ******************************************************************************/
648 int
649 validate_arguments ()
650 {
651 /* check whether to load locally installed MIBS (CPU/disk intensive) */
652 if (miblist == NULL) {
653 if ( needmibs == TRUE ) {
654 miblist = strdup (DEFAULT_MIBLIST);
655 }else{
656 miblist = ""; /* don't read any mib files for numeric oids */
657 }
658 }
660 /* Check server_address is given */
661 if (server_address == NULL)
662 die(STATE_UNKNOWN, _("No host specified\n"));
664 /* Check oid is given */
665 if (numoids == 0)
666 die(STATE_UNKNOWN, _("No OIDs specified\n"));
668 if (proto == NULL)
669 asprintf(&proto, DEFAULT_PROTOCOL);
671 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */
672 numauthpriv = 2;
673 authpriv = calloc (numauthpriv, sizeof (char *));
674 authpriv[0] = strdup ("-c");
675 authpriv[1] = strdup (community);
676 }
677 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
678 if (seclevel == NULL)
679 asprintf(&seclevel, "noAuthNoPriv");
681 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
682 numauthpriv = 2;
683 authpriv = calloc (numauthpriv, sizeof (char *));
684 authpriv[0] = strdup ("-l");
685 authpriv[1] = strdup ("noAuthNoPriv");
686 } else {
687 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
688 usage2 (_("Invalid seclevel"), seclevel);
689 }
691 if (authproto == NULL )
692 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
694 if (secname == NULL)
695 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
697 if (authpasswd == NULL)
698 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
700 if ( strcmp(seclevel, "authNoPriv") == 0 ) {
701 numauthpriv = 8;
702 authpriv = calloc (numauthpriv, sizeof (char *));
703 authpriv[0] = strdup ("-l");
704 authpriv[1] = strdup ("authNoPriv");
705 authpriv[2] = strdup ("-a");
706 authpriv[3] = strdup (authproto);
707 authpriv[4] = strdup ("-u");
708 authpriv[5] = strdup (secname);
709 authpriv[6] = strdup ("-A");
710 authpriv[7] = strdup (authpasswd);
711 } else if ( strcmp(seclevel, "authPriv") == 0 ) {
712 if (privproto == NULL )
713 asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
715 if (privpasswd == NULL)
716 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
718 numauthpriv = 12;
719 authpriv = calloc (numauthpriv, sizeof (char *));
720 authpriv[0] = strdup ("-l");
721 authpriv[1] = strdup ("authPriv");
722 authpriv[2] = strdup ("-a");
723 authpriv[3] = strdup (authproto);
724 authpriv[4] = strdup ("-u");
725 authpriv[5] = strdup (secname);
726 authpriv[6] = strdup ("-A");
727 authpriv[7] = strdup (authpasswd);
728 authpriv[8] = strdup ("-x");
729 authpriv[9] = strdup (privproto);
730 authpriv[10] = strdup ("-X");
731 authpriv[11] = strdup (privpasswd);
732 }
733 }
735 }
736 else {
737 usage2 (_("Invalid SNMP version"), proto);
738 }
740 return OK;
741 }
745 /* trim leading whitespace
746 if there is a leading quote, make sure it balances */
748 char *
749 thisarg (char *str)
750 {
751 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
752 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
753 if (strlen (str) == 1 || !strstr (str + 1, "'"))
754 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
755 }
756 return str;
757 }
761 /* if there's a leading quote, advance to the trailing quote
762 set the trailing quote to '\x0'
763 if the string continues, advance beyond the comma */
765 char *
766 nextarg (char *str)
767 {
768 if (strstr (str, "'") == str) {
769 str[0] = 0;
770 if (strlen (str) > 1) {
771 str = strstr (str + 1, "'");
772 return (++str);
773 }
774 else {
775 return NULL;
776 }
777 }
778 if (strstr (str, ",") == str) {
779 str[0] = 0;
780 if (strlen (str) > 1) {
781 return (++str);
782 }
783 else {
784 return NULL;
785 }
786 }
787 if ((str = strstr (str, ",")) && strlen (str) > 1) {
788 str[0] = 0;
789 return (++str);
790 }
791 return NULL;
792 }
796 void
797 print_help (void)
798 {
799 print_revision (progname, NP_VERSION);
801 printf (COPYRIGHT, copyright, email);
803 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
805 printf ("\n\n");
807 print_usage ();
809 printf (UT_HELP_VRSN);
810 printf (UT_EXTRA_OPTS);
812 printf (UT_HOST_PORT, 'p', DEFAULT_PORT);
814 /* SNMP and Authentication Protocol */
815 printf (" %s\n", "-n, --next");
816 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
817 printf (" %s\n", "-P, --protocol=[1|2c|3]");
818 printf (" %s\n", _("SNMP protocol version"));
819 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
820 printf (" %s\n", _("SNMPv3 securityLevel"));
821 printf (" %s\n", "-a, --authproto=[MD5|SHA]");
822 printf (" %s\n", _("SNMPv3 auth proto"));
823 printf (" %s\n", "-x, --privproto=[DES|AES]");
824 printf (" %s\n", _("SNMPv3 priv proto (default DES)"));
826 /* Authentication Tokens*/
827 printf (" %s\n", "-C, --community=STRING");
828 printf (" %s ", _("Optional community string for SNMP communication"));
829 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
830 printf (" %s\n", "-U, --secname=USERNAME");
831 printf (" %s\n", _("SNMPv3 username"));
832 printf (" %s\n", "-A, --authpassword=PASSWORD");
833 printf (" %s\n", _("SNMPv3 authentication password"));
834 printf (" %s\n", "-X, --privpasswd=PASSWORD");
835 printf (" %s\n", _("SNMPv3 privacy password"));
837 /* OID Stuff */
838 printf (" %s\n", "-o, --oid=OID(s)");
839 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
840 printf (" %s\n", "-m, --miblist=STRING");
841 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
842 printf (" %s\n", _("for symbolic OIDs.)"));
843 printf (" %s\n", "-d, --delimiter=STRING");
844 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
845 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
846 printf (" %s\n", _("to be the data that should be used in the evaluation."));
848 /* Tests Against Integers */
849 printf (" %s\n", "-w, --warning=THRESHOLD(s)");
850 printf (" %s\n", _("Warning threshold range(s)"));
851 printf (" %s\n", "-c, --critical=THRESHOLD(s)");
852 printf (" %s\n", _("Critical threshold range(s)"));
854 /* Tests Against Strings */
855 printf (" %s\n", "-s, --string=STRING");
856 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
857 printf (" %s\n", "-r, --ereg=REGEX");
858 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
859 printf (" %s\n", "-R, --eregi=REGEX");
860 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
861 printf (" %s\n", "-l, --label=STRING");
862 printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
864 /* Output Formatting */
865 printf (" %s\n", "-u, --units=STRING");
866 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
867 printf (" %s\n", "-D, --output-delimiter=STRING");
868 printf (" %s\n", _("Separates output on multiple OID requests"));
870 printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
871 printf (" %s\n", "-e, --retries=INTEGER");
872 printf (" %s\n", _("Number of retries to be used in the requests"));
874 printf (UT_VERBOSE);
876 printf ("\n");
877 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
878 printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
879 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
881 printf ("\n");
882 printf ("%s\n", _("Notes:"));
883 printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
884 printf (" %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
886 printf(" -%s", UT_THRESHOLDS_NOTES);
888 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
889 printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
890 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
891 printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
892 #ifdef NP_EXTRA_OPTS
893 printf (" -%s", UT_EXTRA_OPTS_NOTES);
894 #endif
896 printf (UT_SUPPORT);
897 }
901 void
902 print_usage (void)
903 {
904 printf (_("Usage:"));
905 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
906 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
907 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
908 printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
909 printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");
910 }