Code

Attempt at fixing check_snmp multiline output:
[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, line;
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 *mult_resp = NULL;
130         char *outbuff;
131         char *ptr = NULL;
132         char *show = NULL;
133         char *th_warn=NULL;
134         char *th_crit=NULL;
135         char type[8] = "";
136         output chld_out, chld_err;
138         setlocale (LC_ALL, "");
139         bindtextdomain (PACKAGE, LOCALEDIR);
140         textdomain (PACKAGE);
142         labels = malloc (labels_size);
143         unitv = malloc (unitv_size);
144         for (i = 0; i < MAX_OIDS; i++)
145                 eval_method[i] = CHECK_UNDEF;
147         label = strdup ("SNMP");
148         units = strdup ("");
149         port = strdup (DEFAULT_PORT);
150         outbuff = strdup ("");
151         delimiter = strdup (" = ");
152         output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
153         timeout_interval = DEFAULT_TIMEOUT;
154         retries = DEFAULT_RETRIES;
156         /* Parse extra opts if any */
157         argv=np_extra_opts (&argc, argv, progname);
159         if (process_arguments (argc, argv) == ERROR)
160                 usage4 (_("Could not parse arguments"));
162         /* Populate the thresholds */
163         th_warn=warning_thresholds;
164         th_crit=critical_thresholds;
165         for (i=0; i<numoids; i++) {
166                 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
167                 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
168                 /* Skip empty thresholds, while avoiding segfault */
169                 set_thresholds(&thlds[i],
170                                w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
171                                c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
172                 if (w) {
173                         th_warn=strchr(th_warn, ',');
174                         if (th_warn) th_warn++;
175                         free(w);
176                 }
177                 if (c) {
178                         th_crit=strchr(th_crit, ',');
179                         if (th_crit) th_crit++;
180                         free(c);
181                 }
182         }
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         }
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, strlen(miblist) ? 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 (line=0, i=0; line < chld_out.lines; line++, i++) {
254                 const char *conv = "%.0f";
256                 ptr = chld_out.line[line];
257                 oidname = strpcpy (oidname, ptr, delimiter);
258                 response = strstr (ptr, delimiter);
259                 if (response == NULL)
260                         break;
262                 if (verbose > 2) {
263                         printf("Processing line %i\n  oidname: %s\n  response: %s\n", i+1, oidname, response);
264                 }
266                 /* Clean up type array - Sol10 does not necessarily zero it out */
267                 bzero(type, sizeof(type));
269                 /* We strip out the datatype indicator for PHBs */
270                 if (strstr (response, "Gauge: "))
271                         show = strstr (response, "Gauge: ") + 7;
272                 else if (strstr (response, "Gauge32: "))
273                         show = strstr (response, "Gauge32: ") + 9;
274                 else if (strstr (response, "Counter32: ")) {
275                         show = strstr (response, "Counter32: ") + 11;
276                         strcpy(type, "c");
277                 }
278                 else if (strstr (response, "Counter64: ")) {
279                         show = strstr (response, "Counter64: ") + 11;
280                         strcpy(type, "c");
281                 }
282                 else if (strstr (response, "INTEGER: "))
283                         show = strstr (response, "INTEGER: ") + 9;
284                 else if (strstr (response, "STRING: ")) {
285                         show = strstr (response, "STRING: ") + 8;
286                         conv = "%.10g";
287                         /* Get the rest of the string on multi-line strings */
288                         if (show[0] == '"' && (response[strlen(response)-1] != '\"' || response[strlen(response)-2] != '\\')) {
289                                 /* Strip out unmatched double-quote */
290                                 if (show[0] == '"') show++;
291                                 if (!mult_resp) mult_resp = strdup("");
292                                 asprintf (&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], strstr (response, "STRING: ") + 8);
293                                 for (line++; line < chld_out.lines; line++) {
294                                         asprintf (&mult_resp, "%s%s\n", mult_resp, chld_out.line[line]);
295                                         if (mult_resp[strlen(mult_resp)-2] == '"' && response[strlen(response)-2] != '\\') break;
296                                 }
297                         }
299                 }
300                 else if (strstr (response, "Timeticks: "))
301                         show = strstr (response, "Timeticks: ");
302                 else
303                         show = response;
305                 iresult = STATE_DEPENDENT;
307                 /* Process this block for integer comparisons */
308                 if (thlds[i]->warning || thlds[i]->critical) {
309                         ptr = strpbrk (show, "0123456789");
310                         if (ptr == NULL)
311                                 die (STATE_UNKNOWN,_("No valid data returned"));
312                         response_value[i] = strtod (ptr, NULL);
313                         iresult = get_status(response_value[i], thlds[i]);
314                         asprintf (&show, conv, response_value[i]);
315                 }
317                 /* Process this block for string matching */
318                 else if (eval_method[i] & CRIT_STRING) {
319                         if (strcmp (show, string_value))
320                                 iresult = STATE_CRITICAL;
321                         else
322                                 iresult = STATE_OK;
323                 }
325                 /* Process this block for regex matching */
326                 else if (eval_method[i] & CRIT_REGEX) {
327                         excode = regexec (&preg, response, 10, pmatch, eflags);
328                         if (excode == 0) {
329                                 iresult = STATE_OK;
330                         }
331                         else if (excode != REG_NOMATCH) {
332                                 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
333                                 printf (_("Execute Error: %s\n"), errbuf);
334                                 exit (STATE_CRITICAL);
335                         }
336                         else {
337                                 iresult = STATE_CRITICAL;
338                         }
339                 }
341                 /* Process this block for existence-nonexistence checks */
342                 else {
343                         if (eval_method[i] & CRIT_PRESENT)
344                                 iresult = STATE_CRITICAL;
345                         else if (eval_method[i] & WARN_PRESENT)
346                                 iresult = STATE_WARNING;
347                         else if (response && iresult == STATE_DEPENDENT)
348                                 iresult = STATE_OK;
349                 }
351                 /* Result is the worst outcome of all the OIDs tested */
352                 result = max_state (result, iresult);
354                 /* Prepend a label for this OID if there is one */
355                 if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
356                         asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
357                                 (i == 0) ? " " : output_delim,
358                                 labels[i], mark (iresult), show, mark (iresult));
359                 else
360                         asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
361                                 mark (iresult), show, mark (iresult));
363                 /* Append a unit string for this OID if there is one */
364                 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
365                         asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
367                 /* Write perfdata with whatever can be parsed by strtod, if possible */
368                 ptr = NULL;
369                 strtod(show, &ptr);
370                 if (ptr > show) {
371                         strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
372                         strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
373                         len = sizeof(perfstr)-strlen(perfstr)-1;
374                         strncat(perfstr, show, len>ptr-show ? ptr-show : len);
376                         if (type)
377                                 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
378                         strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
379                 }
380         }
382         printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
383         if (mult_resp) printf ("%s", mult_resp);
385         return result;
390 /* process command-line arguments */
391 int
392 process_arguments (int argc, char **argv)
394         char *ptr;
395         int c = 1;
396         int j = 0, jj = 0, ii = 0;
398         int option = 0;
399         static struct option longopts[] = {
400                 STD_LONG_OPTS,
401                 {"community", required_argument, 0, 'C'},
402                 {"oid", required_argument, 0, 'o'},
403                 {"object", required_argument, 0, 'o'},
404                 {"delimiter", required_argument, 0, 'd'},
405                 {"output-delimiter", required_argument, 0, 'D'},
406                 {"string", required_argument, 0, 's'},
407                 {"timeout", required_argument, 0, 't'},
408                 {"regex", required_argument, 0, 'r'},
409                 {"ereg", required_argument, 0, 'r'},
410                 {"eregi", required_argument, 0, 'R'},
411                 {"label", required_argument, 0, 'l'},
412                 {"units", required_argument, 0, 'u'},
413                 {"port", required_argument, 0, 'p'},
414                 {"retries", required_argument, 0, 'e'},
415                 {"miblist", required_argument, 0, 'm'},
416                 {"protocol", required_argument, 0, 'P'},
417                 {"seclevel", required_argument, 0, 'L'},
418                 {"secname", required_argument, 0, 'U'},
419                 {"authproto", required_argument, 0, 'a'},
420                 {"privproto", required_argument, 0, 'x'},
421                 {"authpasswd", required_argument, 0, 'A'},
422                 {"privpasswd", required_argument, 0, 'X'},
423                 {"next", no_argument, 0, 'n'},
424                 {0, 0, 0, 0}
425         };
427         if (argc < 2)
428                 return ERROR;
430         /* reverse compatibility for very old non-POSIX usage forms */
431         for (c = 1; c < argc; c++) {
432                 if (strcmp ("-to", argv[c]) == 0)
433                         strcpy (argv[c], "-t");
434                 if (strcmp ("-wv", argv[c]) == 0)
435                         strcpy (argv[c], "-w");
436                 if (strcmp ("-cv", argv[c]) == 0)
437                         strcpy (argv[c], "-c");
438         }
440         while (1) {
441                 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:",
442                                                                          longopts, &option);
444                 if (c == -1 || c == EOF)
445                         break;
447                 switch (c) {
448                 case '?':       /* usage */
449                         usage5 ();
450                 case 'h':       /* help */
451                         print_help ();
452                         exit (STATE_OK);
453                 case 'V':       /* version */
454                         print_revision (progname, NP_VERSION);
455                         exit (STATE_OK);
456                 case 'v': /* verbose */
457                         verbose++;
458                         break;
460         /* Connection info */
461                 case 'C':                                                                       /* group or community */
462                         community = optarg;
463                         break;
464                 case 'H':                                                                       /* Host or server */
465                         server_address = optarg;
466                         break;
467                 case 'p':       /* TCP port number */
468                         port = optarg;
469                         break;
470                 case 'm':       /* List of MIBS */
471                         miblist = optarg;
472                         break;
473                 case 'n':       /* usesnmpgetnext */
474                         usesnmpgetnext = TRUE;
475                         break;
476                 case 'P':       /* SNMP protocol version */
477                         proto = optarg;
478                         break;
479                 case 'L':       /* security level */
480                         seclevel = optarg;
481                         break;
482                 case 'U':       /* security username */
483                         secname = optarg;
484                         break;
485                 case 'a':       /* auth protocol */
486                         authproto = optarg;
487                         break;
488                 case 'x':       /* priv protocol */
489                         privproto = optarg;
490                         break;
491                 case 'A':       /* auth passwd */
492                         authpasswd = optarg;
493                         break;
494                 case 'X':       /* priv passwd */
495                         privpasswd = optarg;
496                         break;
497                 case 't':       /* timeout period */
498                         if (!is_integer (optarg))
499                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
500                         else
501                                 timeout_interval = atoi (optarg);
502                         break;
504         /* Test parameters */
505                 case 'c':                                                                       /* critical threshold */
506                         critical_thresholds = optarg;
507                         break;
508                 case 'w':                                                                       /* warning threshold */
509                         warning_thresholds = optarg;
510                         break;
511                 case 'e': /* PRELIMINARY - may change */
512                 case 'E': /* PRELIMINARY - may change */
513                         if (!is_integer (optarg))
514                                 usage2 (_("Retries interval must be a positive integer"), optarg);
515                         else
516                                 retries = atoi(optarg);
517                         break;
518                 case 'o':                                                                       /* object identifier */
519                         if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
520                                         /*
521                                          * we have something other than digits, periods and comas,
522                                          * so we have a mib variable, rather than just an SNMP OID,
523                                          * so we have to actually read the mib files
524                                          */
525                                         needmibs = TRUE;
526                         }
527                         if (!oids) oids = calloc(MAX_OIDS, sizeof (char *));
528                         for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
529                                 oids[j] = strdup(ptr);
530                         }
531                         numoids = j;
532                         if (c == 'E' || c == 'e') {
533                                 jj++;
534                                 ii++;
535                         }
536                         if (c == 'E')
537                                 eval_method[j+1] |= WARN_PRESENT;
538                         else if (c == 'e')
539                                 eval_method[j+1] |= CRIT_PRESENT;
540                         break;
541                 case 's':                                                                       /* string or substring */
542                         strncpy (string_value, optarg, sizeof (string_value) - 1);
543                         string_value[sizeof (string_value) - 1] = 0;
544                         eval_method[jj++] = CRIT_STRING;
545                         ii++;
546                         break;
547                 case 'R':                                                                       /* regex */
548                         cflags = REG_ICASE;
549                 case 'r':                                                                       /* regex */
550                         cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
551                         strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
552                         regex_expect[sizeof (regex_expect) - 1] = 0;
553                         errcode = regcomp (&preg, regex_expect, cflags);
554                         if (errcode != 0) {
555                                 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
556                                 printf (_("Could Not Compile Regular Expression"));
557                                 return ERROR;
558                         }
559                         eval_method[jj++] = CRIT_REGEX;
560                         ii++;
561                         break;
563         /* Format */
564                 case 'd':                                                                       /* delimiter */
565                         delimiter = strscpy (delimiter, optarg);
566                         break;
567                 case 'D':                                                                       /* output-delimiter */
568                         output_delim = strscpy (output_delim, optarg);
569                         break;
570                 case 'l':                                                                       /* label */
571                         label = optarg;
572                         nlabels++;
573                         if (nlabels >= labels_size) {
574                                 labels_size += 8;
575                                 labels = realloc (labels, labels_size);
576                                 if (labels == NULL)
577                                         die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
578                         }
579                         labels[nlabels - 1] = optarg;
580                         ptr = thisarg (optarg);
581                         labels[nlabels - 1] = ptr;
582                         if (strstr (ptr, "'") == ptr)
583                                 labels[nlabels - 1] = ptr + 1;
584                         while (ptr && (ptr = nextarg (ptr))) {
585                                 if (nlabels >= labels_size) {
586                                         labels_size += 8;
587                                         labels = realloc (labels, labels_size);
588                                         if (labels == NULL)
589                                                 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
590                                 }
591                                 labels++;
592                                 ptr = thisarg (ptr);
593                                 if (strstr (ptr, "'") == ptr)
594                                         labels[nlabels - 1] = ptr + 1;
595                                 else
596                                         labels[nlabels - 1] = ptr;
597                         }
598                         break;
599                 case 'u':                                                                       /* units */
600                         units = optarg;
601                         nunits++;
602                         if (nunits >= unitv_size) {
603                                 unitv_size += 8;
604                                 unitv = realloc (unitv, unitv_size);
605                                 if (unitv == NULL)
606                                         die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
607                         }
608                         unitv[nunits - 1] = optarg;
609                         ptr = thisarg (optarg);
610                         unitv[nunits - 1] = ptr;
611                         if (strstr (ptr, "'") == ptr)
612                                 unitv[nunits - 1] = ptr + 1;
613                         while (ptr && (ptr = nextarg (ptr))) {
614                                 if (nunits >= unitv_size) {
615                                         unitv_size += 8;
616                                         unitv = realloc (unitv, unitv_size);
617                                         if (units == NULL)
618                                                 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
619                                 }
620                                 nunits++;
621                                 ptr = thisarg (ptr);
622                                 if (strstr (ptr, "'") == ptr)
623                                         unitv[nunits - 1] = ptr + 1;
624                                 else
625                                         unitv[nunits - 1] = ptr;
626                         }
627                         break;
629                 }
630         }
632         if (server_address == NULL)
633                 server_address = argv[optind];
635         if (community == NULL)
636                 community = strdup (DEFAULT_COMMUNITY);
638         return validate_arguments ();
642 /******************************************************************************
644 @@-
645 <sect3>
646 <title>validate_arguments</title>
648 <para>&PROTO_validate_arguments;</para>
650 <para>Checks to see if the default miblist needs to be loaded. Also verifies
651 the authentication and authorization combinations based on protocol version
652 selected.</para>
654 <para></para>
656 </sect3>
657 -@@
658 ******************************************************************************/
662 int
663 validate_arguments ()
665         /* check whether to load locally installed MIBS (CPU/disk intensive) */
666         if (miblist == NULL) {
667                 if ( needmibs == TRUE ) {
668                         miblist = strdup (DEFAULT_MIBLIST);
669                 }else{
670                         miblist = "";                   /* don't read any mib files for numeric oids */
671                 }
672         }
674         /* Check server_address is given */
675         if (server_address == NULL)
676                 die(STATE_UNKNOWN, _("No host specified\n"));
678         /* Check oid is given */
679         if (numoids == 0)
680                 die(STATE_UNKNOWN, _("No OIDs specified\n"));
682         if (proto == NULL)
683                 asprintf(&proto, DEFAULT_PROTOCOL);
685         if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) {     /* snmpv1 or snmpv2c */
686                 numauthpriv = 2;
687                 authpriv = calloc (numauthpriv, sizeof (char *));
688                 authpriv[0] = strdup ("-c");
689                 authpriv[1] = strdup (community);
690         }
691         else if ( strcmp (proto, "3") == 0 ) {          /* snmpv3 args */
692                 if (seclevel == NULL)
693                         asprintf(&seclevel, "noAuthNoPriv");
695                 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
696                         numauthpriv = 2;
697                         authpriv = calloc (numauthpriv, sizeof (char *));
698                         authpriv[0] = strdup ("-l");
699                         authpriv[1] = strdup ("noAuthNoPriv");
700                 } else {
701                         if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
702                                 usage2 (_("Invalid seclevel"), seclevel);
703                         }
705                         if (authproto == NULL )
706                                 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
708                         if (secname == NULL)
709                                 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
711                         if (authpasswd == NULL)
712                                 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
714                         if ( strcmp(seclevel, "authNoPriv") == 0 ) {
715                                 numauthpriv = 8;
716                                 authpriv = calloc (numauthpriv, sizeof (char *));
717                                 authpriv[0] = strdup ("-l");
718                                 authpriv[1] = strdup ("authNoPriv");
719                                 authpriv[2] = strdup ("-a");
720                                 authpriv[3] = strdup (authproto);
721                                 authpriv[4] = strdup ("-u");
722                                 authpriv[5] = strdup (secname);
723                                 authpriv[6] = strdup ("-A");
724                                 authpriv[7] = strdup (authpasswd);
725                         } else if ( strcmp(seclevel, "authPriv") == 0 ) {
726                                 if (privproto == NULL )
727                                         asprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
729                                 if (privpasswd == NULL)
730                                         die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
732                                 numauthpriv = 12;
733                                 authpriv = calloc (numauthpriv, sizeof (char *));
734                                 authpriv[0] = strdup ("-l");
735                                 authpriv[1] = strdup ("authPriv");
736                                 authpriv[2] = strdup ("-a");
737                                 authpriv[3] = strdup (authproto);
738                                 authpriv[4] = strdup ("-u");
739                                 authpriv[5] = strdup (secname);
740                                 authpriv[6] = strdup ("-A");
741                                 authpriv[7] = strdup (authpasswd);
742                                 authpriv[8] = strdup ("-x");
743                                 authpriv[9] = strdup (privproto);
744                                 authpriv[10] = strdup ("-X");
745                                 authpriv[11] = strdup (privpasswd);
746                         }
747                 }
749         }
750         else {
751                 usage2 (_("Invalid SNMP version"), proto);
752         }
754         return OK;
759 /* trim leading whitespace
760          if there is a leading quote, make sure it balances */
762 char *
763 thisarg (char *str)
765         str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
766         if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
767                 if (strlen (str) == 1 || !strstr (str + 1, "'"))
768                         die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
769         }
770         return str;
775 /* if there's a leading quote, advance to the trailing quote
776          set the trailing quote to '\x0'
777          if the string continues, advance beyond the comma */
779 char *
780 nextarg (char *str)
782         if (strstr (str, "'") == str) {
783                 str[0] = 0;
784                 if (strlen (str) > 1) {
785                         str = strstr (str + 1, "'");
786                         return (++str);
787                 }
788                 else {
789                         return NULL;
790                 }
791         }
792         if (strstr (str, ",") == str) {
793                 str[0] = 0;
794                 if (strlen (str) > 1) {
795                         return (++str);
796                 }
797                 else {
798                         return NULL;
799                 }
800         }
801         if ((str = strstr (str, ",")) && strlen (str) > 1) {
802                 str[0] = 0;
803                 return (++str);
804         }
805         return NULL;
810 void
811 print_help (void)
813         print_revision (progname, NP_VERSION);
815         printf (COPYRIGHT, copyright, email);
817         printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
819         printf ("\n\n");
821         print_usage ();
823         printf (UT_HELP_VRSN);
824         printf (UT_EXTRA_OPTS);
826         printf (UT_HOST_PORT, 'p', DEFAULT_PORT);
828         /* SNMP and Authentication Protocol */
829         printf (" %s\n", "-n, --next");
830         printf ("    %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
831         printf (" %s\n", "-P, --protocol=[1|2c|3]");
832         printf ("    %s\n", _("SNMP protocol version"));
833         printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
834         printf ("    %s\n", _("SNMPv3 securityLevel"));
835         printf (" %s\n", "-a, --authproto=[MD5|SHA]");
836         printf ("    %s\n", _("SNMPv3 auth proto"));
837         printf (" %s\n", "-x, --privproto=[DES|AES]");
838         printf ("    %s\n", _("SNMPv3 priv proto (default DES)"));
840         /* Authentication Tokens*/
841         printf (" %s\n", "-C, --community=STRING");
842         printf ("    %s ", _("Optional community string for SNMP communication"));
843         printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
844         printf (" %s\n", "-U, --secname=USERNAME");
845         printf ("    %s\n", _("SNMPv3 username"));
846         printf (" %s\n", "-A, --authpassword=PASSWORD");
847         printf ("    %s\n", _("SNMPv3 authentication password"));
848         printf (" %s\n", "-X, --privpasswd=PASSWORD");
849         printf ("    %s\n", _("SNMPv3 privacy password"));
851         /* OID Stuff */
852         printf (" %s\n", "-o, --oid=OID(s)");
853         printf ("    %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
854         printf (" %s\n", "-m, --miblist=STRING");
855         printf ("    %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
856         printf ("    %s\n", _("for symbolic OIDs.)"));
857         printf (" %s\n", "-d, --delimiter=STRING");
858         printf ("    %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
859         printf ("    %s\n", _("Any data on the right hand side of the delimiter is considered"));
860         printf ("    %s\n", _("to be the data that should be used in the evaluation."));
862         /* Tests Against Integers */
863         printf (" %s\n", "-w, --warning=THRESHOLD(s)");
864         printf ("    %s\n", _("Warning threshold range(s)"));
865         printf (" %s\n", "-c, --critical=THRESHOLD(s)");
866         printf ("    %s\n", _("Critical threshold range(s)"));
868         /* Tests Against Strings */
869         printf (" %s\n", "-s, --string=STRING");
870         printf ("    %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
871         printf (" %s\n", "-r, --ereg=REGEX");
872         printf ("    %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
873         printf (" %s\n", "-R, --eregi=REGEX");
874         printf ("    %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
875         printf (" %s\n", "-l, --label=STRING");
876         printf ("    %s\n", _("Prefix label for output from plugin (default -s 'SNMP')"));
878         /* Output Formatting */
879         printf (" %s\n", "-u, --units=STRING");
880         printf ("    %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
881         printf (" %s\n", "-D, --output-delimiter=STRING");
882         printf ("    %s\n", _("Separates output on multiple OID requests"));
884         printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
885         printf (" %s\n", "-e, --retries=INTEGER");
886         printf ("    %s\n", _("Number of retries to be used in the requests"));
888         printf (UT_VERBOSE);
890         printf ("\n");
891         printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
892         printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
893         printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
895         printf ("\n");
896         printf ("%s\n", _("Notes:"));
897         printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
898         printf ("   %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
900         printf(" -%s", UT_THRESHOLDS_NOTES);
902         printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
903         printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
904         printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
905         printf ("   %s\n", _("returned from the SNMP query is an unsigned integer."));
906 #ifdef NP_EXTRA_OPTS
907         printf (" -%s", UT_EXTRA_OPTS_NOTES);
908 #endif
910         printf (UT_SUPPORT);
915 void
916 print_usage (void)
918         printf (_("Usage:"));
919         printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
920         printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
921         printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
922         printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
923         printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");