char *name;
char *address;
int version;
+ int timeout;
+ int retries;
/* snmpv1/2 options */
char *community;
return 0;
} /* int csnmp_config_add_host_address */
+static int csnmp_config_add_host_timeout(host_definition_t *hd,
+ oconfig_item_t *ci) {
+ int timeout;
+
+ if (ci->values[0].type != OCONFIG_TYPE_NUMBER) {
+ WARNING("snmp plugin: `Timeout' must be a number");
+ return -1;
+ }
+
+ timeout = (int)ci->values[0].value.number;
+ if (timeout < 0) {
+ WARNING("snmp plugin: `Timeout' must not be negative");
+ return -1;
+ }
+
+ /* net-snmp library timeout is in microseconds */
+ hd->timeout = timeout * 1000000;
+
+ return 0;
+} /* int csnmp_config_add_host_timeout */
+
+static int csnmp_config_add_host_retries(host_definition_t *hd,
+ oconfig_item_t *ci) {
+ int retries;
+
+
+ if (ci->values[0].type != OCONFIG_TYPE_NUMBER) {
+ WARNING("snmp plugin: `Retries' must be a number");
+ return -1;
+ }
+
+ retries = (int)ci->values[0].value.number;
+ if (retries < 0) {
+ WARNING("snmp plugin: `Retries' must not be negative");
+ return -1;
+ }
+
+ hd->retries = retries;
+
+ return 0;
+} /* int csnmp_config_add_host_retries */
+
static int csnmp_config_add_host_collect(host_definition_t *host,
oconfig_item_t *ci) {
data_definition_t *data;
status = cf_util_get_string(option, &hd->community);
else if (strcasecmp("Version", option->key) == 0)
status = csnmp_config_add_host_version(hd, option);
+ else if (strcasecmp("Timeout", option->key) == 0)
+ status = csnmp_config_add_host_timeout(hd, option);
+ else if (strcasecmp("Retries", option->key) == 0)
+ status = csnmp_config_add_host_retries(hd, option);
else if (strcasecmp("Collect", option->key) == 0)
csnmp_config_add_host_collect(hd, option);
else if (strcasecmp("Interval", option->key) == 0)
sess.community_len = strlen(host->community);
}
+ /* Set timeout & retries */
+ sess.timeout = host->timeout;
+ sess.retries = host->retries;
+
/* snmp_sess_open will copy the `struct snmp_session *'. */
host->sess_handle = snmp_sess_open(&sess);
status = 0;
while (status == 0) {
- int oid_list_todo_num;
-
req = snmp_pdu_create(SNMP_MSG_GETNEXT);
if (req == NULL) {
ERROR("snmp plugin: snmp_pdu_create failed.");
break;
}
- oid_list_todo_num = 0;
+ size_t oid_list_todo_num = 0;
+ size_t var_idx[oid_list_len];
+ memset(var_idx, 0, sizeof(var_idx));
+
for (i = 0; i < oid_list_len; i++) {
/* Do not rerequest already finished OIDs */
if (!oid_list_todo[i])
continue;
- oid_list_todo_num++;
snmp_add_null_var(req, oid_list[i].oid, oid_list[i].oid_len);
+ var_idx[oid_list_todo_num] = i;
+ oid_list_todo_num++;
}
if (oid_list_todo_num == 0) {
/* The request is still empty - so we are finished */
DEBUG("snmp plugin: all variables have left their subtree");
+ snmp_free_pdu(req);
status = 0;
break;
}
res = NULL;
status = snmp_sess_synch_response(host->sess_handle, req, &res);
+
+ /* snmp_sess_synch_response always frees our req PDU */
+ req = NULL;
+
if ((status != STAT_SUCCESS) || (res == NULL)) {
char *errstr = NULL;
snmp_free_pdu(res);
res = NULL;
- /* snmp_synch_response already freed our PDU */
- req = NULL;
sfree(errstr);
csnmp_host_close_session(host);
}
if (res->errstat != SNMP_ERR_NOERROR) {
- if (res->errindex != 0 && res->errindex < oid_list_len) {
+ if (res->errindex != 0) {
/* Find the OID which caused error */
for (i = 1, vb = res->variables; vb != NULL && i != res->errindex;
vb = vb->next_variable, i++)
/* do nothing */;
+ }
- char oid_buffer[1024] = {0};
- snprint_objid(oid_buffer, sizeof(oid_buffer) - 1, vb->name,
- vb->name_length);
- NOTICE("snmp plugin: host %s; data %s: OID `%s` failed: %s",
- host->name, data->name, oid_buffer,
- snmp_errstring(res->errstat));
-
- /* Skip that OID */
- i = res->errindex - 1;
- while ((i < oid_list_len) && !oid_list_todo[i])
- i++;
+ if ((res->errindex == 0) || (vb == NULL)) {
+ ERROR("snmp plugin: host %s; data %s: response error: %s (%li) ",
+ host->name, data->name, snmp_errstring(res->errstat),
+ res->errstat);
+ status = -1;
+ break;
+ }
- oid_list_todo[i] = 0;
+ char oid_buffer[1024] = {0};
+ snprint_objid(oid_buffer, sizeof(oid_buffer) - 1, vb->name,
+ vb->name_length);
+ NOTICE("snmp plugin: host %s; data %s: OID `%s` failed: %s", host->name,
+ data->name, oid_buffer, snmp_errstring(res->errstat));
- snmp_free_pdu(res);
- res = NULL;
- continue;
- }
+ /* Get value index from todo list and skip OID found */
+ assert(res->errindex <= oid_list_todo_num);
+ i = var_idx[res->errindex - 1];
+ assert(i < oid_list_len);
+ oid_list_todo[i] = 0;
- ERROR("snmp plugin: host %s; data %s: response error: %s (%li) ",
- host->name, data->name, snmp_errstring(res->errstat), res->errstat);
- status = -1;
- break;
+ snmp_free_pdu(res);
+ res = NULL;
+ continue;
}
for (vb = res->variables, i = 0; (vb != NULL);
snmp_free_pdu(res);
res = NULL;
- if (req != NULL)
- snmp_free_pdu(req);
- req = NULL;
if (status == 0)
csnmp_dispatch_table(host, data, instance_list_head, value_list_head);