Merge branch 'collectd-4.7' into collectd-4.8
[collectd.git] / src / snmp.c
index 7568cf6..ee40263 100644 (file)
@@ -724,7 +724,8 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
     double scale, double shift)
 {
   value_t ret;
-  uint64_t temp = 0;
+  uint64_t tmp_unsigned = 0;
+  int64_t tmp_signed = 0;
   int defined = 1;
 
   if ((vl->type == ASN_INTEGER)
@@ -735,15 +736,17 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
 #endif
       || (vl->type == ASN_GAUGE))
   {
-    temp = (uint32_t) *vl->val.integer;
-    DEBUG ("snmp plugin: Parsed int32 value is %"PRIu64".", temp);
+    tmp_unsigned = (uint32_t) *vl->val.integer;
+    tmp_signed = (int32_t) *vl->val.integer;
+    DEBUG ("snmp plugin: Parsed int32 value is %"PRIi64".", tmp_signed);
   }
   else if (vl->type == ASN_COUNTER64)
   {
-    temp = (uint32_t) vl->val.counter64->high;
-    temp = temp << 32;
-    temp += (uint32_t) vl->val.counter64->low;
-    DEBUG ("snmp plugin: Parsed int64 value is %"PRIu64".", temp);
+    tmp_unsigned = (uint32_t) vl->val.counter64->high;
+    tmp_unsigned = tmp_unsigned << 32;
+    tmp_unsigned += (uint32_t) vl->val.counter64->low;
+    tmp_signed = (int64_t) tmp_unsigned;
+    DEBUG ("snmp plugin: Parsed int64 value is %"PRIu64".", tmp_unsigned);
   }
   else if (vl->type == ASN_OCTET_STR)
   {
@@ -805,12 +808,14 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
     }
   } /* if (vl->type == ASN_OCTET_STR) */
   else if (type == DS_TYPE_COUNTER)
-    ret.counter = temp;
+  {
+    ret.counter = tmp_unsigned;
+  }
   else if (type == DS_TYPE_GAUGE)
   {
     ret.gauge = NAN;
     if (defined != 0)
-      ret.gauge = (scale * temp) + shift;
+      ret.gauge = (scale * tmp_signed) + shift;
   }
   else if (type == DS_TYPE_DERIVE)
     ret.derive = (derive_t) temp;
@@ -889,6 +894,72 @@ static int csnmp_check_res_left_subtree (const host_definition_t *host,
   return (0);
 } /* int csnmp_check_res_left_subtree */
 
+static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
+    const struct variable_list *vb, size_t dst_size)
+{
+  char *buffer_ptr;
+  size_t buffer_free;
+  size_t i;
+
+  buffer_ptr = dst;
+  buffer_free = dst_size;
+
+  for (i = 0; i < vb->val_len; i++)
+  {
+    int status;
+
+    status = snprintf (buffer_ptr, buffer_free,
+       (i == 0) ? "%02x" : ":%02x", (unsigned int) vb->val.bitstring[i]);
+
+    if (status >= buffer_free)
+    {
+      buffer_ptr += (buffer_free - 1);
+      *buffer_ptr = 0;
+      return (dst_size + (buffer_free - status));
+    }
+    else /* if (status < buffer_free) */
+    {
+      buffer_ptr += status;
+      buffer_free -= status;
+    }
+  }
+
+  return ((int) (dst_size - buffer_free));
+} /* }}} int csnmp_strvbcopy_hexstring */
+
+static int csnmp_strvbcopy (char *dst, /* {{{ */
+    const struct variable_list *vb, size_t dst_size)
+{
+  char *src;
+  size_t num_chars;
+  size_t i;
+
+  if (vb->type == ASN_OCTET_STR)
+    src = (char *) vb->val.string;
+  else if (vb->type == ASN_BIT_STR)
+    src = (char *) vb->val.bitstring;
+  else
+  {
+    dst[0] = 0;
+    return (EINVAL);
+  }
+
+  num_chars = dst_size - 1;
+  if (num_chars > vb->val_len)
+    num_chars = vb->val_len;
+
+  for (i = 0; i < num_chars; i++)
+  {
+    /* Check for control characters. */
+    if ((src[i] >= 0) && (src[i] < 32))
+      return (csnmp_strvbcopy_hexstring (dst, vb, dst_size));
+    dst[i] = src[i];
+  }
+  dst[num_chars] = 0;
+
+  return ((int) vb->val_len);
+} /* }}} int csnmp_strvbcopy */
+
 static int csnmp_instance_list_add (csnmp_list_instances_t **head,
     csnmp_list_instances_t **tail,
     const struct snmp_pdu *res)
@@ -917,17 +988,8 @@ static int csnmp_instance_list_add (csnmp_list_instances_t **head,
   if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR))
   {
     char *ptr;
-    size_t instance_len;
-
-    memset (il->instance, 0, sizeof (il->instance));
-    instance_len = sizeof (il->instance) - 1;
-    if (instance_len > vb->val_len)
-      instance_len = vb->val_len;
 
-    sstrncpy (il->instance, (char *) ((vb->type == ASN_OCTET_STR)
-         ? vb->val.string
-         : vb->val.bitstring),
-       instance_len + 1);
+    csnmp_strvbcopy (il->instance, vb, sizeof (il->instance));
 
     for (ptr = il->instance; *ptr != '\0'; ptr++)
     {