* Copyright 2008 Bruno Premont <bonbons at linux-vserver.org>
* Copyright 2009-2013 Florian Forster <octo at collectd.org>
*
- * $Id$
- *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
-#include <string.h>
-#include <glib.h>
#include <epan/packet.h>
-#include <epan/prefs.h>
#include <epan/expert.h>
#include <epan/stats_tree.h>
+#include <epan/to_str.h>
-#define STR_NONNULL(str) ((str) ? (str) : "(null)")
+#include <wsutil/str_util.h>
+
+#define STR_NONNULL(str) ((str) ? ((const gchar*)str) : "(null)")
#define TYPE_HOST 0x0000
#define TYPE_TIME 0x0001
void proto_register_collectd(void);
typedef struct value_data_s {
- gchar *host;
+ const guint8 *host;
gint host_off;
gint host_len;
- guint64 time;
+ guint64 time_value;
gint time_off;
guint64 interval;
gint interval_off;
- gchar *plugin;
+ const guint8 *plugin;
gint plugin_off;
gint plugin_len;
- gchar *plugin_instance;
+ const guint8 *plugin_instance;
gint plugin_instance_off;
gint plugin_instance_len;
- gchar *type;
+ const guint8 *type;
gint type_off;
gint type_len;
- gchar *type_instance;
+ const guint8 *type_instance;
gint type_instance_off;
gint type_instance_len;
} value_data_t;
typedef struct notify_data_s {
- gchar *host;
+ const guint8 *host;
gint host_off;
gint host_len;
- guint64 time;
+ guint64 time_value;
gint time_off;
guint64 severity;
gint severity_off;
- gchar *message;
+ const guint8 *message;
gint message_off;
gint message_len;
} notify_data_t;
#define SEVERITY_FAILURE 0x01
#define SEVERITY_WARNING 0x02
#define SEVERITY_OKAY 0x04
-static const value_string severity_names[] = {
+static const val64_string severity_names[] = {
{ SEVERITY_FAILURE, "FAILURE" },
{ SEVERITY_WARNING, "WARNING" },
{ SEVERITY_OKAY, "OKAY" },
{ 0, NULL }
};
-#define UDP_PORT_COLLECTD 25826
-static guint collectd_udp_port = UDP_PORT_COLLECTD;
+#define UDP_PORT_COLLECTD 25826 /* Not IANA registered */
static gint proto_collectd = -1;
static gint tap_collectd = -1;
static gint st_collectd_values_plugins = -1;
static gint st_collectd_values_types = -1;
+static expert_field ei_collectd_type = EI_INIT;
+static expert_field ei_collectd_invalid_length = EI_INIT;
+static expert_field ei_collectd_data_valcnt = EI_INIT;
+static expert_field ei_collectd_garbage = EI_INIT;
+
/* Prototype for the handoff function */
void proto_reg_handoff_collectd (void);
static nstime_t
collectd_time_to_nstime (guint64 t)
{
- nstime_t nstime = { 0, 0 };
+ nstime_t nstime = NSTIME_INIT_ZERO;;
nstime.secs = (time_t) (t / 1073741824);
nstime.nsecs = (int) (((double) (t % 1073741824)) / 1.073741824);
static void
collectd_stats_tree_init (stats_tree *st)
{
- st_collectd_packets = stats_tree_create_node (st, "Packets", 0, FALSE);
- st_collectd_values = stats_tree_create_node (st, "Values", 0, TRUE);
+ st_collectd_packets = stats_tree_create_node (st, "Packets", 0, STAT_DT_INT, FALSE);
+ st_collectd_values = stats_tree_create_node (st, "Values", 0, STAT_DT_INT, TRUE);
st_collectd_values_hosts = stats_tree_create_pivot (st, "By host",
st_collectd_values);
proto_tree *subtree;
nstime_t nstime;
- root_item = proto_tree_add_text (root, tvb, offset + 6, length - 6,
- "Assembled metric");
+ subtree = proto_tree_add_subtree(root, tvb, offset + 6, length - 6,
+ ett_collectd_dispatch, &root_item, "Assembled metric");
PROTO_ITEM_SET_GENERATED (root_item);
- subtree = proto_item_add_subtree (root_item, ett_collectd_dispatch);
-
proto_tree_add_string (subtree, hf_collectd_data_host, tvb,
vdispatch->host_off, vdispatch->host_len,
STR_NONNULL (vdispatch->host));
vdispatch->type_instance_len,
vdispatch->type_instance);
- nstime = collectd_time_to_nstime (vdispatch->time);
+ nstime = collectd_time_to_nstime (vdispatch->time_value);
proto_tree_add_time (subtree, hf_collectd_data_time, tvb,
vdispatch->time_off, /* length = */ 8, &nstime);
proto_tree *subtree;
nstime_t nstime;
- root_item = proto_tree_add_text (root, tvb, offset + 6, length - 6,
- "Assembled notification");
+ subtree = proto_tree_add_subtree(root, tvb, offset + 6, length - 6,
+ ett_collectd_dispatch, &root_item, "Assembled notification");
PROTO_ITEM_SET_GENERATED (root_item);
- subtree = proto_item_add_subtree (root_item, ett_collectd_dispatch);
-
proto_tree_add_string (subtree, hf_collectd_data_host, tvb,
ndispatch->host_off, ndispatch->host_len,
STR_NONNULL (ndispatch->host));
- nstime = collectd_time_to_nstime (ndispatch->time);
+ nstime = collectd_time_to_nstime (ndispatch->time_value);
proto_tree_add_time (subtree, hf_collectd_data_time, tvb,
ndispatch->time_off, /* length = */ 8, &nstime);
static int
dissect_collectd_string (tvbuff_t *tvb, packet_info *pinfo, gint type_hf,
gint offset, gint *ret_offset, gint *ret_length,
- gchar **ret_string, proto_tree *tree_root,
+ const guint8 **ret_string, proto_tree *tree_root,
proto_item **ret_item)
{
proto_tree *pt;
type = tvb_get_ntohs(tvb, offset);
length = tvb_get_ntohs(tvb, offset + 2);
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, length,
+ ett_collectd_string, &pi, "collectd %s segment: ",
+ val_to_str_const (type, part_names, "UNKNOWN"));
+
if (length > size)
{
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
- "collectd %s segment: Length = %i <BAD>",
- val_to_str_const (type, part_names, "UNKNOWN"),
- length);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
+ proto_item_append_text(pt, "Length = %i <BAD>", length);
+ expert_add_info_format(pinfo, pt, &ei_collectd_invalid_length,
"String part with invalid part length: "
"Part is longer than rest of package.");
return (-1);
*ret_offset = offset + 4;
*ret_length = length - 4;
- *ret_string = tvb_get_ephemeral_string (tvb, *ret_offset, *ret_length);
+ proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
+ proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2, length);
+ proto_tree_add_item_ret_string (pt, type_hf, tvb, *ret_offset, *ret_length, ENC_ASCII|ENC_NA, wmem_packet_scope(), ret_string);
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
- "collectd %s segment: \"%s\"",
- val_to_str_const (type, part_names, "UNKNOWN"),
- *ret_string);
+ proto_item_append_text(pt, "\"%s\"", *ret_string);
if (ret_item != NULL)
*ret_item = pi;
- pt = proto_item_add_subtree (pi, ett_collectd_string);
- proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
- proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2, length);
- proto_tree_add_item (pt, type_hf, tvb, *ret_offset, *ret_length, ENC_ASCII|ENC_NA);
-
return (0);
} /* int dissect_collectd_string */
if (size < 12)
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_integer, NULL, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_integer);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2,
type);
proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2,
length);
- pi = proto_tree_add_text (pt, tvb, offset + 4, -1,
+ proto_tree_add_expert_format(pt, pinfo, &ei_collectd_garbage, tvb, offset + 4, -1,
"Garbage at end of packet: Length = %i <BAD>",
size - 4);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
- "Garbage at end of packet");
return (-1);
}
if (length != 12)
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_integer, &pi, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_integer);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2,
type);
pi = proto_tree_add_uint (pt, hf_collectd_length, tvb,
offset + 2, 2, length);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
+ expert_add_info_format(pinfo, pi, &ei_collectd_invalid_length,
"Invalid length field for an integer part.");
return (-1);
gchar *strtime;
nstime = collectd_time_to_nstime (*ret_value);
- strtime = abs_time_to_str (&nstime, ABSOLUTE_TIME_LOCAL, /* show_zone = */ TRUE);
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
- "collectd %s segment: %s",
+ strtime = abs_time_to_str (wmem_packet_scope(), &nstime, ABSOLUTE_TIME_LOCAL, /* show_zone = */ TRUE);
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, length,
+ ett_collectd_integer, &pi, "collectd %s segment: %s",
val_to_str_const (type, part_names, "UNKNOWN"),
STR_NONNULL (strtime));
}
gchar *strtime;
nstime = collectd_time_to_nstime (*ret_value);
- strtime = rel_time_to_str (&nstime);
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
- "collectd %s segment: %s",
+ strtime = rel_time_to_str (wmem_packet_scope(), &nstime);
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, length,
+ ett_collectd_integer, &pi, "collectd %s segment: %s",
val_to_str_const (type, part_names, "UNKNOWN"),
strtime);
}
else
{
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
- "collectd %s segment: %"G_GINT64_MODIFIER"u",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, length,
+ ett_collectd_integer, &pi, "collectd %s segment: %"G_GINT64_MODIFIER"u",
val_to_str_const (type, part_names, "UNKNOWN"),
*ret_value);
}
if (ret_item != NULL)
*ret_item = pi;
- pt = proto_item_add_subtree (pi, ett_collectd_integer);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2,
length);
dissect_collectd_values(tvbuff_t *tvb, gint msg_off, gint val_cnt,
proto_tree *collectd_tree)
{
- proto_item *pi;
proto_tree *values_tree, *value_tree;
gint i;
- pi = proto_tree_add_text (collectd_tree, tvb, msg_off + 6, val_cnt * 9,
- "%d value%s", val_cnt,
+ values_tree = proto_tree_add_subtree_format(collectd_tree, tvb, msg_off + 6, val_cnt * 9,
+ ett_collectd_value, NULL, "%d value%s", val_cnt,
plurality (val_cnt, "", "s"));
- values_tree = proto_item_add_subtree (pi, ett_collectd_value);
-
for (i = 0; i < val_cnt; i++)
{
gint value_offset;
guint64 val64;
val64 = tvb_get_ntoh64 (tvb, value_offset);
- pi = proto_tree_add_text (values_tree, tvb, msg_off + 6,
- val_cnt * 9,
+ value_tree = proto_tree_add_subtree_format(values_tree, tvb, msg_off + 6,
+ val_cnt * 9, ett_collectd_valinfo, NULL,
"Counter: %"G_GINT64_MODIFIER"u", val64);
- value_tree = proto_item_add_subtree (pi,
- ett_collectd_valinfo);
proto_tree_add_item (value_tree, hf_collectd_val_type,
tvb, value_type_offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item (value_tree,
gdouble val;
val = tvb_get_letohieee_double (tvb, value_offset);
- pi = proto_tree_add_text (values_tree, tvb, msg_off + 6,
- val_cnt * 9,
+ value_tree = proto_tree_add_subtree_format(values_tree, tvb, msg_off + 6,
+ val_cnt * 9, ett_collectd_valinfo, NULL,
"Gauge: %g", val);
- value_tree = proto_item_add_subtree (pi,
- ett_collectd_valinfo);
proto_tree_add_item (value_tree, hf_collectd_val_type,
tvb, value_type_offset, 1, ENC_BIG_ENDIAN);
/* Set the `little endian' flag to TRUE here, because
gint64 val64;
val64 = tvb_get_ntoh64 (tvb, value_offset);
- pi = proto_tree_add_text (values_tree, tvb, msg_off + 6,
- val_cnt * 9,
+ value_tree = proto_tree_add_subtree_format(values_tree, tvb, msg_off + 6,
+ val_cnt * 9, ett_collectd_valinfo, NULL,
"Derive: %"G_GINT64_MODIFIER"i", val64);
- value_tree = proto_item_add_subtree (pi,
- ett_collectd_valinfo);
proto_tree_add_item (value_tree, hf_collectd_val_type,
tvb, value_type_offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item (value_tree,
guint64 val64;
val64 = tvb_get_ntoh64 (tvb, value_offset);
- pi = proto_tree_add_text (values_tree, tvb, msg_off + 6,
- val_cnt * 9,
+ value_tree = proto_tree_add_subtree_format(values_tree, tvb, msg_off + 6,
+ val_cnt * 9, ett_collectd_valinfo, NULL,
"Absolute: %"G_GINT64_MODIFIER"u", val64);
- value_tree = proto_item_add_subtree (pi,
- ett_collectd_valinfo);
proto_tree_add_item (value_tree, hf_collectd_val_type,
tvb, value_type_offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item (value_tree,
guint64 val64;
val64 = tvb_get_ntoh64 (tvb, value_offset);
- pi = proto_tree_add_text (values_tree, tvb, msg_off + 6,
- val_cnt * 9,
+ value_tree = proto_tree_add_subtree_format(values_tree, tvb, msg_off + 6,
+ val_cnt * 9, ett_collectd_valinfo, NULL,
"Unknown: %"G_GINT64_MODIFIER"x",
val64);
- value_tree = proto_item_add_subtree (pi,
- ett_collectd_valinfo);
proto_tree_add_item (value_tree, hf_collectd_val_type,
tvb, value_type_offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item (value_tree, hf_collectd_val_unknown,
if (size < 15)
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_part_value, NULL, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_part_value);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2,
length);
- pi = proto_tree_add_text (pt, tvb, offset + 4, -1,
+ proto_tree_add_expert_format(pt, pinfo, &ei_collectd_garbage, tvb, offset + 4, -1,
"Garbage at end of packet: Length = %i <BAD>",
size - 4);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
- "Garbage at end of packet");
-
return (-1);
}
if ((length < 15) || ((length % 9) != 6))
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_part_value, &pi, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_part_value);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
pi = proto_tree_add_uint (pt, hf_collectd_length, tvb,
offset + 2, 2, length);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
+ expert_add_info_format(pinfo, pi, &ei_collectd_invalid_length,
"Invalid length field for a values part.");
return (-1);
if (values_count != corrected_values_count)
{
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, length,
+ ett_collectd_part_value, NULL,
"collectd %s segment: %d (%d) value%s <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"),
values_count, corrected_values_count,
}
else
{
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, length,
+ ett_collectd_part_value, NULL,
"collectd %s segment: %d value%s",
val_to_str_const (type, part_names, "UNKNOWN"),
values_count,
plurality(values_count, "", "s"));
}
- pt = proto_item_add_subtree (pi, ett_collectd_part_value);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2, length);
pi = proto_tree_add_item (pt, hf_collectd_data_valcnt, tvb,
offset + 4, 2, ENC_BIG_ENDIAN);
if (values_count != corrected_values_count)
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_WARN,
- "Number of values and length of part do not match. "
- "Assuming length is correct.");
+ expert_add_info(pinfo, pi, &ei_collectd_data_valcnt);
values_count = corrected_values_count;
if (size < 36) /* remaining packet size too small for signature */
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_signature, NULL, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_signature);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2,
length);
- pi = proto_tree_add_text (pt, tvb, offset + 4, -1,
+ proto_tree_add_expert_format(pt, pinfo, &ei_collectd_garbage, tvb, offset + 4, -1,
"Garbage at end of packet: Length = %i <BAD>",
size - 4);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
- "Garbage at end of packet");
-
return (-1);
}
if (length < 36)
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_signature, NULL, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_signature);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
pi = proto_tree_add_uint (pt, hf_collectd_length, tvb,
offset + 2, 2, length);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
+ expert_add_info_format(pinfo, pi, &ei_collectd_invalid_length,
"Invalid length field for a signature part.");
return (-1);
}
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
- "collectd %s segment: HMAC-SHA-256",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, length,
+ ett_collectd_signature, NULL, "collectd %s segment: HMAC-SHA-256",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_signature);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2,
length);
if (size < 42) /* remaining packet size too small for signature */
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_encryption, NULL, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_encryption);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2,
length);
- pi = proto_tree_add_text (pt, tvb, offset + 4, -1,
+ proto_tree_add_expert_format(pt, pinfo, &ei_collectd_garbage, tvb, offset + 4, -1,
"Garbage at end of packet: Length = %i <BAD>",
size - 4);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
- "Garbage at end of packet");
-
return (-1);
}
if (length < 42)
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_encryption, NULL, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_encryption);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
pi = proto_tree_add_uint (pt, hf_collectd_length, tvb,
offset + 2, 2, length);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
+ expert_add_info_format(pinfo, pi, &ei_collectd_invalid_length,
"Invalid length field for an encryption part.");
return (-1);
username_length = tvb_get_ntohs (tvb, offset + 4);
if (username_length > (length - 42))
{
- pi = proto_tree_add_text (tree_root, tvb, offset, -1,
- "collectd %s segment: <BAD>",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, -1,
+ ett_collectd_encryption, NULL, "collectd %s segment: <BAD>",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_encryption);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
proto_tree_add_uint (pt, hf_collectd_length, tvb,
offset + 2, 2, length);
pi = proto_tree_add_uint (pt, hf_collectd_data_username_len, tvb,
offset + 4, 2, length);
- expert_add_info_format (pinfo, pi, PI_MALFORMED, PI_ERROR,
+ expert_add_info_format(pinfo, pi, &ei_collectd_invalid_length,
"Invalid username length field for an encryption part.");
return (-1);
}
- pi = proto_tree_add_text (tree_root, tvb, offset, length,
- "collectd %s segment: AES-256",
+ pt = proto_tree_add_subtree_format(tree_root, tvb, offset, length,
+ ett_collectd_encryption, NULL, "collectd %s segment: AES-256",
val_to_str_const (type, part_names, "UNKNOWN"));
- pt = proto_item_add_subtree (pi, ett_collectd_encryption);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset, 2, type);
proto_tree_add_uint (pt, hf_collectd_length, tvb, offset + 2, 2, length);
proto_tree_add_uint (pt, hf_collectd_data_username_len, tvb, offset + 4, 2, username_length);
return (0);
}
- entry = (string_counter_t *)ep_alloc0 (sizeof (*entry));
- entry->string = ep_strdup (new_value);
+ entry = (string_counter_t *)wmem_alloc0 (wmem_packet_scope(), sizeof (*entry));
+ entry->string = wmem_strdup (wmem_packet_scope(), new_value);
entry->count = 1;
entry->next = *ret_list;
return (0);
}
-static void
-dissect_collectd (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int
+dissect_collectd (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
static tap_data_t tap_data;
gint offset;
gint size;
- gchar *pkt_host = NULL;
+ const guint8 *pkt_host = NULL;
gint pkt_plugins = 0, pkt_values = 0, pkt_messages = 0, pkt_unknown = 0, pkt_errors = 0;
value_data_t vdispatch;
notify_data_t ndispatch;
switch (part_type) {
case TYPE_HOST:
- vdispatch.host = tvb_get_ephemeral_string (tvb,
- offset + 4, part_length - 4);
+ vdispatch.host = tvb_get_string_enc(wmem_packet_scope(), tvb,
+ offset + 4, part_length - 4, ENC_ASCII);
if (pkt_host == NULL)
pkt_host = vdispatch.host;
break;
case TYPE_TIME_HR:
break;
case TYPE_PLUGIN:
- vdispatch.plugin = tvb_get_ephemeral_string (tvb,
- offset + 4, part_length - 4);
+ vdispatch.plugin = tvb_get_string_enc(wmem_packet_scope(), tvb,
+ offset + 4, part_length - 4, ENC_ASCII);
pkt_plugins++;
break;
case TYPE_PLUGIN_INSTANCE:
break;
case TYPE_TYPE:
- vdispatch.type = tvb_get_ephemeral_string (tvb,
- offset + 4, part_length - 4);
+ vdispatch.type = tvb_get_string_enc(wmem_packet_scope(), tvb,
+ offset + 4, part_length - 4, ENC_ASCII);
break;
case TYPE_TYPE_INSTANCE:
break;
* at the end of the packet. */
if (size < 4)
{
- pi = proto_tree_add_text (collectd_tree, tvb,
+ proto_tree_add_expert_format(pi, pinfo, &ei_collectd_garbage, tvb,
offset, -1,
"Garbage at end of packet: Length = %i <BAD>",
size);
- expert_add_info_format (pinfo, pi, PI_MALFORMED,
- PI_ERROR,
- "Garbage at end of packet");
pkt_errors++;
break;
}
* provided in the packet.. */
if ((part_length < 4) || (part_length > size))
{
- pi = proto_tree_add_text (collectd_tree, tvb,
- offset, part_length,
+ pt = proto_tree_add_subtree_format(collectd_tree, tvb,
+ offset, part_length, ett_collectd_invalid_length, NULL,
"collectd %s segment: Length = %i <BAD>",
val_to_str_const (part_type, part_names, "UNKNOWN"),
part_length);
- pt = proto_item_add_subtree (pi, ett_collectd_invalid_length);
proto_tree_add_uint (pt, hf_collectd_type, tvb, offset,
2, part_type);
pi = proto_tree_add_uint (pt, hf_collectd_length, tvb,
offset + 2, 2, part_length);
if (part_length < 4)
- expert_add_info_format (pinfo, pi,
- PI_MALFORMED, PI_ERROR,
+ expert_add_info_format(pinfo, pi, &ei_collectd_invalid_length,
"Bad part length: Is %i, expected at least 4",
part_length);
else
- expert_add_info_format (pinfo, pi,
- PI_MALFORMED, PI_ERROR,
+ expert_add_info_format(pinfo, pi, &ei_collectd_invalid_length,
"Bad part length: Larger than remaining packet size.");
pkt_errors++;
hf_collectd_data_time,
offset,
&vdispatch.time_off,
- &vdispatch.time,
+ &vdispatch.time_value,
collectd_tree, &pi);
if (status != 0)
pkt_errors++;
proto_item_set_text (pi,
"collectd SEVERITY segment: "
"%s (%"G_GINT64_MODIFIER"u)",
- val_to_str_const ((gint32)ndispatch.severity, severity_names, "UNKNOWN"),
+ val64_to_str_const (ndispatch.severity, severity_names, "UNKNOWN"),
ndispatch.severity);
}
default:
{
pkt_unknown++;
- pi = proto_tree_add_text (collectd_tree, tvb,
- offset, part_length,
+ pt = proto_tree_add_subtree_format(collectd_tree, tvb,
+ offset, part_length, ett_collectd_unknown, NULL,
"collectd %s segment: %i bytes",
val_to_str_const(part_type, part_names, "UNKNOWN"),
part_length);
- pt = proto_item_add_subtree(pi, ett_collectd_unknown);
pi = proto_tree_add_uint (pt, hf_collectd_type, tvb,
offset, 2, part_type);
proto_tree_add_uint (pt, hf_collectd_length, tvb,
proto_tree_add_item (pt, hf_collectd_data, tvb,
offset + 4, part_length - 4, ENC_NA);
- expert_add_info_format (pinfo, pi,
- PI_UNDECODED, PI_NOTE,
+ expert_add_info_format(pinfo, pi, &ei_collectd_type,
"Unknown part type %#x. Cannot decode data.",
part_type);
}
/* Dispatch tap data. */
tap_queue_packet (tap_collectd, pinfo, &tap_data);
+ return tvb_captured_length(tvb);
} /* void dissect_collectd */
void proto_register_collectd(void)
{
- module_t *collectd_module;
+ expert_module_t* expert_collectd;
/* Setup list of header fields */
static hf_register_info hf[] = {
NULL, 0x0, NULL, HFILL }
},
{ &hf_collectd_data_severity,
- { "Severity", "collectd.data.severity", FT_UINT64, BASE_HEX,
- VALS(severity_names),
+ { "Severity", "collectd.data.severity", FT_UINT64, BASE_HEX | BASE_VAL64_STRING,
+ VALS64(severity_names),
0x0, NULL, HFILL }
},
{ &hf_collectd_data_message,
&ett_collectd_unknown,
};
+ static ei_register_info ei[] = {
+ { &ei_collectd_invalid_length, { "collectd.invalid_length", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
+ { &ei_collectd_garbage, { "collectd.garbage", PI_MALFORMED, PI_ERROR, "Garbage at end of packet", EXPFILL }},
+ { &ei_collectd_data_valcnt, { "collectd.data.valcnt.mismatch", PI_MALFORMED, PI_WARN, "Number of values and length of part do not match. Assuming length is correct.", EXPFILL }},
+ { &ei_collectd_type, { "collectd.type.unknown", PI_UNDECODED, PI_NOTE, "Unknown part type", EXPFILL }},
+ };
+
/* Register the protocol name and description */
- proto_collectd = proto_register_protocol("collectd network data",
- "collectd", "collectd");
+ proto_collectd = proto_register_protocol("collectd network data", "collectd", "collectd");
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_collectd, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+ expert_collectd = expert_register_protocol(proto_collectd);
+ expert_register_field_array(expert_collectd, ei, array_length(ei));
tap_collectd = register_tap ("collectd");
-
- /*
- * Create an unsigned integer preference to allow the user to specify the
- * UDP port on which to capture DIS packets.
- */
- collectd_module = prefs_register_protocol (proto_collectd,
- proto_reg_handoff_collectd);
-
- prefs_register_uint_preference (collectd_module, "udp.port",
- "collectd UDP port",
- "Set the UDP port for collectd messages",
- 10, &collectd_udp_port);
-} /* void proto_register_collectd */
+}
void proto_reg_handoff_collectd (void)
{
- static gboolean first_run = TRUE;
- static gint registered_udp_port = -1;
- static dissector_handle_t collectd_handle;
-
- if (first_run)
- collectd_handle = create_dissector_handle (dissect_collectd,
- proto_collectd);
-
- /* Change the dissector registration if the preferences have been
- * changed. */
- if (registered_udp_port != -1)
- dissector_delete_uint ("udp.port", registered_udp_port,
- collectd_handle);
-
- dissector_add_uint ("udp.port", collectd_udp_port, collectd_handle);
- registered_udp_port = collectd_udp_port;
+ dissector_handle_t collectd_handle;
- if (first_run)
- collectd_stats_tree_register ();
+ collectd_handle = create_dissector_handle(dissect_collectd, proto_collectd);
+ dissector_add_uint_with_preference("udp.port", UDP_PORT_COLLECTD, collectd_handle);
- first_run = FALSE;
+ collectd_stats_tree_register ();
} /* void proto_reg_handoff_collectd */
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */