X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fsnmp.c;h=6c018da7f571bac84ec6621eab71db9a79640adb;hb=7f07c55bac640c7a50d516248a3152235a14af59;hp=9aa63f7915475e3e34175ac305f9243f07629cc1;hpb=1a252483e9c58ac64069a60d16ada29d5994d125;p=collectd.git diff --git a/src/snmp.c b/src/snmp.c index 9aa63f79..6c018da7 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -29,6 +29,7 @@ #include "common.h" #include "plugin.h" #include "utils_complain.h" +#include "utils_ignorelist.h" #include #include @@ -59,6 +60,8 @@ struct data_definition_s { 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; @@ -122,6 +125,7 @@ typedef enum { OID_TYPE_TYPEINSTANCE, OID_TYPE_PLUGININSTANCE, OID_TYPE_HOST, + OID_TYPE_FILTER, } csnmp_oid_type_t; /* @@ -223,6 +227,7 @@ static void csnmp_data_definition_destroy(data_definition_t *dd) { sfree(dd->host.value); sfree(dd->values); sfree(dd->ignores); + ignorelist_free(dd->ignorelist); sfree(dd); } /* void csnmp_data_definition_destroy */ @@ -336,6 +341,41 @@ static int csnmp_config_add_data_blacklist(data_definition_t *dd, 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) @@ -352,6 +392,14 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { 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"); @@ -386,8 +434,7 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { } } 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) @@ -417,7 +464,16 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { 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; @@ -430,7 +486,7 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { 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) { @@ -554,7 +610,7 @@ static int csnmp_config_add_host_version(host_definition_t *hd, 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) { @@ -1222,13 +1278,14 @@ static void csnmp_cell_replace_reserved_chars(csnmp_cell_char_t *cell) { 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; @@ -1236,6 +1293,7 @@ static int csnmp_dispatch_table(host_definition_t *host, 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; @@ -1254,6 +1312,7 @@ static int csnmp_dispatch_table(host_definition_t *host, value_cell_ptr[i] = value_cells[i]; sstrncpy(vl.plugin, data->plugin_name, sizeof(vl.plugin)); + sstrncpy(vl.type, data->type, sizeof(vl.type)); vl.interval = host->interval; @@ -1305,8 +1364,6 @@ static int csnmp_dispatch_table(host_definition_t *host, /* 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."); } } @@ -1326,7 +1383,24 @@ static int csnmp_dispatch_table(host_definition_t *host, /* 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; } } @@ -1346,8 +1420,6 @@ static int csnmp_dispatch_table(host_definition_t *host, /* 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++) */ @@ -1383,59 +1455,72 @@ static int csnmp_dispatch_table(host_definition_t *host, 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; @@ -1478,6 +1563,9 @@ 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]; @@ -1497,6 +1585,8 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { 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; @@ -1547,6 +1637,12 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { 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. */ @@ -1760,6 +1856,32 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { 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); @@ -1771,11 +1893,6 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { 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); @@ -1836,7 +1953,7 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { 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) { @@ -1857,6 +1974,12 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { 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;