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;
121 int iresult = STATE_UNKNOWN;
122 int result = STATE_UNKNOWN;
123 int return_code = 0;
124 int external_error = 0;
125 double perftmp;
126 char **command_line = NULL;
127 char *cl_hidden_auth = NULL;
128 char *oidname = NULL;
129 char *response = 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 (i = 0; i < chld_out.lines; i++) {
254 const char *conv = "%.0f";
256 ptr = chld_out.line[i];
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 }
288 else if (strstr (response, "Timeticks: "))
289 show = strstr (response, "Timeticks: ");
290 else
291 show = response;
293 iresult = STATE_DEPENDENT;
295 /* Process this block for integer comparisons */
296 if (thlds[i]->warning || thlds[i]->critical) {
297 ptr = strpbrk (show, "0123456789");
298 if (ptr == NULL)
299 die (STATE_UNKNOWN,_("No valid data returned"));
300 response_value[i] = strtod (ptr, NULL);
301 iresult = get_status(response_value[i], thlds[i]);
302 asprintf (&show, conv, response_value[i]);
303 }
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;
311 }
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;
318 }
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);
323 }
324 else {
325 iresult = STATE_CRITICAL;
326 }
327 }
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;
337 }
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 /* Try a two-way conversion of show and add perfdata only if we get
356 * something back at the end */
357 ptr = NULL;
358 perftmp = strtod(show, &ptr);
359 if (ptr != show) {
360 ptr = NULL;
361 asprintf(&ptr, "%0.9g", perftmp);
362 strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
363 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
364 strncat(perfstr, ptr, sizeof(perfstr)-strlen(perfstr)-1);
365 free(ptr);
367 if (type)
368 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
369 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
370 }
371 }
373 printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
375 return result;
376 }
380 /* process command-line arguments */
381 int
382 process_arguments (int argc, char **argv)
383 {
384 char *ptr;
385 int c = 1;
386 int j = 0, jj = 0, ii = 0;
388 int option = 0;
389 static struct option longopts[] = {
390 STD_LONG_OPTS,
391 {"community", required_argument, 0, 'C'},
392 {"oid", required_argument, 0, 'o'},
393 {"object", required_argument, 0, 'o'},
394 {"delimiter", required_argument, 0, 'd'},
395 {"output-delimiter", required_argument, 0, 'D'},
396 {"string", required_argument, 0, 's'},
397 {"timeout", required_argument, 0, 't'},
398 {"regex", required_argument, 0, 'r'},
399 {"ereg", required_argument, 0, 'r'},
400 {"eregi", required_argument, 0, 'R'},
401 {"label", required_argument, 0, 'l'},
402 {"units", required_argument, 0, 'u'},
403 {"port", required_argument, 0, 'p'},
404 {"retries", required_argument, 0, 'e'},
405 {"miblist", required_argument, 0, 'm'},
406 {"protocol", required_argument, 0, 'P'},
407 {"seclevel", required_argument, 0, 'L'},
408 {"secname", required_argument, 0, 'U'},
409 {"authproto", required_argument, 0, 'a'},
410 {"privproto", required_argument, 0, 'x'},
411 {"authpasswd", required_argument, 0, 'A'},
412 {"privpasswd", required_argument, 0, 'X'},
413 {"next", no_argument, 0, 'n'},
414 {0, 0, 0, 0}
415 };
417 if (argc < 2)
418 return ERROR;
420 /* reverse compatibility for very old non-POSIX usage forms */
421 for (c = 1; c < argc; c++) {
422 if (strcmp ("-to", argv[c]) == 0)
423 strcpy (argv[c], "-t");
424 if (strcmp ("-wv", argv[c]) == 0)
425 strcpy (argv[c], "-w");
426 if (strcmp ("-cv", argv[c]) == 0)
427 strcpy (argv[c], "-c");
428 }
430 while (1) {
431 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:",
432 longopts, &option);
434 if (c == -1 || c == EOF)
435 break;
437 switch (c) {
438 case '?': /* usage */
439 usage5 ();
440 case 'h': /* help */
441 print_help ();
442 exit (STATE_OK);
443 case 'V': /* version */
444 print_revision (progname, NP_VERSION);
445 exit (STATE_OK);
446 case 'v': /* verbose */
447 verbose++;
448 break;
450 /* Connection info */
451 case 'C': /* group or community */
452 community = optarg;
453 break;
454 case 'H': /* Host or server */
455 server_address = optarg;
456 break;
457 case 'p': /* TCP port number */
458 port = optarg;
459 break;
460 case 'm': /* List of MIBS */
461 miblist = optarg;
462 break;
463 case 'n': /* usesnmpgetnext */
464 usesnmpgetnext = TRUE;
465 break;
466 case 'P': /* SNMP protocol version */
467 proto = optarg;
468 break;
469 case 'L': /* security level */
470 seclevel = optarg;
471 break;
472 case 'U': /* security username */
473 secname = optarg;
474 break;
475 case 'a': /* auth protocol */
476 authproto = optarg;
477 break;
478 case 'x': /* priv protocol */
479 privproto = optarg;
480 break;
481 case 'A': /* auth passwd */
482 authpasswd = optarg;
483 break;
484 case 'X': /* priv passwd */
485 privpasswd = optarg;
486 break;
487 case 't': /* timeout period */
488 if (!is_integer (optarg))
489 usage2 (_("Timeout interval must be a positive integer"), optarg);
490 else
491 timeout_interval = atoi (optarg);
492 break;
494 /* Test parameters */
495 case 'c': /* critical threshold */
496 critical_thresholds = optarg;
497 break;
498 case 'w': /* warning threshold */
499 warning_thresholds = optarg;
500 break;
501 case 'e': /* PRELIMINARY - may change */
502 case 'E': /* PRELIMINARY - may change */
503 if (!is_integer (optarg))
504 usage2 (_("Retries interval must be a positive integer"), optarg);
505 else
506 retries = atoi(optarg);
507 break;
508 case 'o': /* object identifier */
509 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
510 /*
511 * we have something other than digits, periods and comas,
512 * so we have a mib variable, rather than just an SNMP OID,
513 * so we have to actually read the mib files
514 */
515 needmibs = TRUE;
516 }
517 if (!oids) oids = calloc(MAX_OIDS, sizeof (char *));
518 for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
519 oids[j] = strdup(ptr);
520 }
521 numoids = j;
522 if (c == 'E' || c == 'e') {
523 jj++;
524 ii++;
525 }
526 if (c == 'E')
527 eval_method[j+1] |= WARN_PRESENT;
528 else if (c == 'e')
529 eval_method[j+1] |= CRIT_PRESENT;
530 break;
531 case 's': /* string or substring */
532 strncpy (string_value, optarg, sizeof (string_value) - 1);
533 string_value[sizeof (string_value) - 1] = 0;
534 eval_method[jj++] = CRIT_STRING;
535 ii++;
536 break;
537 case 'R': /* regex */
538 cflags = REG_ICASE;
539 case 'r': /* regex */
540 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
541 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
542 regex_expect[sizeof (regex_expect) - 1] = 0;
543 errcode = regcomp (&preg, regex_expect, cflags);
544 if (errcode != 0) {
545 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
546 printf (_("Could Not Compile Regular Expression"));
547 return ERROR;
548 }
549 eval_method[jj++] = CRIT_REGEX;
550 ii++;
551 break;
553 /* Format */
554 case 'd': /* delimiter */
555 delimiter = strscpy (delimiter, optarg);
556 break;
557 case 'D': /* output-delimiter */
558 output_delim = strscpy (output_delim, optarg);
559 break;
560 case 'l': /* label */
561 label = optarg;
562 nlabels++;
563 if (nlabels >= labels_size) {
564 labels_size += 8;
565 labels = realloc (labels, labels_size);
566 if (labels == NULL)
567 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
568 }
569 labels[nlabels - 1] = optarg;
570 ptr = thisarg (optarg);
571 labels[nlabels - 1] = ptr;
572 if (strstr (ptr, "'") == ptr)
573 labels[nlabels - 1] = ptr + 1;
574 while (ptr && (ptr = nextarg (ptr))) {
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\n"));
580 }
581 labels++;
582 ptr = thisarg (ptr);
583 if (strstr (ptr, "'") == ptr)
584 labels[nlabels - 1] = ptr + 1;
585 else
586 labels[nlabels - 1] = ptr;
587 }
588 break;
589 case 'u': /* units */
590 units = optarg;
591 nunits++;
592 if (nunits >= unitv_size) {
593 unitv_size += 8;
594 unitv = realloc (unitv, unitv_size);
595 if (unitv == NULL)
596 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
597 }
598 unitv[nunits - 1] = optarg;
599 ptr = thisarg (optarg);
600 unitv[nunits - 1] = ptr;
601 if (strstr (ptr, "'") == ptr)
602 unitv[nunits - 1] = ptr + 1;
603 while (ptr && (ptr = nextarg (ptr))) {
604 if (nunits >= unitv_size) {
605 unitv_size += 8;
606 unitv = realloc (unitv, unitv_size);
607 if (units == NULL)
608 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
609 }
610 nunits++;
611 ptr = thisarg (ptr);
612 if (strstr (ptr, "'") == ptr)
613 unitv[nunits - 1] = ptr + 1;
614 else
615 unitv[nunits - 1] = ptr;
616 }
617 break;
619 }
620 }
622 if (server_address == NULL)
623 server_address = argv[optind];
625 if (community == NULL)
626 community = strdup (DEFAULT_COMMUNITY);
628 return validate_arguments ();
629 }
632 /******************************************************************************
634 @@-
635 <sect3>
636 <title>validate_arguments</title>
638 <para>&PROTO_validate_arguments;</para>
640 <para>Checks to see if the default miblist needs to be loaded. Also verifies
641 the authentication and authorization combinations based on protocol version
642 selected.</para>
644 <para></para>
646 </sect3>
647 -@@
648 ******************************************************************************/
652 int
653 validate_arguments ()
654 {
655 /* check whether to load locally installed MIBS (CPU/disk intensive) */
656 if (miblist == NULL) {
657 if ( needmibs == TRUE ) {
658 miblist = strdup (DEFAULT_MIBLIST);
659 }else{
660 miblist = ""; /* don't read any mib files for numeric oids */
661 }
662 }
664 /* Check server_address is given */
665 if (server_address == NULL)
666 die(STATE_UNKNOWN, _("No host specified\n"));
668 /* Check oid is given */
669 if (numoids == 0)
670 die(STATE_UNKNOWN, _("No OIDs specified\n"));
672 if (proto == NULL)
673 asprintf(&proto, DEFAULT_PROTOCOL);
675 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */
676 numauthpriv = 2;
677 authpriv = calloc (numauthpriv, sizeof (char *));
678 authpriv[0] = strdup ("-c");
679 authpriv[1] = strdup (community);
680 }
681 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
682 if (seclevel == NULL)
683 asprintf(&seclevel, "noAuthNoPriv");
685 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
686 numauthpriv = 2;
687 authpriv = calloc (numauthpriv, sizeof (char *));
688 authpriv[0] = strdup ("-l");
689 authpriv[1] = strdup ("noAuthNoPriv");
690 } else {
691 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
692 usage2 (_("Invalid seclevel"), seclevel);
693 }
695 if (authproto == NULL )
696 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
698 if (secname == NULL)
699 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
701 if (authpasswd == NULL)
702 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
704 if ( strcmp(seclevel, "authNoPriv") == 0 ) {
705 numauthpriv = 8;
706 authpriv = calloc (numauthpriv, sizeof (char *));
707 authpriv[0] = strdup ("-l");
708 authpriv[1] = strdup ("authNoPriv");
709 authpriv[2] = strdup ("-a");
710 authpriv[3] = strdup (authproto);
711 authpriv[4] = strdup ("-u");
712 authpriv[5] = strdup (secname);
713 authpriv[6] = strdup ("-A");
714 authpriv[7] = strdup (authpasswd);
715 } else if ( strcmp(seclevel, "authPriv") == 0 ) {
716 if (privproto == NULL )
717 asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
719 if (privpasswd == NULL)
720 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
722 numauthpriv = 12;
723 authpriv = calloc (numauthpriv, sizeof (char *));
724 authpriv[0] = strdup ("-l");
725 authpriv[1] = strdup ("authPriv");
726 authpriv[2] = strdup ("-a");
727 authpriv[3] = strdup (authproto);
728 authpriv[4] = strdup ("-u");
729 authpriv[5] = strdup (secname);
730 authpriv[6] = strdup ("-A");
731 authpriv[7] = strdup (authpasswd);
732 authpriv[8] = strdup ("-x");
733 authpriv[9] = strdup (privproto);
734 authpriv[10] = strdup ("-X");
735 authpriv[11] = strdup (privpasswd);
736 }
737 }
739 }
740 else {
741 usage2 (_("Invalid SNMP version"), proto);
742 }
744 return OK;
745 }
749 /* trim leading whitespace
750 if there is a leading quote, make sure it balances */
752 char *
753 thisarg (char *str)
754 {
755 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
756 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
757 if (strlen (str) == 1 || !strstr (str + 1, "'"))
758 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
759 }
760 return str;
761 }
765 /* if there's a leading quote, advance to the trailing quote
766 set the trailing quote to '\x0'
767 if the string continues, advance beyond the comma */
769 char *
770 nextarg (char *str)
771 {
772 if (strstr (str, "'") == str) {
773 str[0] = 0;
774 if (strlen (str) > 1) {
775 str = strstr (str + 1, "'");
776 return (++str);
777 }
778 else {
779 return NULL;
780 }
781 }
782 if (strstr (str, ",") == str) {
783 str[0] = 0;
784 if (strlen (str) > 1) {
785 return (++str);
786 }
787 else {
788 return NULL;
789 }
790 }
791 if ((str = strstr (str, ",")) && strlen (str) > 1) {
792 str[0] = 0;
793 return (++str);
794 }
795 return NULL;
796 }
800 void
801 print_help (void)
802 {
803 print_revision (progname, NP_VERSION);
805 printf (COPYRIGHT, copyright, email);
807 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
809 printf ("\n\n");
811 print_usage ();
813 printf (_(UT_HELP_VRSN));
814 printf (_(UT_EXTRA_OPTS));
816 printf (_(UT_HOST_PORT), 'p', DEFAULT_PORT);
818 /* SNMP and Authentication Protocol */
819 printf (" %s\n", "-n, --next");
820 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
821 printf (" %s\n", "-P, --protocol=[1|2c|3]");
822 printf (" %s\n", _("SNMP protocol version"));
823 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
824 printf (" %s\n", _("SNMPv3 securityLevel"));
825 printf (" %s\n", "-a, --authproto=[MD5|SHA]");
826 printf (" %s\n", _("SNMPv3 auth proto"));
827 printf (" %s\n", "-x, --privproto=[DES|AES]");
828 printf (" %s\n", _("SNMPv3 priv proto (default DES)"));
830 /* Authentication Tokens*/
831 printf (" %s\n", "-C, --community=STRING");
832 printf (" %s ", _("Optional community string for SNMP communication"));
833 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
834 printf (" %s\n", "-U, --secname=USERNAME");
835 printf (" %s\n", _("SNMPv3 username"));
836 printf (" %s\n", "-A, --authpassword=PASSWORD");
837 printf (" %s\n", _("SNMPv3 authentication password"));
838 printf (" %s\n", "-X, --privpasswd=PASSWORD");
839 printf (" %s\n", _("SNMPv3 privacy password"));
841 /* OID Stuff */
842 printf (" %s\n", "-o, --oid=OID(s)");
843 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
844 printf (" %s\n", "-m, --miblist=STRING");
845 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
846 printf (" %s\n", _("for symbolic OIDs.)"));
847 printf (" %s\n", "-d, --delimiter=STRING");
848 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
849 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
850 printf (" %s\n", _("to be the data that should be used in the evaluation."));
852 /* Tests Against Integers */
853 printf (" %s\n", "-w, --warning=THRESHOLD(s)");
854 printf (" %s\n", _("Warning threshold range(s)"));
855 printf (" %s\n", "-c, --critical=THRESHOLD(s)");
856 printf (" %s\n", _("Critical threshold range(s)"));
858 /* Tests Against Strings */
859 printf (" %s\n", "-s, --string=STRING");
860 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
861 printf (" %s\n", "-r, --ereg=REGEX");
862 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
863 printf (" %s\n", "-R, --eregi=REGEX");
864 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
865 printf (" %s\n", "-l, --label=STRING");
866 printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
868 /* Output Formatting */
869 printf (" %s\n", "-u, --units=STRING");
870 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
871 printf (" %s\n", "-D, --output-delimiter=STRING");
872 printf (" %s\n", _("Separates output on multiple OID requests"));
874 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
875 printf (" %s\n", "-e, --retries=INTEGER");
876 printf (" %s\n", _("Number of retries to be used in the requests"));
878 printf (_(UT_VERBOSE));
880 printf ("\n");
881 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
882 printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
883 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
885 printf ("\n");
886 printf ("%s\n", _("Notes:"));
887 printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
888 printf (" %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
890 printf(" -%s", _(UT_THRESHOLDS_NOTES));
892 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
893 printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
894 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
895 printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
896 #ifdef NP_EXTRA_OPTS
897 printf (" -%s", _(UT_EXTRA_OPTS_NOTES));
898 #endif
900 printf (_(UT_SUPPORT));
901 }
905 void
906 print_usage (void)
907 {
908 printf (_("Usage:"));
909 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
910 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
911 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
912 printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
913 printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");
914 }