Code

Fix whitespaces in check_snmp
[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 CRIT_GT 8
57 #define CRIT_LT 16
58 #define CRIT_GE 32
59 #define CRIT_LE 64
60 #define CRIT_EQ 128
61 #define CRIT_NE 256
62 #define CRIT_RANGE 512
63 #define WARN_PRESENT 1024
64 #define WARN_STRING 2048
65 #define WARN_REGEX 4096
66 #define WARN_GT 8192
67 #define WARN_LT 16384
68 #define WARN_GE 32768
69 #define WARN_LE 65536
70 #define WARN_EQ 131072
71 #define WARN_NE 262144
72 #define WARN_RANGE 524288
74 #define MAX_OIDS 8
75 #define MAX_DELIM_LENGTH 8
77 int process_arguments (int, char **);
78 int validate_arguments (void);
79 char *clarify_message (char *);
80 int check_num (int);
81 int llu_getll (unsigned long long *, char *);
82 int llu_getul (unsigned long long *, char *);
83 char *thisarg (char *str);
84 char *nextarg (char *str);
85 void print_usage (void);
86 void print_help (void);
88 #include "regex.h"
89 char regex_expect[MAX_INPUT_BUFFER] = "";
90 regex_t preg;
91 regmatch_t pmatch[10];
92 char timestamp[10] = "";
93 char errbuf[MAX_INPUT_BUFFER] = "";
94 char perfstr[MAX_INPUT_BUFFER] = "| ";
95 int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
96 int eflags = 0;
97 int errcode, excode;
99 char *server_address = NULL;
100 char *community = NULL;
101 char **authpriv = NULL;
102 char *proto = NULL;
103 char *seclevel = NULL;
104 char *secname = NULL;
105 char *authproto = NULL;
106 char *privproto = NULL;
107 char *authpasswd = NULL;
108 char *privpasswd = NULL;
109 char **oids = NULL;
110 char *label;
111 char *units;
112 char *port;
113 char *snmpcmd;
114 char string_value[MAX_INPUT_BUFFER] = "";
115 char **labels = NULL;
116 char **unitv = NULL;
117 size_t nlabels = 0;
118 size_t labels_size = 8;
119 size_t nunits = 0;
120 size_t unitv_size = 8;
121 int numoids = 0;
122 int numauthpriv = 0;
123 int verbose = FALSE;
124 int usesnmpgetnext = FALSE;
125 unsigned long long lower_warn_lim[MAX_OIDS];
126 unsigned long long upper_warn_lim[MAX_OIDS];
127 unsigned long long lower_crit_lim[MAX_OIDS];
128 unsigned long long upper_crit_lim[MAX_OIDS];
129 unsigned long long response_value[MAX_OIDS];
130 int check_warning_value = FALSE;
131 int check_critical_value = FALSE;
132 int retries = 0;
133 unsigned long long eval_method[MAX_OIDS];
134 char *delimiter;
135 char *output_delim;
136 char *miblist = NULL;
137 int needmibs = FALSE;
140 int
141 main (int argc, char **argv)
143         int i = 0;
144         int iresult = STATE_UNKNOWN;
145         int result = STATE_UNKNOWN;
146         int return_code = 0;
147         int external_error = 0;
148         char **command_line = NULL;
149         char *cl_hidden_auth = NULL;
150         char *oidname = NULL;
151         char *response = NULL;
152         char *outbuff;
153         char *ptr = NULL;
154         char *show = NULL;
155         char type[8] = "";
156         output chld_out, chld_err;
158         setlocale (LC_ALL, "");
159         bindtextdomain (PACKAGE, LOCALEDIR);
160         textdomain (PACKAGE);
162         labels = malloc (labels_size);
163         unitv = malloc (unitv_size);
164         for (i = 0; i < MAX_OIDS; i++)
165                 eval_method[i] = CHECK_UNDEF;
166         i = 0;
168         label = strdup ("SNMP");
169         units = strdup ("");
170         port = strdup (DEFAULT_PORT);
171         outbuff = strdup ("");
172         delimiter = strdup (" = ");
173         output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
174         /* miblist = strdup (DEFAULT_MIBLIST); */
175         timeout_interval = DEFAULT_TIMEOUT;
176         retries = DEFAULT_RETRIES;
178         /* Parse extra opts if any */
179         argv=np_extra_opts (&argc, argv, progname);
181         if (process_arguments (argc, argv) == ERROR)
182                 usage4 (_("Could not parse arguments"));
184         /* Create the command array to execute */
185         if(usesnmpgetnext == TRUE) {
186                 snmpcmd = strdup (PATH_TO_SNMPGETNEXT);
187         }else{
188                 snmpcmd = strdup (PATH_TO_SNMPGET);
189         }
190         
191         /* 9 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */
192         command_line = calloc (9 + numauthpriv + 1 + numoids + 1, sizeof (char *));
193         command_line[0] = snmpcmd;
194         command_line[1] = strdup ("-t");
195         asprintf (&command_line[2], "%d", timeout_interval);
196         command_line[3] = strdup ("-r");
197         asprintf (&command_line[4], "%d", retries);
198         command_line[5] = strdup ("-m");
199         command_line[6] = strdup (miblist);
200         command_line[7] = "-v";
201         command_line[8] = strdup (proto);
203         for (i = 0; i < numauthpriv; i++) {
204                 command_line[9 + i] = authpriv[i];
205         }
207         asprintf (&command_line[9 + numauthpriv], "%s:%s", server_address, port);
209         /* This is just for display purposes, so it can remain a string */
210         asprintf(&cl_hidden_auth, "%s -t %d -r %d -m %s -v %s %s %s:%s",
211                 snmpcmd, timeout_interval, retries, miblist, proto, "[authpriv]",
212                 server_address, port);
214         for (i = 0; i < numoids; i++) {
215                 command_line[9 + numauthpriv + 1 + i] = oids[i];
216                 asprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);    
217         }
219         command_line[9 + numauthpriv + 1 + numoids] = NULL;
221         if (verbose)
222                 printf ("%s\n", cl_hidden_auth);
224         /* Run the command */
225         return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0);
227         /* Due to net-snmp sometimes showing stderr messages with poorly formed MIBs,
228            only return state unknown if return code is non zero or there is no stdout.
229            Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
230         */
231         if (return_code != 0)
232                 external_error=1;
233         if (chld_out.lines == 0)
234                 external_error=1;
235         if (external_error) {
236                 if (chld_err.lines > 0) {
237                         printf (_("External command error: %s\n"), chld_err.line[0]);
238                         for (i = 1; i < chld_err.lines; i++) {
239                                 printf ("%s\n", chld_err.line[i]);
240                         }
241                 } else {
242                         printf(_("External command error with no output (return code: %d)\n"), return_code);
243                 }
244                 exit (STATE_UNKNOWN);
245         }
247         if (verbose) {
248                 for (i = 0; i < chld_out.lines; i++) {
249                         printf ("%s\n", chld_out.line[i]);
250                 }
251         }
253         for (i = 0; i < chld_out.lines; i++) {
254                 ptr = chld_out.line[i];
255                 oidname = strpcpy (oidname, ptr, delimiter);
256                 response = strstr (ptr, delimiter);
258                 /* We strip out the datatype indicator for PHBs */
260                 /* Clean up type array - Sol10 does not necessarily zero it out */
261                 bzero(type, sizeof(type));
263                 if (strstr (response, "Gauge: "))
264                         show = strstr (response, "Gauge: ") + 7;
265                 else if (strstr (response, "Gauge32: "))
266                         show = strstr (response, "Gauge32: ") + 9;
267                 else if (strstr (response, "Counter32: ")) {
268                         show = strstr (response, "Counter32: ") + 11;
269                         strcpy(type, "c");
270                 }
271                 else if (strstr (response, "Counter64: ")) {
272                         show = strstr (response, "Counter64: ") + 11;
273                         strcpy(type, "c");
274                 }
275                 else if (strstr (response, "INTEGER: "))
276                         show = strstr (response, "INTEGER: ") + 9;
277                 else if (strstr (response, "STRING: "))
278                         show = strstr (response, "STRING: ") + 8;
279                 else
280                         show = response;
282                 iresult = STATE_DEPENDENT;
284                 /* Process this block for integer comparisons */
285                 if (eval_method[i] & CRIT_GT ||
286                     eval_method[i] & CRIT_LT ||
287                     eval_method[i] & CRIT_GE ||
288                     eval_method[i] & CRIT_LE ||
289                     eval_method[i] & CRIT_EQ ||
290                     eval_method[i] & CRIT_NE ||
291                     eval_method[i] & WARN_GT ||
292                     eval_method[i] & WARN_LT ||
293                     eval_method[i] & WARN_GE ||
294                     eval_method[i] & WARN_LE ||
295                     eval_method[i] & WARN_EQ ||
296                     eval_method[i] & WARN_NE) {
297                         ptr = strpbrk (show, "0123456789");
298                         if (ptr == NULL)
299                                 die (STATE_UNKNOWN,_("No valid data returned"));
300                         response_value[i] = strtoul (ptr, NULL, 10);
301                         iresult = check_num (i);
302                         asprintf (&show, "%llu", response_value[i]);
303                 }
305                 /* Process this block for string matching */
306                 else if (eval_method[i] & CRIT_STRING) {
307                         if (strcmp (show, string_value))
308                                 iresult = STATE_CRITICAL;
309                         else
310                                 iresult = STATE_OK;
311                 }
313                 /* Process this block for regex matching */
314                 else if (eval_method[i] & CRIT_REGEX) {
315                         excode = regexec (&preg, response, 10, pmatch, eflags);
316                         if (excode == 0) {
317                                 iresult = STATE_OK;
318                         }
319                         else if (excode != REG_NOMATCH) {
320                                 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
321                                 printf (_("Execute Error: %s\n"), errbuf);
322                                 exit (STATE_CRITICAL);
323                         }
324                         else {
325                                 iresult = STATE_CRITICAL;
326                         }
327                 }
329                 /* Process this block for existence-nonexistence checks */
330                 else {
331                         if (eval_method[i] & CRIT_PRESENT)
332                                 iresult = STATE_CRITICAL;
333                         else if (eval_method[i] & WARN_PRESENT)
334                                 iresult = STATE_WARNING;
335                         else if (response && iresult == STATE_DEPENDENT)
336                                 iresult = STATE_OK;
337                 }
339                 /* Result is the worst outcome of all the OIDs tested */
340                 result = max_state (result, iresult);
342                 /* Prepend a label for this OID if there is one */
343                 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
344                         asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
345                                 (i == 0) ? " " : output_delim,
346                                 labels[i], mark (iresult), show, mark (iresult));
347                 else
348                         asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
349                                 mark (iresult), show, mark (iresult));
351                 /* Append a unit string for this OID if there is one */
352                 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
353                         asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
355                 if (is_numeric(show)) {
356                         strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
357                         strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
358                         strncat(perfstr, show, sizeof(perfstr)-strlen(perfstr)-1);
360                         if (type)
361                                 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
362                         strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
363                 }
364         }
366 /*      if (nunits == 1 || i == 1) */
367 /*              printf ("%s %s -%s %s\n", label, state_text (result), outbuff, units); */
368 /*      else */
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 = TRUE;
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 time threshold */
492                         if (strspn (optarg, "0123456789:,") < strlen (optarg))
493                                 usage2 (_("Invalid critical threshold"), optarg);
494                         for (ptr = optarg; ptr && jj < MAX_OIDS; jj++) {
495                                 if (llu_getll (&lower_crit_lim[jj], ptr) == 1)
496                                         eval_method[jj] |= CRIT_LT;
497                                 if (llu_getul (&upper_crit_lim[jj], ptr) == 1)
498                                         eval_method[jj] |= CRIT_GT;
499                                 (ptr = index (ptr, ',')) ? ptr++ : ptr;
500                         }
501                         break;
502                 case 'w':                                                                       /* warning time threshold */
503                         if (strspn (optarg, "0123456789:,") < strlen (optarg))
504                                 usage2 (_("Invalid warning threshold"), optarg);
505                         for (ptr = optarg; ptr && ii < MAX_OIDS; ii++) {
506                                 if (llu_getll (&lower_warn_lim[ii], ptr) == 1)
507                                         eval_method[ii] |= WARN_LT;
508                                 if (llu_getul (&upper_warn_lim[ii], ptr) == 1)
509                                         eval_method[ii] |= WARN_GT;
510                                 (ptr = index (ptr, ',')) ? ptr++ : ptr;
511                         }
512                         break;
513                 case 'e': /* PRELIMINARY - may change */
514                 case 'E': /* PRELIMINARY - may change */
515                         if (!is_integer (optarg))
516                                 usage2 (_("Retries interval must be a positive integer"), optarg);
517                         else
518                                 retries = atoi(optarg);
519                         break;
520                 case 'o':                                                                       /* object identifier */
521                         if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
522                                         /*
523                                          * we have something other than digits, periods and comas,
524                                          * so we have a mib variable, rather than just an SNMP OID,
525                                          * so we have to actually read the mib files
526                                          */
527                                         needmibs = TRUE;
528                         }
529                         oids = calloc(MAX_OIDS, sizeof (char *));
530                         for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
531                                 oids[j] = strdup(ptr);
532                         }
533                         numoids = j;
534                         if (c == 'E' || c == 'e') {
535                                 jj++;
536                                 ii++;
537                         }
538                         if (c == 'E')
539                                 eval_method[j+1] |= WARN_PRESENT;
540                         else if (c == 'e')
541                                 eval_method[j+1] |= CRIT_PRESENT;
542                         break;
543                 case 's':                                                                       /* string or substring */
544                         strncpy (string_value, optarg, sizeof (string_value) - 1);
545                         string_value[sizeof (string_value) - 1] = 0;
546                         eval_method[jj++] = CRIT_STRING;
547                         ii++;
548                         break;
549                 case 'R':                                                                       /* regex */
550                         cflags = REG_ICASE;
551                 case 'r':                                                                       /* regex */
552                         cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
553                         strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
554                         regex_expect[sizeof (regex_expect) - 1] = 0;
555                         errcode = regcomp (&preg, regex_expect, cflags);
556                         if (errcode != 0) {
557                                 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
558                                 printf (_("Could Not Compile Regular Expression"));
559                                 return ERROR;
560                         }
561                         eval_method[jj++] = CRIT_REGEX;
562                         ii++;
563                         break;
565         /* Format */
566                 case 'd':                                                                       /* delimiter */
567                         delimiter = strscpy (delimiter, optarg);
568                         break;
569                 case 'D':                                                                       /* output-delimiter */
570                         output_delim = strscpy (output_delim, optarg);
571                         break;
572                 case 'l':                                                                       /* label */
573                         label = optarg;
574                         nlabels++;
575                         if (nlabels >= labels_size) {
576                                 labels_size += 8;
577                                 labels = realloc (labels, labels_size);
578                                 if (labels == NULL)
579                                         die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
580                         }
581                         labels[nlabels - 1] = optarg;
582                         ptr = thisarg (optarg);
583                         labels[nlabels - 1] = ptr;
584                         if (strstr (ptr, "'") == ptr)
585                                 labels[nlabels - 1] = ptr + 1;
586                         while (ptr && (ptr = nextarg (ptr))) {
587                                 if (nlabels >= labels_size) {
588                                         labels_size += 8;
589                                         labels = realloc (labels, labels_size);
590                                         if (labels == NULL)
591                                                 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
592                                 }
593                                 labels++;
594                                 ptr = thisarg (ptr);
595                                 if (strstr (ptr, "'") == ptr)
596                                         labels[nlabels - 1] = ptr + 1;
597                                 else
598                                         labels[nlabels - 1] = ptr;
599                         }
600                         break;
601                 case 'u':                                                                       /* units */
602                         units = optarg;
603                         nunits++;
604                         if (nunits >= unitv_size) {
605                                 unitv_size += 8;
606                                 unitv = realloc (unitv, unitv_size);
607                                 if (unitv == NULL)
608                                         die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
609                         }
610                         unitv[nunits - 1] = optarg;
611                         ptr = thisarg (optarg);
612                         unitv[nunits - 1] = ptr;
613                         if (strstr (ptr, "'") == ptr)
614                                 unitv[nunits - 1] = ptr + 1;
615                         while (ptr && (ptr = nextarg (ptr))) {
616                                 if (nunits >= unitv_size) {
617                                         unitv_size += 8;
618                                         unitv = realloc (unitv, unitv_size);
619                                         if (units == NULL)
620                                                 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
621                                 }
622                                 nunits++;
623                                 ptr = thisarg (ptr);
624                                 if (strstr (ptr, "'") == ptr)
625                                         unitv[nunits - 1] = ptr + 1;
626                                 else
627                                         unitv[nunits - 1] = ptr;
628                         }
629                         break;
631                 }
632         }
634         if (server_address == NULL)
635                 server_address = argv[optind];
637         if (community == NULL)
638                 community = strdup (DEFAULT_COMMUNITY);
640         return validate_arguments ();
644 /******************************************************************************
646 @@-
647 <sect3>
648 <title>validate_arguments</title>
650 <para>&PROTO_validate_arguments;</para>
652 <para>Checks to see if the default miblist needs to be loaded. Also verifies
653 the authentication and authorization combinations based on protocol version
654 selected.</para>
656 <para></para>
658 </sect3>
659 -@@
660 ******************************************************************************/
664 int
665 validate_arguments ()
667         /* check whether to load locally installed MIBS (CPU/disk intensive) */
668         if (miblist == NULL) {
669                 if ( needmibs == TRUE ) {
670                         miblist = strdup (DEFAULT_MIBLIST);
671                 }else{
672                         miblist = "''";                 /* don't read any mib files for numeric oids */
673                 }
674         }
676         /* Check server_address is given */
677         if (server_address == NULL)
678                 die(STATE_UNKNOWN, _("No host specified\n"));
680         /* Check oid is given */
681         if (numoids == 0)
682                 die(STATE_UNKNOWN, _("No OIDs specified\n"));
684         if (proto == NULL)
685                 asprintf(&proto, DEFAULT_PROTOCOL);
687         if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) {     /* snmpv1 or snmpv2c */
688                 numauthpriv = 2;
689                 authpriv = calloc (numauthpriv, sizeof (char *));
690                 authpriv[0] = strdup ("-c");
691                 authpriv[1] = strdup (community);
692         }
693         else if ( strcmp (proto, "3") == 0 ) {          /* snmpv3 args */
694                 if (seclevel == NULL)
695                         asprintf(&seclevel, "noAuthNoPriv");
697                 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
698                         numauthpriv = 2;
699                         authpriv = calloc (numauthpriv, sizeof (char *));
700                         authpriv[0] = strdup ("-l");
701                         authpriv[1] = strdup ("noAuthNoPriv");
702                 } else {
703                         if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
704                                 usage2 (_("Invalid seclevel"), seclevel);
705                         }
707                         if (authproto == NULL )
708                                 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
710                         if (secname == NULL)
711                                 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
713                         if (authpasswd == NULL)
714                                 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
716                         if ( strcmp(seclevel, "authNoPriv") == 0 ) {
717                                 numauthpriv = 8;
718                                 authpriv = calloc (numauthpriv, sizeof (char *));
719                                 authpriv[0] = strdup ("-l");
720                                 authpriv[1] = strdup ("authNoPriv");
721                                 authpriv[2] = strdup ("-a");
722                                 authpriv[3] = strdup (authproto);
723                                 authpriv[4] = strdup ("-u");
724                                 authpriv[5] = strdup (secname);
725                                 authpriv[6] = strdup ("-A");
726                                 authpriv[7] = strdup (authpasswd);
727                         } else if ( strcmp(seclevel, "authPriv") == 0 ) {
728                                 if (privproto == NULL )
729                                         asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
731                                 if (privpasswd == NULL)
732                                         die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
734                                 numauthpriv = 12;
735                                 authpriv = calloc (numauthpriv, sizeof (char *));
736                                 authpriv[0] = strdup ("-l");
737                                 authpriv[1] = strdup ("authPriv");
738                                 authpriv[2] = strdup ("-a");
739                                 authpriv[3] = strdup (authproto);
740                                 authpriv[4] = strdup ("-u");
741                                 authpriv[5] = strdup (secname);
742                                 authpriv[6] = strdup ("-A");
743                                 authpriv[7] = strdup (authpasswd);
744                                 authpriv[8] = strdup ("-x");
745                                 authpriv[9] = strdup (privproto);
746                                 authpriv[10] = strdup ("-X");
747                                 authpriv[11] = strdup (privpasswd);
748                         }
749                 }
751         }
752         else {
753                 usage2 (_("Invalid SNMP version"), proto);
754         }
756         return OK;
761 char *
762 clarify_message (char *msg)
764         int i = 0;
765         int foo;
766         char tmpmsg_c[MAX_INPUT_BUFFER];
767         char *tmpmsg = (char *) &tmpmsg_c;
768         tmpmsg = strcpy (tmpmsg, msg);
769         if (!strncmp (tmpmsg, " Hex:", 5)) {
770                 tmpmsg = strtok (tmpmsg, ":");
771                 while ((tmpmsg = strtok (NULL, " "))) {
772                         foo = strtol (tmpmsg, NULL, 16);
773                         /* Translate chars that are not the same value in the printers
774                          * character set.
775                          */
776                         switch (foo) {
777                         case 208:
778                                 {
779                                         foo = 197;
780                                         break;
781                                 }
782                         case 216:
783                                 {
784                                         foo = 196;
785                                         break;
786                                 }
787                         }
788                         msg[i] = foo;
789                         i++;
790                 }
791                 msg[i] = 0;
792         }
793         return (msg);
798 int
799 check_num (int i)
801         int result;
802         result = STATE_OK;
803         if (eval_method[i] & WARN_GT && eval_method[i] & WARN_LT &&
804                         lower_warn_lim[i] > upper_warn_lim[i]) {
805                 if (response_value[i] <= lower_warn_lim[i] &&
806                                 response_value[i] >= upper_warn_lim[i]) {
807                         result = STATE_WARNING;
808                 }
809         }
810         else if
811                 ((eval_method[i] & WARN_GT && response_value[i] > upper_warn_lim[i]) ||
812                  (eval_method[i] & WARN_GE && response_value[i] >= upper_warn_lim[i]) ||
813                  (eval_method[i] & WARN_LT && response_value[i] < lower_warn_lim[i]) ||
814                  (eval_method[i] & WARN_LE && response_value[i] <= lower_warn_lim[i]) ||
815                  (eval_method[i] & WARN_EQ && response_value[i] == upper_warn_lim[i]) ||
816                  (eval_method[i] & WARN_NE && response_value[i] != upper_warn_lim[i])) {
817                 result = STATE_WARNING;
818         }
820         if (eval_method[i] & CRIT_GT && eval_method[i] & CRIT_LT &&
821                         lower_crit_lim[i] > upper_crit_lim[i]) {
822                 if (response_value[i] <= lower_crit_lim[i] &&
823                                 response_value[i] >= upper_crit_lim[i]) {
824                         result = STATE_CRITICAL;
825                 }
826         }
827         else if
828                 ((eval_method[i] & CRIT_GT && response_value[i] > upper_crit_lim[i]) ||
829                  (eval_method[i] & CRIT_GE && response_value[i] >= upper_crit_lim[i]) ||
830                  (eval_method[i] & CRIT_LT && response_value[i] < lower_crit_lim[i]) ||
831                  (eval_method[i] & CRIT_LE && response_value[i] <= lower_crit_lim[i]) ||
832                  (eval_method[i] & CRIT_EQ && response_value[i] == upper_crit_lim[i]) ||
833                  (eval_method[i] & CRIT_NE && response_value[i] != upper_crit_lim[i])) {
834                 result = STATE_CRITICAL;
835         }
837         return result;
842 int
843 llu_getll (unsigned long long *ll, char *str)
845         char tmp[100];
846         if (strchr (str, ':') == NULL)
847                 return 0;
848         if (strchr (str, ',') != NULL && (strchr (str, ',') < strchr (str, ':')))
849                 return 0;
850         if (sscanf (str, "%llu%[:]", ll, tmp) == 2)
851                 return 1;
852         return 0;
857 int
858 llu_getul (unsigned long long *ul, char *str)
860         char tmp[100];
861         if (sscanf (str, "%llu%[^,]", ul, tmp) == 1)
862                 return 1;
863         if (sscanf (str, ":%llu%[^,]", ul, tmp) == 1)
864                 return 1;
865         if (sscanf (str, "%*u:%llu%[^,]", ul, tmp) == 1)
866                 return 1;
867         return 0;
872 /* trim leading whitespace
873          if there is a leading quote, make sure it balances */
875 char *
876 thisarg (char *str)
878         str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
879         if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
880                 if (strlen (str) == 1 || !strstr (str + 1, "'"))
881                         die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
882         }
883         return str;
888 /* if there's a leading quote, advance to the trailing quote
889          set the trailing quote to '\x0'
890          if the string continues, advance beyond the comma */
892 char *
893 nextarg (char *str)
895         if (strstr (str, "'") == str) {
896                 str[0] = 0;
897                 if (strlen (str) > 1) {
898                         str = strstr (str + 1, "'");
899                         return (++str);
900                 }
901                 else {
902                         return NULL;
903                 }
904         }
905         if (strstr (str, ",") == str) {
906                 str[0] = 0;
907                 if (strlen (str) > 1) {
908                         return (++str);
909                 }
910                 else {
911                         return NULL;
912                 }
913         }
914         if ((str = strstr (str, ",")) && strlen (str) > 1) {
915                 str[0] = 0;
916                 return (++str);
917         }
918         return NULL;
923 void
924 print_help (void)
926         print_revision (progname, NP_VERSION);
928         printf (COPYRIGHT, copyright, email);
930         printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
932         printf ("\n\n");
934         print_usage ();
936         printf (_(UT_HELP_VRSN));
937         printf (_(UT_EXTRA_OPTS));
939         printf (_(UT_HOST_PORT), 'p', DEFAULT_PORT);
941         /* SNMP and Authentication Protocol */
942         printf (" %s\n", "-n, --next");
943         printf ("    %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
944         printf (" %s\n", "-P, --protocol=[1|2c|3]");
945         printf ("    %s\n", _("SNMP protocol version"));
946         printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
947         printf ("    %s\n", _("SNMPv3 securityLevel"));
948         printf (" %s\n", "-a, --authproto=[MD5|SHA]");
949         printf ("    %s\n", _("SNMPv3 auth proto"));
950         printf (" %s\n", "-x, --privproto=[DES|AES]");
951         printf ("    %s\n", _("SNMPv3 priv proto (default DES)"));
953         /* Authentication Tokens*/
954         printf (" %s\n", "-C, --community=STRING");
955         printf ("    %s ", _("Optional community string for SNMP communication"));
956         printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
957         printf (" %s\n", "-U, --secname=USERNAME");
958         printf ("    %s\n", _("SNMPv3 username"));
959         printf (" %s\n", "-A, --authpassword=PASSWORD");
960         printf ("    %s\n", _("SNMPv3 authentication password"));
961         printf (" %s\n", "-X, --privpasswd=PASSWORD");
962         printf ("    %s\n", _("SNMPv3 privacy password"));
964         /* OID Stuff */
965         printf (" %s\n", "-o, --oid=OID(s)");
966         printf ("    %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
967         printf (" %s\n", "-m, --miblist=STRING");
968         printf ("    %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
969         printf ("    %s\n", _("for symbolic OIDs.)"));
970         printf (" %s\n", "-d, --delimiter=STRING");
971         printf ("    %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
972         printf ("    %s\n", _("Any data on the right hand side of the delimiter is considered"));
973         printf ("    %s\n", _("to be the data that should be used in the evaluation."));
975         /* Tests Against Integers */
976         printf (" %s\n", "-w, --warning=INTEGER_RANGE(s)");
977         printf ("    %s\n", _("Range(s) which will not result in a WARNING status"));
978         printf (" %s\n", "-c, --critical=INTEGER_RANGE(s)");
979         printf ("    %s\n", _("Range(s) which will not result in a CRITICAL status"));
981         /* Tests Against Strings */
982         printf (" %s\n", "-s, --string=STRING");
983         printf ("    %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
984         printf (" %s\n", "-r, --ereg=REGEX");
985         printf ("    %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
986         printf (" %s\n", "-R, --eregi=REGEX");
987         printf ("    %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
988         printf (" %s\n", "-l, --label=STRING");
989         printf ("    %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
991         /* Output Formatting */
992         printf (" %s\n", "-u, --units=STRING");
993         printf ("    %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
994         printf (" %s\n", "-D, --output-delimiter=STRING");
995         printf ("    %s\n", _("Separates output on multiple OID requests"));
997         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
998         printf (" %s\n", "-e, --retries=INTEGER");
999         printf ("    %s\n", _("Number of retries to be used in the requests"));
1001         printf (_(UT_VERBOSE));
1003         printf ("\n");
1004         printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
1005         printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
1006         printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
1008         printf ("\n");
1009         printf ("%s\n", _("Notes:"));
1010         printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
1011         printf ("   %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
1013         printf (" %s\n", _("- Ranges are inclusive and are indicated with colons. When specified as"));
1014         printf ("   %s\n", _("'min:max' a STATE_OK will be returned if the result is within the indicated"));
1015         printf ("   %s\n", _("range or is equal to the upper or lower bound. A non-OK state will be"));
1016         printf ("   %s\n", _("returned if the result is outside the specified range."));
1018         printf (" %s\n", _("- If specified in the order 'max:min' a non-OK state will be returned if the"));
1019         printf ("   %s\n", _("result is within the (inclusive) range."));
1021         printf (" %s\n", _("- Upper or lower bounds may be omitted to skip checking the respective limit."));
1022         printf (" %s\n", _("- Bare integers are interpreted as upper limits."));
1023         printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
1024         printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
1025         printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
1026         printf ("   %s\n", _("returned from the SNMP query is an unsigned integer."));
1027 #ifdef NP_EXTRA_OPTS
1028         printf (" -%s", _(UT_EXTRA_OPTS_NOTES));
1029 #endif
1031         printf (_(UT_SUPPORT));
1036 void
1037 print_usage (void)
1039         printf (_("Usage:"));
1040         printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
1041         printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
1042         printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1043         printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
1044         printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");