check_pgsql: update copyright
[monitoring-plugins.git] / plugins / check_snmp.c
blob90a040275f20b27dfea2ba5f5983ab53bf30f388
1 /*****************************************************************************
3 * Monitoring check_snmp plugin
5 * License: GPL
6 * Copyright (c) 1999-2007 Monitoring Plugins Development Team
8 * Description:
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 = "devel@monitoring-plugins.org";
35 #include "common.h"
36 #include "runcmd.h"
37 #include "utils.h"
38 #include "utils_cmd.h"
40 #define DEFAULT_COMMUNITY "public"
41 #define DEFAULT_PORT "161"
42 #define DEFAULT_MIBLIST "ALL"
43 #define DEFAULT_PROTOCOL "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 " "
49 #define DEFAULT_BUFFER_SIZE 100
51 #define mark(a) ((a)!=0?"*":"")
53 #define CHECK_UNDEF 0
54 #define CRIT_PRESENT 1
55 #define CRIT_STRING 2
56 #define CRIT_REGEX 4
57 #define WARN_PRESENT 8
59 #define OID_COUNT_STEP 8
61 /* Longopts only arguments */
62 #define L_CALCULATE_RATE CHAR_MAX+1
63 #define L_RATE_MULTIPLIER CHAR_MAX+2
64 #define L_INVERT_SEARCH CHAR_MAX+3
65 #define L_OFFSET CHAR_MAX+4
66 #define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX+5
68 /* Gobble to string - stop incrementing c when c[0] match one of the
69 * characters in s */
70 #define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; }
71 /* Given c, keep track of backslashes (bk) and double-quotes (dq)
72 * from c[0] */
73 #define COUNT_SEQ(c, bk, dq) switch(c[0]) {\
74 case '\\': \
75 if (bk) bk--; \
76 else bk++; \
77 break; \
78 case '"': \
79 if (!dq) { dq++; } \
80 else if(!bk) { dq--; } \
81 else { bk--; } \
82 break; \
87 static int process_arguments (int, char **);
88 static int validate_arguments (void);
89 static char *thisarg (char *str);
90 static char *nextarg (char *str);
91 void print_usage (void);
92 static void print_help (void);
93 static char *multiply (char *str);
95 #include "regex.h"
96 static char regex_expect[MAX_INPUT_BUFFER] = "";
97 static regex_t preg;
98 static regmatch_t pmatch[10];
99 static char errbuf[MAX_INPUT_BUFFER] = "";
100 static char perfstr[MAX_INPUT_BUFFER] = "| ";
101 static int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
102 static int eflags = 0;
103 static int errcode, excode;
105 static char *server_address = NULL;
106 static char *community = NULL;
107 static char **contextargs = NULL;
108 static char *context = NULL;
109 static char **authpriv = NULL;
110 static char *proto = NULL;
111 static char *seclevel = NULL;
112 static char *secname = NULL;
113 static char *authproto = NULL;
114 static char *privproto = NULL;
115 static char *authpasswd = NULL;
116 static char *privpasswd = NULL;
117 static int nulloid = STATE_UNKNOWN;
118 static char **oids = NULL;
119 static size_t oids_size = 0;
120 static char *label;
121 static char *units;
122 static char *port;
123 static char *snmpcmd;
124 static char string_value[MAX_INPUT_BUFFER] = "";
125 static int invert_search=0;
126 static char **labels = NULL;
127 static char **unitv = NULL;
128 static size_t nlabels = 0;
129 static size_t labels_size = OID_COUNT_STEP;
130 static size_t nunits = 0;
131 static size_t unitv_size = OID_COUNT_STEP;
132 static size_t numoids = 0;
133 static int numauthpriv = 0;
134 static int numcontext = 0;
135 static int verbose = 0;
136 static bool usesnmpgetnext = false;
137 static char *warning_thresholds = NULL;
138 static char *critical_thresholds = NULL;
139 static thresholds **thlds;
140 static size_t thlds_size = OID_COUNT_STEP;
141 static double *response_value;
142 static size_t response_size = OID_COUNT_STEP;
143 static int retries = 0;
144 static int *eval_method;
145 static size_t eval_size = OID_COUNT_STEP;
146 static char *delimiter;
147 static char *output_delim;
148 static char *miblist = NULL;
149 static bool needmibs = false;
150 static int calculate_rate = 0;
151 static double offset = 0.0;
152 static int rate_multiplier = 1;
153 static state_data *previous_state;
154 static double *previous_value;
155 static size_t previous_size = OID_COUNT_STEP;
156 static int perf_labels = 1;
157 static char* ip_version = "";
158 static double multiplier = 1.0;
159 static char *fmtstr = "";
160 static bool fmtstr_set = false;
161 static char buffer[DEFAULT_BUFFER_SIZE];
162 static bool ignore_mib_parsing_errors = false;
164 static char *fix_snmp_range(char *th)
166 double left, right;
167 char *colon, *ret;
169 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0')
170 return th;
172 left = strtod(th, NULL);
173 right = strtod(colon + 1, NULL);
174 if (right >= left)
175 return th;
177 if ((ret = malloc(strlen(th) + 2)) == NULL)
178 die(STATE_UNKNOWN, _("Cannot malloc"));
179 *colon = '\0';
180 sprintf(ret, "@%s:%s", colon + 1, th);
181 free(th);
182 return ret;
186 main (int argc, char **argv)
188 int len, total_oids;
189 size_t line;
190 unsigned int bk_count = 0, dq_count = 0;
191 int iresult = STATE_UNKNOWN;
192 int result = STATE_UNKNOWN;
193 int return_code = 0;
194 int external_error = 0;
195 char **command_line = NULL;
196 char *cl_hidden_auth = NULL;
197 char *oidname = NULL;
198 char *response = NULL;
199 char *mult_resp = NULL;
200 char *outbuff;
201 char *ptr = NULL;
202 char *show = NULL;
203 char *th_warn=NULL;
204 char *th_crit=NULL;
205 char type[8] = "";
206 output chld_out, chld_err;
207 char *previous_string=NULL;
208 char *ap=NULL;
209 char *state_string=NULL;
210 size_t response_length, current_length, string_length;
211 char *temp_string=NULL;
212 char *quote_string=NULL;
213 time_t current_time;
214 double temp_double;
215 time_t duration;
216 char *conv = "12345678";
217 int is_counter=0;
219 setlocale (LC_ALL, "");
220 bindtextdomain (PACKAGE, LOCALEDIR);
221 textdomain (PACKAGE);
223 labels = malloc (labels_size * sizeof(*labels));
224 unitv = malloc (unitv_size * sizeof(*unitv));
225 thlds = malloc (thlds_size * sizeof(*thlds));
226 response_value = malloc (response_size * sizeof(*response_value));
227 previous_value = malloc (previous_size * sizeof(*previous_value));
228 eval_method = calloc (eval_size, sizeof(*eval_method));
229 oids = calloc(oids_size, sizeof (char *));
231 label = strdup ("SNMP");
232 units = strdup ("");
233 port = strdup (DEFAULT_PORT);
234 outbuff = strdup ("");
235 delimiter = strdup (" = ");
236 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
237 timeout_interval = DEFAULT_SOCKET_TIMEOUT;
238 retries = DEFAULT_RETRIES;
240 np_init( (char *) progname, argc, argv );
242 /* Parse extra opts if any */
243 argv=np_extra_opts (&argc, argv, progname);
245 np_set_args(argc, argv);
247 time(&current_time);
249 if (process_arguments (argc, argv) == ERROR)
250 usage4 (_("Could not parse arguments"));
252 if(calculate_rate) {
253 if (!strcmp(label, "SNMP"))
254 label = strdup("SNMP RATE");
256 size_t i = 0;
258 previous_state = np_state_read();
259 if(previous_state!=NULL) {
260 /* Split colon separated values */
261 previous_string = strdup((char *) previous_state->data);
262 while((ap = strsep(&previous_string, ":")) != NULL) {
263 if(verbose>2)
264 printf("State for %zd=%s\n", i, ap);
265 while (i >= previous_size) {
266 previous_size += OID_COUNT_STEP;
267 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value));
269 previous_value[i++]=strtod(ap,NULL);
274 /* Populate the thresholds */
275 th_warn=warning_thresholds;
276 th_crit=critical_thresholds;
277 for (size_t i = 0; i < numoids; i++) {
278 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
279 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
280 /* translate "2:1" to "@1:2" for backwards compatibility */
281 w = w ? fix_snmp_range(w) : NULL;
282 c = c ? fix_snmp_range(c) : NULL;
284 while (i >= thlds_size) {
285 thlds_size += OID_COUNT_STEP;
286 thlds = realloc(thlds, thlds_size * sizeof(*thlds));
289 /* Skip empty thresholds, while avoiding segfault */
290 set_thresholds(&thlds[i],
291 w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
292 c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
293 if (w) {
294 th_warn=strchr(th_warn, ',');
295 if (th_warn) th_warn++;
296 free(w);
298 if (c) {
299 th_crit=strchr(th_crit, ',');
300 if (th_crit) th_crit++;
301 free(c);
305 /* Create the command array to execute */
306 if(usesnmpgetnext) {
307 snmpcmd = strdup (PATH_TO_SNMPGETNEXT);
308 }else{
309 snmpcmd = strdup (PATH_TO_SNMPGET);
312 /* 10 arguments to pass before context and authpriv options + 1 for host and numoids. Add one for terminating NULL */
314 unsigned index = 0;
315 command_line = calloc (11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof (char *));
317 command_line[index++] = snmpcmd;
318 command_line[index++] = strdup ("-Le");
319 command_line[index++] = strdup ("-t");
320 xasprintf (&command_line[index++], "%d", timeout_interval);
321 command_line[index++] = strdup ("-r");
322 xasprintf (&command_line[index++], "%d", retries);
323 command_line[index++] = strdup ("-m");
324 command_line[index++] = strdup (miblist);
325 command_line[index++] = "-v";
326 command_line[index++] = strdup (proto);
328 xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s",
329 snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto);
331 if (ignore_mib_parsing_errors) {
332 command_line[index++] = "-Pe";
333 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth);
337 for (int i = 0; i < numcontext; i++) {
338 command_line[index++] = contextargs[i];
341 for (int i = 0; i < numauthpriv; i++) {
342 command_line[index++] = authpriv[i];
345 xasprintf (&command_line[index++], "%s:%s", server_address, port);
347 xasprintf(&cl_hidden_auth, "%s [context] [authpriv] %s:%s",
348 cl_hidden_auth,
349 server_address,
350 port);
352 for (size_t i = 0; i < numoids; i++) {
353 command_line[index++] = oids[i];
354 xasprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);
357 command_line[index++] = NULL;
359 if (verbose) {
360 printf ("%s\n", cl_hidden_auth);
363 /* Set signal handling and alarm */
364 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
365 usage4 (_("Cannot catch SIGALRM"));
367 alarm(timeout_interval * retries + 5);
369 /* Run the command */
370 return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0);
372 /* disable alarm again */
373 alarm(0);
375 /* Due to net-snmp sometimes showing stderr messages with poorly formed MIBs,
376 only return state unknown if return code is non zero or there is no stdout.
377 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
379 if (return_code != 0)
380 external_error=1;
381 if (chld_out.lines == 0)
382 external_error=1;
383 if (external_error) {
384 if (chld_err.lines > 0) {
385 printf (_("External command error: %s\n"), chld_err.line[0]);
386 for (size_t i = 1; i < chld_err.lines; i++) {
387 printf ("%s\n", chld_err.line[i]);
389 } else {
390 printf(_("External command error with no output (return code: %d)\n"), return_code);
392 exit (STATE_UNKNOWN);
395 if (verbose) {
396 for (size_t i = 0; i < chld_out.lines; i++) {
397 printf ("%s\n", chld_out.line[i]);
401 line = 0;
402 total_oids = 0;
403 for (size_t i = 0; line < chld_out.lines && i < numoids ; line++, i++, total_oids++) {
404 if(calculate_rate)
405 conv = "%.10g";
406 else
407 conv = "%.0f";
409 ptr = chld_out.line[line];
410 oidname = strpcpy (oidname, ptr, delimiter);
411 response = strstr (ptr, delimiter);
412 if (response == NULL)
413 break;
415 if (verbose > 2) {
416 printf("Processing oid %zi (line %zi)\n oidname: %s\n response: %s\n", i+1, line+1, oidname, response);
419 /* Clean up type array - Sol10 does not necessarily zero it out */
420 bzero(type, sizeof(type));
422 is_counter=0;
423 /* We strip out the datatype indicator for PHBs */
424 if (strstr (response, "Gauge: ")) {
425 show = multiply (strstr (response, "Gauge: ") + 7);
427 else if (strstr (response, "Gauge32: ")) {
428 show = multiply (strstr (response, "Gauge32: ") + 9);
430 else if (strstr (response, "Counter32: ")) {
431 show = strstr (response, "Counter32: ") + 11;
432 is_counter=1;
433 if(!calculate_rate)
434 strcpy(type, "c");
436 else if (strstr (response, "Counter64: ")) {
437 show = strstr (response, "Counter64: ") + 11;
438 is_counter=1;
439 if(!calculate_rate)
440 strcpy(type, "c");
442 else if (strstr (response, "INTEGER: ")) {
443 show = multiply (strstr (response, "INTEGER: ") + 9);
445 if (fmtstr_set) {
446 conv = fmtstr;
449 else if (strstr (response, "OID: ")) {
450 show = strstr (response, "OID: ") + 5;
452 else if (strstr (response, "STRING: ")) {
453 show = strstr (response, "STRING: ") + 8;
454 conv = "%.10g";
456 /* Get the rest of the string on multi-line strings */
457 ptr = show;
458 COUNT_SEQ(ptr, bk_count, dq_count)
459 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
460 ptr++;
461 GOBBLE_TOS(ptr, "\n\"\\")
462 COUNT_SEQ(ptr, bk_count, dq_count)
465 if (dq_count) { /* unfinished line */
466 /* copy show verbatim first */
467 if (!mult_resp) mult_resp = strdup("");
468 xasprintf (&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show);
469 /* then strip out unmatched double-quote from single-line output */
470 if (show[0] == '"') show++;
472 /* Keep reading until we match end of double-quoted string */
473 for (line++; line < chld_out.lines; line++) {
474 ptr = chld_out.line[line];
475 xasprintf (&mult_resp, "%s%s\n", mult_resp, ptr);
477 COUNT_SEQ(ptr, bk_count, dq_count)
478 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
479 ptr++;
480 GOBBLE_TOS(ptr, "\n\"\\")
481 COUNT_SEQ(ptr, bk_count, dq_count)
483 /* Break for loop before next line increment when done */
484 if (!dq_count) break;
489 else if (strstr (response, "Timeticks: ")) {
490 show = strstr (response, "Timeticks: ");
492 else
493 show = response + 3;
495 iresult = STATE_DEPENDENT;
497 /* Process this block for numeric comparisons */
498 /* Make some special values,like Timeticks numeric only if a threshold is defined */
499 if (thlds[i]->warning || thlds[i]->critical || calculate_rate) {
500 if (verbose > 2) {
501 print_thresholds(" thresholds", thlds[i]);
503 ptr = strpbrk (show, "-0123456789");
504 if (ptr == NULL){
505 if (nulloid == 3)
506 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show);
507 else if (nulloid == 0)
508 die (STATE_OK,_("No valid data returned (%s)\n"), show);
509 else if (nulloid == 1)
510 die (STATE_WARNING,_("No valid data returned (%s)\n"), show);
511 else if (nulloid == 2)
512 die (STATE_CRITICAL,_("No valid data returned (%s)\n"), show);
514 while (i >= response_size) {
515 response_size += OID_COUNT_STEP;
516 response_value = realloc(response_value, response_size * sizeof(*response_value));
518 response_value[i] = strtod (ptr, NULL) + offset;
520 if(calculate_rate) {
521 if (previous_state!=NULL) {
522 duration = current_time-previous_state->time;
523 if(duration<=0)
524 die(STATE_UNKNOWN,_("Time duration between plugin calls is invalid"));
525 temp_double = response_value[i]-previous_value[i];
526 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */
527 if(is_counter) {
528 if(temp_double<(double)0.0)
529 temp_double+=(double)4294967296.0; /* 2^32 */
530 if(temp_double<(double)0.0)
531 temp_double+=(double)18446744069414584320.0; /* 2^64-2^32 */;
533 /* Convert to per second, then use multiplier */
534 temp_double = temp_double/duration*rate_multiplier;
535 iresult = get_status(temp_double, thlds[i]);
536 xasprintf (&show, conv, temp_double);
538 } else {
539 iresult = get_status(response_value[i], thlds[i]);
540 xasprintf (&show, conv, response_value[i]);
544 /* Process this block for string matching */
545 else if (eval_size > i && eval_method[i] & CRIT_STRING) {
546 if (strcmp (show, string_value))
547 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK;
548 else
549 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL;
552 /* Process this block for regex matching */
553 else if (eval_size > i && eval_method[i] & CRIT_REGEX) {
554 excode = regexec (&preg, response, 10, pmatch, eflags);
555 if (excode == 0) {
556 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL;
558 else if (excode != REG_NOMATCH) {
559 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
560 printf (_("Execute Error: %s\n"), errbuf);
561 exit (STATE_CRITICAL);
563 else {
564 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK;
568 /* Process this block for existence-nonexistence checks */
569 /* TV: Should this be outside of this else block? */
570 else {
571 if (eval_size > i && eval_method[i] & CRIT_PRESENT)
572 iresult = STATE_CRITICAL;
573 else if (eval_size > i && eval_method[i] & WARN_PRESENT)
574 iresult = STATE_WARNING;
575 else if (response && iresult == STATE_DEPENDENT)
576 iresult = STATE_OK;
579 /* Result is the worst outcome of all the OIDs tested */
580 result = max_state (result, iresult);
582 /* Prepend a label for this OID if there is one */
583 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
584 xasprintf (&outbuff, "%s%s%s %s%s%s", outbuff,
585 (i == 0) ? " " : output_delim,
586 labels[i], mark (iresult), show, mark (iresult));
587 else
588 xasprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim,
589 mark (iresult), show, mark (iresult));
591 /* Append a unit string for this OID if there is one */
592 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
593 xasprintf (&outbuff, "%s %s", outbuff, unitv[i]);
595 /* Write perfdata with whatever can be parsed by strtod, if possible */
596 ptr = NULL;
597 strtod(show, &ptr);
598 if (ptr > show) {
599 if (perf_labels && nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
600 temp_string=labels[i];
601 else
602 temp_string=oidname;
603 if (strpbrk (temp_string, " ='\"") == NULL) {
604 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1);
605 } else {
606 if (strpbrk (temp_string, "'") == NULL) {
607 quote_string="'";
608 } else {
609 quote_string="\"";
611 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1);
612 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1);
613 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1);
615 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
616 len = sizeof(perfstr)-strlen(perfstr)-1;
617 strncat(perfstr, show, len>ptr-show ? ptr-show : len);
619 if (strcmp(type, "") != 0) {
620 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
623 if (warning_thresholds) {
624 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
625 if(thlds[i]->warning && thlds[i]->warning->text)
626 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr)-strlen(perfstr)-1);
629 if (critical_thresholds) {
630 if (!warning_thresholds)
631 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
632 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
633 if(thlds[i]->critical && thlds[i]->critical->text)
634 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr)-strlen(perfstr)-1);
637 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
641 /* Save state data, as all data collected now */
642 if(calculate_rate) {
643 string_length=1024;
644 state_string=malloc(string_length);
645 if(state_string==NULL)
646 die(STATE_UNKNOWN, _("Cannot malloc"));
648 current_length=0;
649 for(int i = 0; i < total_oids; i++) {
650 xasprintf(&temp_string,"%.0f",response_value[i]);
651 if(temp_string==NULL)
652 die(STATE_UNKNOWN,_("Cannot asprintf()"));
653 response_length = strlen(temp_string);
654 if(current_length+response_length>string_length) {
655 string_length=current_length+1024;
656 state_string=realloc(state_string,string_length);
657 if(state_string==NULL)
658 die(STATE_UNKNOWN, _("Cannot realloc()"));
660 strcpy(&state_string[current_length],temp_string);
661 current_length=current_length+response_length;
662 state_string[current_length]=':';
663 current_length++;
664 free(temp_string);
666 state_string[--current_length]='\0';
667 if (verbose > 2)
668 printf("State string=%s\n",state_string);
670 /* This is not strictly the same as time now, but any subtle variations will cancel out */
671 np_state_write_string(current_time, state_string );
672 if(previous_state==NULL) {
673 /* Or should this be highest state? */
674 die( STATE_OK, _("No previous data to calculate rate - assume okay" ) );
678 printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr);
679 if (mult_resp) printf ("%s", mult_resp);
681 return result;
686 /* process command-line arguments */
688 process_arguments (int argc, char **argv)
690 char *ptr;
691 int c = 1;
692 size_t j = 0, jj = 0;
694 int option = 0;
695 static struct option longopts[] = {
696 STD_LONG_OPTS,
697 {"community", required_argument, 0, 'C'},
698 {"oid", required_argument, 0, 'o'},
699 {"object", required_argument, 0, 'o'},
700 {"delimiter", required_argument, 0, 'd'},
701 {"nulloid", required_argument, 0, 'z'},
702 {"output-delimiter", required_argument, 0, 'D'},
703 {"string", required_argument, 0, 's'},
704 {"timeout", required_argument, 0, 't'},
705 {"regex", required_argument, 0, 'r'},
706 {"ereg", required_argument, 0, 'r'},
707 {"eregi", required_argument, 0, 'R'},
708 {"label", required_argument, 0, 'l'},
709 {"units", required_argument, 0, 'u'},
710 {"port", required_argument, 0, 'p'},
711 {"retries", required_argument, 0, 'e'},
712 {"miblist", required_argument, 0, 'm'},
713 {"protocol", required_argument, 0, 'P'},
714 {"context", required_argument, 0, 'N'},
715 {"seclevel", required_argument, 0, 'L'},
716 {"secname", required_argument, 0, 'U'},
717 {"authproto", required_argument, 0, 'a'},
718 {"privproto", required_argument, 0, 'x'},
719 {"authpasswd", required_argument, 0, 'A'},
720 {"privpasswd", required_argument, 0, 'X'},
721 {"next", no_argument, 0, 'n'},
722 {"rate", no_argument, 0, L_CALCULATE_RATE},
723 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER},
724 {"offset", required_argument, 0, L_OFFSET},
725 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
726 {"perf-oids", no_argument, 0, 'O'},
727 {"ipv4", no_argument, 0, '4'},
728 {"ipv6", no_argument, 0, '6'},
729 {"multiplier", required_argument, 0, 'M'},
730 {"fmtstr", required_argument, 0, 'f'},
731 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
732 {0, 0, 0, 0}
735 if (argc < 2)
736 return ERROR;
738 /* reverse compatibility for very old non-POSIX usage forms */
739 for (c = 1; c < argc; c++) {
740 if (strcmp ("-to", argv[c]) == 0)
741 strcpy (argv[c], "-t");
742 if (strcmp ("-wv", argv[c]) == 0)
743 strcpy (argv[c], "-w");
744 if (strcmp ("-cv", argv[c]) == 0)
745 strcpy (argv[c], "-c");
748 while (1) {
749 c = getopt_long (argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:M:f:z:",
750 longopts, &option);
752 if (c == -1 || c == EOF)
753 break;
755 switch (c) {
756 case '?': /* usage */
757 usage5 ();
758 case 'h': /* help */
759 print_help ();
760 exit (STATE_UNKNOWN);
761 case 'V': /* version */
762 print_revision (progname, NP_VERSION);
763 exit (STATE_UNKNOWN);
764 case 'v': /* verbose */
765 verbose++;
766 break;
768 /* Connection info */
769 case 'C': /* group or community */
770 community = optarg;
771 break;
772 case 'H': /* Host or server */
773 server_address = optarg;
774 break;
775 case 'p': /* TCP port number */
776 port = optarg;
777 break;
778 case 'm': /* List of MIBS */
779 miblist = optarg;
780 break;
781 case 'n': /* usesnmpgetnext */
782 usesnmpgetnext = true;
783 break;
784 case 'P': /* SNMP protocol version */
785 proto = optarg;
786 break;
787 case 'N': /* SNMPv3 context */
788 context = optarg;
789 break;
790 case 'L': /* security level */
791 seclevel = optarg;
792 break;
793 case 'U': /* security username */
794 secname = optarg;
795 break;
796 case 'a': /* auth protocol */
797 authproto = optarg;
798 break;
799 case 'x': /* priv protocol */
800 privproto = optarg;
801 break;
802 case 'A': /* auth passwd */
803 authpasswd = optarg;
804 break;
805 case 'X': /* priv passwd */
806 privpasswd = optarg;
807 break;
808 case 't': /* timeout period */
809 if (!is_integer (optarg))
810 usage2 (_("Timeout interval must be a positive integer"), optarg);
811 else
812 timeout_interval = atoi (optarg);
813 break;
815 /* Test parameters */
816 case 'c': /* critical threshold */
817 critical_thresholds = optarg;
818 break;
819 case 'w': /* warning threshold */
820 warning_thresholds = optarg;
821 break;
822 case 'e': /* PRELIMINARY - may change */
823 case 'E': /* PRELIMINARY - may change */
824 if (!is_integer (optarg))
825 usage2 (_("Retries interval must be a positive integer"), optarg);
826 else
827 retries = atoi(optarg);
828 break;
829 case 'o': /* object identifier */
830 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) {
832 * we have something other than digits, periods and comas,
833 * so we have a mib variable, rather than just an SNMP OID,
834 * so we have to actually read the mib files
836 needmibs = true;
838 for (ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) {
839 while (j >= oids_size) {
840 oids_size += OID_COUNT_STEP;
841 oids = realloc(oids, oids_size * sizeof (*oids));
843 oids[j] = strdup(ptr);
845 numoids = j;
846 if (c == 'E' || c == 'e') {
847 jj++;
848 while (j+1 >= eval_size) {
849 eval_size += OID_COUNT_STEP;
850 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
851 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8);
853 if (c == 'E')
854 eval_method[j+1] |= WARN_PRESENT;
855 else if (c == 'e')
856 eval_method[j+1] |= CRIT_PRESENT;
858 break;
859 case 'z': /* Null OID Return Check */
860 if (!is_integer (optarg))
861 usage2 (_("Exit status must be a positive integer"), optarg);
862 else
863 nulloid = atoi(optarg);
864 break;
865 case 's': /* string or substring */
866 strncpy (string_value, optarg, sizeof (string_value) - 1);
867 string_value[sizeof (string_value) - 1] = 0;
868 while (jj >= eval_size) {
869 eval_size += OID_COUNT_STEP;
870 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
871 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8);
873 eval_method[jj++] = CRIT_STRING;
874 break;
875 case 'R': /* regex */
876 cflags = REG_ICASE;
877 // fall through
878 case 'r': /* regex */
879 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
880 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
881 regex_expect[sizeof (regex_expect) - 1] = 0;
882 errcode = regcomp (&preg, regex_expect, cflags);
883 if (errcode != 0) {
884 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
885 printf (_("Could Not Compile Regular Expression"));
886 return ERROR;
888 while (jj >= eval_size) {
889 eval_size += OID_COUNT_STEP;
890 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
891 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8);
893 eval_method[jj++] = CRIT_REGEX;
894 break;
896 /* Format */
897 case 'd': /* delimiter */
898 delimiter = strscpy (delimiter, optarg);
899 break;
900 case 'D': /* output-delimiter */
901 output_delim = strscpy (output_delim, optarg);
902 break;
903 case 'l': /* label */
904 nlabels++;
905 if (nlabels > labels_size) {
906 labels_size += 8;
907 labels = realloc (labels, labels_size * sizeof(*labels));
908 if (labels == NULL)
909 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
911 labels[nlabels - 1] = optarg;
912 ptr = thisarg (optarg);
913 labels[nlabels - 1] = ptr;
914 if (ptr[0] == '\'')
915 labels[nlabels - 1] = ptr + 1;
916 while (ptr && (ptr = nextarg (ptr))) {
917 nlabels++;
918 if (nlabels > labels_size) {
919 labels_size += 8;
920 labels = realloc (labels, labels_size * sizeof(*labels));
921 if (labels == NULL)
922 die (STATE_UNKNOWN, _("Could not reallocate labels\n"));
924 ptr = thisarg (ptr);
925 if (ptr[0] == '\'')
926 labels[nlabels - 1] = ptr + 1;
927 else
928 labels[nlabels - 1] = ptr;
930 break;
931 case 'u': /* units */
932 units = optarg;
933 nunits++;
934 if (nunits > unitv_size) {
935 unitv_size += 8;
936 unitv = realloc (unitv, unitv_size * sizeof(*unitv));
937 if (unitv == NULL)
938 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
940 unitv[nunits - 1] = optarg;
941 ptr = thisarg (optarg);
942 unitv[nunits - 1] = ptr;
943 if (ptr[0] == '\'')
944 unitv[nunits - 1] = ptr + 1;
945 while (ptr && (ptr = nextarg (ptr))) {
946 if (nunits > unitv_size) {
947 unitv_size += 8;
948 unitv = realloc (unitv, unitv_size * sizeof(*unitv));
949 if (units == NULL)
950 die (STATE_UNKNOWN, _("Could not realloc() units\n"));
952 nunits++;
953 ptr = thisarg (ptr);
954 if (ptr[0] == '\'')
955 unitv[nunits - 1] = ptr + 1;
956 else
957 unitv[nunits - 1] = ptr;
959 break;
960 case L_CALCULATE_RATE:
961 if(calculate_rate==0)
962 np_enable_state(NULL, 1);
963 calculate_rate = 1;
964 break;
965 case L_RATE_MULTIPLIER:
966 if(!is_integer(optarg)||((rate_multiplier=atoi(optarg))<=0))
967 usage2(_("Rate multiplier must be a positive integer"),optarg);
968 break;
969 case L_OFFSET:
970 offset=strtod(optarg,NULL);
971 break;
972 case L_INVERT_SEARCH:
973 invert_search=1;
974 break;
975 case 'O':
976 perf_labels=0;
977 break;
978 case '4':
979 break;
980 case '6':
981 xasprintf(&ip_version, "udp6:");
982 if(verbose>2)
983 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n");
984 break;
985 case 'M':
986 if ( strspn( optarg, "0123456789.," ) == strlen( optarg ) ) {
987 multiplier=strtod(optarg,NULL);
989 break;
990 case 'f':
991 if (multiplier != 1.0) {
992 fmtstr=optarg;
993 fmtstr_set = true;
995 break;
996 case L_IGNORE_MIB_PARSING_ERRORS:
997 ignore_mib_parsing_errors = true;
1001 if (server_address == NULL)
1002 server_address = argv[optind];
1004 if (community == NULL)
1005 community = strdup (DEFAULT_COMMUNITY);
1007 return validate_arguments ();
1011 /******************************************************************************
1014 <sect3>
1015 <title>validate_arguments</title>
1017 <para>&PROTO_validate_arguments;</para>
1019 <para>Checks to see if the default miblist needs to be loaded. Also verifies
1020 the authentication and authorization combinations based on protocol version
1021 selected.</para>
1023 <para></para>
1025 </sect3>
1027 ******************************************************************************/
1031 static int
1032 validate_arguments ()
1034 /* check whether to load locally installed MIBS (CPU/disk intensive) */
1035 if (miblist == NULL) {
1036 if (needmibs) {
1037 miblist = strdup (DEFAULT_MIBLIST);
1038 }else{
1039 miblist = ""; /* don't read any mib files for numeric oids */
1043 /* Check server_address is given */
1044 if (server_address == NULL)
1045 die(STATE_UNKNOWN, _("No host specified\n"));
1047 /* Check oid is given */
1048 if (numoids == 0)
1049 die(STATE_UNKNOWN, _("No OIDs specified\n"));
1051 if (proto == NULL)
1052 xasprintf(&proto, DEFAULT_PROTOCOL);
1054 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */
1055 numauthpriv = 2;
1056 authpriv = calloc (numauthpriv, sizeof (char *));
1057 authpriv[0] = strdup ("-c");
1058 authpriv[1] = strdup (community);
1060 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
1061 if (!(context == NULL)) {
1062 numcontext = 2;
1063 contextargs = calloc (numcontext, sizeof (char *));
1064 contextargs[0] = strdup ("-n");
1065 contextargs[1] = strdup (context);
1068 if (seclevel == NULL)
1069 xasprintf(&seclevel, "noAuthNoPriv");
1071 if (secname == NULL)
1072 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
1074 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
1075 numauthpriv = 4;
1076 authpriv = calloc (numauthpriv, sizeof (char *));
1077 authpriv[0] = strdup ("-l");
1078 authpriv[1] = strdup ("noAuthNoPriv");
1079 authpriv[2] = strdup ("-u");
1080 authpriv[3] = strdup (secname);
1081 } else {
1082 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) {
1083 usage2 (_("Invalid seclevel"), seclevel);
1086 if (authproto == NULL )
1087 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
1089 if (authpasswd == NULL)
1090 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
1092 if ( strcmp(seclevel, "authNoPriv") == 0 ) {
1093 numauthpriv = 8;
1094 authpriv = calloc (numauthpriv, sizeof (char *));
1095 authpriv[0] = strdup ("-l");
1096 authpriv[1] = strdup ("authNoPriv");
1097 authpriv[2] = strdup ("-a");
1098 authpriv[3] = strdup (authproto);
1099 authpriv[4] = strdup ("-u");
1100 authpriv[5] = strdup (secname);
1101 authpriv[6] = strdup ("-A");
1102 authpriv[7] = strdup (authpasswd);
1103 } else if ( strcmp(seclevel, "authPriv") == 0 ) {
1104 if (privproto == NULL )
1105 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
1107 if (privpasswd == NULL)
1108 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
1110 numauthpriv = 12;
1111 authpriv = calloc (numauthpriv, sizeof (char *));
1112 authpriv[0] = strdup ("-l");
1113 authpriv[1] = strdup ("authPriv");
1114 authpriv[2] = strdup ("-a");
1115 authpriv[3] = strdup (authproto);
1116 authpriv[4] = strdup ("-u");
1117 authpriv[5] = strdup (secname);
1118 authpriv[6] = strdup ("-A");
1119 authpriv[7] = strdup (authpasswd);
1120 authpriv[8] = strdup ("-x");
1121 authpriv[9] = strdup (privproto);
1122 authpriv[10] = strdup ("-X");
1123 authpriv[11] = strdup (privpasswd);
1128 else {
1129 usage2 (_("Invalid SNMP version"), proto);
1132 return OK;
1137 /* trim leading whitespace
1138 if there is a leading quote, make sure it balances */
1140 static char *
1141 thisarg (char *str)
1143 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
1144 if (str[0] == '\'') { /* handle SIMPLE quoted strings */
1145 if (strlen (str) == 1 || !strstr (str + 1, "'"))
1146 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
1148 return str;
1153 /* if there's a leading quote, advance to the trailing quote
1154 set the trailing quote to '\x0'
1155 if the string continues, advance beyond the comma */
1157 static char *
1158 nextarg (char *str)
1160 if (str[0] == '\'') {
1161 str[0] = 0;
1162 if (strlen (str) > 1) {
1163 str = strstr (str + 1, "'");
1164 return (++str);
1166 else {
1167 return NULL;
1170 if (str[0] == ',') {
1171 str[0] = 0;
1172 if (strlen (str) > 1) {
1173 return (++str);
1175 else {
1176 return NULL;
1179 if ((str = strstr (str, ",")) && strlen (str) > 1) {
1180 str[0] = 0;
1181 return (++str);
1183 return NULL;
1188 /* multiply result (values 0 < n < 1 work as divider) */
1189 static char *
1190 multiply (char *str)
1192 char *endptr;
1193 double val;
1194 char *conv = "%f";
1196 if(multiplier == 1)
1197 return(str);
1199 if(verbose>2)
1200 printf(" multiply input: %s\n", str);
1202 val = strtod (str, &endptr);
1203 if ((val == 0.0) && (endptr == str)) {
1204 die(STATE_UNKNOWN, _("multiplier set (%.1f), but input is not a number: %s"), multiplier, str);
1207 if(verbose>2)
1208 printf(" multiply extracted double: %f\n", val);
1209 val *= multiplier;
1210 if (fmtstr_set) {
1211 conv = fmtstr;
1213 if (val == (int)val) {
1214 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val);
1215 } else {
1216 if(verbose>2)
1217 printf(" multiply using format: %s\n", conv);
1218 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val);
1220 if(verbose>2)
1221 printf(" multiply result: %s\n", buffer);
1222 return buffer;
1226 static void
1227 print_help (void)
1229 print_revision (progname, NP_VERSION);
1231 printf (COPYRIGHT, copyright, email);
1233 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
1235 printf ("\n\n");
1237 print_usage ();
1239 printf (UT_HELP_VRSN);
1240 printf (UT_EXTRA_OPTS);
1241 printf (UT_IPv46);
1243 printf (UT_HOST_PORT, 'p', DEFAULT_PORT);
1245 /* SNMP and Authentication Protocol */
1246 printf (" %s\n", "-n, --next");
1247 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
1248 printf (" %s\n", "-P, --protocol=[1|2c|3]");
1249 printf (" %s\n", _("SNMP protocol version"));
1250 printf (" %s\n", "-N, --context=CONTEXT");
1251 printf (" %s\n", _("SNMPv3 context"));
1252 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
1253 printf (" %s\n", _("SNMPv3 securityLevel"));
1254 printf (" %s\n", "-a, --authproto=AUTHENTICATION_PROTOCOL");
1255 printf (" %s\n", _("SNMPv3 authentication protocol (default MD5), available options depend on the specific version of the net-snmp tools"));
1256 printf (" %s\n", _("if < 5.8 SHA (1) and MD5 should be available, if >= 5.8 additionally SHA-224, SHA-256, SHA-384 and SHA-512"));
1257 printf (" %s\n", "-x, --privproto=PRIVACY_PROTOCOL");
1258 printf (" %s\n", _("SNMPv3 privacy protocol (default DES), available options depend on the specific version of the net-snmp tools"));
1259 printf (" %s\n", _("if < 5.8 DES and AES should be available, if >= 5.8 additionally AES-192 and AES-256"));
1261 /* Authentication Tokens*/
1262 printf (" %s\n", "-C, --community=STRING");
1263 printf (" %s ", _("Optional community string for SNMP communication"));
1264 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
1265 printf (" %s\n", "-U, --secname=USERNAME");
1266 printf (" %s\n", _("SNMPv3 username"));
1267 printf (" %s\n", "-A, --authpasswd=PASSWORD");
1268 printf (" %s\n", _("SNMPv3 authentication password"));
1269 printf (" %s\n", "-X, --privpasswd=PASSWORD");
1270 printf (" %s\n", _("SNMPv3 privacy password"));
1272 /* OID Stuff */
1273 printf (" %s\n", "-o, --oid=OID(s)");
1274 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
1275 printf (" %s\n", "-m, --miblist=STRING");
1276 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
1277 printf (" %s\n", _("for symbolic OIDs.)"));
1278 printf (" %s\n", "-d, --delimiter=STRING");
1279 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
1280 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered"));
1281 printf (" %s\n", _("to be the data that should be used in the evaluation."));
1282 printf (" %s\n", "-z, --nulloid=#");
1283 printf (" %s\n", _("If the check returns a 0 length string or NULL value"));
1284 printf (" %s\n", _("This option allows you to choose what status you want it to exit"));
1285 printf (" %s\n", _("Excluding this option renders the default exit of 3(STATE_UNKNOWN)"));
1286 printf (" %s\n", _("0 = OK"));
1287 printf (" %s\n", _("1 = WARNING"));
1288 printf (" %s\n", _("2 = CRITICAL"));
1289 printf (" %s\n", _("3 = UNKNOWN"));
1291 /* Tests Against Integers */
1292 printf (" %s\n", "-w, --warning=THRESHOLD(s)");
1293 printf (" %s\n", _("Warning threshold range(s)"));
1294 printf (" %s\n", "-c, --critical=THRESHOLD(s)");
1295 printf (" %s\n", _("Critical threshold range(s)"));
1296 printf (" %s\n", "--rate");
1297 printf (" %s\n", _("Enable rate calculation. See 'Rate Calculation' below"));
1298 printf (" %s\n", "--rate-multiplier");
1299 printf (" %s\n", _("Converts rate per second. For example, set to 60 to convert to per minute"));
1300 printf (" %s\n", "--offset=OFFSET");
1301 printf (" %s\n", _("Add/subtract the specified OFFSET to numeric sensor data"));
1303 /* Tests Against Strings */
1304 printf (" %s\n", "-s, --string=STRING");
1305 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
1306 printf (" %s\n", "-r, --ereg=REGEX");
1307 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
1308 printf (" %s\n", "-R, --eregi=REGEX");
1309 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
1310 printf (" %s\n", "--invert-search");
1311 printf (" %s\n", _("Invert search result (CRITICAL if found)"));
1313 /* Output Formatting */
1314 printf (" %s\n", "-l, --label=STRING");
1315 printf (" %s\n", _("Prefix label for output from plugin"));
1316 printf (" %s\n", "-u, --units=STRING");
1317 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
1318 printf (" %s\n", "-D, --output-delimiter=STRING");
1319 printf (" %s\n", _("Separates output on multiple OID requests"));
1320 printf (" %s\n", "-M, --multiplier=FLOAT");
1321 printf (" %s\n", _("Multiplies current value, 0 < n < 1 works as divider, defaults to 1"));
1322 printf (" %s\n", "-f, --fmtstr=STRING");
1323 printf (" %s\n", _("C-style format string for float values (see option -M)"));
1325 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1326 printf (" %s\n", _("NOTE the final timeout value is calculated using this formula: timeout_interval * retries + 5"));
1327 printf (" %s\n", "-e, --retries=INTEGER");
1328 printf (" %s%i\n", _("Number of retries to be used in the requests, default: "), DEFAULT_RETRIES);
1330 printf (" %s\n", "-O, --perf-oids");
1331 printf (" %s\n", _("Label performance data with OIDs instead of --label's"));
1333 printf (" %s\n", "--ignore-mib-parsing-errors");
1334 printf (" %s\n", _("Tell snmpget to not print errors encountered when parsing MIB files"));
1336 printf (UT_VERBOSE);
1338 printf ("\n");
1339 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
1340 printf ("%s\n", _("if you don't have the package installed, you will need to download it from"));
1341 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
1343 printf ("\n");
1344 printf ("%s\n", _("Notes:"));
1345 printf (" %s\n", _("- Multiple OIDs (and labels) may be indicated by a comma or space-delimited "));
1346 printf (" %s\n", _("list (lists with internal spaces must be quoted)."));
1348 printf(" -%s", UT_THRESHOLDS_NOTES);
1350 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
1351 printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
1352 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
1353 printf (" %s\n", _("returned from the SNMP query is an unsigned integer."));
1355 printf("\n");
1356 printf("%s\n", _("Rate Calculation:"));
1357 printf(" %s\n", _("In many places, SNMP returns counters that are only meaningful when"));
1358 printf(" %s\n", _("calculating the counter difference since the last check. check_snmp"));
1359 printf(" %s\n", _("saves the last state information in a file so that the rate per second"));
1360 printf(" %s\n", _("can be calculated. Use the --rate option to save state information."));
1361 printf(" %s\n", _("On the first run, there will be no prior state - this will return with OK."));
1362 printf(" %s\n", _("The state is uniquely determined by the arguments to the plugin, so"));
1363 printf(" %s\n", _("changing the arguments will create a new state file."));
1365 printf (UT_SUPPORT);
1370 void
1371 print_usage (void)
1373 printf ("%s\n", _("Usage:"));
1374 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
1375 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
1376 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1377 printf ("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
1378 printf ("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd] [-4|6]\n");
1379 printf ("[-M multiplier [-f format]]\n");