Code

dcb31386478e9b191ed8864c8681362fdde0a6ed
[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         }
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 (response == NULL)
259                         break;
261                 if (verbose > 2) {
262                         printf("Processing line %i\n  oidname: %s\n  response: %s\n", i+1, oidname, response);
263                 }
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");
276                 }
277                 else if (strstr (response, "Counter64: ")) {
278                         show = strstr (response, "Counter64: ") + 11;
279                         strcpy(type, "c");
280                 }
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";
286                 }
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]);
302                 }
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;
310                 }
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;
317                         }
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);
322                         }
323                         else {
324                                 iresult = STATE_CRITICAL;
325                         }
326                 }
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;
336                 }
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);
362                 }
363         }
365         printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
367         return result;
372 /* process command-line arguments */
373 int
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}
407         };
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");
420         }
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 ) ) {
502                                         /*
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
506                                          */
507                                         needmibs = TRUE;
508                         }
509                         if (!oids) 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);
512                         }
513                         numoids = j;
514                         if (c == 'E' || c == 'e') {
515                                 jj++;
516                                 ii++;
517                         }
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;
540                         }
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);
560                         }
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"));
572                                 }
573                                 labels++;
574                                 ptr = thisarg (ptr);
575                                 if (strstr (ptr, "'") == ptr)
576                                         labels[nlabels - 1] = ptr + 1;
577                                 else
578                                         labels[nlabels - 1] = ptr;
579                         }
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);
589                         }
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"));
601                                 }
602                                 nunits++;
603                                 ptr = thisarg (ptr);
604                                 if (strstr (ptr, "'") == ptr)
605                                         unitv[nunits - 1] = ptr + 1;
606                                 else
607                                         unitv[nunits - 1] = ptr;
608                         }
609                         break;
611                 }
612         }
614         if (server_address == NULL)
615                 server_address = argv[optind];
617         if (community == NULL)
618                 community = strdup (DEFAULT_COMMUNITY);
620         return validate_arguments ();
624 /******************************************************************************
626 @@-
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>
639 -@@
640 ******************************************************************************/
644 int
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 */
653                 }
654         }
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);
672         }
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);
685                         }
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);
728                         }
729                 }
731         }
732         else {
733                 usage2 (_("Invalid SNMP version"), proto);
734         }
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"));
751         }
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);
769                 }
770                 else {
771                         return NULL;
772                 }
773         }
774         if (strstr (str, ",") == str) {
775                 str[0] = 0;
776                 if (strlen (str) > 1) {
777                         return (++str);
778                 }
779                 else {
780                         return NULL;
781                 }
782         }
783         if ((str = strstr (str, ",")) && strlen (str) > 1) {
784                 str[0] = 0;
785                 return (++str);
786         }
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");