X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fsnmp.c;h=7caa625e6cb86704b215cb2fc0782a1525860122;hb=c0f5748983a962f7be82bf49ac6c28a59d4658ff;hp=7f325e974089977078d378aa41db426d5a0d4707;hpb=080f01b95a5f6006438e2ffee6ae3d093263d148;p=collectd.git diff --git a/src/snmp.c b/src/snmp.c index 7f325e97..7caa625e 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -108,7 +108,7 @@ static int csnmp_read_host (user_data_t *ud); */ static void csnmp_oid_init (oid_t *dst, oid const *src, size_t n) { - assert (n <= STATIC_ARRAY_LEN (dst->oid)); + assert (n <= STATIC_ARRAY_SIZE (dst->oid)); memcpy (dst->oid, src, sizeof (*src) * n); dst->oid_len = n; } @@ -402,7 +402,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 = csnmp_config_add_data_type (dd, option); @@ -772,8 +771,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); @@ -1054,16 +1052,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 ((size_t) 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) { @@ -1195,15 +1194,22 @@ 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; - oid_t *oid_list; - uint32_t oid_list_len; + + uint32_t oid_list_len = (uint32_t) (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]; + /* Set to false when an OID has left its subtree so we don't re-request it + * again. */ + _Bool oid_list_todo[oid_list_len]; int status; - int i, j; + int i; + uint32_t j; /* `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 @@ -1235,25 +1241,17 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) 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. */ - oid_list_len = data->values_len + 1; - oid_list = (oid_t *) malloc (sizeof (oid_t) * (oid_list_len)); - if (oid_list == NULL) - { - ERROR ("snmp plugin: csnmp_read_table: malloc failed."); - return (-1); - } memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); if (data->instance.oid.oid_len > 0) memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t)); - else + else /* no InstanceFrom option specified. */ oid_list_len--; - /* We also need a 0(=finished)|1(=todo) mask for a todo list */ - int oid_todo_list[oid_list_len]; - for (i=0;isess_handle, req, &res); - if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; @@ -1315,12 +1316,15 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) snmp_free_pdu (res); res = NULL; + /* snmp_synch_response already freed our PDU */ + req = NULL; sfree (errstr); csnmp_host_close_session (host); status = -1; break; } + status = 0; assert (res != NULL); c_release (LOG_INFO, &host->complaint, @@ -1337,55 +1341,55 @@ 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_todo_list[i] == 0 && 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 instance value (last index) */ - if (data->instance.oid.oid_len > 0 && i == data->values_len) { - - if ((vb->type == SNMP_ENDOFMIBVIEW) - || (snmp_oid_ncompare (data->instance.oid.oid, - data->instance.oid.oid_len, - vb->name, vb->name_length, - data->instance.oid.oid_len) != 0)) + /* An instance is configured and the res variable we process is the + * instance value (last index) */ + if ((data->instance.oid.oid_len > 0) && (i == data->values_len)) { - DEBUG ("snmp plugin: host = %s; data = %s; Instance left its subtree.", - host->name, data->name); - oid_todo_list[i] = 0; - continue; - } + if ((vb->type == SNMP_ENDOFMIBVIEW) + || (snmp_oid_ncompare (data->instance.oid.oid, + data->instance.oid.oid_len, + vb->name, vb->name_length, + data->instance.oid.oid_len) != 0)) + { + DEBUG ("snmp plugin: host = %s; data = %s; Instance left its subtree.", + host->name, data->name); + oid_list_todo[i] = 0; + continue; + } - /* Allocate a new `csnmp_list_instances_t', insert the instance name and - * add it to the list */ - if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail, - res, host, data) != 0) - { - ERROR ("snmp plugin: csnmp_instance_list_add failed."); - status = -1; - break; + /* Allocate a new `csnmp_list_instances_t', insert the instance name and + * add it to the list */ + if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail, + res, host, data) != 0) + { + ERROR ("snmp plugin: csnmp_instance_list_add failed."); + status = -1; + break; + } } - - /* The variable we are processing is a normal value */ - } else { - + else /* The variable we are processing is a normal value */ + { csnmp_table_values_t *vt; oid_t vb_name; oid_t suffix; + int ret; csnmp_oid_init (&vb_name, vb->name, vb->name_length); /* Calculate the current suffix. This is later used to check that the * suffix is increasing. This also checks if we left the subtree */ - int ret; ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i); if (ret != 0) { DEBUG ("snmp plugin: host = %s; data = %s; i = %i; " "Value probably left its subtree.", host->name, data->name, i); - oid_todo_list[i] = 0; + oid_list_todo[i] = 0; continue; - } + } /* Make sure the OIDs returned by the agent are increasing. Otherwise our * table matching algorithm will get confused. */ @@ -1395,31 +1399,31 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) DEBUG ("snmp plugin: host = %s; data = %s; i = %i; " "Suffix is not increasing.", host->name, data->name, i); - oid_todo_list[i] = 0; + oid_list_todo[i] = 0; continue; } - vt = malloc (sizeof (*vt)); - if (vt == NULL) - { - ERROR ("snmp plugin: malloc 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); - memcpy (&vt->suffix, &suffix, sizeof (vt->suffix)); - vt->next = NULL; - - if (value_list_tail[i] == NULL) - value_list_head[i] = vt; - else - value_list_tail[i]->next = vt; - value_list_tail[i] = vt; + vt = malloc (sizeof (*vt)); + if (vt == NULL) + { + ERROR ("snmp plugin: malloc 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); + memcpy (&vt->suffix, &suffix, sizeof (vt->suffix)); + vt->next = NULL; + + if (value_list_tail[i] == NULL) + value_list_head[i] = vt; + else + value_list_tail[i]->next = vt; + value_list_tail[i] = vt; } + /* Copy OID to oid_list[i] */ memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[i].oid_len = vb->name_length; @@ -1435,6 +1439,10 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) 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); @@ -1458,7 +1466,6 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) sfree (value_list_head); sfree (value_list_tail); - sfree (oid_list); return (0); } /* int csnmp_read_table */ @@ -1480,7 +1487,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) 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); } @@ -1544,6 +1551,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) res = NULL; sfree (errstr); + sfree (vl.values); csnmp_host_close_session (host); return (-1); @@ -1589,7 +1597,7 @@ static int csnmp_read_host (user_data_t *ud) host = ud->data; if (host->interval == 0) - host->interval = interval_g; + host->interval = plugin_get_interval (); time_start = cdtime (); @@ -1617,10 +1625,10 @@ static int csnmp_read_host (user_data_t *ud) 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)); + "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)