summaryrefslogtreecommitdiffstats
path: root/plugins/check_snmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_snmp.c')
-rw-r--r--plugins/check_snmp.c778
1 files changed, 363 insertions, 415 deletions
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index 3c054259..a5a7afe8 100644
--- a/plugins/check_snmp.c
+++ b/plugins/check_snmp.c
@@ -37,10 +37,8 @@ const char *email = "devel@monitoring-plugins.org";
37#include "./utils.h" 37#include "./utils.h"
38#include "../lib/states.h" 38#include "../lib/states.h"
39 39
40#include "../lib/thresholds.h"
41#include "../lib/utils_base.h" 40#include "../lib/utils_base.h"
42#include "../lib/output.h" 41#include "../lib/output.h"
43#include "../lib/perfdata.h"
44#include "check_snmp.d/check_snmp_helpers.h" 42#include "check_snmp.d/check_snmp_helpers.h"
45 43
46#include <bits/getopt_core.h> 44#include <bits/getopt_core.h>
@@ -49,6 +47,7 @@ const char *email = "devel@monitoring-plugins.org";
49#include <stdint.h> 47#include <stdint.h>
50 48
51#include "check_snmp.d/config.h" 49#include "check_snmp.d/config.h"
50#include <stdlib.h>
52#include <arpa/inet.h> 51#include <arpa/inet.h>
53#include <net-snmp/library/parse.h> 52#include <net-snmp/library/parse.h>
54#include <net-snmp/net-snmp-config.h> 53#include <net-snmp/net-snmp-config.h>
@@ -63,6 +62,7 @@ const char *email = "devel@monitoring-plugins.org";
63#include <net-snmp/library/snmp_impl.h> 62#include <net-snmp/library/snmp_impl.h>
64#include <string.h> 63#include <string.h>
65#include "../gl/regex.h" 64#include "../gl/regex.h"
65#include "../gl/base64.h"
66#include <assert.h> 66#include <assert.h>
67 67
68const char DEFAULT_COMMUNITY[] = "public"; 68const char DEFAULT_COMMUNITY[] = "public";
@@ -86,7 +86,168 @@ static char *get_next_argument(char *str);
86void print_usage(void); 86void print_usage(void);
87void print_help(void); 87void print_help(void);
88 88
89static int verbose = 0; 89int verbose = 0;
90
91typedef struct {
92 int errorcode;
93 char *state_string;
94} gen_state_string_type;
95gen_state_string_type gen_state_string(check_snmp_state_entry *entries, size_t num_of_entries) {
96 char *encoded_string = NULL;
97 gen_state_string_type result = {.errorcode = OK, .state_string = NULL};
98
99 if (verbose > 1) {
100 printf("%s:\n", __FUNCTION__);
101 for (size_t i = 0; i < num_of_entries; i++) {
102 printf("Entry timestamp %lu: %s", entries[i].timestamp, ctime(&entries[i].timestamp));
103 switch (entries[i].type) {
104 case ASN_GAUGE:
105 printf("Type GAUGE\n");
106 break;
107 case ASN_TIMETICKS:
108 printf("Type TIMETICKS\n");
109 break;
110 case ASN_COUNTER:
111 printf("Type COUNTER\n");
112 break;
113 case ASN_UINTEGER:
114 printf("Type UINTEGER\n");
115 break;
116 case ASN_COUNTER64:
117 printf("Type COUNTER64\n");
118 break;
119 case ASN_FLOAT:
120 printf("Type FLOAT\n");
121 case ASN_DOUBLE:
122 printf("Type DOUBLE\n");
123 break;
124 case ASN_INTEGER:
125 printf("Type INTEGER\n");
126 break;
127 }
128
129 switch (entries[i].type) {
130 case ASN_GAUGE:
131 case ASN_TIMETICKS:
132 case ASN_COUNTER:
133 case ASN_UINTEGER:
134 case ASN_COUNTER64:
135 printf("Value %llu\n", entries[i].value.uIntVal);
136 break;
137 case ASN_FLOAT:
138 case ASN_DOUBLE:
139 printf("Value %f\n", entries[i].value.doubleVal);
140 break;
141 case ASN_INTEGER:
142 printf("Value %lld\n", entries[i].value.intVal);
143 break;
144 }
145 }
146 }
147
148 idx_t encoded = base64_encode_alloc((const char *)entries,
149 (idx_t)(num_of_entries * sizeof(check_snmp_state_entry)),
150 &encoded_string);
151
152 if (encoded > 0 && encoded_string != NULL) {
153 // success
154 if (verbose > 1) {
155 printf("encoded string: %s\n", encoded_string);
156 printf("encoded string length: %lu\n", strlen(encoded_string));
157 }
158 result.state_string = encoded_string;
159 return result;
160 }
161 result.errorcode = ERROR;
162 return result;
163}
164
165typedef struct {
166 int errorcode;
167 check_snmp_state_entry *state;
168} recover_state_data_type;
169recover_state_data_type recover_state_data(char *state_string, idx_t state_string_length) {
170 recover_state_data_type result = {.errorcode = OK, .state = NULL};
171
172 if (verbose > 1) {
173 printf("%s:\n", __FUNCTION__);
174 printf("State string: %s\n", state_string);
175 printf("State string length: %lu\n", state_string_length);
176 }
177
178 idx_t outlen = 0;
179 bool decoded =
180 base64_decode_alloc(state_string, state_string_length, (char **)&result.state, &outlen);
181
182 if (!decoded) {
183 if (verbose) {
184 printf("Failed to decode state string\n");
185 }
186 // failure to decode
187 result.errorcode = ERROR;
188 return result;
189 }
190
191 if (result.state == NULL) {
192 // Memory Error?
193 result.errorcode = ERROR;
194 return result;
195 }
196
197 if (verbose > 1) {
198 printf("Recovered %lu entries of size %lu\n",
199 (size_t)outlen / sizeof(check_snmp_state_entry), outlen);
200
201 for (size_t i = 0; i < (size_t)outlen / sizeof(check_snmp_state_entry); i++) {
202 printf("Entry timestamp %lu: %s", result.state[i].timestamp,
203 ctime(&result.state[i].timestamp));
204 switch (result.state[i].type) {
205 case ASN_GAUGE:
206 printf("Type GAUGE\n");
207 break;
208 case ASN_TIMETICKS:
209 printf("Type TIMETICKS\n");
210 break;
211 case ASN_COUNTER:
212 printf("Type COUNTER\n");
213 break;
214 case ASN_UINTEGER:
215 printf("Type UINTEGER\n");
216 break;
217 case ASN_COUNTER64:
218 printf("Type COUNTER64\n");
219 break;
220 case ASN_FLOAT:
221 printf("Type FLOAT\n");
222 case ASN_DOUBLE:
223 printf("Type DOUBLE\n");
224 break;
225 case ASN_INTEGER:
226 printf("Type INTEGER\n");
227 break;
228 }
229
230 switch (result.state[i].type) {
231 case ASN_GAUGE:
232 case ASN_TIMETICKS:
233 case ASN_COUNTER:
234 case ASN_UINTEGER:
235 case ASN_COUNTER64:
236 printf("Value %llu\n", result.state[i].value.uIntVal);
237 break;
238 case ASN_FLOAT:
239 case ASN_DOUBLE:
240 printf("Value %f\n", result.state[i].value.doubleVal);
241 break;
242 case ASN_INTEGER:
243 printf("Value %lld\n", result.state[i].value.intVal);
244 break;
245 }
246 }
247 }
248
249 return result;
250}
90 251
91int main(int argc, char **argv) { 252int main(int argc, char **argv) {
92 setlocale(LC_ALL, ""); 253 setlocale(LC_ALL, "");
@@ -97,6 +258,8 @@ int main(int argc, char **argv) {
97 258
98 np_init((char *)progname, argc, argv); 259 np_init((char *)progname, argc, argv);
99 260
261 state_key stateKey = np_enable_state(NULL, 1, progname, argc, argv);
262
100 /* Parse extra opts if any */ 263 /* Parse extra opts if any */
101 argv = np_extra_opts(&argc, argv, progname); 264 argv = np_extra_opts(&argc, argv, progname);
102 265
@@ -105,9 +268,6 @@ int main(int argc, char **argv) {
105 // Initialize net-snmp before touching the session we are going to use 268 // Initialize net-snmp before touching the session we are going to use
106 init_snmp("check_snmp"); 269 init_snmp("check_snmp");
107 270
108 time_t current_time;
109 time(&current_time);
110
111 process_arguments_wrapper paw_tmp = process_arguments(argc, argv); 271 process_arguments_wrapper paw_tmp = process_arguments(argc, argv);
112 if (paw_tmp.errorcode == ERROR) { 272 if (paw_tmp.errorcode == ERROR) {
113 usage4(_("Could not parse arguments")); 273 usage4(_("Could not parse arguments"));
@@ -119,347 +279,103 @@ int main(int argc, char **argv) {
119 mp_set_format(config.output_format); 279 mp_set_format(config.output_format);
120 } 280 }
121 281
122 if (config.ignore_mib_parsing_errors) {
123 char *opt_toggle_res = snmp_mib_toggle_options("e");
124 if (opt_toggle_res != NULL) {
125 die(STATE_UNKNOWN, "Unable to disable MIB parsing errors");
126 }
127 }
128
129 struct snmp_pdu *pdu = NULL;
130 if (config.use_getnext) {
131 pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
132 } else {
133 pdu = snmp_pdu_create(SNMP_MSG_GET);
134 }
135
136 for (size_t i = 0; i < config.num_of_test_units; i++) {
137 assert(config.test_units[i].oid != NULL);
138 if (verbose > 0) {
139 printf("OID %zu to parse: %s\n", i, config.test_units[i].oid);
140 }
141
142 oid tmp_OID[MAX_OID_LEN];
143 size_t tmp_OID_len = MAX_OID_LEN;
144 if (snmp_parse_oid(config.test_units[i].oid, tmp_OID, &tmp_OID_len) != NULL) {
145 // success
146 snmp_add_null_var(pdu, tmp_OID, tmp_OID_len);
147 } else {
148 // failed
149 snmp_perror("Parsing failure");
150 die(STATE_UNKNOWN, "Failed to parse OID\n");
151 }
152 }
153
154 /* Set signal handling and alarm */ 282 /* Set signal handling and alarm */
155 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) { 283 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
156 usage4(_("Cannot catch SIGALRM")); 284 usage4(_("Cannot catch SIGALRM"));
157 } 285 }
158 286
159 const int timeout_safety_tolerance = 5; 287 time_t current_time;
160 alarm((timeout_interval * (unsigned int)config.snmp_session.retries) + 288 time(&current_time);
161 timeout_safety_tolerance);
162
163 struct snmp_session *active_session = snmp_open(&config.snmp_session);
164 if (active_session == NULL) {
165 int pcliberr = 0;
166 int psnmperr = 0;
167 char *pperrstring = NULL;
168 snmp_error(&config.snmp_session, &pcliberr, &psnmperr, &pperrstring);
169 die(STATE_UNKNOWN, "Failed to open SNMP session: %s\n", pperrstring);
170 }
171
172 struct snmp_pdu *response = NULL;
173 int snmp_query_status = snmp_synch_response(active_session, pdu, &response);
174
175 if (!(snmp_query_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR)) {
176 int pcliberr = 0;
177 int psnmperr = 0;
178 char *pperrstring = NULL;
179 snmp_error(active_session, &pcliberr, &psnmperr, &pperrstring);
180 289
181 if (psnmperr == SNMPERR_TIMEOUT) { 290 if (verbose > 2) {
182 // We exit with critical here for some historical reason 291 printf("current time: %s (timestamp: %lu)\n", ctime(&current_time), current_time);
183 die(STATE_CRITICAL, "SNMP query ran into a timeout\n");
184 }
185 die(STATE_UNKNOWN, "SNMP query failed: %s\n", pperrstring);
186 } 292 }
187 293
188 snmp_close(active_session); 294 snmp_responces response = do_snmp_query(config.snmp_params);
189
190 /* disable alarm again */
191 alarm(0);
192 295
193 mp_check overall = mp_check_init(); 296 mp_check overall = mp_check_init();
194 297
195 mp_subcheck sc_successfull_query = mp_subcheck_init(); 298 if (response.errorcode == OK) {
196 xasprintf(&sc_successfull_query.output, "SNMP query was successful"); 299 mp_subcheck sc_successfull_query = mp_subcheck_init();
197 sc_successfull_query = mp_set_subcheck_state(sc_successfull_query, STATE_OK); 300 xasprintf(&sc_successfull_query.output, "SNMP query was successful");
198 mp_add_subcheck_to_check(&overall, sc_successfull_query); 301 sc_successfull_query = mp_set_subcheck_state(sc_successfull_query, STATE_OK);
199 302 mp_add_subcheck_to_check(&overall, sc_successfull_query);
200 // We got the the query results, now process them 303 } else {
201 size_t loop_index = 0; 304 // Error treatment here, either partial or whole
202 for (netsnmp_variable_list *vars = response->variables; vars; 305 mp_subcheck sc_failed_query = mp_subcheck_init();
203 vars = vars->next_variable, loop_index++) { 306 xasprintf(&sc_failed_query.output, "SNMP query failed");
204 mp_subcheck sc_oid_test = mp_subcheck_init(); 307 sc_failed_query = mp_set_subcheck_state(sc_failed_query, STATE_OK);
308 mp_add_subcheck_to_check(&overall, sc_failed_query);
309 mp_exit(overall);
310 }
205 311
206 if (verbose > 0) { 312 check_snmp_state_entry *prev_state = NULL;
207 printf("loop_index: %zu\n", loop_index); 313 bool have_previous_state = false;
208 }
209 314
210 if ((config.test_units[loop_index].label != NULL) && 315 if (config.evaluation_params.calculate_rate) {
211 (strcmp(config.test_units[loop_index].label, "") != 0)) { 316 state_data *previous_state = np_state_read(stateKey);
212 xasprintf(&sc_oid_test.output, "%s - ", config.test_units[loop_index].label); 317 if (previous_state == NULL) {
318 // failed to recover state
319 // or no previous state
320 have_previous_state = false;
213 } else { 321 } else {
214 sc_oid_test.output = strdup(""); 322 // sanity check
215 } 323 recover_state_data_type prev_state_wrapper =
216 324 recover_state_data(previous_state->data, (idx_t)previous_state->length);
217 char oid_string[(MAX_OID_LEN * 2) + 1] = {};
218
219 int oid_string_result =
220 snprint_objid(oid_string, (MAX_OID_LEN * 2) + 1, vars->name, vars->name_length);
221 if (oid_string_result <= 0) {
222 // TODO error here
223 }
224
225 if (verbose > 2) {
226 printf("Processing oid %s\n", oid_string);
227 }
228 325
229 mp_perfdata_value pd_result_val = {0}; 326 if (prev_state_wrapper.errorcode == OK) {
230 xasprintf(&sc_oid_test.output, "%sOID: %s", sc_oid_test.output, oid_string); 327 have_previous_state = true;
231 sc_oid_test = mp_set_subcheck_default_state(sc_oid_test, STATE_OK); 328 prev_state = prev_state_wrapper.state;
232
233 switch (vars->type) {
234 case ASN_OCTET_STR: {
235 if (verbose) {
236 printf("Debug: Got a string\n");
237 }
238
239 char *tmp = (char *)vars->val.string;
240
241 if (strchr(tmp, '"') != NULL) {
242 // got double quote in the string
243 if (strchr(tmp, '\'') != NULL) {
244 // got single quote in the string too
245 // dont quote that at all to avoid even more confusion
246 xasprintf(&sc_oid_test.output, "%s - Value: %s", sc_oid_test.output, tmp);
247 } else {
248 // quote with single quotes
249 xasprintf(&sc_oid_test.output, "%s - Value: '%s'", sc_oid_test.output, tmp);
250 }
251 } else { 329 } else {
252 // quote with double quotes 330 have_previous_state = false;
253 xasprintf(&sc_oid_test.output, "%s - Value: \"%s\"", sc_oid_test.output, tmp); 331 prev_state = NULL;
254 }
255
256 if (strlen(tmp) == 0) {
257 sc_oid_test = mp_set_subcheck_state(sc_oid_test, config.nulloid_result);
258 } 332 }
259
260 // String matching test
261 if ((config.test_units[loop_index].eval_mthd.crit_string)) {
262 if (strcmp(tmp, config.string_cmp_value)) {
263 sc_oid_test = mp_set_subcheck_state(
264 sc_oid_test, (config.invert_search) ? STATE_CRITICAL : STATE_OK);
265 } else {
266 sc_oid_test = mp_set_subcheck_state(
267 sc_oid_test, (config.invert_search) ? STATE_OK : STATE_CRITICAL);
268 }
269 } else if (config.test_units[loop_index].eval_mthd.crit_regex) {
270 const size_t nmatch = config.regex_cmp_value.re_nsub + 1;
271 regmatch_t pmatch[nmatch];
272 memset(pmatch, '\0', sizeof(regmatch_t) * nmatch);
273
274 int excode = regexec(&config.regex_cmp_value, tmp, nmatch, pmatch, 0);
275 if (excode == 0) {
276 sc_oid_test = mp_set_subcheck_state(
277 sc_oid_test, (config.invert_search) ? STATE_OK : STATE_CRITICAL);
278 } else if (excode != REG_NOMATCH) {
279 char errbuf[MAX_INPUT_BUFFER] = "";
280 regerror(excode, &config.regex_cmp_value, errbuf, MAX_INPUT_BUFFER);
281 printf(_("Execute Error: %s\n"), errbuf);
282 exit(STATE_CRITICAL);
283 } else { // REG_NOMATCH
284 sc_oid_test = mp_set_subcheck_state(
285 sc_oid_test, config.invert_search ? STATE_CRITICAL : STATE_OK);
286 }
287 }
288
289 mp_add_subcheck_to_check(&overall, sc_oid_test);
290 } 333 }
291 continue; 334 }
292 case ASN_OPAQUE:
293 if (verbose) {
294 printf("Debug: Got OPAQUE\n");
295 }
296 break;
297 case ASN_COUNTER64: {
298 if (verbose) {
299 printf("Debug: Got counter64\n");
300 }
301 struct counter64 tmp = *(vars->val.counter64);
302 uint64_t counter = (tmp.high << 32) + tmp.low;
303
304 if (config.multiplier_set || config.offset_set) {
305 double processed = 0;
306 if (config.multiplier_set) {
307 processed = (double)counter * config.multiplier;
308 }
309
310 if (config.offset_set) {
311 processed += config.offset;
312 }
313 pd_result_val = mp_create_pd_value(processed);
314 } else {
315 pd_result_val = mp_create_pd_value(counter);
316 }
317
318 } break;
319 /* Numerical values */
320 case ASN_GAUGE: // same as ASN_UNSIGNED
321 case ASN_TIMETICKS:
322 case ASN_COUNTER:
323 case ASN_UINTEGER: {
324 if (verbose) {
325 printf("Debug: Got a Integer like\n");
326 }
327 unsigned long tmp = (unsigned long)*(vars->val.integer);
328
329 if (config.multiplier_set || config.offset_set) {
330 double processed = 0;
331 if (config.multiplier_set) {
332 processed = (double)tmp * config.multiplier;
333 }
334 335
335 if (config.offset_set) { 336 check_snmp_state_entry *new_state = NULL;
336 processed += config.offset; 337 if (config.evaluation_params.calculate_rate) {
337 } 338 new_state = calloc(config.snmp_params.num_of_test_units, sizeof(check_snmp_state_entry));
338 pd_result_val = mp_create_pd_value(processed); 339 if (new_state == NULL) {
339 } else { 340 die(STATE_UNKNOWN, "memory allocation failed");
340 pd_result_val = mp_create_pd_value(tmp);
341 }
342 break;
343 } 341 }
344 case ASN_INTEGER: { 342 }
345 if (verbose) {
346 printf("Debug: Got a Integer\n");
347 }
348
349 long tmp = *(vars->val.integer);
350
351 if (config.multiplier_set || config.offset_set) {
352 double processed = 0;
353 if (config.multiplier_set) {
354 processed = (double)tmp * config.multiplier;
355 }
356
357 if (config.offset_set) {
358 processed += config.offset;
359 }
360 pd_result_val = mp_create_pd_value(processed);
361 } else {
362 pd_result_val = mp_create_pd_value(tmp);
363 }
364
365 } break;
366 case ASN_FLOAT: {
367 if (verbose) {
368 printf("Debug: Got a float\n");
369 }
370 double tmp = *(vars->val.floatVal);
371
372 if (config.multiplier_set) {
373 tmp *= config.multiplier;
374 }
375
376 if (config.offset_set) {
377 tmp += config.offset;
378 }
379 343
380 pd_result_val = mp_create_pd_value(tmp); 344 // We got the the query results, now process them
381 break; 345 for (size_t loop_index = 0; loop_index < config.snmp_params.num_of_test_units; loop_index++) {
346 if (verbose > 0) {
347 printf("loop_index: %zu\n", loop_index);
382 } 348 }
383 case ASN_DOUBLE: {
384 if (verbose) {
385 printf("Debug: Got a double\n");
386 }
387 double tmp = *(vars->val.doubleVal);
388 if (config.multiplier_set) {
389 tmp *= config.multiplier;
390 }
391
392 if (config.offset_set) {
393 tmp += config.offset;
394 }
395 349
396 pd_result_val = mp_create_pd_value(tmp); 350 check_snmp_state_entry previous_unit_state = {};
397 break; 351 if (config.evaluation_params.calculate_rate && have_previous_state) {
352 previous_unit_state = prev_state[loop_index];
398 } 353 }
399 case ASN_IPADDRESS:
400 if (verbose) {
401 printf("Debug: Got an IP address\n");
402 }
403 continue;
404 default:
405 if (verbose) {
406 printf("Debug: Got a unmatched result type: %hhu\n", vars->type);
407 }
408 // TODO: Error here?
409 continue;
410 }
411
412 // some kind of numerical value
413 mp_perfdata pd_num_val = {
414 .value = pd_result_val,
415 };
416 354
417 if (!config.use_perf_data_labels_from_input) { 355 check_snmp_evaluation single_eval =
418 // Use oid for perdata label 356 evaluate_single_unit(response.response_values[loop_index], config.evaluation_params,
419 pd_num_val.label = strdup(oid_string); 357 config.snmp_params.test_units[loop_index], current_time,
420 // TODO strdup error checking 358 previous_unit_state, have_previous_state);
421 } else if (config.test_units[loop_index].label != NULL &&
422 strcmp(config.test_units[loop_index].label, "") != 0) {
423 pd_num_val.label = config.test_units[loop_index].label;
424 } else {
425 pd_num_val.label = config.test_units[loop_index].oid;
426 }
427 359
428 if (config.test_units[loop_index].unit_value != NULL && 360 if (config.evaluation_params.calculate_rate &&
429 strcmp(config.test_units[loop_index].unit_value, "") != 0) { 361 mp_compute_subcheck_state(single_eval.sc) != STATE_UNKNOWN) {
430 pd_num_val.uom = config.test_units[loop_index].unit_value; 362 new_state[loop_index] = single_eval.state;
431 } 363 }
432 364
433 xasprintf(&sc_oid_test.output, "%s Value: %s", sc_oid_test.output, 365 mp_add_subcheck_to_check(&overall, single_eval.sc);
434 pd_value_to_string(pd_result_val)); 366 }
435 367
436 if (config.test_units[loop_index].unit_value != NULL && 368 if (config.evaluation_params.calculate_rate) {
437 strcmp(config.test_units[loop_index].unit_value, "") != 0) { 369 // store state
438 xasprintf(&sc_oid_test.output, "%s%s", sc_oid_test.output, 370 gen_state_string_type current_state_wrapper =
439 config.test_units[loop_index].unit_value); 371 gen_state_string(new_state, config.snmp_params.num_of_test_units);
440 }
441 372
442 if (config.test_units[loop_index].threshold.warning_is_set || 373 if (current_state_wrapper.errorcode == OK) {
443 config.test_units[loop_index].threshold.critical_is_set) { 374 np_state_write_string(stateKey, current_time, current_state_wrapper.state_string);
444 pd_num_val = mp_pd_set_thresholds(pd_num_val, config.test_units[loop_index].threshold); 375 } else {
445 mp_state_enum tmp_state = mp_get_pd_status(pd_num_val); 376 die(STATE_UNKNOWN, "failed to create state string");
446
447 if (tmp_state == STATE_WARNING) {
448 sc_oid_test = mp_set_subcheck_state(sc_oid_test, STATE_WARNING);
449 xasprintf(&sc_oid_test.output, "%s - number violates warning threshold",
450 sc_oid_test.output);
451 } else if (tmp_state == STATE_CRITICAL) {
452 sc_oid_test = mp_set_subcheck_state(sc_oid_test, STATE_CRITICAL);
453 xasprintf(&sc_oid_test.output, "%s - number violates critical threshold",
454 sc_oid_test.output);
455 }
456 } 377 }
457
458 mp_add_perfdata_to_subcheck(&sc_oid_test, pd_num_val);
459
460 mp_add_subcheck_to_check(&overall, sc_oid_test);
461 } 378 }
462
463 mp_exit(overall); 379 mp_exit(overall);
464} 380}
465 381
@@ -472,6 +388,8 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
472 ignore_mib_parsing_errors_index, 388 ignore_mib_parsing_errors_index,
473 connection_prefix_index, 389 connection_prefix_index,
474 output_format_index, 390 output_format_index,
391 calculate_rate,
392 rate_multiplier
475 }; 393 };
476 394
477 static struct option longopts[] = { 395 static struct option longopts[] = {
@@ -510,6 +428,8 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
510 {"ignore-mib-parsing-errors", no_argument, 0, ignore_mib_parsing_errors_index}, 428 {"ignore-mib-parsing-errors", no_argument, 0, ignore_mib_parsing_errors_index},
511 {"connection-prefix", required_argument, 0, connection_prefix_index}, 429 {"connection-prefix", required_argument, 0, connection_prefix_index},
512 {"output-format", required_argument, 0, output_format_index}, 430 {"output-format", required_argument, 0, output_format_index},
431 {"rate", no_argument, 0, calculate_rate},
432 {"rate-multiplier", required_argument, 0, rate_multiplier},
513 {0, 0, 0, 0}}; 433 {0, 0, 0, 0}};
514 434
515 if (argc < 2) { 435 if (argc < 2) {
@@ -575,8 +495,8 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
575 } 495 }
576 496
577 check_snmp_config config = check_snmp_config_init(); 497 check_snmp_config config = check_snmp_config_init();
578 config.test_units = tmp; 498 config.snmp_params.test_units = tmp;
579 config.num_of_test_units = oid_counter; 499 config.snmp_params.num_of_test_units = oid_counter;
580 500
581 option = 0; 501 option = 0;
582 optind = 1; // Reset argument scanner 502 optind = 1; // Reset argument scanner
@@ -616,11 +536,11 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
616 536
617 /* Connection info */ 537 /* Connection info */
618 case 'C': /* group or community */ 538 case 'C': /* group or community */
619 config.snmp_session.community = (unsigned char *)optarg; 539 config.snmp_params.snmp_session.community = (unsigned char *)optarg;
620 config.snmp_session.community_len = strlen(optarg); 540 config.snmp_params.snmp_session.community_len = strlen(optarg);
621 break; 541 break;
622 case 'H': /* Host or server */ 542 case 'H': /* Host or server */
623 config.snmp_session.peername = optarg; 543 config.snmp_params.snmp_session.peername = optarg;
624 break; 544 break;
625 case 'p': /*port number */ 545 case 'p': /*port number */
626 // Add port to "peername" below to not rely on argument order 546 // Add port to "peername" below to not rely on argument order
@@ -630,15 +550,15 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
630 miblist = optarg; 550 miblist = optarg;
631 break; 551 break;
632 case 'n': /* use_getnext instead of get */ 552 case 'n': /* use_getnext instead of get */
633 config.use_getnext = true; 553 config.snmp_params.use_getnext = true;
634 break; 554 break;
635 case 'P': /* SNMP protocol version */ 555 case 'P': /* SNMP protocol version */
636 if (strcasecmp("1", optarg) == 0) { 556 if (strcasecmp("1", optarg) == 0) {
637 config.snmp_session.version = SNMP_VERSION_1; 557 config.snmp_params.snmp_session.version = SNMP_VERSION_1;
638 } else if (strcasecmp("2c", optarg) == 0) { 558 } else if (strcasecmp("2c", optarg) == 0) {
639 config.snmp_session.version = SNMP_VERSION_2c; 559 config.snmp_params.snmp_session.version = SNMP_VERSION_2c;
640 } else if (strcasecmp("3", optarg) == 0) { 560 } else if (strcasecmp("3", optarg) == 0) {
641 config.snmp_session.version = SNMP_VERSION_3; 561 config.snmp_params.snmp_session.version = SNMP_VERSION_3;
642 } else { 562 } else {
643 die(STATE_UNKNOWN, "invalid SNMP version/protocol: %s", optarg); 563 die(STATE_UNKNOWN, "invalid SNMP version/protocol: %s", optarg);
644 } 564 }
@@ -646,45 +566,51 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
646 566
647 break; 567 break;
648 case 'N': /* SNMPv3 context name */ 568 case 'N': /* SNMPv3 context name */
649 config.snmp_session.contextName = optarg; 569 config.snmp_params.snmp_session.contextName = optarg;
650 config.snmp_session.contextNameLen = strlen(optarg); 570 config.snmp_params.snmp_session.contextNameLen = strlen(optarg);
651 break; 571 break;
652 case 'L': /* security level */ 572 case 'L': /* security level */
653 if (strcasecmp("noAuthNoPriv", optarg) == 0) { 573 if (strcasecmp("noAuthNoPriv", optarg) == 0) {
654 config.snmp_session.securityLevel = SNMP_SEC_LEVEL_NOAUTH; 574 config.snmp_params.snmp_session.securityLevel = SNMP_SEC_LEVEL_NOAUTH;
655 } else if (strcasecmp("authNoPriv", optarg) == 0) { 575 } else if (strcasecmp("authNoPriv", optarg) == 0) {
656 config.snmp_session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; 576 config.snmp_params.snmp_session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
657 } else if (strcasecmp("authPriv", optarg) == 0) { 577 } else if (strcasecmp("authPriv", optarg) == 0) {
658 config.snmp_session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; 578 config.snmp_params.snmp_session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
659 } else { 579 } else {
660 die(STATE_UNKNOWN, "invalid security level: %s", optarg); 580 die(STATE_UNKNOWN, "invalid security level: %s", optarg);
661 } 581 }
662 break; 582 break;
663 case 'U': /* security username */ 583 case 'U': /* security username */
664 config.snmp_session.securityName = optarg; 584 config.snmp_params.snmp_session.securityName = optarg;
665 config.snmp_session.securityNameLen = strlen(optarg); 585 config.snmp_params.snmp_session.securityNameLen = strlen(optarg);
666 break; 586 break;
667 case 'a': /* auth protocol */ 587 case 'a': /* auth protocol */
668 // SNMPv3: SHA or MD5 588 // SNMPv3: SHA or MD5
669 // TODO Test for availability of individual protocols 589 // TODO Test for availability of individual protocols
670 if (strcasecmp("MD5", optarg) == 0) { 590 if (strcasecmp("MD5", optarg) == 0) {
671 config.snmp_session.securityAuthProto = usmHMACMD5AuthProtocol; 591 config.snmp_params.snmp_session.securityAuthProto = usmHMACMD5AuthProtocol;
672 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmHMACMD5AuthProtocol); 592 config.snmp_params.snmp_session.securityAuthProtoLen =
593 OID_LENGTH(usmHMACMD5AuthProtocol);
673 } else if (strcasecmp("SHA", optarg) == 0) { 594 } else if (strcasecmp("SHA", optarg) == 0) {
674 config.snmp_session.securityAuthProto = usmHMACSHA1AuthProtocol; 595 config.snmp_params.snmp_session.securityAuthProto = usmHMACSHA1AuthProtocol;
675 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmHMACSHA1AuthProtocol); 596 config.snmp_params.snmp_session.securityAuthProtoLen =
597 OID_LENGTH(usmHMACSHA1AuthProtocol);
676 } else if (strcasecmp("SHA224", optarg) == 0) { 598 } else if (strcasecmp("SHA224", optarg) == 0) {
677 config.snmp_session.securityAuthProto = usmHMAC128SHA224AuthProtocol; 599 config.snmp_params.snmp_session.securityAuthProto = usmHMAC128SHA224AuthProtocol;
678 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmHMAC128SHA224AuthProtocol); 600 config.snmp_params.snmp_session.securityAuthProtoLen =
601 OID_LENGTH(usmHMAC128SHA224AuthProtocol);
679 } else if (strcasecmp("SHA256", optarg) == 0) { 602 } else if (strcasecmp("SHA256", optarg) == 0) {
680 config.snmp_session.securityAuthProto = usmHMAC192SHA256AuthProtocol; 603 config.snmp_params.snmp_session.securityAuthProto = usmHMAC192SHA256AuthProtocol;
681 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmHMAC192SHA256AuthProtocol); 604 config.snmp_params.snmp_session.securityAuthProtoLen =
605 OID_LENGTH(usmHMAC192SHA256AuthProtocol);
682 } else if (strcasecmp("SHA384", optarg) == 0) { 606 } else if (strcasecmp("SHA384", optarg) == 0) {
683 config.snmp_session.securityAuthProto = usmHMAC256SHA384AuthProtocol; 607 config.snmp_params.snmp_session.securityAuthProto = usmHMAC256SHA384AuthProtocol;
684 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmHMAC256SHA384AuthProtocol); 608 config.snmp_params.snmp_session.securityAuthProtoLen =
609 OID_LENGTH(usmHMAC256SHA384AuthProtocol);
685 } else if (strcasecmp("SHA512", optarg) == 0) { 610 } else if (strcasecmp("SHA512", optarg) == 0) {
686 config.snmp_session.securityAuthProto = usmHMAC384SHA512AuthProtocol; 611 config.snmp_params.snmp_session.securityAuthProto = usmHMAC384SHA512AuthProtocol;
687 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmHMAC384SHA512AuthProtocol); 612 config.snmp_params.snmp_session.securityAuthProtoLen =
613 OID_LENGTH(usmHMAC384SHA512AuthProtocol);
688 } else { 614 } else {
689 die(STATE_UNKNOWN, "Unknown authentication protocol"); 615 die(STATE_UNKNOWN, "Unknown authentication protocol");
690 } 616 }
@@ -692,24 +618,28 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
692 case 'x': /* priv protocol */ 618 case 'x': /* priv protocol */
693 if (strcasecmp("DES", optarg) == 0) { 619 if (strcasecmp("DES", optarg) == 0) {
694#ifdef HAVE_USM_DES_PRIV_PROTOCOL 620#ifdef HAVE_USM_DES_PRIV_PROTOCOL
695 config.snmp_session.securityAuthProto = usmDESPrivProtocol; 621 config.snmp_params.snmp_session.securityAuthProto = usmDESPrivProtocol;
696 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmDESPrivProtocol); 622 config.snmp_params.snmp_session.securityAuthProtoLen =
623 OID_LENGTH(usmDESPrivProtocol);
697#else 624#else
698 die(STATE_UNKNOWN, "DES Privacy Protocol not available on this platform"); 625 die(STATE_UNKNOWN, "DES Privacy Protocol not available on this platform");
699#endif 626#endif
700 } else if (strcasecmp("AES", optarg) == 0) { 627 } else if (strcasecmp("AES", optarg) == 0) {
701 config.snmp_session.securityAuthProto = usmAESPrivProtocol; 628 config.snmp_params.snmp_session.securityAuthProto = usmAESPrivProtocol;
702 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmAESPrivProtocol); 629 config.snmp_params.snmp_session.securityAuthProtoLen =
630 OID_LENGTH(usmAESPrivProtocol);
703 // } else if (strcasecmp("AES128", optarg)) { 631 // } else if (strcasecmp("AES128", optarg)) {
704 // config.snmp_session.securityAuthProto = usmAES128PrivProtocol; 632 // config.snmp_session.securityAuthProto = usmAES128PrivProtocol;
705 // config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmAES128PrivProtocol) 633 // config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmAES128PrivProtocol)
706 // / OID_LENGTH(oid); 634 // / OID_LENGTH(oid);
707 } else if (strcasecmp("AES192", optarg) == 0) { 635 } else if (strcasecmp("AES192", optarg) == 0) {
708 config.snmp_session.securityAuthProto = usmAES192PrivProtocol; 636 config.snmp_params.snmp_session.securityAuthProto = usmAES192PrivProtocol;
709 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmAES192PrivProtocol); 637 config.snmp_params.snmp_session.securityAuthProtoLen =
638 OID_LENGTH(usmAES192PrivProtocol);
710 } else if (strcasecmp("AES256", optarg) == 0) { 639 } else if (strcasecmp("AES256", optarg) == 0) {
711 config.snmp_session.securityAuthProto = usmAES256PrivProtocol; 640 config.snmp_params.snmp_session.securityAuthProto = usmAES256PrivProtocol;
712 config.snmp_session.securityAuthProtoLen = OID_LENGTH(usmAES256PrivProtocol); 641 config.snmp_params.snmp_session.securityAuthProtoLen =
642 OID_LENGTH(usmAES256PrivProtocol);
713 // } else if (strcasecmp("AES192Cisco", optarg)) { 643 // } else if (strcasecmp("AES192Cisco", optarg)) {
714 // config.snmp_session.securityAuthProto = usmAES192CiscoPrivProtocol; 644 // config.snmp_session.securityAuthProto = usmAES192CiscoPrivProtocol;
715 // config.snmp_session.securityAuthProtoLen = 645 // config.snmp_session.securityAuthProtoLen =
@@ -738,7 +668,7 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
738 if (!is_integer(optarg)) { 668 if (!is_integer(optarg)) {
739 usage2(_("Retries interval must be a positive integer"), optarg); 669 usage2(_("Retries interval must be a positive integer"), optarg);
740 } else { 670 } else {
741 config.snmp_session.retries = atoi(optarg); 671 config.snmp_params.snmp_session.retries = atoi(optarg);
742 } 672 }
743 break; 673 break;
744 case 't': /* timeout period */ 674 case 't': /* timeout period */
@@ -751,10 +681,10 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
751 681
752 /* Test parameters */ 682 /* Test parameters */
753 case 'c': /* critical threshold */ 683 case 'c': /* critical threshold */
754 check_snmp_set_thresholds(optarg, config.test_units, oid_counter, true); 684 check_snmp_set_thresholds(optarg, config.snmp_params.test_units, oid_counter, true);
755 break; 685 break;
756 case 'w': /* warning threshold */ 686 case 'w': /* warning threshold */
757 check_snmp_set_thresholds(optarg, config.test_units, oid_counter, false); 687 check_snmp_set_thresholds(optarg, config.snmp_params.test_units, oid_counter, false);
758 break; 688 break;
759 case 'o': /* object identifier */ 689 case 'o': /* object identifier */
760 if (strspn(optarg, "0123456789.,") != strlen(optarg)) { 690 if (strspn(optarg, "0123456789.,") != strlen(optarg)) {
@@ -763,25 +693,27 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
763 * so we have a mib variable, rather than just an SNMP OID, 693 * so we have a mib variable, rather than just an SNMP OID,
764 * so we have to actually read the mib files 694 * so we have to actually read the mib files
765 */ 695 */
766 config.need_mibs = true; 696 config.snmp_params.need_mibs = true;
767 } 697 }
768 698
769 for (char *ptr = strtok(optarg, ", "); ptr != NULL; 699 for (char *ptr = strtok(optarg, ", "); ptr != NULL;
770 ptr = strtok(NULL, ", "), tmp_oid_counter++) { 700 ptr = strtok(NULL, ", "), tmp_oid_counter++) {
771 config.test_units[tmp_oid_counter].oid = strdup(ptr); 701 config.snmp_params.test_units[tmp_oid_counter].oid = strdup(ptr);
772 } 702 }
773 break; 703 break;
774 case 'z': /* Null OID Return Check */ 704 case 'z': /* Null OID Return Check */
775 if (!is_integer(optarg)) { 705 if (!is_integer(optarg)) {
776 usage2(_("Exit status must be a positive integer"), optarg); 706 usage2(_("Exit status must be a positive integer"), optarg);
777 } else { 707 } else {
778 config.nulloid_result = atoi(optarg); 708 config.evaluation_params.nulloid_result = atoi(optarg);
779 } 709 }
780 break; 710 break;
781 case 's': /* string or substring */ 711 case 's': /* string or substring */
782 strncpy(config.string_cmp_value, optarg, sizeof(config.string_cmp_value) - 1); 712 strncpy(config.evaluation_params.string_cmp_value, optarg,
783 config.string_cmp_value[sizeof(config.string_cmp_value) - 1] = 0; 713 sizeof(config.evaluation_params.string_cmp_value) - 1);
784 config.test_units[eval_counter++].eval_mthd.crit_string = true; 714 config.evaluation_params
715 .string_cmp_value[sizeof(config.evaluation_params.string_cmp_value) - 1] = 0;
716 config.snmp_params.test_units[eval_counter++].eval_mthd.crit_string = true;
785 break; 717 break;
786 case 'R': /* regex */ 718 case 'R': /* regex */
787 cflags = REG_ICASE; 719 cflags = REG_ICASE;
@@ -792,72 +724,73 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
792 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 724 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
793 strncpy(regex_expect, optarg, sizeof(regex_expect) - 1); 725 strncpy(regex_expect, optarg, sizeof(regex_expect) - 1);
794 regex_expect[sizeof(regex_expect) - 1] = 0; 726 regex_expect[sizeof(regex_expect) - 1] = 0;
795 int errcode = regcomp(&config.regex_cmp_value, regex_expect, cflags); 727 int errcode = regcomp(&config.evaluation_params.regex_cmp_value, regex_expect, cflags);
796 if (errcode != 0) { 728 if (errcode != 0) {
797 char errbuf[MAX_INPUT_BUFFER] = ""; 729 char errbuf[MAX_INPUT_BUFFER] = "";
798 regerror(errcode, &config.regex_cmp_value, errbuf, MAX_INPUT_BUFFER); 730 regerror(errcode, &config.evaluation_params.regex_cmp_value, errbuf,
731 MAX_INPUT_BUFFER);
799 printf("Could Not Compile Regular Expression: %s", errbuf); 732 printf("Could Not Compile Regular Expression: %s", errbuf);
800 process_arguments_wrapper result = { 733 process_arguments_wrapper result = {
801 .errorcode = ERROR, 734 .errorcode = ERROR,
802 }; 735 };
803 return result; 736 return result;
804 } 737 }
805 config.test_units[eval_counter++].eval_mthd.crit_regex = true; 738 config.snmp_params.test_units[eval_counter++].eval_mthd.crit_regex = true;
806 } break; 739 } break;
807 case 'l': /* label */ 740 case 'l': /* label */
808 { 741 {
809 if (labels_counter >= config.num_of_test_units) { 742 if (labels_counter >= config.snmp_params.num_of_test_units) {
810 break; 743 break;
811 } 744 }
812 char *ptr = trim_whitespaces_and_check_quoting(optarg); 745 char *ptr = trim_whitespaces_and_check_quoting(optarg);
813 if (ptr[0] == '\'') { 746 if (ptr[0] == '\'') {
814 config.test_units[labels_counter].label = ptr + 1; 747 config.snmp_params.test_units[labels_counter].label = ptr + 1;
815 } else { 748 } else {
816 config.test_units[labels_counter].label = ptr; 749 config.snmp_params.test_units[labels_counter].label = ptr;
817 } 750 }
818 751
819 while (ptr && (ptr = get_next_argument(ptr))) { 752 while (ptr && (ptr = get_next_argument(ptr))) {
820 labels_counter++; 753 labels_counter++;
821 ptr = trim_whitespaces_and_check_quoting(ptr); 754 ptr = trim_whitespaces_and_check_quoting(ptr);
822 if (ptr[0] == '\'') { 755 if (ptr[0] == '\'') {
823 config.test_units[labels_counter].label = ptr + 1; 756 config.snmp_params.test_units[labels_counter].label = ptr + 1;
824 } else { 757 } else {
825 config.test_units[labels_counter].label = ptr; 758 config.snmp_params.test_units[labels_counter].label = ptr;
826 } 759 }
827 } 760 }
828 labels_counter++; 761 labels_counter++;
829 } break; 762 } break;
830 case 'u': /* units */ 763 case 'u': /* units */
831 { 764 {
832 if (unitv_counter >= config.num_of_test_units) { 765 if (unitv_counter >= config.snmp_params.num_of_test_units) {
833 break; 766 break;
834 } 767 }
835 char *ptr = trim_whitespaces_and_check_quoting(optarg); 768 char *ptr = trim_whitespaces_and_check_quoting(optarg);
836 if (ptr[0] == '\'') { 769 if (ptr[0] == '\'') {
837 config.test_units[unitv_counter].unit_value = ptr + 1; 770 config.snmp_params.test_units[unitv_counter].unit_value = ptr + 1;
838 } else { 771 } else {
839 config.test_units[unitv_counter].unit_value = ptr; 772 config.snmp_params.test_units[unitv_counter].unit_value = ptr;
840 } 773 }
841 while (ptr && (ptr = get_next_argument(ptr))) { 774 while (ptr && (ptr = get_next_argument(ptr))) {
842 unitv_counter++; 775 unitv_counter++;
843 ptr = trim_whitespaces_and_check_quoting(ptr); 776 ptr = trim_whitespaces_and_check_quoting(ptr);
844 if (ptr[0] == '\'') { 777 if (ptr[0] == '\'') {
845 config.test_units[unitv_counter].unit_value = ptr + 1; 778 config.snmp_params.test_units[unitv_counter].unit_value = ptr + 1;
846 } else { 779 } else {
847 config.test_units[unitv_counter].unit_value = ptr; 780 config.snmp_params.test_units[unitv_counter].unit_value = ptr;
848 } 781 }
849 } 782 }
850 unitv_counter++; 783 unitv_counter++;
851 } break; 784 } break;
852 case offset_index: 785 case offset_index:
853 config.offset = strtod(optarg, NULL); 786 config.evaluation_params.offset = strtod(optarg, NULL);
854 config.offset_set = true; 787 config.evaluation_params.offset_set = true;
855 break; 788 break;
856 case invert_search_index: 789 case invert_search_index:
857 config.invert_search = false; 790 config.evaluation_params.invert_search = false;
858 break; 791 break;
859 case 'O': 792 case 'O':
860 config.use_perf_data_labels_from_input = true; 793 config.evaluation_params.use_oid_as_perf_data_label = true;
861 break; 794 break;
862 case '4': 795 case '4':
863 // The default, do something here to be exclusive to -6 instead of doing nothing? 796 // The default, do something here to be exclusive to -6 instead of doing nothing?
@@ -871,12 +804,12 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
871 break; 804 break;
872 case 'M': 805 case 'M':
873 if (strspn(optarg, "0123456789.,") == strlen(optarg)) { 806 if (strspn(optarg, "0123456789.,") == strlen(optarg)) {
874 config.multiplier = strtod(optarg, NULL); 807 config.evaluation_params.multiplier = strtod(optarg, NULL);
875 config.multiplier_set = true; 808 config.evaluation_params.multiplier_set = true;
876 } 809 }
877 break; 810 break;
878 case ignore_mib_parsing_errors_index: 811 case ignore_mib_parsing_errors_index:
879 config.ignore_mib_parsing_errors = true; 812 config.snmp_params.ignore_mib_parsing_errors = true;
880 break; 813 break;
881 case 'f': // Deprecated format option for floating point values 814 case 'f': // Deprecated format option for floating point values
882 break; 815 break;
@@ -892,13 +825,22 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
892 config.output_format = parser.output_format; 825 config.output_format = parser.output_format;
893 break; 826 break;
894 } 827 }
828 case calculate_rate:
829 config.evaluation_params.calculate_rate = true;
830 break;
831 case rate_multiplier:
832 if (!is_integer(optarg) ||
833 ((config.evaluation_params.rate_multiplier = (unsigned int)atoi(optarg)) <= 0)) {
834 usage2(_("Rate multiplier must be a positive integer"), optarg);
835 }
836 break;
895 default: 837 default:
896 die(STATE_UNKNOWN, "Unknown option"); 838 die(STATE_UNKNOWN, "Unknown option");
897 } 839 }
898 } 840 }
899 841
900 if (config.snmp_session.peername == NULL) { 842 if (config.snmp_params.snmp_session.peername == NULL) {
901 config.snmp_session.peername = argv[optind]; 843 config.snmp_params.snmp_session.peername = argv[optind];
902 } 844 }
903 845
904 // Build true peername here if necessary 846 // Build true peername here if necessary
@@ -908,7 +850,8 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
908 // The default, do nothing 850 // The default, do nothing
909 } else if (strcasecmp(connection_prefix, "tcp") == 0) { 851 } else if (strcasecmp(connection_prefix, "tcp") == 0) {
910 // use tcp/ipv4 852 // use tcp/ipv4
911 xasprintf(&config.snmp_session.peername, "tcp:%s", config.snmp_session.peername); 853 xasprintf(&config.snmp_params.snmp_session.peername, "tcp:%s",
854 config.snmp_params.snmp_session.peername);
912 } else if (strcasecmp(connection_prefix, "tcp6") == 0 || 855 } else if (strcasecmp(connection_prefix, "tcp6") == 0 ||
913 strcasecmp(connection_prefix, "tcpv6") == 0 || 856 strcasecmp(connection_prefix, "tcpv6") == 0 ||
914 strcasecmp(connection_prefix, "tcpipv6") == 0 || 857 strcasecmp(connection_prefix, "tcpipv6") == 0 ||
@@ -917,19 +860,23 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
917 strcasecmp(connection_prefix, "udpv6") == 0) { 860 strcasecmp(connection_prefix, "udpv6") == 0) {
918 // Man page (or net-snmp) code says IPv6 addresses should be wrapped in [], but it 861 // Man page (or net-snmp) code says IPv6 addresses should be wrapped in [], but it
919 // works anyway therefore do nothing here 862 // works anyway therefore do nothing here
920 xasprintf(&config.snmp_session.peername, "%s:%s", connection_prefix, 863 xasprintf(&config.snmp_params.snmp_session.peername, "%s:%s", connection_prefix,
921 config.snmp_session.peername); 864 config.snmp_params.snmp_session.peername);
922 } else if (strcmp(connection_prefix, "tls") == 0) { 865 } else if (strcmp(connection_prefix, "tls") == 0) {
923 // TODO: Anything else to do here? 866 // TODO: Anything else to do here?
924 xasprintf(&config.snmp_session.peername, "tls:%s", config.snmp_session.peername); 867 xasprintf(&config.snmp_params.snmp_session.peername, "tls:%s",
868 config.snmp_params.snmp_session.peername);
925 } else if (strcmp(connection_prefix, "dtls") == 0) { 869 } else if (strcmp(connection_prefix, "dtls") == 0) {
926 // TODO: Anything else to do here? 870 // TODO: Anything else to do here?
927 xasprintf(&config.snmp_session.peername, "dtls:%s", config.snmp_session.peername); 871 xasprintf(&config.snmp_params.snmp_session.peername, "dtls:%s",
872 config.snmp_params.snmp_session.peername);
928 } else if (strcmp(connection_prefix, "unix") == 0) { 873 } else if (strcmp(connection_prefix, "unix") == 0) {
929 // TODO: Check whether this is a valid path? 874 // TODO: Check whether this is a valid path?
930 xasprintf(&config.snmp_session.peername, "unix:%s", config.snmp_session.peername); 875 xasprintf(&config.snmp_params.snmp_session.peername, "unix:%s",
876 config.snmp_params.snmp_session.peername);
931 } else if (strcmp(connection_prefix, "ipx") == 0) { 877 } else if (strcmp(connection_prefix, "ipx") == 0) {
932 xasprintf(&config.snmp_session.peername, "ipx:%s", config.snmp_session.peername); 878 xasprintf(&config.snmp_params.snmp_session.peername, "ipx:%s",
879 config.snmp_params.snmp_session.peername);
933 } else { 880 } else {
934 // Don't know that prefix, die here 881 // Don't know that prefix, die here
935 die(STATE_UNKNOWN, "Unknown connection prefix"); 882 die(STATE_UNKNOWN, "Unknown connection prefix");
@@ -937,17 +884,18 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
937 } 884 }
938 885
939 /* Check server_address is given */ 886 /* Check server_address is given */
940 if (config.snmp_session.peername == NULL) { 887 if (config.snmp_params.snmp_session.peername == NULL) {
941 die(STATE_UNKNOWN, _("No host specified\n")); 888 die(STATE_UNKNOWN, _("No host specified\n"));
942 } 889 }
943 890
944 if (port != NULL) { 891 if (port != NULL) {
945 xasprintf(&config.snmp_session.peername, "%s:%s", config.snmp_session.peername, port); 892 xasprintf(&config.snmp_params.snmp_session.peername, "%s:%s",
893 config.snmp_params.snmp_session.peername, port);
946 } 894 }
947 895
948 /* check whether to load locally installed MIBS (CPU/disk intensive) */ 896 /* check whether to load locally installed MIBS (CPU/disk intensive) */
949 if (miblist == NULL) { 897 if (miblist == NULL) {
950 if (config.need_mibs) { 898 if (config.snmp_params.need_mibs) {
951 setenv("MIBLS", DEFAULT_MIBLIST, 1); 899 setenv("MIBLS", DEFAULT_MIBLIST, 1);
952 } else { 900 } else {
953 setenv("MIBLS", "NONE", 1); 901 setenv("MIBLS", "NONE", 1);
@@ -959,37 +907,37 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
959 } 907 }
960 908
961 // Historical default is SNMP v2c 909 // Historical default is SNMP v2c
962 if (!snmp_version_set_explicitely && config.snmp_session.community != NULL) { 910 if (!snmp_version_set_explicitely && config.snmp_params.snmp_session.community != NULL) {
963 config.snmp_session.version = SNMP_VERSION_2c; 911 config.snmp_params.snmp_session.version = SNMP_VERSION_2c;
964 } 912 }
965 913
966 if ((config.snmp_session.version == SNMP_VERSION_1) || 914 if ((config.snmp_params.snmp_session.version == SNMP_VERSION_1) ||
967 (config.snmp_session.version == SNMP_VERSION_2c)) { /* snmpv1 or snmpv2c */ 915 (config.snmp_params.snmp_session.version == SNMP_VERSION_2c)) { /* snmpv1 or snmpv2c */
968 /* 916 /*
969 config.numauthpriv = 2; 917 config.numauthpriv = 2;
970 config.authpriv = calloc(config.numauthpriv, sizeof(char *)); 918 config.authpriv = calloc(config.numauthpriv, sizeof(char *));
971 config.authpriv[0] = strdup("-c"); 919 config.authpriv[0] = strdup("-c");
972 config.authpriv[1] = strdup(community); 920 config.authpriv[1] = strdup(community);
973 */ 921 */
974 } else if (config.snmp_session.version == SNMP_VERSION_3) { /* snmpv3 args */ 922 } else if (config.snmp_params.snmp_session.version == SNMP_VERSION_3) { /* snmpv3 args */
975 // generate keys for priv and auth here (if demanded) 923 // generate keys for priv and auth here (if demanded)
976 924
977 if (config.snmp_session.securityName == NULL) { 925 if (config.snmp_params.snmp_session.securityName == NULL) {
978 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname"); 926 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "secname");
979 } 927 }
980 928
981 switch (config.snmp_session.securityLevel) { 929 switch (config.snmp_params.snmp_session.securityLevel) {
982 case SNMP_SEC_LEVEL_AUTHPRIV: { 930 case SNMP_SEC_LEVEL_AUTHPRIV: {
983 if (authpasswd == NULL) { 931 if (authpasswd == NULL) {
984 die(STATE_UNKNOWN, 932 die(STATE_UNKNOWN,
985 "No authentication passphrase was given, but authorization was requested"); 933 "No authentication passphrase was given, but authorization was requested");
986 } 934 }
987 // auth and priv 935 // auth and priv
988 int priv_key_generated = 936 int priv_key_generated = generate_Ku(
989 generate_Ku(config.snmp_session.securityPrivProto, 937 config.snmp_params.snmp_session.securityPrivProto,
990 (unsigned int)config.snmp_session.securityPrivProtoLen, authpasswd, 938 (unsigned int)config.snmp_params.snmp_session.securityPrivProtoLen, authpasswd,
991 strlen((const char *)authpasswd), config.snmp_session.securityPrivKey, 939 strlen((const char *)authpasswd), config.snmp_params.snmp_session.securityPrivKey,
992 &config.snmp_session.securityPrivKeyLen); 940 &config.snmp_params.snmp_session.securityPrivKeyLen);
993 941
994 if (priv_key_generated != SNMPERR_SUCCESS) { 942 if (priv_key_generated != SNMPERR_SUCCESS) {
995 die(STATE_UNKNOWN, "Failed to generate privacy key"); 943 die(STATE_UNKNOWN, "Failed to generate privacy key");
@@ -1000,11 +948,11 @@ static process_arguments_wrapper process_arguments(int argc, char **argv) {
1000 if (privpasswd == NULL) { 948 if (privpasswd == NULL) {
1001 die(STATE_UNKNOWN, "No privacy passphrase was given, but privacy was requested"); 949 die(STATE_UNKNOWN, "No privacy passphrase was given, but privacy was requested");
1002 } 950 }
1003 int auth_key_generated = 951 int auth_key_generated = generate_Ku(
1004 generate_Ku(config.snmp_session.securityAuthProto, 952 config.snmp_params.snmp_session.securityAuthProto,
1005 (unsigned int)config.snmp_session.securityAuthProtoLen, privpasswd, 953 (unsigned int)config.snmp_params.snmp_session.securityAuthProtoLen, privpasswd,
1006 strlen((const char *)privpasswd), config.snmp_session.securityAuthKey, 954 strlen((const char *)privpasswd), config.snmp_params.snmp_session.securityAuthKey,
1007 &config.snmp_session.securityAuthKeyLen); 955 &config.snmp_params.snmp_session.securityAuthKeyLen);
1008 956
1009 if (auth_key_generated != SNMPERR_SUCCESS) { 957 if (auth_key_generated != SNMPERR_SUCCESS) {
1010 die(STATE_UNKNOWN, "Failed to generate privacy key"); 958 die(STATE_UNKNOWN, "Failed to generate privacy key");