Code

bb3d295e0f31fe0a14b822a7ccfeaf5f72648d1e
[nagiosplug.git] / plugins / check_snmp.c
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)
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);
175                 }
176                 if (c) {
177                         th_crit=strchr(th_crit, ',');
178                         if (th_crit) th_crit++;
179                         free(c);
180                 }
181         }
183         /* Create the command array to execute */
184         if(usesnmpgetnext == TRUE) {
185                 snmpcmd = strdup (PATH_TO_SNMPGETNEXT);
186         }else{
187                 snmpcmd = strdup (PATH_TO_SNMPGET);
188         }
189         
190         /* 9 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */
191         command_line = calloc (9 + numauthpriv + 1 + numoids + 1, sizeof (char *));
192         command_line[0] = snmpcmd;
193         command_line[1] = strdup ("-t");
194         asprintf (&command_line[2], "%d", timeout_interval);
195         command_line[3] = strdup ("-r");
196         asprintf (&command_line[4], "%d", retries);
197         command_line[5] = strdup ("-m");
198         command_line[6] = strdup (miblist);
199         command_line[7] = "-v";
200         command_line[8] = strdup (proto);
202         for (i = 0; i < numauthpriv; i++) {
203                 command_line[9 + i] = authpriv[i];
204         }
206         asprintf (&command_line[9 + numauthpriv], "%s:%s", server_address, port);
208         /* This is just for display purposes, so it can remain a string */
209         asprintf(&cl_hidden_auth, "%s -t %d -r %d -m %s -v %s %s %s:%s",
210                 snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto, "[authpriv]",
211                 server_address, port);
213         for (i = 0; i < numoids; i++) {
214                 command_line[9 + numauthpriv + 1 + i] = oids[i];
215                 asprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);    
216         }
218         command_line[9 + numauthpriv + 1 + numoids] = NULL;
220         if (verbose)
221                 printf ("%s\n", cl_hidden_auth);
223         /* Run the command */
224         return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0);
226         /* Due to net-snmp sometimes showing stderr messages with poorly formed MIBs,
227            only return state unknown if return code is non zero or there is no stdout.
228            Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
229         */
230         if (return_code != 0)
231                 external_error=1;
232         if (chld_out.lines == 0)
233                 external_error=1;
234         if (external_error) {
235                 if (chld_err.lines > 0) {
236                         printf (_("External command error: %s\n"), chld_err.line[0]);
237                         for (i = 1; i < chld_err.lines; i++) {
238                                 printf ("%s\n", chld_err.line[i]);
239                         }
240                 } else {
241                         printf(_("External command error with no output (return code: %d)\n"), return_code);
242                 }
243                 exit (STATE_UNKNOWN);
244         }
246         if (verbose) {
247                 for (i = 0; i < chld_out.lines; i++) {
248                         printf ("%s\n", chld_out.line[i]);
249                 }
250         }
252         for (i = 0; i < chld_out.lines; i++) {
253                 const char *conv = "%.0f";
255                 ptr = chld_out.line[i];
256                 oidname = strpcpy (oidname, ptr, delimiter);
257                 response = strstr (ptr, delimiter);
258                 if (verbose > 2) {
259                         printf("Processing line %i\n  oidname: %s\n  response: %s\n", i+1, oidname, response);
260                 }
262                 /* We strip out the datatype indicator for PHBs */
264                 /* Clean up type array - Sol10 does not necessarily zero it out */
265                 bzero(type, sizeof(type));
267                 if (strstr (response, "Gauge: "))
268                         show = strstr (response, "Gauge: ") + 7;
269                 else if (strstr (response, "Gauge32: "))
270                         show = strstr (response, "Gauge32: ") + 9;
271                 else if (strstr (response, "Counter32: ")) {
272                         show = strstr (response, "Counter32: ") + 11;
273                         strcpy(type, "c");
274                 }
275                 else if (strstr (response, "Counter64: ")) {
276                         show = strstr (response, "Counter64: ") + 11;
277                         strcpy(type, "c");
278                 }
279                 else if (strstr (response, "INTEGER: "))
280                         show = strstr (response, "INTEGER: ") + 9;
281                 else if (strstr (response, "STRING: ")) {
282                         show = strstr (response, "STRING: ") + 8;
283                         conv = "%.10g";
284                 }
285                 else if (strstr (response, "Timeticks: "))
286                         show = strstr (response, "Timeticks: ");
287                 else
288                         show = response;
290                 iresult = STATE_DEPENDENT;
292                 /* Process this block for integer comparisons */
293                 if (thlds[i]->warning || thlds[i]->critical) {
294                         ptr = strpbrk (show, "0123456789");
295                         if (ptr == NULL)
296                                 die (STATE_UNKNOWN,_("No valid data returned"));
297                         response_value[i] = strtod (ptr, NULL);
298                         iresult = get_status(response_value[i], thlds[i]);
299                         asprintf (&show, conv, response_value[i]);
300                 }
302                 /* Process this block for string matching */
303                 else if (eval_method[i] & CRIT_STRING) {
304                         if (strcmp (show, string_value))
305                                 iresult = STATE_CRITICAL;
306                         else
307                                 iresult = STATE_OK;
308                 }
310                 /* Process this block for regex matching */
311                 else if (eval_method[i] & CRIT_REGEX) {
312                         excode = regexec (&preg, response, 10, pmatch, eflags);
313                         if (excode == 0) {
314                                 iresult = STATE_OK;
315                         }
316                         else if (excode != REG_NOMATCH) {
317                                 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
318                                 printf (_("Execute Error: %s\n"), errbuf);
319                                 exit (STATE_CRITICAL);
320                         }
321                         else {
322                                 iresult = STATE_CRITICAL;
323                         }
324                 }
326                 /* Process this block for existence-nonexistence checks */
327                 else {
328                         if (eval_method[i] & CRIT_PRESENT)
329                                 iresult = STATE_CRITICAL;
330                         else if (eval_method[i] & WARN_PRESENT)
331                                 iresult = STATE_WARNING;
332                         else if (response && iresult == STATE_DEPENDENT)
333                                 iresult = STATE_OK;
334                 }
336                 /* Result is the worst outcome of all the OIDs tested */
337                 result = max_state (result, iresult);
339                 /* Prepend a label for this OID if there is one */
340                 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
341                         asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
342                                 (i == 0) ? " " : output_delim,
343                                 labels[i], mark (iresult), show, mark (iresult));
344                 else
345                         asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
346                                 mark (iresult), show, mark (iresult));
348                 /* Append a unit string for this OID if there is one */
349                 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
350                         asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
352                 if (is_numeric(show)) {
353                         strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
354                         strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
355                         strncat(perfstr, show, sizeof(perfstr)-strlen(perfstr)-1);
357                         if (type)
358                                 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
359                         strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
360                 }
361         }
363         printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
365         return result;
370 /* process command-line arguments */
371 int
372 process_arguments (int argc, char **argv)
374         char *ptr;
375         int c = 1;
376         int j = 0, jj = 0, ii = 0;
378         int option = 0;
379         static struct option longopts[] = {
380                 STD_LONG_OPTS,
381                 {"community", required_argument, 0, 'C'},
382                 {"oid", required_argument, 0, 'o'},
383                 {"object", required_argument, 0, 'o'},
384                 {"delimiter", required_argument, 0, 'd'},
385                 {"output-delimiter", required_argument, 0, 'D'},
386                 {"string", required_argument, 0, 's'},
387                 {"timeout", required_argument, 0, 't'},
388                 {"regex", required_argument, 0, 'r'},
389                 {"ereg", required_argument, 0, 'r'},
390                 {"eregi", required_argument, 0, 'R'},
391                 {"label", required_argument, 0, 'l'},
392                 {"units", required_argument, 0, 'u'},
393                 {"port", required_argument, 0, 'p'},
394                 {"retries", required_argument, 0, 'e'},
395                 {"miblist", required_argument, 0, 'm'},
396                 {"protocol", required_argument, 0, 'P'},
397                 {"seclevel", required_argument, 0, 'L'},
398                 {"secname", required_argument, 0, 'U'},
399                 {"authproto", required_argument, 0, 'a'},
400                 {"privproto", required_argument, 0, 'x'},
401                 {"authpasswd", required_argument, 0, 'A'},
402                 {"privpasswd", required_argument, 0, 'X'},
403                 {"next", no_argument, 0, 'n'},
404                 {0, 0, 0, 0}
405         };
407         if (argc < 2)
408                 return ERROR;
410         /* reverse compatibility for very old non-POSIX usage forms */
411         for (c = 1; c < argc; c++) {
412                 if (strcmp ("-to", argv[c]) == 0)
413                         strcpy (argv[c], "-t");
414                 if (strcmp ("-wv", argv[c]) == 0)
415                         strcpy (argv[c], "-w");
416                 if (strcmp ("-cv", argv[c]) == 0)
417                         strcpy (argv[c], "-c");
418         }
420         while (1) {
421                 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:",
422                                                                          longopts, &option);
424                 if (c == -1 || c == EOF)
425                         break;
427                 switch (c) {
428                 case '?':       /* usage */
429                         usage5 ();
430                 case 'h':       /* help */
431                         print_help ();
432                         exit (STATE_OK);
433                 case 'V':       /* version */
434                         print_revision (progname, NP_VERSION);
435                         exit (STATE_OK);
436                 case 'v': /* verbose */
437                         verbose++;
438                         break;
440         /* Connection info */
441                 case 'C':                                                                       /* group or community */
442                         community = optarg;
443                         break;
444                 case 'H':                                                                       /* Host or server */
445                         server_address = optarg;
446                         break;
447                 case 'p':       /* TCP port number */
448                         port = optarg;
449                         break;
450                 case 'm':       /* List of MIBS */
451                         miblist = optarg;
452                         break;
453                 case 'n':       /* usesnmpgetnext */
454                         usesnmpgetnext = TRUE;
455                         break;
456                 case 'P':       /* SNMP protocol version */
457                         proto = optarg;
458                         break;
459                 case 'L':       /* security level */
460                         seclevel = optarg;
461                         break;
462                 case 'U':       /* security username */
463                         secname = optarg;
464                         break;
465                 case 'a':       /* auth protocol */
466                         authproto = optarg;
467                         break;
468                 case 'x':       /* priv protocol */
469                         privproto = optarg;
470                         break;
471                 case 'A':       /* auth passwd */
472                         authpasswd = optarg;
473                         break;
474                 case 'X':       /* priv passwd */
475                         privpasswd = optarg;
476                         break;
477                 case 't':       /* timeout period */
478                         if (!is_integer (optarg))
479                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
480                         else
481                                 timeout_interval = atoi (optarg);
482                         break;
484         /* Test parameters */
485                 case 'c':                                                                       /* critical threshold */
486                         critical_thresholds = optarg;
487                         break;
488                 case 'w':                                                                       /* warning threshold */
489                         warning_thresholds = optarg;
490                         break;
491                 case 'e': /* PRELIMINARY - may change */
492                 case 'E': /* PRELIMINARY - may change */
493                         if (!is_integer (optarg))
494                                 usage2 (_("Retries interval must be a positive integer"), optarg);
495                         else
496                                 retries = atoi(optarg);
497                         break;
498                 case 'o':                                                                       /* object identifier */
499                         if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
500                                         /*
501                                          * we have something other than digits, periods and comas,
502                                          * so we have a mib variable, rather than just an SNMP OID,
503                                          * so we have to actually read the mib files
504                                          */
505                                         needmibs = TRUE;
506                         }
507                         oids = calloc(MAX_OIDS, sizeof (char *));
508                         for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
509                                 oids[j] = strdup(ptr);
510                         }
511                         numoids = j;
512                         if (c == 'E' || c == 'e') {
513                                 jj++;
514                                 ii++;
515                         }
516                         if (c == 'E')
517                                 eval_method[j+1] |= WARN_PRESENT;
518                         else if (c == 'e')
519                                 eval_method[j+1] |= CRIT_PRESENT;
520                         break;
521                 case 's':                                                                       /* string or substring */
522                         strncpy (string_value, optarg, sizeof (string_value) - 1);
523                         string_value[sizeof (string_value) - 1] = 0;
524                         eval_method[jj++] = CRIT_STRING;
525                         ii++;
526                         break;
527                 case 'R':                                                                       /* regex */
528                         cflags = REG_ICASE;
529                 case 'r':                                                                       /* regex */
530                         cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
531                         strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
532                         regex_expect[sizeof (regex_expect) - 1] = 0;
533                         errcode = regcomp (&preg, regex_expect, cflags);
534                         if (errcode != 0) {
535                                 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
536                                 printf (_("Could Not Compile Regular Expression"));
537                                 return ERROR;
538                         }
539                         eval_method[jj++] = CRIT_REGEX;
540                         ii++;
541                         break;
543         /* Format */
544                 case 'd':                                                                       /* delimiter */
545                         delimiter = strscpy (delimiter, optarg);
546                         break;
547                 case 'D':                                                                       /* output-delimiter */
548                         output_delim = strscpy (output_delim, optarg);
549                         break;
550                 case 'l':                                                                       /* label */
551                         label = optarg;
552                         nlabels++;
553                         if (nlabels >= labels_size) {
554                                 labels_size += 8;
555                                 labels = realloc (labels, labels_size);
556                                 if (labels == NULL)
557                                         die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
558                         }
559                         labels[nlabels - 1] = optarg;
560                         ptr = thisarg (optarg);
561                         labels[nlabels - 1] = ptr;
562                         if (strstr (ptr, "'") == ptr)
563                                 labels[nlabels - 1] = ptr + 1;
564                         while (ptr && (ptr = nextarg (ptr))) {
565                                 if (nlabels >= labels_size) {
566                                         labels_size += 8;
567                                         labels = realloc (labels, labels_size);
568                                         if (labels == NULL)
569                                                 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
570                                 }
571                                 labels++;
572                                 ptr = thisarg (ptr);
573                                 if (strstr (ptr, "'") == ptr)
574                                         labels[nlabels - 1] = ptr + 1;
575                                 else
576                                         labels[nlabels - 1] = ptr;
577                         }
578                         break;
579                 case 'u':                                                                       /* units */
580                         units = optarg;
581                         nunits++;
582                         if (nunits >= unitv_size) {
583                                 unitv_size += 8;
584                                 unitv = realloc (unitv, unitv_size);
585                                 if (unitv == NULL)
586                                         die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
587                         }
588                         unitv[nunits - 1] = optarg;
589                         ptr = thisarg (optarg);
590                         unitv[nunits - 1] = ptr;
591                         if (strstr (ptr, "'") == ptr)
592                                 unitv[nunits - 1] = ptr + 1;
593                         while (ptr && (ptr = nextarg (ptr))) {
594                                 if (nunits >= unitv_size) {
595                                         unitv_size += 8;
596                                         unitv = realloc (unitv, unitv_size);
597                                         if (units == NULL)
598                                                 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
599                                 }
600                                 nunits++;
601                                 ptr = thisarg (ptr);
602                                 if (strstr (ptr, "'") == ptr)
603                                         unitv[nunits - 1] = ptr + 1;
604                                 else
605                                         unitv[nunits - 1] = ptr;
606                         }
607                         break;
609                 }
610         }
612         if (server_address == NULL)
613                 server_address = argv[optind];
615         if (community == NULL)
616                 community = strdup (DEFAULT_COMMUNITY);
618         return validate_arguments ();
622 /******************************************************************************
624 @@-
625 <sect3>
626 <title>validate_arguments</title>
628 <para>&PROTO_validate_arguments;</para>
630 <para>Checks to see if the default miblist needs to be loaded. Also verifies
631 the authentication and authorization combinations based on protocol version
632 selected.</para>
634 <para></para>
636 </sect3>
637 -@@
638 ******************************************************************************/
642 int
643 validate_arguments ()
645         /* check whether to load locally installed MIBS (CPU/disk intensive) */
646         if (miblist == NULL) {
647                 if ( needmibs == TRUE ) {
648                         miblist = strdup (DEFAULT_MIBLIST);
649                 }else{
650                         miblist = "";                   /* don't read any mib files for numeric oids */
651                 }
652         }
654         /* Check server_address is given */
655         if (server_address == NULL)
656                 die(STATE_UNKNOWN, _("No host specified\n"));
658         /* Check oid is given */
659         if (numoids == 0)
660                 die(STATE_UNKNOWN, _("No OIDs specified\n"));
662         if (proto == NULL)
663                 asprintf(&proto, DEFAULT_PROTOCOL);
665         if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) {     /* snmpv1 or snmpv2c */
666                 numauthpriv = 2;
667                 authpriv = calloc (numauthpriv, sizeof (char *));
668                 authpriv[0] = strdup ("-c");
669                 authpriv[1] = strdup (community);
670         }
671         else if ( strcmp (proto, "3") == 0 ) {          /* snmpv3 args */
672                 if (seclevel == NULL)
673                         asprintf(&seclevel, "noAuthNoPriv");
675                 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
676                         numauthpriv = 2;
677                         authpriv = calloc (numauthpriv, sizeof (char *));
678                         authpriv[0] = strdup ("-l");
679                         authpriv[1] = strdup ("noAuthNoPriv");
680                 } else {
681                         if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
682                                 usage2 (_("Invalid seclevel"), seclevel);
683                         }
685                         if (authproto == NULL )
686                                 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
688                         if (secname == NULL)
689                                 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
691                         if (authpasswd == NULL)
692                                 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
694                         if ( strcmp(seclevel, "authNoPriv") == 0 ) {
695                                 numauthpriv = 8;
696                                 authpriv = calloc (numauthpriv, sizeof (char *));
697                                 authpriv[0] = strdup ("-l");
698                                 authpriv[1] = strdup ("authNoPriv");
699                                 authpriv[2] = strdup ("-a");
700                                 authpriv[3] = strdup (authproto);
701                                 authpriv[4] = strdup ("-u");
702                                 authpriv[5] = strdup (secname);
703                                 authpriv[6] = strdup ("-A");
704                                 authpriv[7] = strdup (authpasswd);
705                         } else if ( strcmp(seclevel, "authPriv") == 0 ) {
706                                 if (privproto == NULL )
707                                         asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
709                                 if (privpasswd == NULL)
710                                         die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
712                                 numauthpriv = 12;
713                                 authpriv = calloc (numauthpriv, sizeof (char *));
714                                 authpriv[0] = strdup ("-l");
715                                 authpriv[1] = strdup ("authPriv");
716                                 authpriv[2] = strdup ("-a");
717                                 authpriv[3] = strdup (authproto);
718                                 authpriv[4] = strdup ("-u");
719                                 authpriv[5] = strdup (secname);
720                                 authpriv[6] = strdup ("-A");
721                                 authpriv[7] = strdup (authpasswd);
722                                 authpriv[8] = strdup ("-x");
723                                 authpriv[9] = strdup (privproto);
724                                 authpriv[10] = strdup ("-X");
725                                 authpriv[11] = strdup (privpasswd);
726                         }
727                 }
729         }
730         else {
731                 usage2 (_("Invalid SNMP version"), proto);
732         }
734         return OK;
739 /* trim leading whitespace
740          if there is a leading quote, make sure it balances */
742 char *
743 thisarg (char *str)
745         str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
746         if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
747                 if (strlen (str) == 1 || !strstr (str + 1, "'"))
748                         die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
749         }
750         return str;
755 /* if there's a leading quote, advance to the trailing quote
756          set the trailing quote to '\x0'
757          if the string continues, advance beyond the comma */
759 char *
760 nextarg (char *str)
762         if (strstr (str, "'") == str) {
763                 str[0] = 0;
764                 if (strlen (str) > 1) {
765                         str = strstr (str + 1, "'");
766                         return (++str);
767                 }
768                 else {
769                         return NULL;
770                 }
771         }
772         if (strstr (str, ",") == str) {
773                 str[0] = 0;
774                 if (strlen (str) > 1) {
775                         return (++str);
776                 }
777                 else {
778                         return NULL;
779                 }
780         }
781         if ((str = strstr (str, ",")) && strlen (str) > 1) {
782                 str[0] = 0;
783                 return (++str);
784         }
785         return NULL;
790 void
791 print_help (void)
793         print_revision (progname, NP_VERSION);
795         printf (COPYRIGHT, copyright, email);
797         printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
799         printf ("\n\n");
801         print_usage ();
803         printf (_(UT_HELP_VRSN));
804         printf (_(UT_EXTRA_OPTS));
806         printf (_(UT_HOST_PORT), 'p', DEFAULT_PORT);
808         /* SNMP and Authentication Protocol */
809         printf (" %s\n", "-n, --next");
810         printf ("    %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
811         printf (" %s\n", "-P, --protocol=[1|2c|3]");
812         printf ("    %s\n", _("SNMP protocol version"));
813         printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
814         printf ("    %s\n", _("SNMPv3 securityLevel"));
815         printf (" %s\n", "-a, --authproto=[MD5|SHA]");
816         printf ("    %s\n", _("SNMPv3 auth proto"));
817         printf (" %s\n", "-x, --privproto=[DES|AES]");
818         printf ("    %s\n", _("SNMPv3 priv proto (default DES)"));
820         /* Authentication Tokens*/
821         printf (" %s\n", "-C, --community=STRING");
822         printf ("    %s ", _("Optional community string for SNMP communication"));
823         printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
824         printf (" %s\n", "-U, --secname=USERNAME");
825         printf ("    %s\n", _("SNMPv3 username"));
826         printf (" %s\n", "-A, --authpassword=PASSWORD");
827         printf ("    %s\n", _("SNMPv3 authentication password"));
828         printf (" %s\n", "-X, --privpasswd=PASSWORD");
829         printf ("    %s\n", _("SNMPv3 privacy password"));
831         /* OID Stuff */
832         printf (" %s\n", "-o, --oid=OID(s)");
833         printf ("    %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
834         printf (" %s\n", "-m, --miblist=STRING");
835         printf ("    %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
836         printf ("    %s\n", _("for symbolic OIDs.)"));
837         printf (" %s\n", "-d, --delimiter=STRING");
838         printf ("    %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
839         printf ("    %s\n", _("Any data on the right hand side of the delimiter is considered"));
840         printf ("    %s\n", _("to be the data that should be used in the evaluation."));
842         /* Tests Against Integers */
843         printf (" %s\n", "-w, --warning=THRESHOLD(s)");
844         printf ("    %s\n", _("Warning threshold range(s)"));
845         printf (" %s\n", "-c, --critical=THRESHOLD(s)");
846         printf ("    %s\n", _("Critical threshold range(s)"));
848         /* Tests Against Strings */
849         printf (" %s\n", "-s, --string=STRING");
850         printf ("    %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
851         printf (" %s\n", "-r, --ereg=REGEX");
852         printf ("    %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
853         printf (" %s\n", "-R, --eregi=REGEX");
854         printf ("    %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
855         printf (" %s\n", "-l, --label=STRING");
856         printf ("    %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
858         /* Output Formatting */
859         printf (" %s\n", "-u, --units=STRING");
860         printf ("    %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
861         printf (" %s\n", "-D, --output-delimiter=STRING");
862         printf ("    %s\n", _("Separates output on multiple OID requests"));
864         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
865         printf (" %s\n", "-e, --retries=INTEGER");
866         printf ("    %s\n", _("Number of retries to be used in the requests"));
868         printf (_(UT_VERBOSE));
870         printf ("\n");
871         printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
872         printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
873         printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
875         printf ("\n");
876         printf ("%s\n", _("Notes:"));
877         printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
878         printf ("   %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
880         printf(" -%s", _(UT_THRESHOLDS_NOTES));
882         printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
883         printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
884         printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
885         printf ("   %s\n", _("returned from the SNMP query is an unsigned integer."));
886 #ifdef NP_EXTRA_OPTS
887         printf (" -%s", _(UT_EXTRA_OPTS_NOTES));
888 #endif
890         printf (_(UT_SUPPORT));
895 void
896 print_usage (void)
898         printf (_("Usage:"));
899         printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
900         printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
901         printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
902         printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
903         printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");