Fix segfault in check_snmp (definitive fix is still in the works - see bug #2832451)
[monitoring-plugins.git] / plugins / check_snmp.c
blobdb16462bec5e20e7a53abbfc05c8bf4d32e21cb9
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 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;
118 main (int argc, char **argv)
120 int i;
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);
176 if (c) {
177 th_crit=strchr(th_crit, ',');
178 if (th_crit) th_crit++;
179 free(c);
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);
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];
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]);
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
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]);
240 } else {
241 printf(_("External command error with no output (return code: %d)\n"), return_code);
243 exit (STATE_UNKNOWN);
246 if (verbose) {
247 for (i = 0; i < chld_out.lines; i++) {
248 printf ("%s\n", chld_out.line[i]);
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);
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");
277 else if (strstr (response, "Counter64: ")) {
278 show = strstr (response, "Counter64: ") + 11;
279 strcpy(type, "c");
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";
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]);
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;
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;
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);
323 else {
324 iresult = STATE_CRITICAL;
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;
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 if (is_numeric(show)) {
355 strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
356 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
357 strncat(perfstr, show, sizeof(perfstr)-strlen(perfstr)-1);
359 if (type)
360 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
361 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
365 printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
367 return result;
372 /* process command-line arguments */
374 process_arguments (int argc, char **argv)
376 char *ptr;
377 int c = 1;
378 int j = 0, jj = 0, ii = 0;
380 int option = 0;
381 static struct option longopts[] = {
382 STD_LONG_OPTS,
383 {"community", required_argument, 0, 'C'},
384 {"oid", required_argument, 0, 'o'},
385 {"object", required_argument, 0, 'o'},
386 {"delimiter", required_argument, 0, 'd'},
387 {"output-delimiter", required_argument, 0, 'D'},
388 {"string", required_argument, 0, 's'},
389 {"timeout", required_argument, 0, 't'},
390 {"regex", required_argument, 0, 'r'},
391 {"ereg", required_argument, 0, 'r'},
392 {"eregi", required_argument, 0, 'R'},
393 {"label", required_argument, 0, 'l'},
394 {"units", required_argument, 0, 'u'},
395 {"port", required_argument, 0, 'p'},
396 {"retries", required_argument, 0, 'e'},
397 {"miblist", required_argument, 0, 'm'},
398 {"protocol", required_argument, 0, 'P'},
399 {"seclevel", required_argument, 0, 'L'},
400 {"secname", required_argument, 0, 'U'},
401 {"authproto", required_argument, 0, 'a'},
402 {"privproto", required_argument, 0, 'x'},
403 {"authpasswd", required_argument, 0, 'A'},
404 {"privpasswd", required_argument, 0, 'X'},
405 {"next", no_argument, 0, 'n'},
406 {0, 0, 0, 0}
409 if (argc < 2)
410 return ERROR;
412 /* reverse compatibility for very old non-POSIX usage forms */
413 for (c = 1; c < argc; c++) {
414 if (strcmp ("-to", argv[c]) == 0)
415 strcpy (argv[c], "-t");
416 if (strcmp ("-wv", argv[c]) == 0)
417 strcpy (argv[c], "-w");
418 if (strcmp ("-cv", argv[c]) == 0)
419 strcpy (argv[c], "-c");
422 while (1) {
423 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:",
424 longopts, &option);
426 if (c == -1 || c == EOF)
427 break;
429 switch (c) {
430 case '?': /* usage */
431 usage5 ();
432 case 'h': /* help */
433 print_help ();
434 exit (STATE_OK);
435 case 'V': /* version */
436 print_revision (progname, NP_VERSION);
437 exit (STATE_OK);
438 case 'v': /* verbose */
439 verbose++;
440 break;
442 /* Connection info */
443 case 'C': /* group or community */
444 community = optarg;
445 break;
446 case 'H': /* Host or server */
447 server_address = optarg;
448 break;
449 case 'p': /* TCP port number */
450 port = optarg;
451 break;
452 case 'm': /* List of MIBS */
453 miblist = optarg;
454 break;
455 case 'n': /* usesnmpgetnext */
456 usesnmpgetnext = TRUE;
457 break;
458 case 'P': /* SNMP protocol version */
459 proto = optarg;
460 break;
461 case 'L': /* security level */
462 seclevel = optarg;
463 break;
464 case 'U': /* security username */
465 secname = optarg;
466 break;
467 case 'a': /* auth protocol */
468 authproto = optarg;
469 break;
470 case 'x': /* priv protocol */
471 privproto = optarg;
472 break;
473 case 'A': /* auth passwd */
474 authpasswd = optarg;
475 break;
476 case 'X': /* priv passwd */
477 privpasswd = optarg;
478 break;
479 case 't': /* timeout period */
480 if (!is_integer (optarg))
481 usage2 (_("Timeout interval must be a positive integer"), optarg);
482 else
483 timeout_interval = atoi (optarg);
484 break;
486 /* Test parameters */
487 case 'c': /* critical threshold */
488 critical_thresholds = optarg;
489 break;
490 case 'w': /* warning threshold */
491 warning_thresholds = optarg;
492 break;
493 case 'e': /* PRELIMINARY - may change */
494 case 'E': /* PRELIMINARY - may change */
495 if (!is_integer (optarg))
496 usage2 (_("Retries interval must be a positive integer"), optarg);
497 else
498 retries = atoi(optarg);
499 break;
500 case 'o': /* object identifier */
501 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
503 * we have something other than digits, periods and comas,
504 * so we have a mib variable, rather than just an SNMP OID,
505 * so we have to actually read the mib files
507 needmibs = TRUE;
509 oids = calloc(MAX_OIDS, sizeof (char *));
510 for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
511 oids[j] = strdup(ptr);
513 numoids = j;
514 if (c == 'E' || c == 'e') {
515 jj++;
516 ii++;
518 if (c == 'E')
519 eval_method[j+1] |= WARN_PRESENT;
520 else if (c == 'e')
521 eval_method[j+1] |= CRIT_PRESENT;
522 break;
523 case 's': /* string or substring */
524 strncpy (string_value, optarg, sizeof (string_value) - 1);
525 string_value[sizeof (string_value) - 1] = 0;
526 eval_method[jj++] = CRIT_STRING;
527 ii++;
528 break;
529 case 'R': /* regex */
530 cflags = REG_ICASE;
531 case 'r': /* regex */
532 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
533 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
534 regex_expect[sizeof (regex_expect) - 1] = 0;
535 errcode = regcomp (&preg, regex_expect, cflags);
536 if (errcode != 0) {
537 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
538 printf (_("Could Not Compile Regular Expression"));
539 return ERROR;
541 eval_method[jj++] = CRIT_REGEX;
542 ii++;
543 break;
545 /* Format */
546 case 'd': /* delimiter */
547 delimiter = strscpy (delimiter, optarg);
548 break;
549 case 'D': /* output-delimiter */
550 output_delim = strscpy (output_delim, optarg);
551 break;
552 case 'l': /* label */
553 label = optarg;
554 nlabels++;
555 if (nlabels >= labels_size) {
556 labels_size += 8;
557 labels = realloc (labels, labels_size);
558 if (labels == NULL)
559 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
561 labels[nlabels - 1] = optarg;
562 ptr = thisarg (optarg);
563 labels[nlabels - 1] = ptr;
564 if (strstr (ptr, "'") == ptr)
565 labels[nlabels - 1] = ptr + 1;
566 while (ptr && (ptr = nextarg (ptr))) {
567 if (nlabels >= labels_size) {
568 labels_size += 8;
569 labels = realloc (labels, labels_size);
570 if (labels == NULL)
571 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
573 labels++;
574 ptr = thisarg (ptr);
575 if (strstr (ptr, "'") == ptr)
576 labels[nlabels - 1] = ptr + 1;
577 else
578 labels[nlabels - 1] = ptr;
580 break;
581 case 'u': /* units */
582 units = optarg;
583 nunits++;
584 if (nunits >= unitv_size) {
585 unitv_size += 8;
586 unitv = realloc (unitv, unitv_size);
587 if (unitv == NULL)
588 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
590 unitv[nunits - 1] = optarg;
591 ptr = thisarg (optarg);
592 unitv[nunits - 1] = ptr;
593 if (strstr (ptr, "'") == ptr)
594 unitv[nunits - 1] = ptr + 1;
595 while (ptr && (ptr = nextarg (ptr))) {
596 if (nunits >= unitv_size) {
597 unitv_size += 8;
598 unitv = realloc (unitv, unitv_size);
599 if (units == NULL)
600 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
602 nunits++;
603 ptr = thisarg (ptr);
604 if (strstr (ptr, "'") == ptr)
605 unitv[nunits - 1] = ptr + 1;
606 else
607 unitv[nunits - 1] = ptr;
609 break;
614 if (server_address == NULL)
615 server_address = argv[optind];
617 if (community == NULL)
618 community = strdup (DEFAULT_COMMUNITY);
620 return validate_arguments ();
624 /******************************************************************************
627 <sect3>
628 <title>validate_arguments</title>
630 <para>&PROTO_validate_arguments;</para>
632 <para>Checks to see if the default miblist needs to be loaded. Also verifies
633 the authentication and authorization combinations based on protocol version
634 selected.</para>
636 <para></para>
638 </sect3>
640 ******************************************************************************/
645 validate_arguments ()
647 /* check whether to load locally installed MIBS (CPU/disk intensive) */
648 if (miblist == NULL) {
649 if ( needmibs == TRUE ) {
650 miblist = strdup (DEFAULT_MIBLIST);
651 }else{
652 miblist = ""; /* don't read any mib files for numeric oids */
656 /* Check server_address is given */
657 if (server_address == NULL)
658 die(STATE_UNKNOWN, _("No host specified\n"));
660 /* Check oid is given */
661 if (numoids == 0)
662 die(STATE_UNKNOWN, _("No OIDs specified\n"));
664 if (proto == NULL)
665 asprintf(&proto, DEFAULT_PROTOCOL);
667 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */
668 numauthpriv = 2;
669 authpriv = calloc (numauthpriv, sizeof (char *));
670 authpriv[0] = strdup ("-c");
671 authpriv[1] = strdup (community);
673 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
674 if (seclevel == NULL)
675 asprintf(&seclevel, "noAuthNoPriv");
677 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
678 numauthpriv = 2;
679 authpriv = calloc (numauthpriv, sizeof (char *));
680 authpriv[0] = strdup ("-l");
681 authpriv[1] = strdup ("noAuthNoPriv");
682 } else {
683 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
684 usage2 (_("Invalid seclevel"), seclevel);
687 if (authproto == NULL )
688 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
690 if (secname == NULL)
691 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
693 if (authpasswd == NULL)
694 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
696 if ( strcmp(seclevel, "authNoPriv") == 0 ) {
697 numauthpriv = 8;
698 authpriv = calloc (numauthpriv, sizeof (char *));
699 authpriv[0] = strdup ("-l");
700 authpriv[1] = strdup ("authNoPriv");
701 authpriv[2] = strdup ("-a");
702 authpriv[3] = strdup (authproto);
703 authpriv[4] = strdup ("-u");
704 authpriv[5] = strdup (secname);
705 authpriv[6] = strdup ("-A");
706 authpriv[7] = strdup (authpasswd);
707 } else if ( strcmp(seclevel, "authPriv") == 0 ) {
708 if (privproto == NULL )
709 asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
711 if (privpasswd == NULL)
712 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
714 numauthpriv = 12;
715 authpriv = calloc (numauthpriv, sizeof (char *));
716 authpriv[0] = strdup ("-l");
717 authpriv[1] = strdup ("authPriv");
718 authpriv[2] = strdup ("-a");
719 authpriv[3] = strdup (authproto);
720 authpriv[4] = strdup ("-u");
721 authpriv[5] = strdup (secname);
722 authpriv[6] = strdup ("-A");
723 authpriv[7] = strdup (authpasswd);
724 authpriv[8] = strdup ("-x");
725 authpriv[9] = strdup (privproto);
726 authpriv[10] = strdup ("-X");
727 authpriv[11] = strdup (privpasswd);
732 else {
733 usage2 (_("Invalid SNMP version"), proto);
736 return OK;
741 /* trim leading whitespace
742 if there is a leading quote, make sure it balances */
744 char *
745 thisarg (char *str)
747 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
748 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
749 if (strlen (str) == 1 || !strstr (str + 1, "'"))
750 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
752 return str;
757 /* if there's a leading quote, advance to the trailing quote
758 set the trailing quote to '\x0'
759 if the string continues, advance beyond the comma */
761 char *
762 nextarg (char *str)
764 if (strstr (str, "'") == str) {
765 str[0] = 0;
766 if (strlen (str) > 1) {
767 str = strstr (str + 1, "'");
768 return (++str);
770 else {
771 return NULL;
774 if (strstr (str, ",") == str) {
775 str[0] = 0;
776 if (strlen (str) > 1) {
777 return (++str);
779 else {
780 return NULL;
783 if ((str = strstr (str, ",")) && strlen (str) > 1) {
784 str[0] = 0;
785 return (++str);
787 return NULL;
792 void
793 print_help (void)
795 print_revision (progname, NP_VERSION);
797 printf (COPYRIGHT, copyright, email);
799 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
801 printf ("\n\n");
803 print_usage ();
805 printf (_(UT_HELP_VRSN));
806 printf (_(UT_EXTRA_OPTS));
808 printf (_(UT_HOST_PORT), 'p', DEFAULT_PORT);
810 /* SNMP and Authentication Protocol */
811 printf (" %s\n", "-n, --next");
812 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
813 printf (" %s\n", "-P, --protocol=[1|2c|3]");
814 printf (" %s\n", _("SNMP protocol version"));
815 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
816 printf (" %s\n", _("SNMPv3 securityLevel"));
817 printf (" %s\n", "-a, --authproto=[MD5|SHA]");
818 printf (" %s\n", _("SNMPv3 auth proto"));
819 printf (" %s\n", "-x, --privproto=[DES|AES]");
820 printf (" %s\n", _("SNMPv3 priv proto (default DES)"));
822 /* Authentication Tokens*/
823 printf (" %s\n", "-C, --community=STRING");
824 printf (" %s ", _("Optional community string for SNMP communication"));
825 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
826 printf (" %s\n", "-U, --secname=USERNAME");
827 printf (" %s\n", _("SNMPv3 username"));
828 printf (" %s\n", "-A, --authpassword=PASSWORD");
829 printf (" %s\n", _("SNMPv3 authentication password"));
830 printf (" %s\n", "-X, --privpasswd=PASSWORD");
831 printf (" %s\n", _("SNMPv3 privacy password"));
833 /* OID Stuff */
834 printf (" %s\n", "-o, --oid=OID(s)");
835 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
836 printf (" %s\n", "-m, --miblist=STRING");
837 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
838 printf (" %s\n", _("for symbolic OIDs.)"));
839 printf (" %s\n", "-d, --delimiter=STRING");
840 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
841 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
842 printf (" %s\n", _("to be the data that should be used in the evaluation."));
844 /* Tests Against Integers */
845 printf (" %s\n", "-w, --warning=THRESHOLD(s)");
846 printf (" %s\n", _("Warning threshold range(s)"));
847 printf (" %s\n", "-c, --critical=THRESHOLD(s)");
848 printf (" %s\n", _("Critical threshold range(s)"));
850 /* Tests Against Strings */
851 printf (" %s\n", "-s, --string=STRING");
852 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
853 printf (" %s\n", "-r, --ereg=REGEX");
854 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
855 printf (" %s\n", "-R, --eregi=REGEX");
856 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
857 printf (" %s\n", "-l, --label=STRING");
858 printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
860 /* Output Formatting */
861 printf (" %s\n", "-u, --units=STRING");
862 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
863 printf (" %s\n", "-D, --output-delimiter=STRING");
864 printf (" %s\n", _("Separates output on multiple OID requests"));
866 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
867 printf (" %s\n", "-e, --retries=INTEGER");
868 printf (" %s\n", _("Number of retries to be used in the requests"));
870 printf (_(UT_VERBOSE));
872 printf ("\n");
873 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
874 printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
875 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
877 printf ("\n");
878 printf ("%s\n", _("Notes:"));
879 printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
880 printf (" %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
882 printf(" -%s", _(UT_THRESHOLDS_NOTES));
884 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
885 printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
886 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
887 printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
888 #ifdef NP_EXTRA_OPTS
889 printf (" -%s", _(UT_EXTRA_OPTS_NOTES));
890 #endif
892 printf (_(UT_SUPPORT));
897 void
898 print_usage (void)
900 printf (_("Usage:"));
901 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
902 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
903 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
904 printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
905 printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");