Code

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