/**
* collectd - src/snmp_agent.c
*
- * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ * Copyright(c) 2017-2018 Intel Corporation. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
will be split into sepearate
tokens */
- _Bool tokens_done; /* Set to 1 when all tokens are generated */
+ bool tokens_done; /* Set to true when all tokens are generated */
};
typedef struct table_definition_s table_definition_t;
typedef struct snmp_agent_ctx_s snmp_agent_ctx_t;
static snmp_agent_ctx_t *g_agent;
-const char *const index_opts[MAX_KEY_SOURCES] = {
+static const char *index_opts[MAX_KEY_SOURCES] = {
"Hostname", "Plugin", "PluginInstance", "Type", "TypeInstance"};
#define CHECK_DD_TYPE(_dd, _p, _pi, _t, _ti) \
return 0;
}
-static int snmp_agent_parse_index_key(const char *input, char *regex,
- regex_t *regex_info, int gi,
- regmatch_t *m) {
+static int snmp_agent_parse_index_key(const char *input, regex_t *regex_info,
+ int gi, regmatch_t *m) {
regmatch_t matches[MAX_MATCHES];
int ret = regexec(regex_info, input, MAX_MATCHES, matches, 0);
static int snmp_agent_create_token(char const *input, int t_off, int n,
c_avl_tree_t *tree,
netsnmp_variable_list *index_key) {
+ assert(tree != NULL);
+
token_t *token = malloc(sizeof(*token));
+
+ if (token == NULL)
+ goto error;
+
int *offset = malloc(sizeof(*offset));
- int ret = 0;
- assert(tree != NULL);
+ if (offset == NULL)
+ goto free_token_error;
- if (token == NULL || offset == NULL)
- goto error;
+ int ret = 0;
token->key = index_key;
- token->str = strndup(input + t_off, n);
+ input += t_off;
+ size_t len = strlen(input);
+
+ if (n < len)
+ len = n;
+
+ token->str = malloc(len + 1);
if (token->str == NULL)
- goto error;
+ goto free_offset_error;
+ /* copy at most n bytes from input with offset t_off into token->str */
+ sstrncpy(token->str, input, len + 1);
*offset = t_off;
ret = c_avl_insert(tree, (void *)offset, (void *)token);
- if (ret != 0)
- goto error;
+ if (ret == 0)
+ return 0;
- return 0;
+ sfree(token->str);
-error:
+free_offset_error:
+ sfree(offset);
- ERROR(PLUGIN_NAME ": Could not allocate memory to create token");
- sfree(token->str);
+free_token_error:
sfree(token);
- sfree(offset);
+
+error:
+ ERROR(PLUGIN_NAME ": Could not allocate memory to create token");
+
return -1;
}
/* var should never be NULL */
assert(key != NULL);
ptr = NULL;
- ret = 0;
const index_key_src_t source = td->index_keys[i].source;
c_avl_tree_t *const tokens = td->tokens[source];
/* Generating list filled with all data necessary to generate an OID */
ERROR(PLUGIN_NAME ": Unknown index key source provided");
return -EINVAL;
}
- if (ret != 0)
- return -EINVAL;
/* Parsing input string if necessary */
if (td->index_keys[i].regex) {
- regmatch_t m = {-1, -1};
+ regmatch_t m;
/* Parsing input string */
- ret = snmp_agent_parse_index_key(ptr, td->index_keys[i].regex,
- &td->index_keys[i].regex_info,
+ ret = snmp_agent_parse_index_key(ptr, &td->index_keys[i].regex_info,
td->index_keys[i].group, &m);
if (ret != 0) {
ERROR(PLUGIN_NAME ": Error executing regex");
}
/* Tokenizing input string if not done yet */
- if (td->tokens_done == 0)
+ if (td->tokens_done == false)
ret = snmp_agent_tokenize(ptr, tokens, &m, key);
if (ret != 0)
if (td->index_keys[i].type == ASN_INTEGER) {
int val = strtol(ptr + m.rm_so, NULL, 0);
+
+#ifdef HAVE_NETSNMP_OLD_API
+ ret = snmp_set_var_value(key, (const u_char *)&val, sizeof(val));
+#else
ret = snmp_set_var_value(key, &val, sizeof(val));
+#endif
} else
+#ifdef HAVE_NETSNMP_OLD_API
+ ret = snmp_set_var_value(key, (const u_char *)(ptr + m.rm_so),
+ m.rm_eo - m.rm_so);
+#else
ret = snmp_set_var_value(key, ptr + m.rm_so, m.rm_eo - m.rm_so);
+#endif
} else
+#ifdef HAVE_NETSNMP_OLD_API
+ ret = snmp_set_var_value(key, (const u_char *)ptr, strlen(ptr));
+#else
ret = snmp_set_var_value(key, ptr, strlen(ptr));
+#endif
+
+ if (ret != 0)
+ return -1;
+
key = key->next_variable;
}
/* Tokens for all source strings are generated */
for (i = 0; i < MAX_KEY_SOURCES; i++)
- td->tokens_done = 1;
+ td->tokens_done = true;
return 0;
}
return snmp_agent_unregister_oid(&new_oid);
}
-static int snmp_agent_table_data_remove(data_definition_t *dd,
- table_definition_t *td,
- oid_t **index_oid) {
+static void snmp_agent_table_data_remove(data_definition_t *dd,
+ table_definition_t *td,
+ oid_t *index_oid) {
int *index = NULL;
oid_t *ind_oid = NULL;
if (td->index_oid.oid_len) {
- if ((c_avl_get(td->instance_index, *index_oid, (void **)&index) != 0) ||
+ if ((c_avl_get(td->instance_index, index_oid, (void **)&index) != 0) ||
(c_avl_get(td->index_instance, index, NULL) != 0))
- return 0;
+ return;
} else {
- if (c_avl_get(td->instance_index, *index_oid, NULL) != 0)
- return 0;
+ if (c_avl_get(td->instance_index, index_oid, NULL) != 0)
+ return;
}
pthread_mutex_lock(&g_agent->agentx_lock);
+ int reg_oids = -1; /* Number of registered oids for given instance */
+
for (size_t i = 0; i < dd->oids_len; i++) {
if (td->index_oid.oid_len)
snmp_agent_unregister_oid_index(&dd->oids[i], *index);
else
- snmp_agent_unregister_oid_string(&dd->oids[i], *index_oid);
+ snmp_agent_unregister_oid_string(&dd->oids[i], index_oid);
+
+ reg_oids =
+ snmp_agent_update_instance_oids(td->instance_oids, index_oid, -1);
}
/* Checking if any metrics are left registered */
- if (snmp_agent_update_instance_oids(td->instance_oids, *index_oid, -1) > 0) {
+ if (reg_oids != 0) {
pthread_mutex_unlock(&g_agent->agentx_lock);
- return 0;
+ return;
}
/* All metrics have been unregistered. Unregistering index key OIDs */
if (td->index_oid.oid_len)
snmp_agent_unregister_oid_index(&idd->oids[i], *index);
else
- snmp_agent_unregister_oid_string(&idd->oids[i], *index_oid);
+ snmp_agent_unregister_oid_string(&idd->oids[i], index_oid);
if (++keys_processed >= td->index_keys_len)
break;
char index_str[DATA_MAX_NAME_LEN];
if (index == NULL)
- snmp_agent_oid_to_string(index_str, sizeof(index_str), *index_oid);
+ snmp_agent_oid_to_string(index_str, sizeof(index_str), index_oid);
else
snprintf(index_str, sizeof(index_str), "%d", *index);
int *val = NULL;
- c_avl_remove(td->instance_oids, *index_oid, NULL, (void **)&val);
+ c_avl_remove(td->instance_oids, index_oid, NULL, (void **)&val);
sfree(val);
- if (td->index_oid.oid_len) {
+ if (index != NULL) {
pthread_mutex_lock(&g_agent->agentx_lock);
snmp_agent_unregister_oid_index(&td->index_oid, *index);
pthread_mutex_unlock(&g_agent->agentx_lock);
c_avl_remove(td->index_instance, index, NULL, (void **)&ind_oid);
- c_avl_remove(td->instance_index, *index_oid, NULL, (void **)&index);
+ c_avl_remove(td->instance_index, index_oid, NULL, (void **)&index);
sfree(index);
sfree(ind_oid);
} else {
- c_avl_remove(td->instance_index, *index_oid, NULL, NULL);
- sfree(*index_oid);
+ c_avl_remove(td->instance_index, index_oid, NULL, NULL);
}
-
- return 0;
}
static int snmp_agent_clear_missing(const value_list_t *vl,
for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) {
data_definition_t *dd = de->value;
- oid_t *index_oid = (oid_t *)calloc(1, sizeof(*index_oid));
- int ret;
if (!dd->is_index_key) {
if (CHECK_DD_TYPE(dd, vl->plugin, vl->plugin_instance, vl->type,
vl->type_instance)) {
- ret = snmp_agent_generate_index(td, vl, index_oid);
+ oid_t *index_oid = calloc(1, sizeof(*index_oid));
+
+ if (index_oid == NULL) {
+ ERROR(PLUGIN_NAME ": Could not allocate memory for index_oid");
+ return -ENOMEM;
+ }
+
+ int ret = snmp_agent_generate_index(td, vl, index_oid);
+
if (ret == 0)
- ret = snmp_agent_table_data_remove(dd, td, &index_oid);
+ snmp_agent_table_data_remove(dd, td, index_oid);
+ sfree(index_oid);
return ret;
}
static int snmp_agent_parse_oid_index_keys(const table_definition_t *td,
oid_t *index_oid) {
+ assert(index_oid != NULL);
int ret = parse_oid_indexes(index_oid->oid, index_oid->oid_len,
td->index_list_cont);
if (ret != SNMPERR_SUCCESS)
}
static int snmp_agent_build_name(char **name, c_avl_tree_t *tokens) {
-
int *pos;
token_t *tok;
char str[DATA_MAX_NAME_LEN];
}
while (c_avl_iterator_next(it, (void **)&pos, (void **)&tok) == 0) {
- strncat(out, tok->str, strlen(tok->str));
+ strncat(out, tok->str, DATA_MAX_NAME_LEN - strlen(out) - 1);
if (tok->key != NULL) {
if (tok->key->type == ASN_INTEGER) {
snprintf(str, sizeof(str), "%ld", *tok->key->val.integer);
- strncat(out, str, strlen(str));
- } else { /* OCTET_STR */
+ strncat(out, str, DATA_MAX_NAME_LEN - strlen(out) - 1);
+ } else /* OCTET_STR */
strncat(out, (char *)tok->key->val.string,
- strlen((char *)tok->key->val.string));
- }
+ DATA_MAX_NAME_LEN - strlen(out) - 1);
}
}
- *name = strdup(out);
+
c_avl_iterator_destroy(it);
+ *name = strdup(out);
if (*name == NULL) {
ERROR(PLUGIN_NAME ": Could not allocate memory");
requests->requestvb->type = td->index_keys[dd->index_key_pos].type;
if (requests->requestvb->type == ASN_INTEGER)
+#ifdef HAVE_NETSNMP_OLD_API
+ snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type,
+ (const u_char *)key->val.integer,
+ sizeof(*key->val.integer));
+#else
snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type,
key->val.integer, sizeof(*key->val.integer));
+#endif
else /* OCTET_STR */
+#ifdef HAVE_NETSNMP_OLD_API
snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type,
(const u_char *)key->val.string,
strlen((const char *)key->val.string));
+#else
+ snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type,
+ key->val.string,
+ strlen((const char *)key->val.string));
+#endif
pthread_mutex_unlock(&g_agent->lock);
return -EINVAL;
}
- if (dd->oids != NULL)
- sfree(dd->oids);
+ if (dd->oids != NULL) {
+ WARNING(PLUGIN_NAME ": OIDs can be configured only once for each data");
+ return -EINVAL;
+ }
+
dd->oids_len = 0;
dd->oids = calloc(ci->values_num, sizeof(*dd->oids));
+
if (dd->oids == NULL)
return -ENOMEM;
dd->oids_len = (size_t)ci->values_num;
if (ret != 0)
return -1;
- _Bool match = 0;
+ bool match = false;
for (int i = 0; i < MAX_KEY_SOURCES; i++) {
if (strcasecmp(index_opts[i], (const char *)val) == 0) {
sfree(val);
dd->index_key_pos = td->index_keys_len++;
- dd->is_index_key = 1;
+ dd->is_index_key = true;
return 0;
}
}
index_key_src_t source = index_key->source;
- if (td->tokens[source] == NULL && index_key->regex != NULL) {
+ if (td->tokens[source] == NULL) {
td->tokens[source] =
c_avl_create((int (*)(const void *, const void *))num_compare);
if (td->tokens[source] == NULL) {
dd->shift = 0.0;
/* NULL if it's a scalar */
dd->table = td;
- dd->is_index_key = 0;
+ dd->is_index_key = false;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *option = ci->children + i;
/* First 3 options are reserved for table entry only */
if (td != NULL && strcasecmp("IndexKey", option->key) == 0) {
- dd->is_index_key = 1;
+ dd->is_index_key = true;
option_tmp = option;
} else if (strcasecmp("Plugin", option->key) == 0)
ret = cf_util_get_string(option, &dd->plugin);
/* Append to column list in parent table */
if (td != NULL)
llist_append(td->columns, entry);
+ else
+ llentry_destroy(entry);
return 0;
}
for (int i = 0; i < MAX_KEY_SOURCES; i++)
td->tokens[i] = NULL;
- td->tokens_done = 0;
+ td->tokens_done = false;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *option = ci->children + i;
}
static int snmp_agent_update_index(data_definition_t *dd,
- table_definition_t *td, oid_t **index_oid) {
+ table_definition_t *td, oid_t *index_oid,
+ bool *free_index_oid) {
int ret;
int *index = NULL;
- _Bool free_index_oid = 1;
+ int *value = NULL;
- if (c_avl_get(td->instance_index, (void *)*index_oid, (void **)&index) != 0) {
- free_index_oid = 0;
+ if (c_avl_get(td->instance_index, (void *)index_oid, (void **)&index) != 0) {
+ /* We'll keep index_oid stored in AVL tree */
+ *free_index_oid = false;
/* need to generate index for the table */
if (td->index_oid.oid_len) {
index = calloc(1, sizeof(*index));
if (index == NULL) {
- sfree(*index_oid);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto error;
}
*index = c_avl_size(td->instance_index) + 1;
- ret = c_avl_insert(td->instance_index, *index_oid, index);
- if (ret != 0) {
- sfree(*index_oid);
- sfree(index);
- return ret;
- }
+ ret = c_avl_insert(td->instance_index, index_oid, index);
+ if (ret != 0)
+ goto free_index;
- ret = c_avl_insert(td->index_instance, index, *index_oid);
+ ret = c_avl_insert(td->index_instance, index, index_oid);
if (ret < 0) {
DEBUG(PLUGIN_NAME ": Failed to update index_instance for '%s' table",
td->name);
- c_avl_remove(td->instance_index, *index_oid, NULL, (void **)&index);
- sfree(*index_oid);
- sfree(index);
- return ret;
+ goto remove_avl_index_oid;
}
ret = snmp_agent_register_oid_index(&td->index_oid, *index,
snmp_agent_table_index_oid_handler);
if (ret != 0)
- return ret;
+ goto remove_avl_index;
} else {
/* instance as a key is required for any table */
- ret = c_avl_insert(td->instance_index, *index_oid, NULL);
- if (ret != 0) {
- sfree(*index_oid);
- return ret;
- }
+ ret = c_avl_insert(td->instance_index, index_oid, NULL);
+ if (ret != 0)
+ goto error;
}
- int *value = calloc(1, sizeof(*value));
+ value = calloc(1, sizeof(*value));
+
+ if (value == NULL) {
+ ERROR(PLUGIN_NAME ": Failed to allocate memory");
+ ret = -ENOMEM;
+ goto unregister_index;
+ }
+
+ ret = c_avl_insert(td->instance_oids, index_oid, value);
- ret = c_avl_insert(td->instance_oids, *index_oid, value);
if (ret < 0) {
- if (td->index_oid.oid_len) {
- c_avl_remove(td->index_instance, index, NULL, NULL);
- }
- c_avl_remove(td->instance_index, *index_oid, NULL, (void **)&index);
- sfree(index);
- sfree(*index_oid);
+ DEBUG(PLUGIN_NAME ": Failed to update instance_oids for '%s' table",
+ td->name);
+ goto free_value;
}
int keys_processed = 0;
+ /* Registering index keys OIDs */
for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) {
data_definition_t *idd = de->value;
if (!idd->is_index_key)
ret = snmp_agent_register_oid_index(&idd->oids[i], *index,
snmp_agent_table_oid_handler);
else
- ret = snmp_agent_register_oid_string(&idd->oids[i], *index_oid,
+ ret = snmp_agent_register_oid_string(&idd->oids[i], index_oid,
snmp_agent_table_oid_handler);
if (ret != 0) {
ERROR(PLUGIN_NAME ": Could not register OID");
- return ret;
+ goto free_index;
}
}
ret = snmp_agent_register_oid_index(&dd->oids[i], *index,
snmp_agent_table_oid_handler);
else
- ret = snmp_agent_register_oid_string(&dd->oids[i], *index_oid,
+ ret = snmp_agent_register_oid_string(&dd->oids[i], index_oid,
snmp_agent_table_oid_handler);
if (ret < 0)
- return ret;
+ goto free_index;
else if (ret == OID_EXISTS)
break;
- else
- ret = snmp_agent_update_instance_oids(td->instance_oids, *index_oid, 1);
+ else if (snmp_agent_update_instance_oids(td->instance_oids, index_oid, 1) <
+ 0)
+ goto free_index;
}
if (ret != OID_EXISTS) {
char index_str[DATA_MAX_NAME_LEN];
if (index == NULL)
- snmp_agent_oid_to_string(index_str, sizeof(index_str), *index_oid);
+ snmp_agent_oid_to_string(index_str, sizeof(index_str), index_oid);
else
snprintf(index_str, sizeof(index_str), "%d", *index);
plugin_dispatch_notification(&n);
}
- if (free_index_oid)
- sfree(*index_oid);
-
return 0;
+
+free_value:
+ sfree(value);
+unregister_index:
+ if (td->index_oid.oid_len)
+ snmp_agent_unregister_oid_index(index_oid, *index);
+remove_avl_index:
+ if (td->index_oid.oid_len)
+ c_avl_remove(td->index_instance, index, NULL, NULL);
+remove_avl_index_oid:
+ c_avl_remove(td->instance_index, index_oid, NULL, NULL);
+free_index:
+ if (index != NULL)
+ sfree(index);
+error:
+ *free_index_oid = true;
+
+ return ret;
}
static int snmp_agent_write(value_list_t const *vl) {
for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) {
data_definition_t *dd = de->value;
- oid_t *index_oid = (oid_t *)calloc(1, sizeof(*index_oid));
- int ret;
-
- if (index_oid == NULL)
- return -ENOMEM;
if (!dd->is_index_key) {
if (CHECK_DD_TYPE(dd, vl->plugin, vl->plugin_instance, vl->type,
vl->type_instance)) {
- ret = snmp_agent_generate_index(td, vl, index_oid);
+ oid_t *index_oid = calloc(1, sizeof(*index_oid));
+ bool free_index_oid = true;
+
+ if (index_oid == NULL) {
+ ERROR(PLUGIN_NAME ": Could not allocate memory for index_oid");
+ return -ENOMEM;
+ }
+
+ int ret = snmp_agent_generate_index(td, vl, index_oid);
+
if (ret == 0)
- ret = snmp_agent_update_index(dd, td, &index_oid);
+ ret = snmp_agent_update_index(dd, td, index_oid, &free_index_oid);
+
+ /* Index exists or update failed */
+ if (free_index_oid)
+ sfree(index_oid);
return ret;
}
return OID_EXISTS;
else {
oid_t *new_oid = calloc(1, sizeof(*oid));
+
+ if (new_oid == NULL) {
+ ERROR(PLUGIN_NAME ": Could not allocate memory to register new OID");
+ return -ENOMEM;
+ }
+
memcpy(new_oid, oid, sizeof(*oid));
int ret = c_avl_insert(g_agent->registered_oids, (void *)new_oid, NULL);