1 /******************************************************************************
2 *
3 * Program: SNMP plugin for Nagios
4 * License: GPL
5 *
6 * License Information:
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 *./plugins/check_snmp 127.0.0.1 -c public -o .1.3.6.1.4.1.2021.9.1.2.1
23 *
24 *****************************************************************************/
26 const char *progname = "check_snmp";
27 #define REVISION "$Revision$"
28 #define COPYRIGHT "1999-2002"
29 #define AUTHOR "Ethan Galstad"
30 #define EMAIL "nagios@nagios.org"
31 #define SUMMARY "Check status of remote machines using SNMP.\n"
33 #define OPTIONS "\
34 -H <ip_address> -o <OID> [-w warn_range] [-c crit_range] \n\
35 [-C community] [-s string] [-r regex] [-R regexi] [-t timeout]\n\
36 [-l label] [-u units] [-p port-number] [-d delimiter]\n\
37 [-D output-delimiter] [-m miblist] [-P snmp version]\n\
38 [-L seclevel] [-U secname] [-a authproto] [-A authpasswd]\n\
39 [-X privpasswd]\n"
41 #define LONGOPTIONS "\
42 -H, --hostname=HOST\n\
43 Name or IP address of the device you wish to query\n\
44 -o, --oid=OID(s)\n\
45 Object identifier(s) whose value you wish to query\n\
46 -w, --warning=INTEGER_RANGE(s)\n\
47 Range(s) which will not result in a WARNING status\n\
48 -c, --critical=INTEGER_RANGE(s)\n\
49 Range(s) which will not result in a CRITICAL status\n\
50 -C, --community=STRING\n\
51 Optional community string for SNMP communication\n\
52 (default is \"%s\")\n\
53 -u, --units=STRING\n\
54 Units label(s) for output data (e.g., 'sec.').\n\
55 -p, --port=STRING\n\
56 UDP port number target is listening on. Default is \"%s\"\n\
57 -P, --protocol=[1|3]\n\
58 SNMP protocol version\n\
59 -L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]\n\
60 SNMPv3 securityLevel\n\
61 -U, --secname=USERNAME\n\
62 SNMPv3 username\n\
63 -a, --authproto=[MD5|SHA]\n\
64 SNMPv3 auth proto\n\
65 -A, --authpassword=PASSWORD\n\
66 SNMPv3 authentication password\n\
67 -X, --privpasswd=PASSWORD\n\
68 SNMPv3 crypt passwd (DES)\n\
69 -d, --delimiter=STRING\n\
70 Delimiter to use when parsing returned data. Default is \"%s\"\n\
71 Any data on the right hand side of the delimiter is considered\n\
72 to be the data that should be used in the evaluation.\n\
73 -t, --timeout=INTEGER\n\
74 Seconds to wait before plugin times out (see also nagios server timeout).\n\
75 Default is %d seconds\n\
76 -D, --output-delimiter=STRING\n\
77 Separates output on multiple OID requests\n\
78 -s, --string=STRING\n\
79 Return OK state (for that OID) if STRING is an exact match\n\
80 -r, --ereg=REGEX\n\
81 Return OK state (for that OID) if extended regular expression REGEX matches\n\
82 -R, --eregi=REGEX\n\
83 Return OK state (for that OID) if case-insensitive extended REGEX matches\n\
84 -l, --label=STRING\n\
85 Prefix label for output from plugin (default -s 'SNMP')\n\
86 -v, --verbose\n\
87 Debugging the output\n\
88 -m, --miblist=STRING\n\
89 List of MIBS to be loaded (default = ALL)\n"
91 #define NOTES "\
92 - This plugin uses the 'snmpget' command included with the NET-SNMP package.\n\
93 If you don't have the package installed, you will need to download it from\n\
94 http://net-snmp.sourceforge.net before you can use this plugin.\n\
95 - Multiple OIDs may be indicated by a comma- or space-delimited list (lists with\n\
96 internal spaces must be quoted) [max 8 OIDs]\n\
97 - Ranges are inclusive and are indicated with colons. When specified as\n\
98 'min:max' a STATE_OK will be returned if the result is within the indicated\n\
99 range or is equal to the upper or lower bound. A non-OK state will be\n\
100 returned if the result is outside the specified range.\n\
101 - If specified in the order 'max:min' a non-OK state will be returned if the\n\
102 result is within the (inclusive) range.\n\
103 - Upper or lower bounds may be omitted to skip checking the respective limit.\n\
104 - Bare integers are interpreted as upper limits.\n\
105 - When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'\n\
106 - Note that only one string and one regex may be checked at present\n\
107 - All evaluation methods other than PR, STR, and SUBSTR expect that the value\n\
108 returned from the SNMP query is an unsigned integer.\n"
110 #define DESCRIPTION "\
111 This plugin gets system information on a remote server via snmp.\n"
113 #define DEFAULT_COMMUNITY "public"
114 #define DEFAULT_PORT "161"
115 #define DEFAULT_TIMEOUT 10
116 #define DEFAULT_MIBLIST "ALL"
117 #define DEFAULT_PROTOCOL "1"
118 #define DEFAULT_AUTH_PROTOCOL "MD5"
120 #include "common.h"
121 #include "utils.h"
122 #include "popen.h"
124 #define mark(a) ((a)!=0?"*":"")
126 #define CHECK_UNDEF 0
127 #define CRIT_PRESENT 1
128 #define CRIT_STRING 2
129 #define CRIT_REGEX 4
130 #define CRIT_GT 8
131 #define CRIT_LT 16
132 #define CRIT_GE 32
133 #define CRIT_LE 64
134 #define CRIT_EQ 128
135 #define CRIT_NE 256
136 #define CRIT_RANGE 512
137 #define WARN_PRESENT 1024
138 #define WARN_STRING 2048
139 #define WARN_REGEX 4096
140 #define WARN_GT 8192
141 #define WARN_LT 16384
142 #define WARN_GE 32768
143 #define WARN_LE 65536
144 #define WARN_EQ 131072
145 #define WARN_NE 262144
146 #define WARN_RANGE 524288
148 #define MAX_OIDS 8
149 #define MAX_DELIM_LENGTH 8
150 #define DEFAULT_DELIMITER "="
151 #define DEFAULT_OUTPUT_DELIMITER " "
153 void print_usage (void);
154 void print_help (void);
155 int process_arguments (int, char **);
156 int validate_arguments (void);
157 int check_num (int);
158 char *clarify_message (char *);
159 int lu_getll (unsigned long *, char *);
160 int lu_getul (unsigned long *, char *);
161 char *thisarg (char *str);
162 char *nextarg (char *str);
164 #ifdef HAVE_REGEX_H
165 #include <regex.h>
166 char regex_expect[MAX_INPUT_BUFFER] = "";
167 regex_t preg;
168 regmatch_t pmatch[10];
169 char timestamp[10] = "";
170 char errbuf[MAX_INPUT_BUFFER];
171 int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
172 int eflags = 0;
173 int errcode, excode;
174 #endif
176 char *server_address = NULL;
177 char *community = DEFAULT_COMMUNITY;
178 char *authpriv = NULL;
179 char *proto = NULL;
180 char *seclevel = NULL;
181 char *secname = NULL;
182 char *authproto = NULL;
183 char *authpasswd = NULL;
184 char *privpasswd = NULL;
185 char *oid = "";
186 char *label = "SNMP";
187 char *units = "";
188 char *port = DEFAULT_PORT;
189 char string_value[MAX_INPUT_BUFFER] = "";
190 char **labels = NULL;
191 char **unitv = NULL;
192 int nlabels = 0;
193 int labels_size = 8;
194 int nunits = 0;
195 int unitv_size = 8;
196 int verbose = FALSE;
197 unsigned long lower_warn_lim[MAX_OIDS];
198 unsigned long upper_warn_lim[MAX_OIDS];
199 unsigned long lower_crit_lim[MAX_OIDS];
200 unsigned long upper_crit_lim[MAX_OIDS];
201 unsigned long response_value[MAX_OIDS];
202 int check_warning_value = FALSE;
203 int check_critical_value = FALSE;
204 int eval_method[MAX_OIDS];
205 char *delimiter = DEFAULT_DELIMITER;
206 char *output_delim = DEFAULT_OUTPUT_DELIMITER;
207 char *miblist = DEFAULT_MIBLIST;
210 int
211 main (int argc, char **argv)
212 {
213 int i = 0;
214 int iresult = STATE_UNKNOWN;
215 int found = 0;
216 int result = STATE_DEPENDENT;
217 char input_buffer[MAX_INPUT_BUFFER];
218 char *command_line = NULL;
219 char *response = NULL;
220 char *outbuff = "";
221 char *output = "";
222 char *ptr = NULL;
223 char *p2 = NULL;
224 char *show = NULL;
226 labels = malloc (labels_size);
227 unitv = malloc (unitv_size);
228 for (i = 0; i < MAX_OIDS; i++)
229 eval_method[i] = CHECK_UNDEF;
230 i = 0;
232 if (process_arguments (argc, argv) == ERROR)
233 usage ("Incorrect arguments supplied\n");
235 /* create the command line to execute */
236 asprintf (&command_line, "%s -m %s -v %s %s %s:%s %s",
237 PATH_TO_SNMPGET, miblist, proto, authpriv, server_address, port, oid);
238 if (verbose)
239 printf ("%s\n", command_line);
241 /* run the command */
242 child_process = spopen (command_line);
243 if (child_process == NULL) {
244 printf ("Could not open pipe: %s\n", command_line);
245 exit (STATE_UNKNOWN);
246 }
248 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
249 if (child_stderr == NULL) {
250 printf ("Could not open stderr for %s\n", command_line);
251 }
253 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
254 asprintf (&output, "%s%s", output, input_buffer);
256 if (verbose)
257 printf ("%s\n", output);
259 ptr = output;
261 while (ptr) {
263 ptr = strstr (ptr, delimiter);
264 if (ptr == NULL)
265 break;
267 ptr += strlen (delimiter);
268 ptr += strspn (ptr, " ");
270 found++;
272 if (ptr[0] == '"') {
273 ptr++;
274 response = strpcpy (response, ptr, "\"");
275 ptr = strpbrk (ptr, "\"");
276 ptr += strspn (ptr, "\"\n");
277 }
278 else {
279 response = strpcpy (response, ptr, "\n");
280 ptr = strpbrk (ptr, "\n");
281 ptr += strspn (ptr, "\n");
282 while
283 (strstr (ptr, delimiter) &&
284 strstr (ptr, "\n") && strstr (ptr, "\n") < strstr (ptr, delimiter)) {
285 response = strpcat (response, ptr, "\n");
286 ptr = strpbrk (ptr, "\n");
287 }
288 if (ptr && strstr (ptr, delimiter) == NULL) {
289 response = strscat (response, ptr);
290 ptr = NULL;
291 }
292 }
294 /* We strip out the datatype indicator for PHBs */
295 if (strstr (response, "Gauge: "))
296 show = strstr (response, "Gauge: ") + 7;
297 else if (strstr (response, "Gauge32: "))
298 show = strstr (response, "Gauge32: ") + 9;
299 else if (strstr (response, "Counter32: "))
300 show = strstr (response, "Counter32: ") + 11;
301 else if (strstr (response, "INTEGER: "))
302 show = strstr (response, "INTEGER: ") + 9;
303 else if (strstr (response, "STRING: "))
304 show = strstr (response, "STRING: ") + 8;
305 else
306 show = response;
307 p2 = show;
309 iresult = STATE_DEPENDENT;
311 /* Process this block for integer comparisons */
312 if (eval_method[i] & CRIT_GT ||
313 eval_method[i] & CRIT_LT ||
314 eval_method[i] & CRIT_GE ||
315 eval_method[i] & CRIT_LE ||
316 eval_method[i] & CRIT_EQ ||
317 eval_method[i] & CRIT_NE ||
318 eval_method[i] & WARN_GT ||
319 eval_method[i] & WARN_LT ||
320 eval_method[i] & WARN_GE ||
321 eval_method[i] & WARN_LE ||
322 eval_method[i] & WARN_EQ ||
323 eval_method[i] & WARN_NE) {
324 p2 = strpbrk (p2, "0123456789");
325 if (p2 == NULL)
326 terminate (STATE_UNKNOWN,"No valid data returned");
327 response_value[i] = strtoul (p2, NULL, 10);
328 iresult = check_num (i);
329 asprintf (&show, "%lu", response_value[i]);
330 }
332 /* Process this block for string matching */
333 else if (eval_method[i] & CRIT_STRING) {
334 if (strcmp (response, string_value))
335 iresult = STATE_CRITICAL;
336 else
337 iresult = STATE_OK;
338 }
340 /* Process this block for regex matching */
341 else if (eval_method[i] & CRIT_REGEX) {
342 #ifdef HAVE_REGEX_H
343 excode = regexec (&preg, response, 10, pmatch, eflags);
344 if (excode == 0) {
345 iresult = STATE_OK;
346 }
347 else if (excode != REG_NOMATCH) {
348 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
349 printf ("Execute Error: %s\n", errbuf);
350 exit (STATE_CRITICAL);
351 }
352 else {
353 iresult = STATE_CRITICAL;
354 }
355 #else
356 printf ("%s UNKNOWN: call for regex which was not a compiled option", label);
357 exit (STATE_UNKNOWN);
358 #endif
359 }
361 /* Process this block for existence-nonexistence checks */
362 else {
363 if (eval_method[i] & CRIT_PRESENT)
364 iresult = STATE_CRITICAL;
365 else if (eval_method[i] & WARN_PRESENT)
366 iresult = STATE_WARNING;
367 else if (response && iresult == STATE_DEPENDENT)
368 iresult = STATE_OK;
369 }
371 /* Result is the worst outcome of all the OIDs tested */
372 result = max_state (result, iresult);
374 /* Prepend a label for this OID if there is one */
375 if (nlabels > 1 && i < nlabels && labels[i] != NULL)
376 asprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
377 (i == 0) ? " " : output_delim,
378 labels[i], mark (iresult), show, mark (iresult));
379 else
380 asprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
381 mark (iresult), show, mark (iresult));
383 /* Append a unit string for this OID if there is one */
384 if (nunits > 0 && i < nunits && unitv[i] != NULL)
385 asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
387 i++;
389 } /* end while (ptr) */
391 if (found == 0)
392 terminate
393 (STATE_UNKNOWN,
394 "%s problem - No data recieved from host\nCMD: %s\n",
395 label, command_line);
397 /* WARNING if output found on stderr */
398 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
399 result = max_state (result, STATE_WARNING);
401 /* close stderr */
402 (void) fclose (child_stderr);
404 /* close the pipe */
405 if (spclose (child_process))
406 result = max_state (result, STATE_WARNING);
408 /* if (nunits == 1 || i == 1) */
409 /* printf ("%s %s -%s %s\n", label, state_text (result), outbuff, units); */
410 /* else */
411 printf ("%s %s -%s\n", label, state_text (result), outbuff);
413 return result;
414 }
416 /* process command-line arguments */
417 int
418 process_arguments (int argc, char **argv)
419 {
420 char *ptr;
421 int c = 1;
422 int j = 0, jj = 0, ii = 0;
424 int option_index = 0;
425 static struct option long_options[] = {
426 STD_LONG_OPTS,
427 {"community", required_argument, 0, 'C'},
428 {"oid", required_argument, 0, 'o'},
429 {"object", required_argument, 0, 'o'},
430 {"delimiter", required_argument, 0, 'd'},
431 {"output-delimiter", required_argument, 0, 'D'},
432 {"string", required_argument, 0, 's'},
433 {"regex", required_argument, 0, 'r'},
434 {"ereg", required_argument, 0, 'r'},
435 {"eregi", required_argument, 0, 'R'},
436 {"label", required_argument, 0, 'l'},
437 {"units", required_argument, 0, 'u'},
438 {"port", required_argument, 0, 'p'},
439 {"miblist", required_argument, 0, 'm'},
440 {"protocol", required_argument, 0, 'P'},
441 {"seclevel", required_argument, 0, 'L'},
442 {"secname", required_argument, 0, 'U'},
443 {"authproto", required_argument, 0, 'a'},
444 {"authpasswd", required_argument, 0, 'A'},
445 {"privpasswd", required_argument, 0, 'X'},
446 {0, 0, 0, 0}
447 };
449 if (argc < 2)
450 return ERROR;
452 /* reverse compatibility for very old non-POSIX usage forms */
453 for (c = 1; c < argc; c++) {
454 if (strcmp ("-to", argv[c]) == 0)
455 strcpy (argv[c], "-t");
456 if (strcmp ("-wv", argv[c]) == 0)
457 strcpy (argv[c], "-w");
458 if (strcmp ("-cv", argv[c]) == 0)
459 strcpy (argv[c], "-c");
460 }
462 while (1) {
463 c = getopt_long (argc, argv, "hvVt:c:w:H:C:o:e:E:d:D:s:R:r:l:u:p:m:P:L:U:a:A:X:",
464 long_options, &option_index);
466 if (c == -1 || c == EOF)
467 break;
469 switch (c) {
470 case '?': /* usage */
471 usage3 ("Unknown argument", optopt);
472 case 'h': /* help */
473 print_help ();
474 exit (STATE_OK);
475 case 'V': /* version */
476 print_revision (progname, REVISION);
477 exit (STATE_OK);
478 case 'v': /* verbose */
479 verbose = TRUE;
480 break;
482 /* Connection info */
483 case 'C': /* group or community */
484 community = strscpy (community, optarg);
485 break;
486 case 'H': /* Host or server */
487 server_address = strscpy (server_address, optarg);
488 break;
489 case 'p': /* TCP port number */
490 port = strscpy(port, optarg);
491 break;
492 case 'm': /* List of MIBS */
493 miblist = strscpy(miblist, optarg);
494 break;
495 case 'P': /* SNMP protocol version */
496 proto = strscpy(proto, optarg);
497 break;
498 case 'L': /* security level */
499 seclevel = strscpy(seclevel,optarg);
500 break;
501 case 'U': /* security username */
502 secname = strscpy(secname, optarg);
503 break;
504 case 'a': /* auth protocol */
505 asprintf (&authproto, optarg);
506 break;
507 case 'A': /* auth passwd */
508 authpasswd = strscpy(authpasswd, optarg);
509 break;
510 case 'X': /* priv passwd */
511 privpasswd = strscpy(privpasswd, optarg);
512 break;
513 case 't': /* timeout period */
514 if (!is_integer (optarg))
515 usage2 ("Timeout Interval must be an integer", optarg);
516 timeout_interval = atoi (optarg);
517 break;
519 /* Test parameters */
520 case 'c': /* critical time threshold */
521 if (strspn (optarg, "0123456789:,") < strlen (optarg)) {
522 printf ("Invalid critical threshold: %s\n", optarg);
523 print_usage ();
524 exit (STATE_UNKNOWN);
525 }
526 for (ptr = optarg; ptr && jj < MAX_OIDS; jj++) {
527 if (lu_getll (&lower_crit_lim[jj], ptr) == 1)
528 eval_method[jj] |= CRIT_LT;
529 if (lu_getul (&upper_crit_lim[jj], ptr) == 1)
530 eval_method[jj] |= CRIT_GT;
531 (ptr = index (ptr, ',')) ? ptr++ : ptr;
532 }
533 break;
534 case 'w': /* warning time threshold */
535 if (strspn (optarg, "0123456789:,") < strlen (optarg)) {
536 printf ("Invalid warning threshold: %s\n", optarg);
537 print_usage ();
538 exit (STATE_UNKNOWN);
539 }
540 for (ptr = optarg; ptr && ii < MAX_OIDS; ii++) {
541 if (lu_getll (&lower_warn_lim[ii], ptr) == 1)
542 eval_method[ii] |= WARN_LT;
543 if (lu_getul (&upper_warn_lim[ii], ptr) == 1)
544 eval_method[ii] |= WARN_GT;
545 (ptr = index (ptr, ',')) ? ptr++ : ptr;
546 }
547 break;
548 case 'o': /* object identifier */
549 case 'e': /* PRELIMINARY - may change */
550 case 'E': /* PRELIMINARY - may change */
551 for (ptr = optarg; (ptr = index (ptr, ',')); ptr++)
552 ptr[0] = ' '; /* relpace comma with space */
553 for (ptr = optarg; (ptr = index (ptr, ' ')); ptr++)
554 j++; /* count OIDs */
555 asprintf (&oid, "%s %s", (oid?oid:""), optarg);
556 if (c == 'E' || c == 'e') {
557 jj++;
558 ii++;
559 }
560 if (c == 'E')
561 eval_method[j+1] |= WARN_PRESENT;
562 else if (c == 'e')
563 eval_method[j+1] |= CRIT_PRESENT;
564 break;
565 case 's': /* string or substring */
566 strncpy (string_value, optarg, sizeof (string_value) - 1);
567 string_value[sizeof (string_value) - 1] = 0;
568 eval_method[jj++] = CRIT_STRING;
569 ii++;
570 break;
571 case 'R': /* regex */
572 #ifdef HAVE_REGEX_H
573 cflags = REG_ICASE;
574 #endif
575 case 'r': /* regex */
576 #ifdef HAVE_REGEX_H
577 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
578 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
579 regex_expect[sizeof (regex_expect) - 1] = 0;
580 errcode = regcomp (&preg, regex_expect, cflags);
581 if (errcode != 0) {
582 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
583 printf ("Could Not Compile Regular Expression");
584 return ERROR;
585 }
586 eval_method[jj++] = CRIT_REGEX;
587 ii++;
588 #else
589 printf ("%s UNKNOWN: call for regex which was not a compiled option", label);
590 exit (STATE_UNKNOWN);
591 #endif
592 break;
594 /* Format */
595 case 'd': /* delimiter */
596 delimiter = strscpy (delimiter, optarg);
597 break;
598 case 'D': /* output-delimiter */
599 output_delim = strscpy (output_delim, optarg);
600 break;
601 case 'l': /* label */
602 label = optarg;
603 nlabels++;
604 if (nlabels >= labels_size) {
605 labels_size += 8;
606 labels = realloc (labels, labels_size);
607 if (labels == NULL)
608 terminate (STATE_UNKNOWN,
609 "Could not realloc() labels[%d]", nlabels);
610 }
611 labels[nlabels - 1] = optarg;
612 ptr = thisarg (optarg);
613 if (strstr (ptr, "'") == ptr)
614 labels[nlabels - 1] = ptr + 1;
615 else
616 labels[nlabels - 1] = ptr;
617 while (ptr && (ptr = nextarg (ptr))) {
618 if (nlabels >= labels_size) {
619 labels_size += 8;
620 labels = realloc (labels, labels_size);
621 if (labels == NULL)
622 terminate (STATE_UNKNOWN, "Could not realloc() labels\n");
623 }
624 labels++;
625 ptr = thisarg (ptr);
626 if (strstr (ptr, "'") == ptr)
627 labels[nlabels - 1] = ptr + 1;
628 else
629 labels[nlabels - 1] = ptr;
630 }
631 break;
632 case 'u': /* units */
633 units = optarg;
634 nunits++;
635 if (nunits >= unitv_size) {
636 unitv_size += 8;
637 unitv = realloc (unitv, unitv_size);
638 if (unitv == NULL)
639 terminate (STATE_UNKNOWN,
640 "Could not realloc() units [%d]\n", nunits);
641 }
642 unitv[nunits - 1] = optarg;
643 ptr = thisarg (optarg);
644 if (strstr (ptr, "'") == ptr)
645 unitv[nunits - 1] = ptr + 1;
646 else
647 unitv[nunits - 1] = ptr;
648 while (ptr && (ptr = nextarg (ptr))) {
649 if (nunits >= unitv_size) {
650 unitv_size += 8;
651 unitv = realloc (unitv, unitv_size);
652 if (units == NULL)
653 terminate (STATE_UNKNOWN, "Could not realloc() units\n");
654 }
655 nunits++;
656 ptr = thisarg (ptr);
657 if (strstr (ptr, "'") == ptr)
658 unitv[nunits - 1] = ptr + 1;
659 else
660 unitv[nunits - 1] = ptr;
661 }
662 break;
664 }
665 }
667 if (server_address == NULL)
668 asprintf (&server_address, argv[optind]);
670 return validate_arguments ();
671 }
673 /******************************************************************************
675 @@-
676 <sect3>
677 <title>validate_arguments</title>
679 <para>&PROTO_validate_arguments;</para>
681 <para>Given a database name, this function returns TRUE if the string
682 is a valid PostgreSQL database name, and returns false if it is
683 not.</para>
685 <para>Valid PostgreSQL database names are less than &NAMEDATALEN;
686 characters long and consist of letters, numbers, and underscores. The
687 first character cannot be a number, however.</para>
689 </sect3>
690 -@@
691 ******************************************************************************/
693 int
694 validate_arguments ()
695 {
697 /* Need better checks to verify seclevel and authproto choices */
699 if (seclevel == NULL)
700 asprintf (&seclevel, "noAuthNoPriv");
703 if (authproto == NULL )
704 asprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
708 if (proto == NULL || (strcmp(proto,DEFAULT_PROTOCOL) == 0) ) { /* default protocol version */
709 asprintf(&proto, DEFAULT_PROTOCOL);
710 asprintf(&authpriv, "%s%s", "-c ", community);
711 }
712 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
713 asprintf(&proto, "%s", "3");
715 if ( (strcmp(seclevel, "noAuthNoPriv") == 0) || seclevel == NULL ) {
716 asprintf(&authpriv, "%s", "-l noAuthNoPriv" );
717 }
718 else if ( strcmp(seclevel, "authNoPriv") == 0 ) {
719 if ( secname == NULL || authpasswd == NULL) {
720 printf ("Missing secname (%s) or authpassword (%s) ! \n",secname, authpasswd );
721 print_usage ();
722 exit (STATE_UNKNOWN);
723 }
724 asprintf(&authpriv, "-l authNoPriv -a %s -u %s -A %s ", authproto, secname, authpasswd);
725 }
726 else if ( strcmp(seclevel, "authPriv") == 0 ) {
727 if ( secname == NULL || authpasswd == NULL || privpasswd == NULL ) {
728 printf ("Missing secname (%s), authpassword (%s), or privpasswd (%s)! \n",secname, authpasswd,privpasswd );
729 print_usage ();
730 exit (STATE_UNKNOWN);
731 }
732 asprintf(&authpriv, "-l authPriv -a %s -u %s -A %s -x DES -X %s ", authproto, secname, authpasswd, privpasswd);
733 }
736 }
737 else {
738 printf ("Invalid SNMP version: %s\n", proto);
739 print_usage ();
740 exit (STATE_UNKNOWN);
741 }
746 return OK;
747 }
751 void
752 print_help (void)
753 {
754 print_revision (progname, REVISION);
755 printf
756 ("Copyright (c) %s %s <%s>\n\n%s\n", COPYRIGHT, AUTHOR, EMAIL, SUMMARY);
757 print_usage ();
758 printf
759 ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n" NOTES "\n",
760 DEFAULT_COMMUNITY, DEFAULT_PORT, DEFAULT_DELIMITER, DEFAULT_TIMEOUT);
761 support ();
762 }
764 void
765 print_usage (void)
766 {
767 printf
768 ("Usage:\n" " %s %s\n"
769 " %s (-h | --help) for detailed help\n"
770 " %s (-V | --version) for version information\n",
771 progname, OPTIONS, progname, progname);
772 }
773 \f
776 char *
777 clarify_message (char *msg)
778 {
779 int i = 0;
780 int foo;
781 char tmpmsg_c[MAX_INPUT_BUFFER];
782 char *tmpmsg = (char *) &tmpmsg_c;
783 tmpmsg = strcpy (tmpmsg, msg);
784 if (!strncmp (tmpmsg, " Hex:", 5)) {
785 tmpmsg = strtok (tmpmsg, ":");
786 while ((tmpmsg = strtok (NULL, " "))) {
787 foo = strtol (tmpmsg, NULL, 16);
788 /* Translate chars that are not the same value in the printers
789 * character set.
790 */
791 switch (foo) {
792 case 208:
793 {
794 foo = 197;
795 break;
796 }
797 case 216:
798 {
799 foo = 196;
800 break;
801 }
802 }
803 msg[i] = foo;
804 i++;
805 }
806 msg[i] = 0;
807 }
808 return (msg);
809 }
812 int
813 check_num (int i)
814 {
815 int result;
816 result = STATE_OK;
817 if (eval_method[i] & WARN_GT && eval_method[i] & WARN_LT &&
818 lower_warn_lim[i] > upper_warn_lim[i]) {
819 if (response_value[i] <= lower_warn_lim[i] &&
820 response_value[i] >= upper_warn_lim[i]) {
821 result = STATE_WARNING;
822 }
823 }
824 else if
825 ((eval_method[i] & WARN_GT && response_value[i] > upper_warn_lim[i]) ||
826 (eval_method[i] & WARN_GE && response_value[i] >= upper_warn_lim[i]) ||
827 (eval_method[i] & WARN_LT && response_value[i] < lower_warn_lim[i]) ||
828 (eval_method[i] & WARN_LE && response_value[i] <= lower_warn_lim[i]) ||
829 (eval_method[i] & WARN_EQ && response_value[i] == upper_warn_lim[i]) ||
830 (eval_method[i] & WARN_NE && response_value[i] != upper_warn_lim[i])) {
831 result = STATE_WARNING;
832 }
834 if (eval_method[i] & CRIT_GT && eval_method[i] & CRIT_LT &&
835 lower_warn_lim[i] > upper_warn_lim[i]) {
836 if (response_value[i] <= lower_crit_lim[i] &&
837 response_value[i] >= upper_crit_lim[i]) {
838 result = STATE_CRITICAL;
839 }
840 }
841 else if
842 ((eval_method[i] & CRIT_GT && response_value[i] > upper_crit_lim[i]) ||
843 (eval_method[i] & CRIT_GE && response_value[i] >= upper_crit_lim[i]) ||
844 (eval_method[i] & CRIT_LT && response_value[i] < lower_crit_lim[i]) ||
845 (eval_method[i] & CRIT_LE && response_value[i] <= lower_crit_lim[i]) ||
846 (eval_method[i] & CRIT_EQ && response_value[i] == upper_crit_lim[i]) ||
847 (eval_method[i] & CRIT_NE && response_value[i] != upper_crit_lim[i])) {
848 result = STATE_CRITICAL;
849 }
851 return result;
852 }
855 int
856 lu_getll (unsigned long *ll, char *str)
857 {
858 char tmp[100];
859 if (strchr (str, ':') == NULL)
860 return 0;
861 if (strchr (str, ',') != NULL && (strchr (str, ',') < strchr (str, ':')))
862 return 0;
863 if (sscanf (str, "%lu%[:]", ll, tmp) == 2)
864 return 1;
865 return 0;
866 }
868 int
869 lu_getul (unsigned long *ul, char *str)
870 {
871 char tmp[100];
872 if (sscanf (str, "%lu%[^,]", ul, tmp) == 1)
873 return 1;
874 if (sscanf (str, ":%lu%[^,]", ul, tmp) == 1)
875 return 1;
876 if (sscanf (str, "%*u:%lu%[^,]", ul, tmp) == 1)
877 return 1;
878 return 0;
879 }
886 /* trim leading whitespace
887 if there is a leading quote, make sure it balances */
889 char *
890 thisarg (char *str)
891 {
892 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
893 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
894 if (strlen (str) == 1 || !strstr (str + 1, "'"))
895 terminate (STATE_UNKNOWN, "Unbalanced quotes\n");
896 }
897 return str;
898 }
901 /* if there's a leading quote, advance to the trailing quote
902 set the trailing quote to '\x0'
903 if the string continues, advance beyond the comma */
905 char *
906 nextarg (char *str)
907 {
908 if (strstr (str, "'") == str) {
909 if (strlen (str) > 1) {
910 str = strstr (str + 1, "'");
911 str[0] = 0;
912 return (++str);
913 }
914 else {
915 str[0] = 0;
916 return NULL;
917 }
918 }
919 if (strstr (str, ",") == str) {
920 if (strlen (str) > 1) {
921 str[0] = 0;
922 return (++str);
923 }
924 else {
925 str[0] = 0;
926 return NULL;
927 }
928 }
929 if ((str = strstr (str, ",")) && strlen (str) > 1) {
930 str[0] = 0;
931 return (++str);
932 }
933 return NULL;
934 }