X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fsnmp.c;h=89cbc46016db0610e5e2e6f71f234b2eedcaa495;hb=db35efb33e81d0a013e09a8a6ffa362ad5962f7c;hp=51afea1b14e644b9a1b4c478a9883b65dbbe69ac;hpb=3489284330462f4edc85a75445a5cc8014e29db0;p=collectd.git diff --git a/src/snmp.c b/src/snmp.c index 51afea1b..89cbc460 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -61,7 +61,7 @@ struct data_definition_s instance_t instance; char *instance_prefix; oid_t *values; - int values_len; + size_t values_len; double scale; double shift; struct data_definition_s *next; @@ -310,10 +310,10 @@ static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t * sfree (dd->values); dd->values_len = 0; - dd->values = (oid_t *) malloc (sizeof (oid_t) * ci->values_num); + dd->values = malloc (sizeof (*dd->values) * ci->values_num); if (dd->values == NULL) return (-1); - dd->values_len = ci->values_num; + dd->values_len = (size_t) ci->values_num; for (i = 0; i < ci->values_num; i++) { @@ -384,10 +384,9 @@ static int csnmp_config_add_data (oconfig_item_t *ci) int status = 0; int i; - dd = (data_definition_t *) malloc (sizeof (data_definition_t)); + dd = calloc (1, sizeof (*dd)); if (dd == NULL) return (-1); - memset (dd, '\0', sizeof (data_definition_t)); status = cf_util_get_string(ci, &dd->name); if (status != 0) @@ -402,7 +401,6 @@ static int csnmp_config_add_data (oconfig_item_t *ci) for (i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; - status = 0; if (strcasecmp ("Type", option->key) == 0) status = cf_util_get_string(option, &dd->type); @@ -460,7 +458,7 @@ static int csnmp_config_add_data (oconfig_item_t *ci) return (-1); } - DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %i }", + DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %zu }", dd->name, dd->type, (dd->is_table != 0) ? "true" : "false", dd->values_len); if (data_head == NULL) @@ -522,7 +520,7 @@ static int csnmp_config_add_host_collect (host_definition_t *host, } data_list_len = host->data_list_len + ci->values_num; - data_list = (data_definition_t **) realloc (host->data_list, + data_list = realloc (host->data_list, sizeof (data_definition_t *) * data_list_len); if (data_list == NULL) return (-1); @@ -647,16 +645,18 @@ static int csnmp_config_add_host (oconfig_item_t *ci) char cb_name[DATA_MAX_NAME_LEN]; user_data_t cb_data; - hd = (host_definition_t *) malloc (sizeof (host_definition_t)); + hd = calloc (1, sizeof (*hd)); if (hd == NULL) return (-1); - memset (hd, '\0', sizeof (host_definition_t)); hd->version = 2; C_COMPLAIN_INIT (&hd->complaint); status = cf_util_get_string(ci, &hd->name); if (status != 0) + { + sfree (hd); return status; + } hd->sess_handle = NULL; hd->interval = 0; @@ -925,8 +925,7 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type, tmp_unsigned = (uint32_t) *vl->val.integer; tmp_signed = (int32_t) *vl->val.integer; - if ((vl->type == ASN_INTEGER) - || (vl->type == ASN_GAUGE)) + if (vl->type == ASN_INTEGER) prefer_signed = 1; DEBUG ("snmp plugin: Parsed int32 value is %"PRIu64".", tmp_unsigned); @@ -1050,6 +1049,10 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type, return (ret); } /* value_t csnmp_value_list_to_value */ +/* csnmp_strvbcopy_hexstring converts the bit string contained in "vb" to a hex + * representation and writes it to dst. Returns zero on success and ENOMEM if + * dst is not large enough to hold the string. dst is guaranteed to be + * nul-terminated. */ static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */ const struct variable_list *vb, size_t dst_size) { @@ -1057,6 +1060,8 @@ static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */ size_t buffer_free; size_t i; + dst[0] = 0; + buffer_ptr = dst; buffer_free = dst_size; @@ -1066,23 +1071,28 @@ static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */ status = snprintf (buffer_ptr, buffer_free, (i == 0) ? "%02x" : ":%02x", (unsigned int) vb->val.bitstring[i]); + assert (status >= 0); - if (status >= buffer_free) + if (((size_t) status) >= buffer_free) /* truncated */ { - buffer_ptr += (buffer_free - 1); - *buffer_ptr = 0; - return (dst_size + (buffer_free - status)); + dst[dst_size - 1] = 0; + return ENOMEM; } else /* if (status < buffer_free) */ { - buffer_ptr += status; - buffer_free -= status; + buffer_ptr += (size_t) status; + buffer_free -= (size_t) status; } } - return ((int) (dst_size - buffer_free)); + return 0; } /* }}} int csnmp_strvbcopy_hexstring */ +/* csnmp_strvbcopy copies the octet string or bit string contained in vb to + * dst. If non-printable characters are detected, it will switch to a hex + * representation of the string. Returns zero on success, EINVAL if vb does not + * contain a string and ENOMEM if dst is not large enough to contain the + * string. */ static int csnmp_strvbcopy (char *dst, /* {{{ */ const struct variable_list *vb, size_t dst_size) { @@ -1094,6 +1104,14 @@ static int csnmp_strvbcopy (char *dst, /* {{{ */ src = (char *) vb->val.string; else if (vb->type == ASN_BIT_STR) src = (char *) vb->val.bitstring; + else if (vb->type == ASN_IPADDRESS) + { + return ssnprintf (dst, dst_size, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"", + (uint8_t) vb->val.string[0], + (uint8_t) vb->val.string[1], + (uint8_t) vb->val.string[2], + (uint8_t) vb->val.string[3]); + } else { dst[0] = 0; @@ -1112,8 +1130,12 @@ static int csnmp_strvbcopy (char *dst, /* {{{ */ dst[i] = src[i]; } dst[num_chars] = 0; + dst[dst_size - 1] = 0; + + if (dst_size <= vb->val_len) + return ENOMEM; - return ((int) vb->val_len); + return 0; } /* }}} int csnmp_strvbcopy */ static int csnmp_instance_list_add (csnmp_list_instances_t **head, @@ -1138,13 +1160,12 @@ static int csnmp_instance_list_add (csnmp_list_instances_t **head, csnmp_oid_init (&vb_name, vb->name, vb->name_length); - il = malloc (sizeof (*il)); + il = calloc (1, sizeof (*il)); if (il == NULL) { - ERROR ("snmp plugin: malloc failed."); + ERROR ("snmp plugin: calloc failed."); return (-1); } - memset (il, 0, sizeof (*il)); il->next = NULL; status = csnmp_oid_suffix (&il->suffix, &vb_name, &dd->instance.oid); @@ -1155,7 +1176,7 @@ static int csnmp_instance_list_add (csnmp_list_instances_t **head, } /* Get instance name */ - if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR)) + if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR) || (vb->type == ASN_IPADDRESS)) { char *ptr; @@ -1221,7 +1242,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat csnmp_list_instances_t *instance_list_ptr; csnmp_table_values_t **value_table_ptr; - int i; + size_t i; _Bool have_more; oid_t current_suffix; @@ -1232,16 +1253,17 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat return (-1); } assert (ds->ds_num == data->values_len); + assert (data->values_len > 0); instance_list_ptr = instance_list; - value_table_ptr = malloc (sizeof (*value_table_ptr) * data->values_len); + value_table_ptr = calloc (data->values_len, sizeof (*value_table_ptr)); if (value_table_ptr == NULL) return (-1); for (i = 0; i < data->values_len; i++) value_table_ptr[i] = value_table[i]; - vl.values_len = ds->ds_num; + vl.values_len = data->values_len; vl.values = malloc (sizeof (*vl.values) * vl.values_len); if (vl.values == NULL) { @@ -1373,12 +1395,12 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat static int csnmp_read_table (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; - struct snmp_pdu *res; + struct snmp_pdu *res = NULL; struct variable_list *vb; const data_set_t *ds; - uint32_t oid_list_len = (uint32_t) (data->values_len + 1); + size_t oid_list_len = data->values_len + 1; /* Holds the last OID returned by the device. We use this in the GETNEXT * request to proceed. */ oid_t oid_list[oid_list_len]; @@ -1387,8 +1409,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) _Bool oid_list_todo[oid_list_len]; int status; - int i; - uint32_t j; + size_t i; /* `value_list_head' and `value_list_tail' implement a linked list for each * value. `instance_list_head' and `instance_list_tail' implement a linked list of @@ -1416,10 +1437,11 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) if (ds->ds_num != data->values_len) { - ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i", + ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu", data->type, ds->ds_num, data->values_len); return (-1); } + assert (data->values_len > 0); /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); @@ -1428,8 +1450,8 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) else /* no InstanceFrom option specified. */ oid_list_len--; - for (j = 0; j < oid_list_len; j++) - oid_list_todo[j] = 1; + for (i = 0; i < oid_list_len; i++) + oid_list_todo[i] = 1; /* We're going to construct n linked lists, one for each "value". * value_list_head will contain pointers to the heads of these linked lists, @@ -1461,13 +1483,13 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) } oid_list_todo_num = 0; - for (j = 0; j < oid_list_len; j++) + for (i = 0; i < oid_list_len; i++) { /* Do not rerequest already finished OIDs */ - if (!oid_list_todo[j]) + if (!oid_list_todo[i]) continue; oid_list_todo_num++; - snmp_add_null_var (req, oid_list[j].oid, oid_list[j].oid_len); + snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len); } if (oid_list_todo_num == 0) @@ -1519,7 +1541,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) for (vb = res->variables, i = 0; (vb != NULL); vb = vb->next_variable, i++) { /* Calculate value index from todo list */ - while (!oid_list_todo[i] && (i < oid_list_len)) + while ((i < oid_list_len) && !oid_list_todo[i]) i++; /* An instance is configured and the res variable we process is the @@ -1563,7 +1585,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i); if (ret != 0) { - DEBUG ("snmp plugin: host = %s; data = %s; i = %i; " + DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; " "Value probably left its subtree.", host->name, data->name, i); oid_list_todo[i] = 0; @@ -1575,21 +1597,20 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) if ((value_list_tail[i] != NULL) && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0)) { - DEBUG ("snmp plugin: host = %s; data = %s; i = %i; " + DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; " "Suffix is not increasing.", host->name, data->name, i); oid_list_todo[i] = 0; continue; } - vt = malloc (sizeof (*vt)); + vt = calloc (1, sizeof (*vt)); if (vt == NULL) { - ERROR ("snmp plugin: malloc failed."); + ERROR ("snmp plugin: calloc failed."); status = -1; break; } - memset (vt, 0, sizeof (*vt)); vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type, data->scale, data->shift, host->name, data->name); @@ -1652,21 +1673,21 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) static int csnmp_read_value (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; - struct snmp_pdu *res; + struct snmp_pdu *res = NULL; struct variable_list *vb; const data_set_t *ds; value_list_t vl = VALUE_LIST_INIT; int status; - int i; + size_t i; DEBUG ("snmp plugin: csnmp_read_value (host = %s, data = %s)", host->name, data->name); if (host->sess_handle == NULL) { - DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL"); + DEBUG ("snmp plugin: csnmp_read_value: host->sess_handle == NULL"); return (-1); } @@ -1679,13 +1700,13 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) if (ds->ds_num != data->values_len) { - ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i", + ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu", data->type, ds->ds_num, data->values_len); return (-1); } vl.values_len = ds->ds_num; - vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len); + vl.values = malloc (sizeof (*vl.values) * vl.values_len); if (vl.values == NULL) return (-1); for (i = 0; i < vl.values_len; i++) @@ -1714,7 +1735,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) for (i = 0; i < data->values_len; i++) snmp_add_null_var (req, data->values[i].oid, data->values[i].oid_len); - res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); if ((status != STAT_SUCCESS) || (res == NULL)) @@ -1727,9 +1747,9 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) if (res != NULL) snmp_free_pdu (res); - res = NULL; sfree (errstr); + sfree (vl.values); csnmp_host_close_session (host); return (-1); @@ -1752,9 +1772,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) data->scale, data->shift, host->name, data->name); } /* for (res->variables) */ - if (res != NULL) - snmp_free_pdu (res); - res = NULL; + snmp_free_pdu (res); DEBUG ("snmp plugin: -> plugin_dispatch_values (&vl);"); plugin_dispatch_values (&vl); @@ -1766,8 +1784,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) static int csnmp_read_host (user_data_t *ud) { host_definition_t *host; - cdtime_t time_start; - cdtime_t time_end; int status; int success; int i; @@ -1777,8 +1793,6 @@ static int csnmp_read_host (user_data_t *ud) if (host->interval == 0) host->interval = plugin_get_interval (); - time_start = cdtime (); - if (host->sess_handle == NULL) csnmp_host_open_session (host); @@ -1799,16 +1813,6 @@ static int csnmp_read_host (user_data_t *ud) success++; } - time_end = cdtime (); - if ((time_end - time_start) > host->interval) - { - WARNING ("snmp plugin: Host `%s' should be queried every %.3f " - "seconds, but reading all values takes %.3f seconds.", - host->name, - CDTIME_T_TO_DOUBLE (host->interval), - CDTIME_T_TO_DOUBLE (time_end - time_start)); - } - if (success == 0) return (-1);