#include "common.h"
#include "plugin.h"
#include "utils_complain.h"
+#include "utils_ignorelist.h"
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
instance_t type_instance;
instance_t plugin_instance;
instance_t host;
+ oid_t filter_oid;
+ ignorelist_t *ignorelist;
char *plugin_name;
oid_t *values;
size_t values_len;
void *sess_handle;
c_complain_t complaint;
- cdtime_t interval;
data_definition_t **data_list;
int data_list_len;
};
OID_TYPE_TYPEINSTANCE,
OID_TYPE_PLUGININSTANCE,
OID_TYPE_HOST,
+ OID_TYPE_FILTER,
} csnmp_oid_type_t;
/*
sfree(dd->host.value);
sfree(dd->values);
sfree(dd->ignores);
+ ignorelist_free(dd->ignorelist);
sfree(dd);
} /* void csnmp_data_definition_destroy */
return 0;
} /* int csnmp_config_add_data_blacklist */
+static int csnmp_config_add_data_filter_values(data_definition_t *data,
+ oconfig_item_t *ci) {
+ if (ci->values_num < 1) {
+ WARNING("snmp plugin: `FilterValues' needs at least one argument.");
+ return -1;
+ }
+
+ for (int i = 0; i < ci->values_num; i++) {
+ if (ci->values[i].type != OCONFIG_TYPE_STRING) {
+ WARNING("snmp plugin: All arguments to `FilterValues' must be strings.");
+ return -1;
+ }
+ ignorelist_add(data->ignorelist, ci->values[i].value.string);
+ }
+
+ return 0;
+} /* int csnmp_config_add_data_filter_values */
+
+static int csnmp_config_add_data_filter_oid(data_definition_t *data,
+ oconfig_item_t *ci) {
+
+ char buffer[DATA_MAX_NAME_LEN];
+ int status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
+
+ data->filter_oid.oid_len = MAX_OID_LEN;
+
+ if (!read_objid(buffer, data->filter_oid.oid, &data->filter_oid.oid_len)) {
+ ERROR("snmp plugin: read_objid (%s) failed.", buffer);
+ return -1;
+ }
+ return 0;
+} /* int csnmp_config_add_data_filter_oid */
+
static int csnmp_config_add_data(oconfig_item_t *ci) {
data_definition_t *dd = calloc(1, sizeof(*dd));
if (dd == NULL)
dd->ignores_len = 0;
dd->ignores = NULL;
+ dd->ignorelist = ignorelist_create(/* invert = */ 1);
+ if (dd->ignorelist == NULL) {
+ sfree(dd->name);
+ sfree(dd);
+ ERROR("snmp plugin: ignorelist_create() failed.");
+ return ENOMEM;
+ }
+
dd->plugin_name = strdup("snmp");
if (dd->plugin_name == NULL) {
ERROR("snmp plugin: Can't allocate memory");
}
} else if (strcasecmp("InstancePrefix", option->key) == 0) {
WARNING("snmp plugin: data %s: Option `InstancePrefix' is deprecated, "
- "please use "
- "option `TypeInstancePrefix'.",
+ "please use option `TypeInstancePrefix'.",
dd->name);
status = cf_util_get_string(option, &dd->type_instance.prefix);
} else if (strcasecmp("PluginInstance", option->key) == 0)
status = csnmp_config_add_data_blacklist(dd, option);
else if (strcasecmp("InvertMatch", option->key) == 0)
status = cf_util_get_boolean(option, &dd->invert_match);
- else {
+ else if (strcasecmp("FilterOID", option->key) == 0) {
+ status = csnmp_config_add_data_filter_oid(dd, option);
+ } else if (strcasecmp("FilterValues", option->key) == 0) {
+ status = csnmp_config_add_data_filter_values(dd, option);
+ } else if (strcasecmp("FilterIgnoreSelected", option->key) == 0) {
+ bool t;
+ status = cf_util_get_boolean(option, &t);
+ if (status == 0)
+ ignorelist_set_invert(dd->ignorelist, /* invert = */ !t);
+ } else {
WARNING("snmp plugin: data %s: Option `%s' not allowed here.", dd->name,
option->key);
status = -1;
while (status == 0) {
if (dd->is_table) {
/* Set type_instance to SUBID by default */
- if (!dd->type_instance.configured && !dd->host.configured)
+ if (!dd->plugin_instance.configured && !dd->host.configured)
dd->type_instance.configured = true;
if (dd->plugin_instance.value && dd->plugin_instance.configured) {
hd->version = version;
return 0;
-} /* int csnmp_config_add_host_address */
+} /* int csnmp_config_add_host_version */
static int csnmp_config_add_host_collect(host_definition_t *host,
oconfig_item_t *ci) {
int status = 0;
/* Registration stuff. */
+ cdtime_t interval = 0;
char cb_name[DATA_MAX_NAME_LEN];
hd = calloc(1, sizeof(*hd));
}
hd->sess_handle = NULL;
- hd->interval = 0;
/* These mean that we have not set a timeout or retry value */
hd->timeout = 0;
else if (strcasecmp("Collect", option->key) == 0)
status = csnmp_config_add_host_collect(hd, option);
else if (strcasecmp("Interval", option->key) == 0)
- status = cf_util_get_cdtime(option, &hd->interval);
+ status = cf_util_get_cdtime(option, &interval);
else if (strcasecmp("Username", option->key) == 0)
status = cf_util_get_string(option, &hd->username);
else if (strcasecmp("AuthProtocol", option->key) == 0)
snprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
status = plugin_register_complex_read(
- /* group = */ NULL, cb_name, csnmp_read_host, hd->interval,
+ /* group = */ NULL, cb_name, csnmp_read_host, interval,
&(user_data_t){
.data = hd, .free_func = csnmp_host_definition_destroy,
});
if (((size_t)status) >= buffer_free) /* truncated */
{
- dst[dst_size - 1] = 0;
+ dst[dst_size - 1] = '\0';
return ENOMEM;
} else /* if (status < buffer_free) */
{
dst[i] = src[i];
}
dst[num_chars] = 0;
- dst[dst_size - 1] = 0;
+ dst[dst_size - 1] = '\0';
if (dst_size <= vb->val_len)
return ENOMEM;
else if (*ptr == '/')
*ptr = '_';
}
-}
+} /* void csnmp_cell_replace_reserved_chars */
static int csnmp_dispatch_table(host_definition_t *host,
data_definition_t *data,
csnmp_cell_char_t *type_instance_cells,
csnmp_cell_char_t *plugin_instance_cells,
csnmp_cell_char_t *hostname_cells,
+ csnmp_cell_char_t *filter_cells,
csnmp_cell_value_t **value_cells) {
const data_set_t *ds;
value_list_t vl = VALUE_LIST_INIT;
csnmp_cell_char_t *type_instance_cell_ptr = type_instance_cells;
csnmp_cell_char_t *plugin_instance_cell_ptr = plugin_instance_cells;
csnmp_cell_char_t *hostname_cell_ptr = hostname_cells;
+ csnmp_cell_char_t *filter_cell_ptr = filter_cells;
csnmp_cell_value_t *value_cell_ptr[data->values_len];
size_t i;
value_cell_ptr[i] = value_cells[i];
sstrncpy(vl.plugin, data->plugin_name, sizeof(vl.plugin));
-
- vl.interval = host->interval;
+ sstrncpy(vl.type, data->type, sizeof(vl.type));
have_more = 1;
while (have_more) {
/* This suffix is missing in the subtree. Indicate this with the
* "suffix_skipped" flag and try the next instance / suffix. */
suffix_skipped = 1;
- NOTICE("snmp plugin: suffix skipped, variable not found for "
- "TypeInstanceOID.");
}
}
/* This suffix is missing in the subtree. Indicate this with the
* "suffix_skipped" flag and try the next instance / suffix. */
suffix_skipped = 1;
- NOTICE("snmp plugin: suffix skipped, variable not found for HostOID.");
+ }
+ }
+
+ /* Update filter_cell_ptr to point expected suffix */
+ if (filter_cells != NULL) {
+ while ((filter_cell_ptr != NULL) &&
+ (csnmp_oid_compare(&filter_cell_ptr->suffix, ¤t_suffix) < 0))
+ filter_cell_ptr = filter_cell_ptr->next;
+
+ if (filter_cell_ptr == NULL) {
+ have_more = 0;
+ continue;
+ }
+
+ if (csnmp_oid_compare(&filter_cell_ptr->suffix, ¤t_suffix) > 0) {
+ /* This suffix is missing in the subtree. Indicate this with the
+ * "suffix_skipped" flag and try the next instance / suffix. */
+ suffix_skipped = 1;
}
}
/* This suffix is missing in the subtree. Indicate this with the
* "suffix_skipped" flag and try the next instance / suffix. */
suffix_skipped = 1;
- NOTICE(
- "snmp plugin: suffix skipped, variable not found for Value OID.");
break;
}
} /* for (i = 0; i < columns; i++) */
assert((hostname_cell_ptr == NULL) ||
(csnmp_oid_compare(&hostname_cell_ptr->suffix,
&value_cell_ptr[0]->suffix) == 0));
+ assert((filter_cell_ptr == NULL) ||
+ (csnmp_oid_compare(&filter_cell_ptr->suffix,
+ &value_cell_ptr[0]->suffix) == 0));
#endif
- sstrncpy(vl.type, data->type, sizeof(vl.type));
+ /* Check the value in filter column */
+ if (filter_cell_ptr &&
+ ignorelist_match(data->ignorelist, filter_cell_ptr->value) != 0) {
+ if (type_instance_cells != NULL)
+ type_instance_cell_ptr = type_instance_cell_ptr->next;
+ else
+ value_cell_ptr[0] = value_cell_ptr[0]->next;
- {
- if (data->host.configured) {
- char temp[DATA_MAX_NAME_LEN];
- if (hostname_cell_ptr == NULL)
- csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
- else
- sstrncpy(temp, hostname_cell_ptr->value, sizeof(temp));
+ continue;
+ }
- if (data->host.prefix == NULL)
- sstrncpy(vl.host, temp, sizeof(vl.host));
- else
- snprintf(vl.host, sizeof(vl.host), "%s%s", data->host.prefix, temp);
- } else {
- sstrncpy(vl.host, host->name, sizeof(vl.host));
- }
+ /* set vl.host */
+ if (data->host.configured) {
+ char temp[DATA_MAX_NAME_LEN];
+ if (hostname_cell_ptr == NULL)
+ csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
+ else
+ sstrncpy(temp, hostname_cell_ptr->value, sizeof(temp));
- if (data->type_instance.configured) {
- char temp[DATA_MAX_NAME_LEN];
- if (type_instance_cell_ptr == NULL)
- csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
- else
- sstrncpy(temp, type_instance_cell_ptr->value, sizeof(temp));
+ if (data->host.prefix == NULL)
+ sstrncpy(vl.host, temp, sizeof(vl.host));
+ else
+ snprintf(vl.host, sizeof(vl.host), "%s%s", data->host.prefix, temp);
+ } else {
+ sstrncpy(vl.host, host->name, sizeof(vl.host));
+ }
- if (data->type_instance.prefix == NULL)
- sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance));
- else
- snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
- data->type_instance.prefix, temp);
- } else if (data->type_instance.value) {
- sstrncpy(vl.type_instance, data->type_instance.value,
- sizeof(vl.type_instance));
- }
+ /* set vl.type_instance */
+ if (data->type_instance.configured) {
+ char temp[DATA_MAX_NAME_LEN];
+ if (type_instance_cell_ptr == NULL)
+ csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
+ else
+ sstrncpy(temp, type_instance_cell_ptr->value, sizeof(temp));
- if (data->plugin_instance.configured) {
- char temp[DATA_MAX_NAME_LEN];
- if (plugin_instance_cell_ptr == NULL)
- csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
- else
- sstrncpy(temp, plugin_instance_cell_ptr->value, sizeof(temp));
+ if (data->type_instance.prefix == NULL)
+ sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance));
+ else
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
+ data->type_instance.prefix, temp);
+ } else if (data->type_instance.value) {
+ sstrncpy(vl.type_instance, data->type_instance.value,
+ sizeof(vl.type_instance));
+ }
- if (data->plugin_instance.prefix == NULL)
- sstrncpy(vl.plugin_instance, temp, sizeof(vl.plugin_instance));
- else
- snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s",
- data->plugin_instance.prefix, temp);
- } else if (data->plugin_instance.value) {
- sstrncpy(vl.plugin_instance, data->plugin_instance.value,
- sizeof(vl.plugin_instance));
- }
+ /* set vl.plugin_instance */
+ if (data->plugin_instance.configured) {
+ char temp[DATA_MAX_NAME_LEN];
+ if (plugin_instance_cell_ptr == NULL)
+ csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
+ else
+ sstrncpy(temp, plugin_instance_cell_ptr->value, sizeof(temp));
+
+ if (data->plugin_instance.prefix == NULL)
+ sstrncpy(vl.plugin_instance, temp, sizeof(vl.plugin_instance));
+ else
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s",
+ data->plugin_instance.prefix, temp);
+ } else if (data->plugin_instance.value) {
+ sstrncpy(vl.plugin_instance, data->plugin_instance.value,
+ sizeof(vl.plugin_instance));
}
vl.values_len = data->values_len;
value_cell_ptr[0] = value_cell_ptr[0]->next;
} /* while (have_more) */
- return (0);
+ return 0;
} /* int csnmp_dispatch_table */
static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
if (data->host.oid.oid_len > 0)
oid_list_len++;
+ if (data->filter_oid.oid_len > 0)
+ oid_list_len++;
+
/* Holds the last OID returned by the device. We use this in the GETNEXT
* request to proceed. */
oid_t oid_list[oid_list_len];
csnmp_cell_char_t *plugin_instance_cells_tail = NULL;
csnmp_cell_char_t *hostname_cells_head = NULL;
csnmp_cell_char_t *hostname_cells_tail = NULL;
+ csnmp_cell_char_t *filter_cells_head = NULL;
+ csnmp_cell_char_t *filter_cells_tail = NULL;
csnmp_cell_value_t **value_cells_head;
csnmp_cell_value_t **value_cells_tail;
i++;
}
+ if (data->filter_oid.oid_len > 0) {
+ memcpy(oid_list + i, &data->filter_oid, sizeof(oid_t));
+ oid_list_todo[i] = OID_TYPE_FILTER;
+ i++;
+ }
+
/* We're going to construct n linked lists, one for each "value".
* value_cells_head will contain pointers to the heads of these linked lists,
* value_cells_tail will contain pointers to the tail of the lists. */
DEBUG("snmp plugin: il->hostname = `%s';", cell->value);
csnmp_cells_append(&hostname_cells_head, &hostname_cells_tail, cell);
+ } else if (oid_list_todo[i] == OID_TYPE_FILTER) {
+ if ((vb->type == SNMP_ENDOFMIBVIEW) ||
+ (snmp_oid_ncompare(data->filter_oid.oid, data->filter_oid.oid_len,
+ vb->name, vb->name_length,
+ data->filter_oid.oid_len) != 0)) {
+ DEBUG("snmp plugin: host = %s; data = %s; Host left its subtree.",
+ host->name, data->name);
+ oid_list_todo[i] = 0;
+ continue;
+ }
+
+ /* Allocate a new `csnmp_cell_char_t', insert the instance name and
+ * add it to the list */
+ csnmp_cell_char_t *cell =
+ csnmp_get_char_cell(vb, &data->filter_oid, host, data);
+ if (cell == NULL) {
+ ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.",
+ host->name);
+ status = -1;
+ break;
+ }
+
+ csnmp_cell_replace_reserved_chars(cell);
+
+ DEBUG("snmp plugin: il->filter = `%s';", cell->value);
+ csnmp_cells_append(&filter_cells_head, &filter_cells_tail, cell);
} else /* The variable we are processing is a normal value */
{
assert(oid_list_todo[i] == OID_TYPE_VARIABLE);
csnmp_oid_init(&vb_name, vb->name, vb->name_length);
- DEBUG("snmp plugin: src.oid_len = %" PRIsz " root.oid_len = %" PRIsz
- " is_endofmib = %s",
- vb_name.oid_len, (data->values + i)->oid_len,
- (vb->type == SNMP_ENDOFMIBVIEW) ? "true" : "false");
-
/* Calculate the current suffix. This is later used to check that the
* suffix is increasing. This also checks if we left the subtree */
ret = csnmp_oid_suffix(&suffix, &vb_name, data->values + i);
if (status == 0)
csnmp_dispatch_table(host, data, type_instance_cells_head,
plugin_instance_cells_head, hostname_cells_head,
- value_cells_head);
+ filter_cells_head, value_cells_head);
/* Free all allocated variables here */
while (type_instance_cells_head != NULL) {
hostname_cells_head = next;
}
+ while (filter_cells_head != NULL) {
+ csnmp_cell_char_t *next = filter_cells_head->next;
+ sfree(filter_cells_head);
+ filter_cells_head = next;
+ }
+
for (i = 0; i < data->values_len; i++) {
while (value_cells_head[i] != NULL) {
csnmp_cell_value_t *next = value_cells_head[i]->next;
sstrncpy(vl.plugin_instance, data->plugin_instance.value,
sizeof(vl.plugin_instance));
- vl.interval = host->interval;
-
req = snmp_pdu_create(SNMP_MSG_GET);
if (req == NULL) {
ERROR("snmp plugin: snmp_pdu_create failed.");
host = ud->data;
- if (host->interval == 0)
- host->interval = plugin_get_interval();
-
if (host->sess_handle == NULL)
csnmp_host_open_session(host);