Code

Whitespace indent fixes for check_pgsql
[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 = FALSE;
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, 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);
259                 /* We strip out the datatype indicator for PHBs */
261                 /* Clean up type array - Sol10 does not necessarily zero it out */
262                 bzero(type, sizeof(type));
264                 if (strstr (response, "Gauge: "))
265                         show = strstr (response, "Gauge: ") + 7;
266                 else if (strstr (response, "Gauge32: "))
267                         show = strstr (response, "Gauge32: ") + 9;
268                 else if (strstr (response, "Counter32: ")) {
269                         show = strstr (response, "Counter32: ") + 11;
270                         strcpy(type, "c");
271                 }
272                 else if (strstr (response, "Counter64: ")) {
273                         show = strstr (response, "Counter64: ") + 11;
274                         strcpy(type, "c");
275                 }
276                 else if (strstr (response, "INTEGER: "))
277                         show = strstr (response, "INTEGER: ") + 9;
278                 else if (strstr (response, "STRING: ")) {
279                         show = strstr (response, "STRING: ") + 8;
280                         conv = "%.10g";
281                 }
282                 else if (strstr (response, "Timeticks: "))
283                         show = strstr (response, "Timeticks: ");
284                 else
285                         show = response;
287                 iresult = STATE_DEPENDENT;
289                 /* Process this block for integer comparisons */
290                 if (thlds[i]->warning || thlds[i]->critical) {
291                         ptr = strpbrk (show, "0123456789");
292                         if (ptr == NULL)
293                                 die (STATE_UNKNOWN,_("No valid data returned"));
294                         response_value[i] = strtod (ptr, NULL);
295                         iresult = get_status(response_value[i], thlds[i]);
296                         asprintf (&show, conv, response_value[i]);
297                 }
299                 /* Process this block for string matching */
300                 else if (eval_method[i] & CRIT_STRING) {
301                         if (strcmp (show, string_value))
302                                 iresult = STATE_CRITICAL;
303                         else
304                                 iresult = STATE_OK;
305                 }
307                 /* Process this block for regex matching */
308                 else if (eval_method[i] & CRIT_REGEX) {
309                         excode = regexec (&preg, response, 10, pmatch, eflags);
310                         if (excode == 0) {
311                                 iresult = STATE_OK;
312                         }
313                         else if (excode != REG_NOMATCH) {
314                                 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
315                                 printf (_("Execute Error: %s\n"), errbuf);
316                                 exit (STATE_CRITICAL);
317                         }
318                         else {
319                                 iresult = STATE_CRITICAL;
320                         }
321                 }
323                 /* Process this block for existence-nonexistence checks */
324                 else {
325                         if (eval_method[i] & CRIT_PRESENT)
326                                 iresult = STATE_CRITICAL;
327                         else if (eval_method[i] & WARN_PRESENT)
328                                 iresult = STATE_WARNING;
329                         else if (response && iresult == STATE_DEPENDENT)
330                                 iresult = STATE_OK;
331                 }
333                 /* Result is the worst outcome of all the OIDs tested */
334                 result = max_state (result, iresult);
336                 /* Prepend a label for this OID if there is one */
337                 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
338                         asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
339                                 (i == 0) ? " " : output_delim,
340                                 labels[i], mark (iresult), show, mark (iresult));
341                 else
342                         asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
343                                 mark (iresult), show, mark (iresult));
345                 /* Append a unit string for this OID if there is one */
346                 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
347                         asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
349                 if (is_numeric(show)) {
350                         strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
351                         strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
352                         strncat(perfstr, show, sizeof(perfstr)-strlen(perfstr)-1);
354                         if (type)
355                                 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
356                         strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
357                 }
358         }
360         printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
362         return result;
367 /* process command-line arguments */
368 int
369 process_arguments (int argc, char **argv)
371         char *ptr;
372         int c = 1;
373         int j = 0, jj = 0, ii = 0;
375         int option = 0;
376         static struct option longopts[] = {
377                 STD_LONG_OPTS,
378                 {"community", required_argument, 0, 'C'},
379                 {"oid", required_argument, 0, 'o'},
380                 {"object", required_argument, 0, 'o'},
381                 {"delimiter", required_argument, 0, 'd'},
382                 {"output-delimiter", required_argument, 0, 'D'},
383                 {"string", required_argument, 0, 's'},
384                 {"timeout", required_argument, 0, 't'},
385                 {"regex", required_argument, 0, 'r'},
386                 {"ereg", required_argument, 0, 'r'},
387                 {"eregi", required_argument, 0, 'R'},
388                 {"label", required_argument, 0, 'l'},
389                 {"units", required_argument, 0, 'u'},
390                 {"port", required_argument, 0, 'p'},
391                 {"retries", required_argument, 0, 'e'},
392                 {"miblist", required_argument, 0, 'm'},
393                 {"protocol", required_argument, 0, 'P'},
394                 {"seclevel", required_argument, 0, 'L'},
395                 {"secname", required_argument, 0, 'U'},
396                 {"authproto", required_argument, 0, 'a'},
397                 {"privproto", required_argument, 0, 'x'},
398                 {"authpasswd", required_argument, 0, 'A'},
399                 {"privpasswd", required_argument, 0, 'X'},
400                 {"next", no_argument, 0, 'n'},
401                 {0, 0, 0, 0}
402         };
404         if (argc < 2)
405                 return ERROR;
407         /* reverse compatibility for very old non-POSIX usage forms */
408         for (c = 1; c < argc; c++) {
409                 if (strcmp ("-to", argv[c]) == 0)
410                         strcpy (argv[c], "-t");
411                 if (strcmp ("-wv", argv[c]) == 0)
412                         strcpy (argv[c], "-w");
413                 if (strcmp ("-cv", argv[c]) == 0)
414                         strcpy (argv[c], "-c");
415         }
417         while (1) {
418                 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:",
419                                                                          longopts, &option);
421                 if (c == -1 || c == EOF)
422                         break;
424                 switch (c) {
425                 case '?':       /* usage */
426                         usage5 ();
427                 case 'h':       /* help */
428                         print_help ();
429                         exit (STATE_OK);
430                 case 'V':       /* version */
431                         print_revision (progname, NP_VERSION);
432                         exit (STATE_OK);
433                 case 'v': /* verbose */
434                         verbose = TRUE;
435                         break;
437         /* Connection info */
438                 case 'C':                                                                       /* group or community */
439                         community = optarg;
440                         break;
441                 case 'H':                                                                       /* Host or server */
442                         server_address = optarg;
443                         break;
444                 case 'p':       /* TCP port number */
445                         port = optarg;
446                         break;
447                 case 'm':       /* List of MIBS */
448                         miblist = optarg;
449                         break;
450                 case 'n':       /* usesnmpgetnext */
451                         usesnmpgetnext = TRUE;
452                         break;
453                 case 'P':       /* SNMP protocol version */
454                         proto = optarg;
455                         break;
456                 case 'L':       /* security level */
457                         seclevel = optarg;
458                         break;
459                 case 'U':       /* security username */
460                         secname = optarg;
461                         break;
462                 case 'a':       /* auth protocol */
463                         authproto = optarg;
464                         break;
465                 case 'x':       /* priv protocol */
466                         privproto = optarg;
467                         break;
468                 case 'A':       /* auth passwd */
469                         authpasswd = optarg;
470                         break;
471                 case 'X':       /* priv passwd */
472                         privpasswd = optarg;
473                         break;
474                 case 't':       /* timeout period */
475                         if (!is_integer (optarg))
476                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
477                         else
478                                 timeout_interval = atoi (optarg);
479                         break;
481         /* Test parameters */
482                 case 'c':                                                                       /* critical threshold */
483                         critical_thresholds = optarg;
484                         break;
485                 case 'w':                                                                       /* warning threshold */
486                         warning_thresholds = optarg;
487                         break;
488                 case 'e': /* PRELIMINARY - may change */
489                 case 'E': /* PRELIMINARY - may change */
490                         if (!is_integer (optarg))
491                                 usage2 (_("Retries interval must be a positive integer"), optarg);
492                         else
493                                 retries = atoi(optarg);
494                         break;
495                 case 'o':                                                                       /* object identifier */
496                         if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
497                                         /*
498                                          * we have something other than digits, periods and comas,
499                                          * so we have a mib variable, rather than just an SNMP OID,
500                                          * so we have to actually read the mib files
501                                          */
502                                         needmibs = TRUE;
503                         }
504                         oids = calloc(MAX_OIDS, sizeof (char *));
505                         for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
506                                 oids[j] = strdup(ptr);
507                         }
508                         numoids = j;
509                         if (c == 'E' || c == 'e') {
510                                 jj++;
511                                 ii++;
512                         }
513                         if (c == 'E')
514                                 eval_method[j+1] |= WARN_PRESENT;
515                         else if (c == 'e')
516                                 eval_method[j+1] |= CRIT_PRESENT;
517                         break;
518                 case 's':                                                                       /* string or substring */
519                         strncpy (string_value, optarg, sizeof (string_value) - 1);
520                         string_value[sizeof (string_value) - 1] = 0;
521                         eval_method[jj++] = CRIT_STRING;
522                         ii++;
523                         break;
524                 case 'R':                                                                       /* regex */
525                         cflags = REG_ICASE;
526                 case 'r':                                                                       /* regex */
527                         cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
528                         strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
529                         regex_expect[sizeof (regex_expect) - 1] = 0;
530                         errcode = regcomp (&preg, regex_expect, cflags);
531                         if (errcode != 0) {
532                                 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
533                                 printf (_("Could Not Compile Regular Expression"));
534                                 return ERROR;
535                         }
536                         eval_method[jj++] = CRIT_REGEX;
537                         ii++;
538                         break;
540         /* Format */
541                 case 'd':                                                                       /* delimiter */
542                         delimiter = strscpy (delimiter, optarg);
543                         break;
544                 case 'D':                                                                       /* output-delimiter */
545                         output_delim = strscpy (output_delim, optarg);
546                         break;
547                 case 'l':                                                                       /* label */
548                         label = optarg;
549                         nlabels++;
550                         if (nlabels >= labels_size) {
551                                 labels_size += 8;
552                                 labels = realloc (labels, labels_size);
553                                 if (labels == NULL)
554                                         die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
555                         }
556                         labels[nlabels - 1] = optarg;
557                         ptr = thisarg (optarg);
558                         labels[nlabels - 1] = ptr;
559                         if (strstr (ptr, "'") == ptr)
560                                 labels[nlabels - 1] = ptr + 1;
561                         while (ptr && (ptr = nextarg (ptr))) {
562                                 if (nlabels >= labels_size) {
563                                         labels_size += 8;
564                                         labels = realloc (labels, labels_size);
565                                         if (labels == NULL)
566                                                 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
567                                 }
568                                 labels++;
569                                 ptr = thisarg (ptr);
570                                 if (strstr (ptr, "'") == ptr)
571                                         labels[nlabels - 1] = ptr + 1;
572                                 else
573                                         labels[nlabels - 1] = ptr;
574                         }
575                         break;
576                 case 'u':                                                                       /* units */
577                         units = optarg;
578                         nunits++;
579                         if (nunits >= unitv_size) {
580                                 unitv_size += 8;
581                                 unitv = realloc (unitv, unitv_size);
582                                 if (unitv == NULL)
583                                         die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
584                         }
585                         unitv[nunits - 1] = optarg;
586                         ptr = thisarg (optarg);
587                         unitv[nunits - 1] = ptr;
588                         if (strstr (ptr, "'") == ptr)
589                                 unitv[nunits - 1] = ptr + 1;
590                         while (ptr && (ptr = nextarg (ptr))) {
591                                 if (nunits >= unitv_size) {
592                                         unitv_size += 8;
593                                         unitv = realloc (unitv, unitv_size);
594                                         if (units == NULL)
595                                                 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
596                                 }
597                                 nunits++;
598                                 ptr = thisarg (ptr);
599                                 if (strstr (ptr, "'") == ptr)
600                                         unitv[nunits - 1] = ptr + 1;
601                                 else
602                                         unitv[nunits - 1] = ptr;
603                         }
604                         break;
606                 }
607         }
609         if (server_address == NULL)
610                 server_address = argv[optind];
612         if (community == NULL)
613                 community = strdup (DEFAULT_COMMUNITY);
615         return validate_arguments ();
619 /******************************************************************************
621 @@-
622 <sect3>
623 <title>validate_arguments</title>
625 <para>&PROTO_validate_arguments;</para>
627 <para>Checks to see if the default miblist needs to be loaded. Also verifies
628 the authentication and authorization combinations based on protocol version
629 selected.</para>
631 <para></para>
633 </sect3>
634 -@@
635 ******************************************************************************/
639 int
640 validate_arguments ()
642         /* check whether to load locally installed MIBS (CPU/disk intensive) */
643         if (miblist == NULL) {
644                 if ( needmibs == TRUE ) {
645                         miblist = strdup (DEFAULT_MIBLIST);
646                 }else{
647                         miblist = "''";                 /* don't read any mib files for numeric oids */
648                 }
649         }
651         /* Check server_address is given */
652         if (server_address == NULL)
653                 die(STATE_UNKNOWN, _("No host specified\n"));
655         /* Check oid is given */
656         if (numoids == 0)
657                 die(STATE_UNKNOWN, _("No OIDs specified\n"));
659         if (proto == NULL)
660                 asprintf(&proto, DEFAULT_PROTOCOL);
662         if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) {     /* snmpv1 or snmpv2c */
663                 numauthpriv = 2;
664                 authpriv = calloc (numauthpriv, sizeof (char *));
665                 authpriv[0] = strdup ("-c");
666                 authpriv[1] = strdup (community);
667         }
668         else if ( strcmp (proto, "3") == 0 ) {          /* snmpv3 args */
669                 if (seclevel == NULL)
670                         asprintf(&seclevel, "noAuthNoPriv");
672                 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
673                         numauthpriv = 2;
674                         authpriv = calloc (numauthpriv, sizeof (char *));
675                         authpriv[0] = strdup ("-l");
676                         authpriv[1] = strdup ("noAuthNoPriv");
677                 } else {
678                         if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
679                                 usage2 (_("Invalid seclevel"), seclevel);
680                         }
682                         if (authproto == NULL )
683                                 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
685                         if (secname == NULL)
686                                 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
688                         if (authpasswd == NULL)
689                                 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
691                         if ( strcmp(seclevel, "authNoPriv") == 0 ) {
692                                 numauthpriv = 8;
693                                 authpriv = calloc (numauthpriv, sizeof (char *));
694                                 authpriv[0] = strdup ("-l");
695                                 authpriv[1] = strdup ("authNoPriv");
696                                 authpriv[2] = strdup ("-a");
697                                 authpriv[3] = strdup (authproto);
698                                 authpriv[4] = strdup ("-u");
699                                 authpriv[5] = strdup (secname);
700                                 authpriv[6] = strdup ("-A");
701                                 authpriv[7] = strdup (authpasswd);
702                         } else if ( strcmp(seclevel, "authPriv") == 0 ) {
703                                 if (privproto == NULL )
704                                         asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
706                                 if (privpasswd == NULL)
707                                         die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
709                                 numauthpriv = 12;
710                                 authpriv = calloc (numauthpriv, sizeof (char *));
711                                 authpriv[0] = strdup ("-l");
712                                 authpriv[1] = strdup ("authPriv");
713                                 authpriv[2] = strdup ("-a");
714                                 authpriv[3] = strdup (authproto);
715                                 authpriv[4] = strdup ("-u");
716                                 authpriv[5] = strdup (secname);
717                                 authpriv[6] = strdup ("-A");
718                                 authpriv[7] = strdup (authpasswd);
719                                 authpriv[8] = strdup ("-x");
720                                 authpriv[9] = strdup (privproto);
721                                 authpriv[10] = strdup ("-X");
722                                 authpriv[11] = strdup (privpasswd);
723                         }
724                 }
726         }
727         else {
728                 usage2 (_("Invalid SNMP version"), proto);
729         }
731         return OK;
736 /* trim leading whitespace
737          if there is a leading quote, make sure it balances */
739 char *
740 thisarg (char *str)
742         str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
743         if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
744                 if (strlen (str) == 1 || !strstr (str + 1, "'"))
745                         die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
746         }
747         return str;
752 /* if there's a leading quote, advance to the trailing quote
753          set the trailing quote to '\x0'
754          if the string continues, advance beyond the comma */
756 char *
757 nextarg (char *str)
759         if (strstr (str, "'") == str) {
760                 str[0] = 0;
761                 if (strlen (str) > 1) {
762                         str = strstr (str + 1, "'");
763                         return (++str);
764                 }
765                 else {
766                         return NULL;
767                 }
768         }
769         if (strstr (str, ",") == str) {
770                 str[0] = 0;
771                 if (strlen (str) > 1) {
772                         return (++str);
773                 }
774                 else {
775                         return NULL;
776                 }
777         }
778         if ((str = strstr (str, ",")) && strlen (str) > 1) {
779                 str[0] = 0;
780                 return (++str);
781         }
782         return NULL;
787 void
788 print_help (void)
790         print_revision (progname, NP_VERSION);
792         printf (COPYRIGHT, copyright, email);
794         printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
796         printf ("\n\n");
798         print_usage ();
800         printf (_(UT_HELP_VRSN));
801         printf (_(UT_EXTRA_OPTS));
803         printf (_(UT_HOST_PORT), 'p', DEFAULT_PORT);
805         /* SNMP and Authentication Protocol */
806         printf (" %s\n", "-n, --next");
807         printf ("    %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
808         printf (" %s\n", "-P, --protocol=[1|2c|3]");
809         printf ("    %s\n", _("SNMP protocol version"));
810         printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
811         printf ("    %s\n", _("SNMPv3 securityLevel"));
812         printf (" %s\n", "-a, --authproto=[MD5|SHA]");
813         printf ("    %s\n", _("SNMPv3 auth proto"));
814         printf (" %s\n", "-x, --privproto=[DES|AES]");
815         printf ("    %s\n", _("SNMPv3 priv proto (default DES)"));
817         /* Authentication Tokens*/
818         printf (" %s\n", "-C, --community=STRING");
819         printf ("    %s ", _("Optional community string for SNMP communication"));
820         printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
821         printf (" %s\n", "-U, --secname=USERNAME");
822         printf ("    %s\n", _("SNMPv3 username"));
823         printf (" %s\n", "-A, --authpassword=PASSWORD");
824         printf ("    %s\n", _("SNMPv3 authentication password"));
825         printf (" %s\n", "-X, --privpasswd=PASSWORD");
826         printf ("    %s\n", _("SNMPv3 privacy password"));
828         /* OID Stuff */
829         printf (" %s\n", "-o, --oid=OID(s)");
830         printf ("    %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
831         printf (" %s\n", "-m, --miblist=STRING");
832         printf ("    %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
833         printf ("    %s\n", _("for symbolic OIDs.)"));
834         printf (" %s\n", "-d, --delimiter=STRING");
835         printf ("    %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
836         printf ("    %s\n", _("Any data on the right hand side of the delimiter is considered"));
837         printf ("    %s\n", _("to be the data that should be used in the evaluation."));
839         /* Tests Against Integers */
840         printf (" %s\n", "-w, --warning=THRESHOLD(s)");
841         printf ("    %s\n", _("Warning threshold range(s)"));
842         printf (" %s\n", "-c, --critical=THRESHOLD(s)");
843         printf ("    %s\n", _("Critical threshold range(s)"));
845         /* Tests Against Strings */
846         printf (" %s\n", "-s, --string=STRING");
847         printf ("    %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
848         printf (" %s\n", "-r, --ereg=REGEX");
849         printf ("    %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
850         printf (" %s\n", "-R, --eregi=REGEX");
851         printf ("    %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
852         printf (" %s\n", "-l, --label=STRING");
853         printf ("    %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
855         /* Output Formatting */
856         printf (" %s\n", "-u, --units=STRING");
857         printf ("    %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
858         printf (" %s\n", "-D, --output-delimiter=STRING");
859         printf ("    %s\n", _("Separates output on multiple OID requests"));
861         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
862         printf (" %s\n", "-e, --retries=INTEGER");
863         printf ("    %s\n", _("Number of retries to be used in the requests"));
865         printf (_(UT_VERBOSE));
867         printf ("\n");
868         printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
869         printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
870         printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
872         printf ("\n");
873         printf ("%s\n", _("Notes:"));
874         printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
875         printf ("   %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
877         printf(" -%s", _(UT_THRESHOLDS_NOTES));
879         printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
880         printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
881         printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
882         printf ("   %s\n", _("returned from the SNMP query is an unsigned integer."));
883 #ifdef NP_EXTRA_OPTS
884         printf (" -%s", _(UT_EXTRA_OPTS_NOTES));
885 #endif
887         printf (_(UT_SUPPORT));
892 void
893 print_usage (void)
895         printf (_("Usage:"));
896         printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
897         printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
898         printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
899         printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
900         printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");