1 /*****************************************************************************
3 * Nagios check_snmp plugin
6 * Copyright (c) 1999-2007 Nagios Plugins Development Team
10 * This file contains the check_snmp plugin
12 * Check status of remote machines and obtain system information via SNMP
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.
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.
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/>.
29 *****************************************************************************/
31 const char *progname
= "check_snmp";
32 const char *copyright
= "1999-2007";
33 const char *email
= "nagiosplug-devel@lists.sourceforge.net";
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?"*":"")
53 #define CRIT_PRESENT 1
62 #define CRIT_RANGE 512
63 #define WARN_PRESENT 1024
64 #define WARN_STRING 2048
65 #define WARN_REGEX 4096
70 #define WARN_EQ 131072
71 #define WARN_NE 262144
72 #define WARN_RANGE 524288
75 #define MAX_DELIM_LENGTH 8
77 int process_arguments (int, char **);
78 int validate_arguments (void);
79 char *clarify_message (char *);
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);
89 char regex_expect
[MAX_INPUT_BUFFER
] = "";
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
;
99 char *server_address
= NULL
;
100 char *community
= NULL
;
101 char **authpriv
= 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
;
114 char string_value
[MAX_INPUT_BUFFER
] = "";
115 char **labels
= NULL
;
118 size_t labels_size
= 8;
120 size_t unitv_size
= 8;
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
;
133 unsigned long long eval_method
[MAX_OIDS
];
136 char *miblist
= NULL
;
137 int needmibs
= FALSE
;
141 main (int argc
, char **argv
)
144 int iresult
= STATE_UNKNOWN
;
145 int result
= STATE_UNKNOWN
;
147 int external_error
= 0;
148 char **command_line
= NULL
;
149 char *cl_hidden_auth
= NULL
;
150 char *oidname
= NULL
;
151 char *response
= NULL
;
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
;
168 label
= strdup ("SNMP");
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
);
188 snmpcmd
= strdup (PATH_TO_SNMPGET
);
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
];
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
]);
219 command_line
[9 + numauthpriv
+ 1 + numoids
] = NULL
;
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
231 if (return_code
!= 0)
233 if (chld_out
.lines
== 0)
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
]);
242 printf(_("External command error with no output (return code: %d)\n"), return_code
);
244 exit (STATE_UNKNOWN
);
248 for (i
= 0; i
< chld_out
.lines
; i
++) {
249 printf ("%s\n", chld_out
.line
[i
]);
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;
271 else if (strstr (response
, "Counter64: ")) {
272 show
= strstr (response
, "Counter64: ") + 11;
275 else if (strstr (response
, "INTEGER: "))
276 show
= strstr (response
, "INTEGER: ") + 9;
277 else if (strstr (response
, "STRING: "))
278 show
= strstr (response
, "STRING: ") + 8;
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");
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
]);
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
;
313 /* Process this block for regex matching */
314 else if (eval_method
[i
] & CRIT_REGEX
) {
315 excode
= regexec (&preg
, response
, 10, pmatch
, eflags
);
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
);
325 iresult
= STATE_CRITICAL
;
329 /* Process this block for existence-nonexistence checks */
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
)
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
));
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);
361 strncat(perfstr
, type
, sizeof(perfstr
)-strlen(perfstr
)-1);
362 strncat(perfstr
, " ", sizeof(perfstr
)-strlen(perfstr
)-1);
366 /* if (nunits == 1 || i == 1) */
367 /* printf ("%s %s -%s %s\n", label, state_text (result), outbuff, units); */
369 printf ("%s %s -%s %s \n", label
, state_text (result
), outbuff
, perfstr
);
376 /* process command-line arguments */
378 process_arguments (int argc
, char **argv
)
382 int j
= 0, jj
= 0, ii
= 0;
385 static struct option longopts
[] = {
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'},
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");
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:",
430 if (c
== -1 || c
== EOF
)
434 case '?': /* usage */
439 case 'V': /* version */
440 print_revision (progname
, NP_VERSION
);
442 case 'v': /* verbose */
446 /* Connection info */
447 case 'C': /* group or community */
450 case 'H': /* Host or server */
451 server_address
= optarg
;
453 case 'p': /* TCP port number */
456 case 'm': /* List of MIBS */
459 case 'n': /* usesnmpgetnext */
460 usesnmpgetnext
= TRUE
;
462 case 'P': /* SNMP protocol version */
465 case 'L': /* security level */
468 case 'U': /* security username */
471 case 'a': /* auth protocol */
474 case 'x': /* priv protocol */
477 case 'A': /* auth passwd */
480 case 'X': /* priv passwd */
483 case 't': /* timeout period */
484 if (!is_integer (optarg
))
485 usage2 (_("Timeout interval must be a positive integer"), optarg
);
487 timeout_interval
= atoi (optarg
);
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
;
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
;
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
);
518 retries
= atoi(optarg
);
520 case 'o': /* object identifier */
521 if ( strspn( optarg
, "0123456789.," ) != strlen( optarg
) ) {
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
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
);
534 if (c
== 'E' || c
== 'e') {
539 eval_method
[j
+1] |= WARN_PRESENT
;
541 eval_method
[j
+1] |= CRIT_PRESENT
;
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
;
549 case 'R': /* regex */
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
);
557 regerror (errcode
, &preg
, errbuf
, MAX_INPUT_BUFFER
);
558 printf (_("Could Not Compile Regular Expression"));
561 eval_method
[jj
++] = CRIT_REGEX
;
566 case 'd': /* delimiter */
567 delimiter
= strscpy (delimiter
, optarg
);
569 case 'D': /* output-delimiter */
570 output_delim
= strscpy (output_delim
, optarg
);
572 case 'l': /* label */
575 if (nlabels
>= labels_size
) {
577 labels
= realloc (labels
, labels_size
);
579 die (STATE_UNKNOWN
, _("Could not reallocate labels[%d]"), (int)nlabels
);
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
) {
589 labels
= realloc (labels
, labels_size
);
591 die (STATE_UNKNOWN
, _("Could not reallocate labels\n"));
595 if (strstr (ptr
, "'") == ptr
)
596 labels
[nlabels
- 1] = ptr
+ 1;
598 labels
[nlabels
- 1] = ptr
;
601 case 'u': /* units */
604 if (nunits
>= unitv_size
) {
606 unitv
= realloc (unitv
, unitv_size
);
608 die (STATE_UNKNOWN
, _("Could not reallocate units [%d]\n"), (int)nunits
);
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
) {
618 unitv
= realloc (unitv
, unitv_size
);
620 die (STATE_UNKNOWN
, _("Could not realloc() units\n"));
624 if (strstr (ptr
, "'") == ptr
)
625 unitv
[nunits
- 1] = ptr
+ 1;
627 unitv
[nunits
- 1] = ptr
;
634 if (server_address
== NULL
)
635 server_address
= argv
[optind
];
637 if (community
== NULL
)
638 community
= strdup (DEFAULT_COMMUNITY
);
640 return validate_arguments ();
644 /******************************************************************************
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
660 ******************************************************************************/
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
);
672 miblist
= "''"; /* don't read any mib files for numeric oids */
676 /* Check server_address is given */
677 if (server_address
== NULL
)
678 die(STATE_UNKNOWN
, _("No host specified\n"));
680 /* Check oid is given */
682 die(STATE_UNKNOWN
, _("No OIDs specified\n"));
685 asprintf(&proto
, DEFAULT_PROTOCOL
);
687 if ((strcmp(proto
,"1") == 0) || (strcmp(proto
, "2c")==0)) { /* snmpv1 or snmpv2c */
689 authpriv
= calloc (numauthpriv
, sizeof (char *));
690 authpriv
[0] = strdup ("-c");
691 authpriv
[1] = strdup (community
);
693 else if ( strcmp (proto
, "3") == 0 ) { /* snmpv3 args */
694 if (seclevel
== NULL
)
695 asprintf(&seclevel
, "noAuthNoPriv");
697 if (strcmp(seclevel
, "noAuthNoPriv") == 0) {
699 authpriv
= calloc (numauthpriv
, sizeof (char *));
700 authpriv
[0] = strdup ("-l");
701 authpriv
[1] = strdup ("noAuthNoPriv");
703 if (! ( (strcmp(seclevel
, "authNoPriv")==0) || (strcmp(seclevel
, "authPriv")==0) ) ) {
704 usage2 (_("Invalid seclevel"), seclevel
);
707 if (authproto
== NULL
)
708 asprintf(&authproto
, DEFAULT_AUTH_PROTOCOL
);
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 ) {
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");
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
);
753 usage2 (_("Invalid SNMP version"), proto
);
762 clarify_message (char *msg
)
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
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
;
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
;
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
;
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
;
843 llu_getll (unsigned long long *ll
, char *str
)
846 if (strchr (str
, ':') == NULL
)
848 if (strchr (str
, ',') != NULL
&& (strchr (str
, ',') < strchr (str
, ':')))
850 if (sscanf (str
, "%llu%[:]", ll
, tmp
) == 2)
858 llu_getul (unsigned long long *ul
, char *str
)
861 if (sscanf (str
, "%llu%[^,]", ul
, tmp
) == 1)
863 if (sscanf (str
, ":%llu%[^,]", ul
, tmp
) == 1)
865 if (sscanf (str
, "%*u:%llu%[^,]", ul
, tmp
) == 1)
872 /* trim leading whitespace
873 if there is a leading quote, make sure it balances */
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"));
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 */
895 if (strstr (str
, "'") == str
) {
897 if (strlen (str
) > 1) {
898 str
= strstr (str
+ 1, "'");
905 if (strstr (str
, ",") == str
) {
907 if (strlen (str
) > 1) {
914 if ((str
= strstr (str
, ",")) && strlen (str
) > 1) {
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"));
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"));
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
));
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."));
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
));
1031 printf (_(UT_SUPPORT
));
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");