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, line;
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 *mult_resp = NULL;
130 char *outbuff;
131 char *ptr = NULL;
132 char *show = NULL;
133 char *th_warn=NULL;
134 char *th_crit=NULL;
135 char type[8] = "";
136 output chld_out, chld_err;
138 setlocale (LC_ALL, "");
139 bindtextdomain (PACKAGE, LOCALEDIR);
140 textdomain (PACKAGE);
142 labels = malloc (labels_size);
143 unitv = malloc (unitv_size);
144 for (i = 0; i < MAX_OIDS; i++)
145 eval_method[i] = CHECK_UNDEF;
147 label = strdup ("SNMP");
148 units = strdup ("");
149 port = strdup (DEFAULT_PORT);
150 outbuff = strdup ("");
151 delimiter = strdup (" = ");
152 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
153 timeout_interval = DEFAULT_TIMEOUT;
154 retries = DEFAULT_RETRIES;
156 /* Parse extra opts if any */
157 argv=np_extra_opts (&argc, argv, progname);
159 if (process_arguments (argc, argv) == ERROR)
160 usage4 (_("Could not parse arguments"));
162 /* Populate the thresholds */
163 th_warn=warning_thresholds;
164 th_crit=critical_thresholds;
165 for (i=0; i<numoids; i++) {
166 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
167 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
168 /* Skip empty thresholds, while avoiding segfault */
169 set_thresholds(&thlds[i],
170 w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
171 c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
172 if (w) {
173 th_warn=strchr(th_warn, ',');
174 if (th_warn) th_warn++;
175 free(w);
176 }
177 if (c) {
178 th_crit=strchr(th_crit, ',');
179 if (th_crit) th_crit++;
180 free(c);
181 }
182 }
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);
189 }
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];
205 }
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, strlen(miblist) ? 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]);
217 }
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
230 */
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]);
240 }
241 } else {
242 printf(_("External command error with no output (return code: %d)\n"), return_code);
243 }
244 exit (STATE_UNKNOWN);
245 }
247 if (verbose) {
248 for (i = 0; i < chld_out.lines; i++) {
249 printf ("%s\n", chld_out.line[i]);
250 }
251 }
253 for (line=0, i=0; line < chld_out.lines; line++, i++) {
254 const char *conv = "%.0f";
256 ptr = chld_out.line[line];
257 oidname = strpcpy (oidname, ptr, delimiter);
258 response = strstr (ptr, delimiter);
259 if (response == NULL)
260 break;
262 if (verbose > 2) {
263 printf("Processing line %i\n oidname: %s\n response: %s\n", i+1, oidname, response);
264 }
266 /* Clean up type array - Sol10 does not necessarily zero it out */
267 bzero(type, sizeof(type));
269 /* We strip out the datatype indicator for PHBs */
270 if (strstr (response, "Gauge: "))
271 show = strstr (response, "Gauge: ") + 7;
272 else if (strstr (response, "Gauge32: "))
273 show = strstr (response, "Gauge32: ") + 9;
274 else if (strstr (response, "Counter32: ")) {
275 show = strstr (response, "Counter32: ") + 11;
276 strcpy(type, "c");
277 }
278 else if (strstr (response, "Counter64: ")) {
279 show = strstr (response, "Counter64: ") + 11;
280 strcpy(type, "c");
281 }
282 else if (strstr (response, "INTEGER: "))
283 show = strstr (response, "INTEGER: ") + 9;
284 else if (strstr (response, "STRING: ")) {
285 show = strstr (response, "STRING: ") + 8;
286 conv = "%.10g";
287 /* Get the rest of the string on multi-line strings */
288 if (show[0] == '"' && (response[strlen(response)-1] != '\"' || response[strlen(response)-2] != '\\')) {
289 /* Strip out unmatched double-quote */
290 if (show[0] == '"') show++;
291 if (!mult_resp) mult_resp = strdup("");
292 asprintf (&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], strstr (response, "STRING: ") + 8);
293 for (line++; line < chld_out.lines; line++) {
294 asprintf (&mult_resp, "%s%s\n", mult_resp, chld_out.line[line]);
295 if (mult_resp[strlen(mult_resp)-2] == '"' && response[strlen(response)-2] != '\\') break;
296 }
297 }
299 }
300 else if (strstr (response, "Timeticks: "))
301 show = strstr (response, "Timeticks: ");
302 else
303 show = response;
305 iresult = STATE_DEPENDENT;
307 /* Process this block for integer comparisons */
308 if (thlds[i]->warning || thlds[i]->critical) {
309 ptr = strpbrk (show, "0123456789");
310 if (ptr == NULL)
311 die (STATE_UNKNOWN,_("No valid data returned"));
312 response_value[i] = strtod (ptr, NULL);
313 iresult = get_status(response_value[i], thlds[i]);
314 asprintf (&show, conv, response_value[i]);
315 }
317 /* Process this block for string matching */
318 else if (eval_method[i] & CRIT_STRING) {
319 if (strcmp (show, string_value))
320 iresult = STATE_CRITICAL;
321 else
322 iresult = STATE_OK;
323 }
325 /* Process this block for regex matching */
326 else if (eval_method[i] & CRIT_REGEX) {
327 excode = regexec (&preg, response, 10, pmatch, eflags);
328 if (excode == 0) {
329 iresult = STATE_OK;
330 }
331 else if (excode != REG_NOMATCH) {
332 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
333 printf (_("Execute Error: %s\n"), errbuf);
334 exit (STATE_CRITICAL);
335 }
336 else {
337 iresult = STATE_CRITICAL;
338 }
339 }
341 /* Process this block for existence-nonexistence checks */
342 else {
343 if (eval_method[i] & CRIT_PRESENT)
344 iresult = STATE_CRITICAL;
345 else if (eval_method[i] & WARN_PRESENT)
346 iresult = STATE_WARNING;
347 else if (response && iresult == STATE_DEPENDENT)
348 iresult = STATE_OK;
349 }
351 /* Result is the worst outcome of all the OIDs tested */
352 result = max_state (result, iresult);
354 /* Prepend a label for this OID if there is one */
355 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
356 asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
357 (i == 0) ? " " : output_delim,
358 labels[i], mark (iresult), show, mark (iresult));
359 else
360 asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
361 mark (iresult), show, mark (iresult));
363 /* Append a unit string for this OID if there is one */
364 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
365 asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
367 /* Write perfdata with whatever can be parsed by strtod, if possible */
368 ptr = NULL;
369 strtod(show, &ptr);
370 if (ptr > show) {
371 strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
372 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
373 len = sizeof(perfstr)-strlen(perfstr)-1;
374 strncat(perfstr, show, len>ptr-show ? ptr-show : len);
376 if (type)
377 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
378 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
379 }
380 }
382 printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
383 if (mult_resp) printf ("%s", mult_resp);
385 return result;
386 }
390 /* process command-line arguments */
391 int
392 process_arguments (int argc, char **argv)
393 {
394 char *ptr;
395 int c = 1;
396 int j = 0, jj = 0, ii = 0;
398 int option = 0;
399 static struct option longopts[] = {
400 STD_LONG_OPTS,
401 {"community", required_argument, 0, 'C'},
402 {"oid", required_argument, 0, 'o'},
403 {"object", required_argument, 0, 'o'},
404 {"delimiter", required_argument, 0, 'd'},
405 {"output-delimiter", required_argument, 0, 'D'},
406 {"string", required_argument, 0, 's'},
407 {"timeout", required_argument, 0, 't'},
408 {"regex", required_argument, 0, 'r'},
409 {"ereg", required_argument, 0, 'r'},
410 {"eregi", required_argument, 0, 'R'},
411 {"label", required_argument, 0, 'l'},
412 {"units", required_argument, 0, 'u'},
413 {"port", required_argument, 0, 'p'},
414 {"retries", required_argument, 0, 'e'},
415 {"miblist", required_argument, 0, 'm'},
416 {"protocol", required_argument, 0, 'P'},
417 {"seclevel", required_argument, 0, 'L'},
418 {"secname", required_argument, 0, 'U'},
419 {"authproto", required_argument, 0, 'a'},
420 {"privproto", required_argument, 0, 'x'},
421 {"authpasswd", required_argument, 0, 'A'},
422 {"privpasswd", required_argument, 0, 'X'},
423 {"next", no_argument, 0, 'n'},
424 {0, 0, 0, 0}
425 };
427 if (argc < 2)
428 return ERROR;
430 /* reverse compatibility for very old non-POSIX usage forms */
431 for (c = 1; c < argc; c++) {
432 if (strcmp ("-to", argv[c]) == 0)
433 strcpy (argv[c], "-t");
434 if (strcmp ("-wv", argv[c]) == 0)
435 strcpy (argv[c], "-w");
436 if (strcmp ("-cv", argv[c]) == 0)
437 strcpy (argv[c], "-c");
438 }
440 while (1) {
441 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:",
442 longopts, &option);
444 if (c == -1 || c == EOF)
445 break;
447 switch (c) {
448 case '?': /* usage */
449 usage5 ();
450 case 'h': /* help */
451 print_help ();
452 exit (STATE_OK);
453 case 'V': /* version */
454 print_revision (progname, NP_VERSION);
455 exit (STATE_OK);
456 case 'v': /* verbose */
457 verbose++;
458 break;
460 /* Connection info */
461 case 'C': /* group or community */
462 community = optarg;
463 break;
464 case 'H': /* Host or server */
465 server_address = optarg;
466 break;
467 case 'p': /* TCP port number */
468 port = optarg;
469 break;
470 case 'm': /* List of MIBS */
471 miblist = optarg;
472 break;
473 case 'n': /* usesnmpgetnext */
474 usesnmpgetnext = TRUE;
475 break;
476 case 'P': /* SNMP protocol version */
477 proto = optarg;
478 break;
479 case 'L': /* security level */
480 seclevel = optarg;
481 break;
482 case 'U': /* security username */
483 secname = optarg;
484 break;
485 case 'a': /* auth protocol */
486 authproto = optarg;
487 break;
488 case 'x': /* priv protocol */
489 privproto = optarg;
490 break;
491 case 'A': /* auth passwd */
492 authpasswd = optarg;
493 break;
494 case 'X': /* priv passwd */
495 privpasswd = optarg;
496 break;
497 case 't': /* timeout period */
498 if (!is_integer (optarg))
499 usage2 (_("Timeout interval must be a positive integer"), optarg);
500 else
501 timeout_interval = atoi (optarg);
502 break;
504 /* Test parameters */
505 case 'c': /* critical threshold */
506 critical_thresholds = optarg;
507 break;
508 case 'w': /* warning threshold */
509 warning_thresholds = optarg;
510 break;
511 case 'e': /* PRELIMINARY - may change */
512 case 'E': /* PRELIMINARY - may change */
513 if (!is_integer (optarg))
514 usage2 (_("Retries interval must be a positive integer"), optarg);
515 else
516 retries = atoi(optarg);
517 break;
518 case 'o': /* object identifier */
519 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
520 /*
521 * we have something other than digits, periods and comas,
522 * so we have a mib variable, rather than just an SNMP OID,
523 * so we have to actually read the mib files
524 */
525 needmibs = TRUE;
526 }
527 if (!oids) oids = calloc(MAX_OIDS, sizeof (char *));
528 for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
529 oids[j] = strdup(ptr);
530 }
531 numoids = j;
532 if (c == 'E' || c == 'e') {
533 jj++;
534 ii++;
535 }
536 if (c == 'E')
537 eval_method[j+1] |= WARN_PRESENT;
538 else if (c == 'e')
539 eval_method[j+1] |= CRIT_PRESENT;
540 break;
541 case 's': /* string or substring */
542 strncpy (string_value, optarg, sizeof (string_value) - 1);
543 string_value[sizeof (string_value) - 1] = 0;
544 eval_method[jj++] = CRIT_STRING;
545 ii++;
546 break;
547 case 'R': /* regex */
548 cflags = REG_ICASE;
549 case 'r': /* regex */
550 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
551 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
552 regex_expect[sizeof (regex_expect) - 1] = 0;
553 errcode = regcomp (&preg, regex_expect, cflags);
554 if (errcode != 0) {
555 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
556 printf (_("Could Not Compile Regular Expression"));
557 return ERROR;
558 }
559 eval_method[jj++] = CRIT_REGEX;
560 ii++;
561 break;
563 /* Format */
564 case 'd': /* delimiter */
565 delimiter = strscpy (delimiter, optarg);
566 break;
567 case 'D': /* output-delimiter */
568 output_delim = strscpy (output_delim, optarg);
569 break;
570 case 'l': /* label */
571 label = optarg;
572 nlabels++;
573 if (nlabels >= labels_size) {
574 labels_size += 8;
575 labels = realloc (labels, labels_size);
576 if (labels == NULL)
577 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
578 }
579 labels[nlabels - 1] = optarg;
580 ptr = thisarg (optarg);
581 labels[nlabels - 1] = ptr;
582 if (strstr (ptr, "'") == ptr)
583 labels[nlabels - 1] = ptr + 1;
584 while (ptr && (ptr = nextarg (ptr))) {
585 if (nlabels >= labels_size) {
586 labels_size += 8;
587 labels = realloc (labels, labels_size);
588 if (labels == NULL)
589 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
590 }
591 labels++;
592 ptr = thisarg (ptr);
593 if (strstr (ptr, "'") == ptr)
594 labels[nlabels - 1] = ptr + 1;
595 else
596 labels[nlabels - 1] = ptr;
597 }
598 break;
599 case 'u': /* units */
600 units = optarg;
601 nunits++;
602 if (nunits >= unitv_size) {
603 unitv_size += 8;
604 unitv = realloc (unitv, unitv_size);
605 if (unitv == NULL)
606 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
607 }
608 unitv[nunits - 1] = optarg;
609 ptr = thisarg (optarg);
610 unitv[nunits - 1] = ptr;
611 if (strstr (ptr, "'") == ptr)
612 unitv[nunits - 1] = ptr + 1;
613 while (ptr && (ptr = nextarg (ptr))) {
614 if (nunits >= unitv_size) {
615 unitv_size += 8;
616 unitv = realloc (unitv, unitv_size);
617 if (units == NULL)
618 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
619 }
620 nunits++;
621 ptr = thisarg (ptr);
622 if (strstr (ptr, "'") == ptr)
623 unitv[nunits - 1] = ptr + 1;
624 else
625 unitv[nunits - 1] = ptr;
626 }
627 break;
629 }
630 }
632 if (server_address == NULL)
633 server_address = argv[optind];
635 if (community == NULL)
636 community = strdup (DEFAULT_COMMUNITY);
638 return validate_arguments ();
639 }
642 /******************************************************************************
644 @@-
645 <sect3>
646 <title>validate_arguments</title>
648 <para>&PROTO_validate_arguments;</para>
650 <para>Checks to see if the default miblist needs to be loaded. Also verifies
651 the authentication and authorization combinations based on protocol version
652 selected.</para>
654 <para></para>
656 </sect3>
657 -@@
658 ******************************************************************************/
662 int
663 validate_arguments ()
664 {
665 /* check whether to load locally installed MIBS (CPU/disk intensive) */
666 if (miblist == NULL) {
667 if ( needmibs == TRUE ) {
668 miblist = strdup (DEFAULT_MIBLIST);
669 }else{
670 miblist = ""; /* don't read any mib files for numeric oids */
671 }
672 }
674 /* Check server_address is given */
675 if (server_address == NULL)
676 die(STATE_UNKNOWN, _("No host specified\n"));
678 /* Check oid is given */
679 if (numoids == 0)
680 die(STATE_UNKNOWN, _("No OIDs specified\n"));
682 if (proto == NULL)
683 asprintf(&proto, DEFAULT_PROTOCOL);
685 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */
686 numauthpriv = 2;
687 authpriv = calloc (numauthpriv, sizeof (char *));
688 authpriv[0] = strdup ("-c");
689 authpriv[1] = strdup (community);
690 }
691 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
692 if (seclevel == NULL)
693 asprintf(&seclevel, "noAuthNoPriv");
695 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
696 numauthpriv = 2;
697 authpriv = calloc (numauthpriv, sizeof (char *));
698 authpriv[0] = strdup ("-l");
699 authpriv[1] = strdup ("noAuthNoPriv");
700 } else {
701 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
702 usage2 (_("Invalid seclevel"), seclevel);
703 }
705 if (authproto == NULL )
706 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
708 if (secname == NULL)
709 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
711 if (authpasswd == NULL)
712 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
714 if ( strcmp(seclevel, "authNoPriv") == 0 ) {
715 numauthpriv = 8;
716 authpriv = calloc (numauthpriv, sizeof (char *));
717 authpriv[0] = strdup ("-l");
718 authpriv[1] = strdup ("authNoPriv");
719 authpriv[2] = strdup ("-a");
720 authpriv[3] = strdup (authproto);
721 authpriv[4] = strdup ("-u");
722 authpriv[5] = strdup (secname);
723 authpriv[6] = strdup ("-A");
724 authpriv[7] = strdup (authpasswd);
725 } else if ( strcmp(seclevel, "authPriv") == 0 ) {
726 if (privproto == NULL )
727 asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
729 if (privpasswd == NULL)
730 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
732 numauthpriv = 12;
733 authpriv = calloc (numauthpriv, sizeof (char *));
734 authpriv[0] = strdup ("-l");
735 authpriv[1] = strdup ("authPriv");
736 authpriv[2] = strdup ("-a");
737 authpriv[3] = strdup (authproto);
738 authpriv[4] = strdup ("-u");
739 authpriv[5] = strdup (secname);
740 authpriv[6] = strdup ("-A");
741 authpriv[7] = strdup (authpasswd);
742 authpriv[8] = strdup ("-x");
743 authpriv[9] = strdup (privproto);
744 authpriv[10] = strdup ("-X");
745 authpriv[11] = strdup (privpasswd);
746 }
747 }
749 }
750 else {
751 usage2 (_("Invalid SNMP version"), proto);
752 }
754 return OK;
755 }
759 /* trim leading whitespace
760 if there is a leading quote, make sure it balances */
762 char *
763 thisarg (char *str)
764 {
765 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
766 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
767 if (strlen (str) == 1 || !strstr (str + 1, "'"))
768 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
769 }
770 return str;
771 }
775 /* if there's a leading quote, advance to the trailing quote
776 set the trailing quote to '\x0'
777 if the string continues, advance beyond the comma */
779 char *
780 nextarg (char *str)
781 {
782 if (strstr (str, "'") == str) {
783 str[0] = 0;
784 if (strlen (str) > 1) {
785 str = strstr (str + 1, "'");
786 return (++str);
787 }
788 else {
789 return NULL;
790 }
791 }
792 if (strstr (str, ",") == str) {
793 str[0] = 0;
794 if (strlen (str) > 1) {
795 return (++str);
796 }
797 else {
798 return NULL;
799 }
800 }
801 if ((str = strstr (str, ",")) && strlen (str) > 1) {
802 str[0] = 0;
803 return (++str);
804 }
805 return NULL;
806 }
810 void
811 print_help (void)
812 {
813 print_revision (progname, NP_VERSION);
815 printf (COPYRIGHT, copyright, email);
817 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
819 printf ("\n\n");
821 print_usage ();
823 printf (UT_HELP_VRSN);
824 printf (UT_EXTRA_OPTS);
826 printf (UT_HOST_PORT, 'p', DEFAULT_PORT);
828 /* SNMP and Authentication Protocol */
829 printf (" %s\n", "-n, --next");
830 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
831 printf (" %s\n", "-P, --protocol=[1|2c|3]");
832 printf (" %s\n", _("SNMP protocol version"));
833 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
834 printf (" %s\n", _("SNMPv3 securityLevel"));
835 printf (" %s\n", "-a, --authproto=[MD5|SHA]");
836 printf (" %s\n", _("SNMPv3 auth proto"));
837 printf (" %s\n", "-x, --privproto=[DES|AES]");
838 printf (" %s\n", _("SNMPv3 priv proto (default DES)"));
840 /* Authentication Tokens*/
841 printf (" %s\n", "-C, --community=STRING");
842 printf (" %s ", _("Optional community string for SNMP communication"));
843 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
844 printf (" %s\n", "-U, --secname=USERNAME");
845 printf (" %s\n", _("SNMPv3 username"));
846 printf (" %s\n", "-A, --authpassword=PASSWORD");
847 printf (" %s\n", _("SNMPv3 authentication password"));
848 printf (" %s\n", "-X, --privpasswd=PASSWORD");
849 printf (" %s\n", _("SNMPv3 privacy password"));
851 /* OID Stuff */
852 printf (" %s\n", "-o, --oid=OID(s)");
853 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
854 printf (" %s\n", "-m, --miblist=STRING");
855 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
856 printf (" %s\n", _("for symbolic OIDs.)"));
857 printf (" %s\n", "-d, --delimiter=STRING");
858 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
859 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
860 printf (" %s\n", _("to be the data that should be used in the evaluation."));
862 /* Tests Against Integers */
863 printf (" %s\n", "-w, --warning=THRESHOLD(s)");
864 printf (" %s\n", _("Warning threshold range(s)"));
865 printf (" %s\n", "-c, --critical=THRESHOLD(s)");
866 printf (" %s\n", _("Critical threshold range(s)"));
868 /* Tests Against Strings */
869 printf (" %s\n", "-s, --string=STRING");
870 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
871 printf (" %s\n", "-r, --ereg=REGEX");
872 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
873 printf (" %s\n", "-R, --eregi=REGEX");
874 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
875 printf (" %s\n", "-l, --label=STRING");
876 printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
878 /* Output Formatting */
879 printf (" %s\n", "-u, --units=STRING");
880 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
881 printf (" %s\n", "-D, --output-delimiter=STRING");
882 printf (" %s\n", _("Separates output on multiple OID requests"));
884 printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
885 printf (" %s\n", "-e, --retries=INTEGER");
886 printf (" %s\n", _("Number of retries to be used in the requests"));
888 printf (UT_VERBOSE);
890 printf ("\n");
891 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
892 printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
893 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
895 printf ("\n");
896 printf ("%s\n", _("Notes:"));
897 printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
898 printf (" %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
900 printf(" -%s", UT_THRESHOLDS_NOTES);
902 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
903 printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
904 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
905 printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
906 #ifdef NP_EXTRA_OPTS
907 printf (" -%s", UT_EXTRA_OPTS_NOTES);
908 #endif
910 printf (UT_SUPPORT);
911 }
915 void
916 print_usage (void)
917 {
918 printf (_("Usage:"));
919 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
920 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
921 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
922 printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
923 printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");
924 }