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 /* Gobble to string - stop incrementing c when c[0] match one of the
63 * characters in s */
64 #define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; }
65 /* Given c, keep track of backslashes (bk) and double-quotes (dq)
66 * from c[0] */
67 #define COUNT_SEQ(c, bk, dq) switch(c[0]) {\
68 case '\\': \
69 if (bk) bk--; \
70 else bk++; \
71 break; \
72 case '"': \
73 if (!dq) { dq++; } \
74 else if(!bk) { dq--; } \
75 else { bk--; } \
76 break; \
77 }
81 int process_arguments (int, char **);
82 int validate_arguments (void);
83 char *thisarg (char *str);
84 char *nextarg (char *str);
85 void print_usage (void);
86 void print_help (void);
88 #include "regex.h"
89 char regex_expect[MAX_INPUT_BUFFER] = "";
90 regex_t preg;
91 regmatch_t pmatch[10];
92 char errbuf[MAX_INPUT_BUFFER] = "";
93 char perfstr[MAX_INPUT_BUFFER] = "| ";
94 int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
95 int eflags = 0;
96 int errcode, excode;
98 char *server_address = NULL;
99 char *community = NULL;
100 char **authpriv = NULL;
101 char *proto = NULL;
102 char *seclevel = NULL;
103 char *secname = NULL;
104 char *authproto = NULL;
105 char *privproto = NULL;
106 char *authpasswd = NULL;
107 char *privpasswd = NULL;
108 char **oids = NULL;
109 char *label;
110 char *units;
111 char *port;
112 char *snmpcmd;
113 char string_value[MAX_INPUT_BUFFER] = "";
114 char **labels = NULL;
115 char **unitv = NULL;
116 size_t nlabels = 0;
117 size_t labels_size = 8;
118 size_t nunits = 0;
119 size_t unitv_size = 8;
120 int numoids = 0;
121 int numauthpriv = 0;
122 int verbose = 0;
123 int usesnmpgetnext = FALSE;
124 char *warning_thresholds = NULL;
125 char *critical_thresholds = NULL;
126 thresholds *thlds[MAX_OIDS];
127 double response_value[MAX_OIDS];
128 int retries = 0;
129 int eval_method[MAX_OIDS];
130 char *delimiter;
131 char *output_delim;
132 char *miblist = NULL;
133 int needmibs = FALSE;
136 int
137 main (int argc, char **argv)
138 {
139 int i, len, line;
140 unsigned int bk_count = 0, dq_count = 0;
141 int iresult = STATE_UNKNOWN;
142 int result = STATE_UNKNOWN;
143 int return_code = 0;
144 int external_error = 0;
145 char **command_line = NULL;
146 char *cl_hidden_auth = NULL;
147 char *oidname = NULL;
148 char *response = NULL;
149 char *mult_resp = NULL;
150 char *outbuff;
151 char *ptr = NULL;
152 char *show = NULL;
153 char *th_warn=NULL;
154 char *th_crit=NULL;
155 char type[8] = "";
156 output chld_out, chld_err;
158 setlocale (LC_ALL, "");
159 bindtextdomain (PACKAGE, LOCALEDIR);
160 textdomain (PACKAGE);
162 labels = malloc (labels_size);
163 unitv = malloc (unitv_size);
164 for (i = 0; i < MAX_OIDS; i++)
165 eval_method[i] = CHECK_UNDEF;
167 label = strdup ("SNMP");
168 units = strdup ("");
169 port = strdup (DEFAULT_PORT);
170 outbuff = strdup ("");
171 delimiter = strdup (" = ");
172 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
173 timeout_interval = DEFAULT_TIMEOUT;
174 retries = DEFAULT_RETRIES;
176 /* Parse extra opts if any */
177 argv=np_extra_opts (&argc, argv, progname);
179 if (process_arguments (argc, argv) == ERROR)
180 usage4 (_("Could not parse arguments"));
182 /* Populate the thresholds */
183 th_warn=warning_thresholds;
184 th_crit=critical_thresholds;
185 for (i=0; i<numoids; i++) {
186 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
187 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
188 /* Skip empty thresholds, while avoiding segfault */
189 set_thresholds(&thlds[i],
190 w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
191 c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
192 if (w) {
193 th_warn=strchr(th_warn, ',');
194 if (th_warn) th_warn++;
195 free(w);
196 }
197 if (c) {
198 th_crit=strchr(th_crit, ',');
199 if (th_crit) th_crit++;
200 free(c);
201 }
202 }
204 /* Create the command array to execute */
205 if(usesnmpgetnext == TRUE) {
206 snmpcmd = strdup (PATH_TO_SNMPGETNEXT);
207 }else{
208 snmpcmd = strdup (PATH_TO_SNMPGET);
209 }
211 /* 9 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */
212 command_line = calloc (9 + numauthpriv + 1 + numoids + 1, sizeof (char *));
213 command_line[0] = snmpcmd;
214 command_line[1] = strdup ("-t");
215 asprintf (&command_line[2], "%d", timeout_interval);
216 command_line[3] = strdup ("-r");
217 asprintf (&command_line[4], "%d", retries);
218 command_line[5] = strdup ("-m");
219 command_line[6] = strdup (miblist);
220 command_line[7] = "-v";
221 command_line[8] = strdup (proto);
223 for (i = 0; i < numauthpriv; i++) {
224 command_line[9 + i] = authpriv[i];
225 }
227 asprintf (&command_line[9 + numauthpriv], "%s:%s", server_address, port);
229 /* This is just for display purposes, so it can remain a string */
230 asprintf(&cl_hidden_auth, "%s -t %d -r %d -m %s -v %s %s %s:%s",
231 snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto, "[authpriv]",
232 server_address, port);
234 for (i = 0; i < numoids; i++) {
235 command_line[9 + numauthpriv + 1 + i] = oids[i];
236 asprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);
237 }
239 command_line[9 + numauthpriv + 1 + numoids] = NULL;
241 if (verbose)
242 printf ("%s\n", cl_hidden_auth);
244 /* Run the command */
245 return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0);
247 /* Due to net-snmp sometimes showing stderr messages with poorly formed MIBs,
248 only return state unknown if return code is non zero or there is no stdout.
249 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
250 */
251 if (return_code != 0)
252 external_error=1;
253 if (chld_out.lines == 0)
254 external_error=1;
255 if (external_error) {
256 if (chld_err.lines > 0) {
257 printf (_("External command error: %s\n"), chld_err.line[0]);
258 for (i = 1; i < chld_err.lines; i++) {
259 printf ("%s\n", chld_err.line[i]);
260 }
261 } else {
262 printf(_("External command error with no output (return code: %d)\n"), return_code);
263 }
264 exit (STATE_UNKNOWN);
265 }
267 if (verbose) {
268 for (i = 0; i < chld_out.lines; i++) {
269 printf ("%s\n", chld_out.line[i]);
270 }
271 }
273 for (line=0, i=0; line < chld_out.lines; line++, i++) {
274 const char *conv = "%.0f";
276 ptr = chld_out.line[line];
277 oidname = strpcpy (oidname, ptr, delimiter);
278 response = strstr (ptr, delimiter);
279 if (response == NULL)
280 break;
282 if (verbose > 2) {
283 printf("Processing oid %i (line %i)\n oidname: %s\n response: %s\n", i+1, line+1, oidname, response);
284 }
286 /* Clean up type array - Sol10 does not necessarily zero it out */
287 bzero(type, sizeof(type));
289 /* We strip out the datatype indicator for PHBs */
290 if (strstr (response, "Gauge: "))
291 show = strstr (response, "Gauge: ") + 7;
292 else if (strstr (response, "Gauge32: "))
293 show = strstr (response, "Gauge32: ") + 9;
294 else if (strstr (response, "Counter32: ")) {
295 show = strstr (response, "Counter32: ") + 11;
296 strcpy(type, "c");
297 }
298 else if (strstr (response, "Counter64: ")) {
299 show = strstr (response, "Counter64: ") + 11;
300 strcpy(type, "c");
301 }
302 else if (strstr (response, "INTEGER: "))
303 show = strstr (response, "INTEGER: ") + 9;
304 else if (strstr (response, "STRING: ")) {
305 show = strstr (response, "STRING: ") + 8;
306 conv = "%.10g";
308 /* Get the rest of the string on multi-line strings */
309 ptr = show;
310 COUNT_SEQ(ptr, bk_count, dq_count)
311 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
312 ptr++;
313 GOBBLE_TOS(ptr, "\n\"\\")
314 COUNT_SEQ(ptr, bk_count, dq_count)
315 }
317 if (dq_count) { /* unfinished line */
318 /* copy show verbatim first */
319 if (!mult_resp) mult_resp = strdup("");
320 asprintf (&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show);
321 /* then strip out unmatched double-quote from single-line output */
322 if (show[0] == '"') show++;
324 /* Keep reading until we match end of double-quoted string */
325 for (line++; line < chld_out.lines; line++) {
326 ptr = chld_out.line[line];
327 asprintf (&mult_resp, "%s%s\n", mult_resp, ptr);
329 COUNT_SEQ(ptr, bk_count, dq_count)
330 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
331 ptr++;
332 GOBBLE_TOS(ptr, "\n\"\\")
333 COUNT_SEQ(ptr, bk_count, dq_count)
334 }
335 /* Break for loop before next line increment when done */
336 if (!dq_count) break;
337 }
338 }
340 }
341 else if (strstr (response, "Timeticks: "))
342 show = strstr (response, "Timeticks: ");
343 else
344 show = response;
346 iresult = STATE_DEPENDENT;
348 /* Process this block for integer comparisons */
349 if (thlds[i]->warning || thlds[i]->critical) {
350 ptr = strpbrk (show, "0123456789");
351 if (ptr == NULL)
352 die (STATE_UNKNOWN,_("No valid data returned"));
353 response_value[i] = strtod (ptr, NULL);
354 iresult = get_status(response_value[i], thlds[i]);
355 asprintf (&show, conv, response_value[i]);
356 }
358 /* Process this block for string matching */
359 else if (eval_method[i] & CRIT_STRING) {
360 if (strcmp (show, string_value))
361 iresult = STATE_CRITICAL;
362 else
363 iresult = STATE_OK;
364 }
366 /* Process this block for regex matching */
367 else if (eval_method[i] & CRIT_REGEX) {
368 excode = regexec (&preg, response, 10, pmatch, eflags);
369 if (excode == 0) {
370 iresult = STATE_OK;
371 }
372 else if (excode != REG_NOMATCH) {
373 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
374 printf (_("Execute Error: %s\n"), errbuf);
375 exit (STATE_CRITICAL);
376 }
377 else {
378 iresult = STATE_CRITICAL;
379 }
380 }
382 /* Process this block for existence-nonexistence checks */
383 else {
384 if (eval_method[i] & CRIT_PRESENT)
385 iresult = STATE_CRITICAL;
386 else if (eval_method[i] & WARN_PRESENT)
387 iresult = STATE_WARNING;
388 else if (response && iresult == STATE_DEPENDENT)
389 iresult = STATE_OK;
390 }
392 /* Result is the worst outcome of all the OIDs tested */
393 result = max_state (result, iresult);
395 /* Prepend a label for this OID if there is one */
396 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
397 asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
398 (i == 0) ? " " : output_delim,
399 labels[i], mark (iresult), show, mark (iresult));
400 else
401 asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
402 mark (iresult), show, mark (iresult));
404 /* Append a unit string for this OID if there is one */
405 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
406 asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
408 /* Write perfdata with whatever can be parsed by strtod, if possible */
409 ptr = NULL;
410 strtod(show, &ptr);
411 if (ptr > show) {
412 strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
413 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
414 len = sizeof(perfstr)-strlen(perfstr)-1;
415 strncat(perfstr, show, len>ptr-show ? ptr-show : len);
417 if (type)
418 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
419 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
420 }
421 }
423 printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr);
424 if (mult_resp) printf ("%s", mult_resp);
426 return result;
427 }
431 /* process command-line arguments */
432 int
433 process_arguments (int argc, char **argv)
434 {
435 char *ptr;
436 int c = 1;
437 int j = 0, jj = 0, ii = 0;
439 int option = 0;
440 static struct option longopts[] = {
441 STD_LONG_OPTS,
442 {"community", required_argument, 0, 'C'},
443 {"oid", required_argument, 0, 'o'},
444 {"object", required_argument, 0, 'o'},
445 {"delimiter", required_argument, 0, 'd'},
446 {"output-delimiter", required_argument, 0, 'D'},
447 {"string", required_argument, 0, 's'},
448 {"timeout", required_argument, 0, 't'},
449 {"regex", required_argument, 0, 'r'},
450 {"ereg", required_argument, 0, 'r'},
451 {"eregi", required_argument, 0, 'R'},
452 {"label", required_argument, 0, 'l'},
453 {"units", required_argument, 0, 'u'},
454 {"port", required_argument, 0, 'p'},
455 {"retries", required_argument, 0, 'e'},
456 {"miblist", required_argument, 0, 'm'},
457 {"protocol", required_argument, 0, 'P'},
458 {"seclevel", required_argument, 0, 'L'},
459 {"secname", required_argument, 0, 'U'},
460 {"authproto", required_argument, 0, 'a'},
461 {"privproto", required_argument, 0, 'x'},
462 {"authpasswd", required_argument, 0, 'A'},
463 {"privpasswd", required_argument, 0, 'X'},
464 {"next", no_argument, 0, 'n'},
465 {0, 0, 0, 0}
466 };
468 if (argc < 2)
469 return ERROR;
471 /* reverse compatibility for very old non-POSIX usage forms */
472 for (c = 1; c < argc; c++) {
473 if (strcmp ("-to", argv[c]) == 0)
474 strcpy (argv[c], "-t");
475 if (strcmp ("-wv", argv[c]) == 0)
476 strcpy (argv[c], "-w");
477 if (strcmp ("-cv", argv[c]) == 0)
478 strcpy (argv[c], "-c");
479 }
481 while (1) {
482 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:",
483 longopts, &option);
485 if (c == -1 || c == EOF)
486 break;
488 switch (c) {
489 case '?': /* usage */
490 usage5 ();
491 case 'h': /* help */
492 print_help ();
493 exit (STATE_OK);
494 case 'V': /* version */
495 print_revision (progname, NP_VERSION);
496 exit (STATE_OK);
497 case 'v': /* verbose */
498 verbose++;
499 break;
501 /* Connection info */
502 case 'C': /* group or community */
503 community = optarg;
504 break;
505 case 'H': /* Host or server */
506 server_address = optarg;
507 break;
508 case 'p': /* TCP port number */
509 port = optarg;
510 break;
511 case 'm': /* List of MIBS */
512 miblist = optarg;
513 break;
514 case 'n': /* usesnmpgetnext */
515 usesnmpgetnext = TRUE;
516 break;
517 case 'P': /* SNMP protocol version */
518 proto = optarg;
519 break;
520 case 'L': /* security level */
521 seclevel = optarg;
522 break;
523 case 'U': /* security username */
524 secname = optarg;
525 break;
526 case 'a': /* auth protocol */
527 authproto = optarg;
528 break;
529 case 'x': /* priv protocol */
530 privproto = optarg;
531 break;
532 case 'A': /* auth passwd */
533 authpasswd = optarg;
534 break;
535 case 'X': /* priv passwd */
536 privpasswd = optarg;
537 break;
538 case 't': /* timeout period */
539 if (!is_integer (optarg))
540 usage2 (_("Timeout interval must be a positive integer"), optarg);
541 else
542 timeout_interval = atoi (optarg);
543 break;
545 /* Test parameters */
546 case 'c': /* critical threshold */
547 critical_thresholds = optarg;
548 break;
549 case 'w': /* warning threshold */
550 warning_thresholds = optarg;
551 break;
552 case 'e': /* PRELIMINARY - may change */
553 case 'E': /* PRELIMINARY - may change */
554 if (!is_integer (optarg))
555 usage2 (_("Retries interval must be a positive integer"), optarg);
556 else
557 retries = atoi(optarg);
558 break;
559 case 'o': /* object identifier */
560 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
561 /*
562 * we have something other than digits, periods and comas,
563 * so we have a mib variable, rather than just an SNMP OID,
564 * so we have to actually read the mib files
565 */
566 needmibs = TRUE;
567 }
568 if (!oids) oids = calloc(MAX_OIDS, sizeof (char *));
569 for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
570 oids[j] = strdup(ptr);
571 }
572 numoids = j;
573 if (c == 'E' || c == 'e') {
574 jj++;
575 ii++;
576 }
577 if (c == 'E')
578 eval_method[j+1] |= WARN_PRESENT;
579 else if (c == 'e')
580 eval_method[j+1] |= CRIT_PRESENT;
581 break;
582 case 's': /* string or substring */
583 strncpy (string_value, optarg, sizeof (string_value) - 1);
584 string_value[sizeof (string_value) - 1] = 0;
585 eval_method[jj++] = CRIT_STRING;
586 ii++;
587 break;
588 case 'R': /* regex */
589 cflags = REG_ICASE;
590 case 'r': /* regex */
591 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
592 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
593 regex_expect[sizeof (regex_expect) - 1] = 0;
594 errcode = regcomp (&preg, regex_expect, cflags);
595 if (errcode != 0) {
596 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
597 printf (_("Could Not Compile Regular Expression"));
598 return ERROR;
599 }
600 eval_method[jj++] = CRIT_REGEX;
601 ii++;
602 break;
604 /* Format */
605 case 'd': /* delimiter */
606 delimiter = strscpy (delimiter, optarg);
607 break;
608 case 'D': /* output-delimiter */
609 output_delim = strscpy (output_delim, optarg);
610 break;
611 case 'l': /* label */
612 label = optarg;
613 nlabels++;
614 if (nlabels >= labels_size) {
615 labels_size += 8;
616 labels = realloc (labels, labels_size);
617 if (labels == NULL)
618 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
619 }
620 labels[nlabels - 1] = optarg;
621 ptr = thisarg (optarg);
622 labels[nlabels - 1] = ptr;
623 if (strstr (ptr, "'") == ptr)
624 labels[nlabels - 1] = ptr + 1;
625 while (ptr && (ptr = nextarg (ptr))) {
626 if (nlabels >= labels_size) {
627 labels_size += 8;
628 labels = realloc (labels, labels_size);
629 if (labels == NULL)
630 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
631 }
632 labels++;
633 ptr = thisarg (ptr);
634 if (strstr (ptr, "'") == ptr)
635 labels[nlabels - 1] = ptr + 1;
636 else
637 labels[nlabels - 1] = ptr;
638 }
639 break;
640 case 'u': /* units */
641 units = optarg;
642 nunits++;
643 if (nunits >= unitv_size) {
644 unitv_size += 8;
645 unitv = realloc (unitv, unitv_size);
646 if (unitv == NULL)
647 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
648 }
649 unitv[nunits - 1] = optarg;
650 ptr = thisarg (optarg);
651 unitv[nunits - 1] = ptr;
652 if (strstr (ptr, "'") == ptr)
653 unitv[nunits - 1] = ptr + 1;
654 while (ptr && (ptr = nextarg (ptr))) {
655 if (nunits >= unitv_size) {
656 unitv_size += 8;
657 unitv = realloc (unitv, unitv_size);
658 if (units == NULL)
659 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
660 }
661 nunits++;
662 ptr = thisarg (ptr);
663 if (strstr (ptr, "'") == ptr)
664 unitv[nunits - 1] = ptr + 1;
665 else
666 unitv[nunits - 1] = ptr;
667 }
668 break;
670 }
671 }
673 if (server_address == NULL)
674 server_address = argv[optind];
676 if (community == NULL)
677 community = strdup (DEFAULT_COMMUNITY);
679 return validate_arguments ();
680 }
683 /******************************************************************************
685 @@-
686 <sect3>
687 <title>validate_arguments</title>
689 <para>&PROTO_validate_arguments;</para>
691 <para>Checks to see if the default miblist needs to be loaded. Also verifies
692 the authentication and authorization combinations based on protocol version
693 selected.</para>
695 <para></para>
697 </sect3>
698 -@@
699 ******************************************************************************/
703 int
704 validate_arguments ()
705 {
706 /* check whether to load locally installed MIBS (CPU/disk intensive) */
707 if (miblist == NULL) {
708 if ( needmibs == TRUE ) {
709 miblist = strdup (DEFAULT_MIBLIST);
710 }else{
711 miblist = ""; /* don't read any mib files for numeric oids */
712 }
713 }
715 /* Check server_address is given */
716 if (server_address == NULL)
717 die(STATE_UNKNOWN, _("No host specified\n"));
719 /* Check oid is given */
720 if (numoids == 0)
721 die(STATE_UNKNOWN, _("No OIDs specified\n"));
723 if (proto == NULL)
724 asprintf(&proto, DEFAULT_PROTOCOL);
726 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */
727 numauthpriv = 2;
728 authpriv = calloc (numauthpriv, sizeof (char *));
729 authpriv[0] = strdup ("-c");
730 authpriv[1] = strdup (community);
731 }
732 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
733 if (seclevel == NULL)
734 asprintf(&seclevel, "noAuthNoPriv");
736 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
737 numauthpriv = 2;
738 authpriv = calloc (numauthpriv, sizeof (char *));
739 authpriv[0] = strdup ("-l");
740 authpriv[1] = strdup ("noAuthNoPriv");
741 } else {
742 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
743 usage2 (_("Invalid seclevel"), seclevel);
744 }
746 if (authproto == NULL )
747 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
749 if (secname == NULL)
750 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
752 if (authpasswd == NULL)
753 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
755 if ( strcmp(seclevel, "authNoPriv") == 0 ) {
756 numauthpriv = 8;
757 authpriv = calloc (numauthpriv, sizeof (char *));
758 authpriv[0] = strdup ("-l");
759 authpriv[1] = strdup ("authNoPriv");
760 authpriv[2] = strdup ("-a");
761 authpriv[3] = strdup (authproto);
762 authpriv[4] = strdup ("-u");
763 authpriv[5] = strdup (secname);
764 authpriv[6] = strdup ("-A");
765 authpriv[7] = strdup (authpasswd);
766 } else if ( strcmp(seclevel, "authPriv") == 0 ) {
767 if (privproto == NULL )
768 asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
770 if (privpasswd == NULL)
771 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
773 numauthpriv = 12;
774 authpriv = calloc (numauthpriv, sizeof (char *));
775 authpriv[0] = strdup ("-l");
776 authpriv[1] = strdup ("authPriv");
777 authpriv[2] = strdup ("-a");
778 authpriv[3] = strdup (authproto);
779 authpriv[4] = strdup ("-u");
780 authpriv[5] = strdup (secname);
781 authpriv[6] = strdup ("-A");
782 authpriv[7] = strdup (authpasswd);
783 authpriv[8] = strdup ("-x");
784 authpriv[9] = strdup (privproto);
785 authpriv[10] = strdup ("-X");
786 authpriv[11] = strdup (privpasswd);
787 }
788 }
790 }
791 else {
792 usage2 (_("Invalid SNMP version"), proto);
793 }
795 return OK;
796 }
800 /* trim leading whitespace
801 if there is a leading quote, make sure it balances */
803 char *
804 thisarg (char *str)
805 {
806 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
807 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
808 if (strlen (str) == 1 || !strstr (str + 1, "'"))
809 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
810 }
811 return str;
812 }
816 /* if there's a leading quote, advance to the trailing quote
817 set the trailing quote to '\x0'
818 if the string continues, advance beyond the comma */
820 char *
821 nextarg (char *str)
822 {
823 if (strstr (str, "'") == str) {
824 str[0] = 0;
825 if (strlen (str) > 1) {
826 str = strstr (str + 1, "'");
827 return (++str);
828 }
829 else {
830 return NULL;
831 }
832 }
833 if (strstr (str, ",") == str) {
834 str[0] = 0;
835 if (strlen (str) > 1) {
836 return (++str);
837 }
838 else {
839 return NULL;
840 }
841 }
842 if ((str = strstr (str, ",")) && strlen (str) > 1) {
843 str[0] = 0;
844 return (++str);
845 }
846 return NULL;
847 }
851 void
852 print_help (void)
853 {
854 print_revision (progname, NP_VERSION);
856 printf (COPYRIGHT, copyright, email);
858 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
860 printf ("\n\n");
862 print_usage ();
864 printf (UT_HELP_VRSN);
865 printf (UT_EXTRA_OPTS);
867 printf (UT_HOST_PORT, 'p', DEFAULT_PORT);
869 /* SNMP and Authentication Protocol */
870 printf (" %s\n", "-n, --next");
871 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
872 printf (" %s\n", "-P, --protocol=[1|2c|3]");
873 printf (" %s\n", _("SNMP protocol version"));
874 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
875 printf (" %s\n", _("SNMPv3 securityLevel"));
876 printf (" %s\n", "-a, --authproto=[MD5|SHA]");
877 printf (" %s\n", _("SNMPv3 auth proto"));
878 printf (" %s\n", "-x, --privproto=[DES|AES]");
879 printf (" %s\n", _("SNMPv3 priv proto (default DES)"));
881 /* Authentication Tokens*/
882 printf (" %s\n", "-C, --community=STRING");
883 printf (" %s ", _("Optional community string for SNMP communication"));
884 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
885 printf (" %s\n", "-U, --secname=USERNAME");
886 printf (" %s\n", _("SNMPv3 username"));
887 printf (" %s\n", "-A, --authpassword=PASSWORD");
888 printf (" %s\n", _("SNMPv3 authentication password"));
889 printf (" %s\n", "-X, --privpasswd=PASSWORD");
890 printf (" %s\n", _("SNMPv3 privacy password"));
892 /* OID Stuff */
893 printf (" %s\n", "-o, --oid=OID(s)");
894 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
895 printf (" %s\n", "-m, --miblist=STRING");
896 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
897 printf (" %s\n", _("for symbolic OIDs.)"));
898 printf (" %s\n", "-d, --delimiter=STRING");
899 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
900 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
901 printf (" %s\n", _("to be the data that should be used in the evaluation."));
903 /* Tests Against Integers */
904 printf (" %s\n", "-w, --warning=THRESHOLD(s)");
905 printf (" %s\n", _("Warning threshold range(s)"));
906 printf (" %s\n", "-c, --critical=THRESHOLD(s)");
907 printf (" %s\n", _("Critical threshold range(s)"));
909 /* Tests Against Strings */
910 printf (" %s\n", "-s, --string=STRING");
911 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
912 printf (" %s\n", "-r, --ereg=REGEX");
913 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
914 printf (" %s\n", "-R, --eregi=REGEX");
915 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
916 printf (" %s\n", "-l, --label=STRING");
917 printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
919 /* Output Formatting */
920 printf (" %s\n", "-u, --units=STRING");
921 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
922 printf (" %s\n", "-D, --output-delimiter=STRING");
923 printf (" %s\n", _("Separates output on multiple OID requests"));
925 printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
926 printf (" %s\n", "-e, --retries=INTEGER");
927 printf (" %s\n", _("Number of retries to be used in the requests"));
929 printf (UT_VERBOSE);
931 printf ("\n");
932 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
933 printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
934 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
936 printf ("\n");
937 printf ("%s\n", _("Notes:"));
938 printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
939 printf (" %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
941 printf(" -%s", UT_THRESHOLDS_NOTES);
943 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
944 printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
945 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
946 printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
948 printf (UT_SUPPORT);
949 }
953 void
954 print_usage (void)
955 {
956 printf ("%s\n", _("Usage:"));
957 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
958 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
959 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
960 printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
961 printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");
962 }