*
* $Id$
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * 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
#include <glib.h>
#include <float.h>
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
#include "packet.h"
+#include "ptvcursor.h"
#include "strutil.h"
#include "addr_resolv.h"
+#include "oid_resolv.h"
#include "plugins.h"
-#include "ipv6-utils.h"
#include "proto.h"
#include "epan_dissect.h"
#include "slab.h"
#include "tvbuff.h"
+#include "emem.h"
+
+struct ptvcursor {
+ proto_tree *tree;
+ tvbuff_t *tvb;
+ gint offset;
+};
#define cVALS(x) (const value_string*)(x)
+#if 1
+#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
+ /* If this item is not referenced we dont have to do much work \
+ at all but we should still return a node so that \
+ field items below this node ( think proto_item_add_subtree() )\
+ will still have somewhere to attach to \
+ or else filtering will not work (they would be ignored since tree\
+ would be NULL). \
+ DONT try to fake a node where PITEM_FINFO(pi) is NULL \
+ since dissectors that want to do proto_item_set_len() ot \
+ other operations that dereference this would crash. \
+ We dont fake FT_PROTOCOL either since these are cheap and \
+ some stuff (proto hier stat) assumes they always exist. \
+ */ \
+ if(!(PTREE_DATA(tree)->visible)){ \
+ if(PITEM_FINFO(tree)){ \
+ register header_field_info *hfinfo; \
+ PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
+ if((hfinfo->ref_count == 0) \
+ && (hfinfo->type!=FT_PROTOCOL)){ \
+ /* just return tree back to the caller */\
+ return tree; \
+ } \
+ } \
+ }
+#else
+#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
+#endif
+
static gboolean
proto_tree_free_node(proto_node *node, gpointer data);
static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
int hfinfo_bitwidth(header_field_info *hfinfo);
-static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
-static char* hfinfo_uint_format(header_field_info *hfinfo);
-static char* hfinfo_uint64_format(header_field_info *hfinfo);
-static char* hfinfo_int_vals_format(header_field_info *hfinfo);
-static char* hfinfo_int_format(header_field_info *hfinfo);
-static char* hfinfo_int64_format(header_field_info *hfinfo);
+static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
+static const char* hfinfo_uint_format(header_field_info *hfinfo);
+static const char* hfinfo_uint64_format(header_field_info *hfinfo);
+static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
+static const char* hfinfo_int_format(header_field_info *hfinfo);
+static const char* hfinfo_int64_format(header_field_info *hfinfo);
static proto_item*
proto_tree_add_node(proto_tree *tree, field_info *fi);
+static header_field_info *
+get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
+ gint *item_length);
+
+static field_info *
+new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
+ gint start, gint item_length);
+
static field_info *
alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
gint start, gint *length);
proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
gint start, gint *length, field_info **pfi);
+static void
+proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
static void
proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
static void
proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
static void
+proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
+static void
+proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
+static void
+proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
+static void
+proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
+static void
proto_tree_set_boolean(field_info *fi, guint32 value);
static void
proto_tree_set_float(field_info *fi, float value);
/* Structure for information about a protocol */
struct _protocol {
- char *name; /* long description */
- char *short_name; /* short description */
- char *filter_name; /* name of this protocol in filters */
- int proto_id; /* field ID for this protocol */
- GList *fields; /* fields for this protocol */
- GList *last_field; /* pointer to end of list of fields */
- gboolean is_enabled; /* TRUE if protocol is enabled */
- gboolean can_toggle; /* TRUE if is_enabled can be changed */
+ const char *name; /* long description */
+ const char *short_name; /* short description */
+ const char *filter_name; /* name of this protocol in filters */
+ int proto_id; /* field ID for this protocol */
+ GList *fields; /* fields for this protocol */
+ GList *last_field; /* pointer to end of list of fields */
+ gboolean is_enabled; /* TRUE if protocol is enabled */
+ gboolean can_toggle; /* TRUE if is_enabled can be changed */
};
/* List of all protocols */
-static GList *protocols;
+static GList *protocols = NULL;
#define INITIAL_NUM_PROTOCOL_HFINFO 200
SLAB_FREE(il, item_label_t)
+#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
+ DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
+ hfinfo=gpa_hfinfo.hfi[hfindex];
+
/* List which stores protocols and fields that have been registered */
typedef struct _gpa_hfinfo_t {
/* Number of elements in that array. */
int num_tree_types;
+/* Name hashtables for fast detection of duplicate names */
+static GHashTable* proto_names = NULL;
+static GHashTable* proto_short_names = NULL;
+static GHashTable* proto_filter_names = NULL;
+
+static gint
+proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
+{
+ const protocol_t *p1 = p1_arg;
+ const protocol_t *p2 = p2_arg;
+
+ return g_strcasecmp(p1->short_name, p2->short_name);
+}
+
+
/* initialize data structures and register protocols and fields */
void
proto_init(const char *plugin_dir
NULL, HFILL }},
};
+
+ proto_names = g_hash_table_new(g_int_hash, g_int_equal);
+ proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
+ proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
+
proto_cleanup();
gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
ftypes_initialize();
/* Register one special-case FT_TEXT_ONLY field for use when
- converting ethereal to new-style proto_tree. These fields
+ converting wireshark to new-style proto_tree. These fields
are merely strings on the GUI tree; they are not filterable */
proto_register_field_array(-1, hf, array_length(hf));
register_all_plugin_handoffs();
#endif
+ /* sort the protocols by protocol name */
+ protocols = g_list_sort(protocols, proto_compare_name);
+
/* We've assigned all the subtree type values; allocate the array
for them, and zero it out. */
- tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
- memset(tree_is_expanded, 0, num_tree_types*sizeof (gint *));
+ tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
+ memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
}
/* String comparison func for dfilter_token GTree */
free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
{
GPtrArray *ptrs = value;
+ gint hfid = (gint)key;
+ header_field_info *hfinfo;
+
+
+ PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
+ if(hfinfo->ref_count){
+ /* when a field is referenced by a filter this also
+ affects the refcount for the parent protocol so we need
+ to adjust the refcount for the parent as well
+ */
+ if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
+ header_field_info *parent_hfinfo;
+ PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
+ parent_hfinfo->ref_count -= hfinfo->ref_count;
+ }
+ hfinfo->ref_count = 0;
+ }
g_ptr_array_free(ptrs, TRUE);
}
/* Is the parsing being done for a visible proto_tree or an invisible one?
* By setting this correctly, the proto_tree creation is sped up by not
- * having to call vsnprintf and copy strings around.
+ * having to call g_vsnprintf and copy strings around.
*/
void
proto_tree_set_visible(proto_tree *tree, gboolean visible)
PTREE_DATA(tree)->visible = visible;
}
-#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
- g_assert((guint)hfindex < gpa_hfinfo.len); \
- hfinfo=gpa_hfinfo.hfi[hfindex];
+/* Assume dissector set only its protocol fields.
+ This function is called by dissectors and allowes to speed up filtering
+ in wireshark, if this function returns FALSE it is safe to reset tree to NULL
+ and thus skip calling most of the expensive proto_tree_add_...()
+ functions.
+ If the tree is visible we implicitely assume the field is referenced.
+*/
+gboolean
+proto_field_is_referenced(proto_tree *tree, int proto_id)
+{
+ register header_field_info *hfinfo;
+
+
+ if (!tree)
+ return FALSE;
+
+ if (PTREE_DATA(tree)->visible)
+ return TRUE;
+
+ PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
+ if (hfinfo->ref_count != 0)
+ return TRUE;
+
+ return FALSE;
+}
+
/* Finds a record in the hf_info_records array by id. */
header_field_info*
/* Finds a record in the hf_info_records array by name.
*/
header_field_info*
-proto_registrar_get_byname(char *field_name)
+proto_registrar_get_byname(const char *field_name)
{
- g_assert(field_name != NULL);
+ DISSECTOR_ASSERT(field_name != NULL);
return g_tree_lookup(gpa_name_tree, field_name);
}
+/* Allocates an initializes a ptvcursor_t with 3 variables:
+ * proto_tree, tvbuff, and offset. */
+ptvcursor_t*
+ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ ptvcursor_t *ptvc;
+
+ ptvc = g_new(ptvcursor_t, 1);
+ ptvc->tree = tree;
+ ptvc->tvb = tvb;
+ ptvc->offset = offset;
+ return ptvc;
+}
+
+/* Frees memory for ptvcursor_t, but nothing deeper than that. */
+void
+ptvcursor_free(ptvcursor_t *ptvc)
+{
+ g_free(ptvc);
+}
+
+/* Returns tvbuff. */
+tvbuff_t*
+ptvcursor_tvbuff(ptvcursor_t* ptvc)
+{
+ return ptvc->tvb;
+}
+
+/* Returns current offset. */
+gint
+ptvcursor_current_offset(ptvcursor_t* ptvc)
+{
+ return ptvc->offset;
+}
+
+proto_tree*
+ptvcursor_tree(ptvcursor_t* ptvc)
+{
+ return ptvc->tree;
+}
+
+void
+ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
+{
+ ptvc->tree = tree;
+}
+
/* Add a text-only node, leaving it to our caller to fill the text in */
static proto_item *
proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
break;
default:
- g_assert_not_reached();
+ THROW(ReportedBoundsError);
value = 0;
break;
}
break;
default:
- g_assert_not_reached();
+ THROW(ReportedBoundsError);
value = 0;
break;
}
/* Add an item to a proto_tree, using the text label registered to that item;
the item is extracted from the tvbuff handed to it. */
-proto_item *
-proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
- gint start, gint length, gboolean little_endian)
+static proto_item *
+proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
+ tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
{
- field_info *new_fi;
proto_item *pi;
guint32 value, n;
float floatval;
GHashTable *hash;
GPtrArray *ptrs;
- if (!tree)
- return(NULL);
-
- new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
-
- if (new_fi == NULL)
- return(NULL);
-
/* there is a possibility here that we might raise an exception
* and thus would lose track of the field_info.
* store it in a temp so that if we come here again we can reclaim
case FT_INT64:
case FT_UINT64:
- g_assert(length == 8);
+ DISSECTOR_ASSERT(length == 8);
proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
break;
break;
case FT_IPv4:
- g_assert(length == 4);
- tvb_memcpy(tvb, (guint8 *)&value, start, 4);
+ DISSECTOR_ASSERT(length == 4);
+ value = tvb_get_ipv4(tvb, start);
proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
break;
case FT_IPXNET:
- g_assert(length == 4);
+ DISSECTOR_ASSERT(length == 4);
proto_tree_set_ipxnet(new_fi,
get_uint_value(tvb, start, 4, FALSE));
break;
case FT_IPv6:
- g_assert(length == 16);
+ DISSECTOR_ASSERT(length == 16);
proto_tree_set_ipv6_tvb(new_fi, tvb, start);
break;
case FT_ETHER:
- g_assert(length == 6);
+ DISSECTOR_ASSERT(length == 6);
proto_tree_set_ether_tvb(new_fi, tvb, start);
break;
+ case FT_GUID:
+ DISSECTOR_ASSERT(length == 16);
+ proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
+ break;
+
+ case FT_OID:
+ proto_tree_set_oid_tvb(new_fi, tvb, start, length);
+ break;
+
case FT_FLOAT:
- g_assert(length == 4);
+ DISSECTOR_ASSERT(length == 4);
if (little_endian)
floatval = tvb_get_letohieee_float(tvb, start);
else
break;
case FT_DOUBLE:
- g_assert(length == 8);
+ DISSECTOR_ASSERT(length == 8);
if (little_endian)
doubleval = tvb_get_letohieee_double(tvb, start);
else
break;
case FT_STRINGZ:
- if (length != 0) { /* XXX - Should we throw an exception instead? */
- /* Instead of calling proto_item_set_len(),
- * since we don't yet have a proto_item, we
- * set the field_info's length ourselves.
+ DISSECTOR_ASSERT(length >= -1);
+ /* Instead of calling proto_item_set_len(),
+ * since we don't yet have a proto_item, we
+ * set the field_info's length ourselves.
+ *
+ * XXX - our caller can't use that length to
+ * advance an offset unless they arrange that
+ * there always be a protocol tree into which
+ * we're putting this item.
+ */
+ if (length == -1) {
+ /* This can throw an exception */
+ length = tvb_strsize(tvb, start);
+
+ /* This g_malloc'ed memory is freed
+ in proto_tree_free_node() */
+ string = g_malloc(length);
+
+ tvb_memcpy(tvb, string, start, length);
+ } else if (length == 0) {
+ string = g_strdup("[Empty]");
+ } else {
+ /* In this case, length signifies
+ * the length of the string.
+ *
+ * This could either be a null-padded
+ * string, which doesn't necessarily
+ * have a '\0' at the end, or a
+ * null-terminated string, with a
+ * trailing '\0'. (Yes, there are
+ * cases where you have a string
+ * that's both counted and null-
+ * terminated.)
+ *
+ * In the first case, we must
+ * allocate a buffer of length
+ * "length+1", to make room for
+ * a trailing '\0'.
*
- * XXX - our caller can't use that length to
- * advance an offset unless they arrange that
- * there always be a protocol tree into which
- * we're putting this item.
+ * In the second case, we don't
+ * assume that there is a trailing
+ * '\0' there, as the packet might
+ * be malformed. (XXX - should we
+ * throw an exception if there's no
+ * trailing '\0'?) Therefore, we
+ * allocate a buffer of length
+ * "length+1", and put in a trailing
+ * '\0', just to be safe.
+ *
+ * (XXX - this would change if
+ * we made string values counted
+ * rather than null-terminated.)
*/
- if (length == -1) {
- /* This can throw an exception */
- length = tvb_strsize(tvb, start);
-
- /* This g_malloc'ed memory is freed
- in proto_tree_free_node() */
- string = g_malloc(length);
- tvb_memcpy(tvb, string, start, length);
- new_fi->length = length;
- }
- else {
- /* In this case, length signifies
- * the length of the string.
- *
- * This could either be a null-padded
- * string, which doesn't necessarily
- * have a '\0' at the end, or a
- * null-terminated string, with a
- * trailing '\0'. (Yes, there are
- * cases where you have a string
- * that's both counted and null-
- * terminated.)
- *
- * In the first case, we must
- * allocate a buffer of length
- * "length+1", to make room for
- * a trailing '\0'.
- *
- * In the second case, we don't
- * assume that there is a trailing
- * '\0' there, as the packet might
- * be malformed. (XXX - should we
- * throw an exception if there's no
- * trailing '\0'?) Therefore, we
- * allocate a buffer of length
- * "length+1", and put in a trailing
- * '\0', just to be safe.
- *
- * (XXX - this would change if
- * we made string values counted
- * rather than null-terminated.)
- */
-
- /* This g_malloc'ed memory is freed
- * in proto_tree_free_node() */
- string = tvb_get_string(tvb, start,
- length);
- new_fi->length = length;
- }
- proto_tree_set_string(new_fi, string, TRUE);
+ /* This g_malloc'ed memory is freed
+ * in proto_tree_free_node() */
+ string = tvb_get_string(tvb, start,
+ length);
}
+ new_fi->length = length;
+ proto_tree_set_string(new_fi, string, TRUE);
break;
case FT_UINT_STRING:
g_error("new_fi->hfinfo->type %d (%s) not handled\n",
new_fi->hfinfo->type,
ftype_name(new_fi->hfinfo->type));
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
break;
}
/* If the proto_tree wants to keep a record of this finfo
* for quick lookup, then record it. */
- hash = PTREE_DATA(tree)->interesting_hfids;
- ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
- if (ptrs) {
- g_ptr_array_add(ptrs, new_fi);
+ if (new_fi->hfinfo->ref_count) {
+ /*HERE*/
+ hash = PTREE_DATA(tree)->interesting_hfids;
+ ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
+ if (ptrs) {
+ g_ptr_array_add(ptrs, new_fi);
+ }
}
return pi;
}
+/* Gets data from tvbuff, adds it to proto_tree, increments offset,
+ and returns proto_item* */
+proto_item*
+ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
+ gboolean little_endian)
+{
+ field_info *new_fi;
+ header_field_info *hfinfo;
+ gint item_length;
+ guint32 n;
+ int offset;
+
+ offset = ptvc->offset;
+ hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
+ &item_length);
+ ptvc->offset += length;
+ if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
+ /*
+ * The length of the rest of the item is in the first N
+ * bytes of the item.
+ */
+ n = get_uint_value(ptvc->tvb, offset, length, little_endian);
+ ptvc->offset += n;
+ }
+ if (ptvc->tree == NULL)
+ return NULL;
+
+ TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
+
+ new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
+ item_length);
+ if (new_fi == NULL)
+ return NULL;
+
+ return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
+ offset, length, little_endian);
+}
+
+/* Add an item to a proto_tree, using the text label registered to that item;
+ the item is extracted from the tvbuff handed to it. */
+proto_item *
+proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, gboolean little_endian)
+{
+ field_info *new_fi;
+
+ if (!tree)
+ return(NULL);
+
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
+ new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
+
+ if (new_fi == NULL)
+ return(NULL);
+
+ return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
+ length, little_endian);
+}
+
proto_item *
proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
gint start, gint length, gboolean little_endian)
return (NULL);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_NONE);
+ DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
return pi;
}
+/* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
+ * offset, and returns proto_item* */
+proto_item*
+ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
+ gboolean endianness)
+{
+ proto_item *item;
+
+ item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
+ length, endianness);
+
+ return item;
+}
+
+/* Advance the ptvcursor's offset within its tvbuff without
+ * adding anything to the proto_tree. */
+void
+ptvcursor_advance(ptvcursor_t* ptvc, gint length)
+{
+ ptvc->offset += length;
+}
+
static void
proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
return (NULL);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_PROTOCOL);
+ DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_BYTES);
+ DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_bytes(new_fi, start_ptr, length);
return pi;
}
+proto_item *
+proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, const guint8 *start_ptr,
+ const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
gint length, const guint8 *start_ptr, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_ABSOLUTE_TIME ||
+ DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
hfinfo->type == FT_RELATIVE_TIME);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
return pi;
}
+proto_item *
+proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, nstime_t *value_ptr,
+ const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
nstime_t *value_ptr, const char *format, ...)
static void
proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
{
+ DISSECTOR_ASSERT(value_ptr != NULL);
fvalue_set(&fi->value, value_ptr, FALSE);
}
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_IPXNET);
+ DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_ipxnet(new_fi, value);
return pi;
}
+proto_item *
+proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, guint32 value, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
guint32 value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_IPv4);
+ DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_ipv4(new_fi, value);
return pi;
}
+proto_item *
+proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, guint32 value, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
guint32 value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_IPv6);
+ DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_ipv6(new_fi, value_ptr);
return pi;
}
+proto_item *
+proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, const guint8* value_ptr,
+ const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
const guint8* value_ptr, const char *format, ...)
static void
proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
{
+ DISSECTOR_ASSERT(value_ptr != NULL);
fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
}
proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
}
-static void
-proto_tree_set_uint64(field_info *fi, guint64 value)
-{
- fvalue_set_integer64(&fi->value, value);
-}
-
-static void
-proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
-{
- guint64 value;
-
- value = little_endian ? tvb_get_letoh64(tvb, start)
- : tvb_get_ntoh64(tvb, start);
-
- proto_tree_set_uint64(fi, value);
-}
-
-/* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
- * and frees it when the proto_tree is destroyed. */
+/* Add a FT_GUID to a proto_tree */
proto_item *
-proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
- gint length, const char* value)
+proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
+ const e_guid_t *value_ptr)
{
proto_item *pi;
field_info *new_fi;
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
+ DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
- g_assert(length >= 0);
+ proto_tree_set_guid(new_fi, value_ptr);
+
+ return pi;
+}
+
+proto_item *
+proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
+ const e_guid_t *value_ptr)
+{
+ proto_item *pi;
+
+ pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ PROTO_ITEM_SET_HIDDEN(pi);
+
+ return pi;
+}
+
+proto_item *
+proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, const e_guid_t *value_ptr,
+ const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
+proto_item *
+proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
+ const e_guid_t *value_ptr, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
+/* Set the FT_GUID value */
+static void
+proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
+{
+ DISSECTOR_ASSERT(value_ptr != NULL);
+ fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
+}
+
+static void
+proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
+{
+ e_guid_t guid;
+
+ tvb_get_guid(tvb, start, &guid, little_endian);
+ proto_tree_set_guid(fi, &guid);
+}
+
+/* Add a FT_OID to a proto_tree */
+proto_item *
+proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
+ const guint8* value_ptr)
+{
+ proto_item *pi;
+ field_info *new_fi;
+ header_field_info *hfinfo;
+
+ if (!tree)
+ return (NULL);
+
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
+ PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+ DISSECTOR_ASSERT(hfinfo->type == FT_OID);
+
+ pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
+ proto_tree_set_oid(new_fi, value_ptr, length);
+
+ return pi;
+}
+
+proto_item *
+proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
+ const guint8* value_ptr)
+{
+ proto_item *pi;
+
+ pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ PROTO_ITEM_SET_HIDDEN(pi);
+
+ return pi;
+}
+
+proto_item *
+proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, const guint8* value_ptr,
+ const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
+proto_item *
+proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
+ const guint8* value_ptr, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
+/* Set the FT_OID value */
+static void
+proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
+{
+ GByteArray *bytes;
+
+ DISSECTOR_ASSERT(value_ptr != NULL);
+
+ bytes = g_byte_array_new();
+ if (length > 0) {
+ g_byte_array_append(bytes, value_ptr, length);
+ }
+ fvalue_set(&fi->value, bytes, TRUE);
+}
+
+static void
+proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
+{
+ proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
+}
+
+static void
+proto_tree_set_uint64(field_info *fi, guint64 value)
+{
+ fvalue_set_integer64(&fi->value, value);
+}
+
+static void
+proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
+{
+ guint64 value;
+
+ value = little_endian ? tvb_get_letoh64(tvb, start)
+ : tvb_get_ntoh64(tvb, start);
+
+ proto_tree_set_uint64(fi, value);
+}
+
+/* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
+ * and frees it when the proto_tree is destroyed. */
+proto_item *
+proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
+ gint length, const char* value)
+{
+ proto_item *pi;
+ field_info *new_fi;
+ header_field_info *hfinfo;
+
+ if (!tree)
+ return (NULL);
+
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
+ PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+ DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
+
+ pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
+ DISSECTOR_ASSERT(length >= 0);
proto_tree_set_string(new_fi, value, FALSE);
return pi;
return pi;
}
+proto_item *
+proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, const char* value, const char *format,
+ ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
gint length, const char* value, const char *format, ...)
* field info update instead of only updating the representation as does
* proto_item_append_text()
*/
+/* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
+ * speed optimization.
+ * Currently only WSP use this function so it is not that bad but try to
+ * avoid using this one if possible.
+ * IF you must use this function you MUST also disable the
+ * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
+ * using proto_item_append_string().
+ * Do that by faking that the tree is visible by setting :
+ * PTREE_DATA(tree)->visible=1; (see packet-wsp.c)
+ * BEFORE you create the item you are later going to use
+ * proto_item_append_string() on.
+ */
void
proto_item_append_string(proto_item *pi, const char *str)
{
fi = PITEM_FINFO(pi);
hfinfo = fi->hfinfo;
- g_assert(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
+ if (hfinfo->type == FT_PROTOCOL) {
+ /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
+ return;
+ }
+ DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
old_str = fvalue_get(&fi->value);
- new_str = g_malloc(strlen(old_str) + strlen(str) + 1);
- sprintf(new_str, "%s%s", old_str, str);
+ new_str = g_strdup_printf("%s%s", old_str, str);
fvalue_set(&fi->value, new_str, TRUE);
}
proto_tree_set_string(field_info *fi, const char* value,
gboolean already_allocated)
{
- fvalue_set(&fi->value, (gpointer) value, already_allocated);
+ if (value)
+ fvalue_set(&fi->value, (gpointer) value, already_allocated);
+ else
+ fvalue_set(&fi->value, (gpointer) "[ Null ]", already_allocated);
}
static void
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_ETHER);
+ DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_ether(new_fi, value);
return pi;
}
+proto_item *
+proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, const guint8* value,
+ const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
const guint8* value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_BOOLEAN);
+ DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_boolean(new_fi, value);
return pi;
}
+proto_item *
+proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
+ tvbuff_t *tvb, gint start, gint length, guint32 value,
+ const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
guint32 value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_FLOAT);
+ DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_float(new_fi, value);
return pi;
}
+proto_item *
+proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, float value, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
float value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_DOUBLE);
+ DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_double(new_fi, value);
return pi;
}
+proto_item *
+proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, double value, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
double value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
switch(hfinfo->type) {
case FT_UINT8:
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
}
return pi;
return pi;
}
+proto_item *
+proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, guint32 value, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
guint32 value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_UINT64);
+ DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_uint64(new_fi, value);
return pi;
}
+proto_item *
+proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, guint64 value, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
guint64 value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
switch(hfinfo->type) {
case FT_INT8:
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
}
return pi;
return pi;
}
+proto_item *
+proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, gint32 value, const char *format, ...)
+{
+ proto_item *pi = NULL;
+ va_list ap;
+
+ pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
gint32 value, const char *format, ...)
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
- g_assert(hfinfo->type == FT_INT64);
+ DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
proto_tree_set_uint64(new_fi, (guint64)value);
return pi;
}
+proto_item *
+proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, gint64 value, const char *format, ...)
+{
+ proto_item *pi;
+ va_list ap;
+
+ pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
+ if (pi == NULL)
+ return (NULL);
+
+ va_start(ap, format);
+ proto_tree_set_representation_value(pi, format, ap);
+ va_end(ap);
+
+ return pi;
+}
+
proto_item *
proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
gint64 value, const char *format, ...)
return pi;
}
-
+/* Throw an exception if we exceed this many tree items. */
+/* XXX - This should probably be a preference */
+#define MAX_TREE_ITEMS (1 * 1000 * 1000)
/* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
static proto_item *
proto_tree_add_node(proto_tree *tree, field_info *fi)
*/
tnode = tree;
tfi = tnode->finfo;
- g_assert(tfi == NULL ||
+ if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
+ REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
+ fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
+ /* XXX - is it safe to continue here? */
+ }
+
+ DISSECTOR_ASSERT(tfi == NULL ||
(tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
+ PTREE_DATA(tree)->count++;
+ if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
+ /* Let the exception handler add items to the tree */
+ PTREE_DATA(tree)->count = 0;
+ THROW_MESSAGE(DissectorError,
+ ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
+ }
+
PROTO_NODE_NEW(pnode);
pnode->parent = tnode;
pnode->finfo = fi;
if (tnode->last_child != NULL) {
sibling = tnode->last_child;
- g_assert(sibling->next == NULL);
+ DISSECTOR_ASSERT(sibling->next == NULL);
sibling->next = pnode;
} else
tnode->first_child = pnode;
/* If the proto_tree wants to keep a record of this finfo
* for quick lookup, then record it. */
- hash = PTREE_DATA(tree)->interesting_hfids;
- ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
- if (ptrs) {
- g_ptr_array_add(ptrs, fi);
+ if (fi->hfinfo->ref_count) {
+ /*HERE*/
+ hash = PTREE_DATA(tree)->interesting_hfids;
+ ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
+ if (ptrs) {
+ g_ptr_array_add(ptrs, fi);
+ }
}
/* Does the caller want to know the fi pointer? */
return pi;
}
-static field_info *
-alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
- gint *length)
+
+static header_field_info *
+get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
+ gint *item_length)
{
header_field_info *hfinfo;
- field_info *fi;
+ gint length_remaining;
/*
* We only allow a null tvbuff if the item has a zero length,
* i.e. if there's no data backing it.
*/
- g_assert(tvb != NULL || *length == 0);
+ DISSECTOR_ASSERT(tvb != NULL || *length == 0);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+ /*
+ * XXX - in some protocols, there are 32-bit unsigned length
+ * fields, so lengths in protocol tree and tvbuff routines
+ * should really be unsigned. We should have, for those
+ * field types for which "to the end of the tvbuff" makes sense,
+ * additional routines that take no length argument and
+ * add fields that run to the end of the tvbuff.
+ */
if (*length == -1) {
/*
* For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
*/
tvb_ensure_bytes_exist(tvb, start, 0);
}
- g_assert(*length >= 0);
+ DISSECTOR_ASSERT(*length >= 0);
break;
case FT_NONE:
case FT_BYTES:
case FT_STRING:
*length = tvb_ensure_length_remaining(tvb, start);
- g_assert(*length >= 0);
+ DISSECTOR_ASSERT(*length >= 0);
break;
case FT_STRINGZ:
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
}
- } else
- g_assert(*length >= 0);
+ *item_length = *length;
+ } else {
+ *item_length = *length;
+ if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
+ /*
+ * These types are for interior nodes of the
+ * tree, and don't have data associated with
+ * them; if the length is negative (XXX - see
+ * above) or goes past the end of the tvbuff,
+ * cut it short at the end of the tvbuff.
+ * That way, if this field is selected in
+ * Wireshark, we don't highlight stuff past
+ * the end of the data.
+ */
+ /* XXX - what to do, if we don't have a tvb? */
+ if (tvb) {
+ length_remaining = tvb_length_remaining(tvb, start);
+ if (*item_length < 0 ||
+ (*item_length > 0 &&
+ (length_remaining < *item_length)))
+ *item_length = length_remaining;
+ }
+ }
+ if (*item_length < 0) {
+ THROW(ReportedBoundsError);
+ }
+ }
+
+ return hfinfo;
+}
+
+static field_info *
+new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
+ gint start, gint item_length)
+{
+ field_info *fi;
FIELD_INFO_NEW(fi);
fi->hfinfo = hfinfo;
fi->start = start;
fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
- fi->length = *length;
+ fi->length = item_length;
fi->tree_type = -1;
fi->flags = 0;
if (!PTREE_DATA(tree)->visible)
return fi;
}
-/* Set representation of a proto_tree entry, if the protocol tree is to
- be visible. */
+static field_info *
+alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
+ gint *length)
+{
+ header_field_info *hfinfo;
+ gint item_length;
+
+ hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
+ return new_field_info(tree, hfinfo, tvb, start, item_length);
+}
+
+/* If the protocol tree is to be visible, set the representation of a
+ proto_tree entry with the name of the field for the item and with
+ the value formatted with the supplied printf-style format and
+ argument list. */
+static void
+proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
+{
+ int ret; /*tmp return value */
+ int replen;
+ field_info *fi = PITEM_FINFO(pi);
+
+ if (!PROTO_ITEM_IS_HIDDEN(pi)) {
+ ITEM_LABEL_NEW(fi->rep);
+ replen = 0;
+ ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
+ "%s: ", fi->hfinfo->name);
+ if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
+ /* That's all we can put in the representation. */
+ fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
+ return;
+ }
+ replen = ret;
+ ret = g_vsnprintf(fi->rep->representation + replen,
+ ITEM_LABEL_LENGTH - replen, format, ap);
+ if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen))
+ fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
+ }
+}
+
+/* If the protocol tree is to be visible, set the representation of a
+ proto_tree entry with the representation formatted with the supplied
+ printf-style format and argument list. */
static void
proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
{
if (!PROTO_ITEM_IS_HIDDEN(pi)) {
ITEM_LABEL_NEW(fi->rep);
- ret = vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
+ ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
}
fi = PITEM_FINFO(pi);
- if (!PROTO_ITEM_IS_HIDDEN(pi)) {
+ if (!PROTO_ITEM_IS_HIDDEN(pi)) {
va_start(ap, format);
/*
curlen = strlen(fi->rep->representation);
if (ITEM_LABEL_LENGTH > curlen) {
- ret = vsnprintf(fi->rep->representation + curlen,
+ ret = g_vsnprintf(fi->rep->representation + curlen,
ITEM_LABEL_LENGTH - curlen, format, ap);
if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
if (pi == NULL)
return;
fi = PITEM_FINFO(pi);
- g_assert(length >= 0);
+ DISSECTOR_ASSERT(length >= 0);
fi->length = length;
}
return;
fi = PITEM_FINFO(pi);
end += TVB_RAW_OFFSET(tvb);
- g_assert(end >= fi->start);
+ DISSECTOR_ASSERT(end >= fi->start);
fi->length = end - fi->start;
}
return fi->length;
}
+
+/** clear flags according to the mask and set new flag values */
+#define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
+ (fi->flags = (fi)->flags & ~(mask)); \
+ (fi->flags = (fi)->flags | (flags_in)); \
+}
+
+gboolean
+proto_item_set_expert_flags(proto_item *pi, int group, int severity)
+{
+ if(pi == NULL || pi->finfo == NULL)
+ return FALSE;
+
+ /* only change things if severity is worse or at least equal than before */
+ if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
+ FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
+ FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
proto_tree*
proto_tree_create_root(void)
{
* changed, then we'll find out very quickly. */
pnode->tree_data->visible = FALSE;
+ /* Keep track of the number of children */
+ pnode->tree_data->count = 0;
+
return (proto_tree*) pnode;
}
void
proto_tree_prime_hfid(proto_tree *tree, gint hfid)
{
+ header_field_info *hfinfo;
+
g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
GINT_TO_POINTER(hfid), g_ptr_array_new());
-}
+ PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
+ /* this field is referenced by a filter so increase the refcount.
+ also increase the refcount for the parent, i.e the protocol.
+ */
+ hfinfo->ref_count++;
+ /* only increase the refcount if there is a parent.
+ if this is a protocol and not a field then parent will be -1
+ and there is no parent to add any refcounting for.
+ */
+ if (hfinfo->parent != -1) {
+ header_field_info *parent_hfinfo;
+ PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
+ parent_hfinfo->ref_count++;
+ }
+}
proto_tree*
proto_item_add_subtree(proto_item *pi, gint idx) {
return(NULL);
fi = PITEM_FINFO(pi);
- g_assert(idx >= 0 && idx < num_tree_types);
+ DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
fi->tree_type = idx;
+
return (proto_tree*) pi;
}
if (!pi)
return(NULL);
fi = PITEM_FINFO(pi);
- if (fi->tree_type == -1)
+ if ( (!fi) || (fi->tree_type == -1) )
return(NULL);
return (proto_tree*) pi;
}
proto_item*
proto_item_get_parent(proto_item *ti) {
- if (!ti)
+ /* dont bother if tree is not visible */
+ if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
return (NULL);
return ti->parent;
}
proto_item*
proto_item_get_parent_nth(proto_item *ti, int gen) {
- if (!ti)
+ /* dont bother if tree is not visible */
+ if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
return (NULL);
while (gen--) {
ti = ti->parent;
}
-proto_item*
+proto_item*
proto_tree_get_parent(proto_tree *tree) {
- if (!tree)
+ /* dont bother if tree is not visible */
+ if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
return (NULL);
return (proto_item*) tree;
}
-static gint
-proto_match_short_name(gconstpointer p_arg, gconstpointer name_arg)
-{
- const protocol_t *p = p_arg;
- const char *name = name_arg;
-
- return g_strcasecmp(p->short_name, name);
+proto_tree*
+proto_tree_get_root(proto_tree *tree) {
+ /* dont bother if tree is not visible */
+ if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
+ return (NULL);
+ while (tree->parent) {
+ tree = tree->parent;
+ }
+ return tree;
}
-static gint
-proto_match_name(gconstpointer p_arg, gconstpointer name_arg)
+void
+proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
{
- const protocol_t *p = p_arg;
- const char *name = name_arg;
+ proto_item *curr_item;
- return g_strcasecmp(p->name, name);
-}
-static gint
-proto_match_filter_name(gconstpointer p_arg, gconstpointer name_arg)
-{
- const protocol_t *p = p_arg;
- const char *name = name_arg;
+ /*** cut item_to_move out ***/
- return g_strcasecmp(p->filter_name, name);
-}
+ /* is item_to_move the first? */
+ if(tree->first_child == item_to_move) {
+ /* simply change first child to next */
+ tree->first_child = item_to_move->next;
+ } else {
+ /* find previous and change it's next */
+ for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
+ if(curr_item->next == item_to_move) {
+ break;
+ }
+ }
-static gint
-proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
-{
- const protocol_t *p1 = p1_arg;
- const protocol_t *p2 = p2_arg;
+ DISSECTOR_ASSERT(curr_item);
- return g_strcasecmp(p1->short_name, p2->short_name);
+ curr_item->next = item_to_move->next;
+
+ /* fix last_child if required */
+ if(tree->last_child == item_to_move) {
+ tree->last_child = curr_item;
+ }
+ }
+
+ /*** insert to_move after fixed ***/
+ item_to_move->next = fixed_item->next;
+ fixed_item->next = item_to_move;
+ if(tree->last_child == fixed_item) {
+ tree->last_child = item_to_move;
+ }
}
-int
-proto_register_protocol(char *name, char *short_name, char *filter_name)
-{
- protocol_t *protocol;
- header_field_info *hfinfo;
- int proto_id;
- /*
- * Make sure there's not already a protocol with any of those
- * names. Crash if there is, as that's an error in the code,
- * and the code has to be fixed not to register more than one
- * protocol with the same name.
- */
- g_assert(g_list_find_custom(protocols, name, proto_match_name) == NULL);
- g_assert(g_list_find_custom(protocols, short_name, proto_match_short_name) == NULL);
- g_assert(g_list_find_custom(protocols, filter_name, proto_match_filter_name) == NULL);
-
- /* Add this protocol to the list of known protocols; the list
- is sorted by protocol short name. */
- protocol = g_malloc(sizeof (protocol_t));
- protocol->name = name;
- protocol->short_name = short_name;
- protocol->filter_name = filter_name;
- protocol->fields = NULL;
- protocol->is_enabled = TRUE; /* protocol is enabled by default */
- protocol->can_toggle = TRUE;
- protocols = g_list_insert_sorted(protocols, protocol,
- proto_compare_name);
-
- /* Here we do allocate a new header_field_info struct */
- hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
- hfinfo->name = name;
- hfinfo->abbrev = filter_name;
- hfinfo->type = FT_PROTOCOL;
- hfinfo->strings = NULL;
- hfinfo->bitmask = 0;
- hfinfo->bitshift = 0;
- hfinfo->blurb = "";
- hfinfo->parent = -1; /* this field differentiates protos and fields */
-
- proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
- protocol->proto_id = proto_id;
- return proto_id;
+int
+proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
+{
+ protocol_t *protocol;
+ header_field_info *hfinfo;
+ int proto_id;
+ char *existing_name;
+ gint *key;
+ guint i;
+ guchar c;
+ gboolean found_invalid;
+
+ /*
+ * Make sure there's not already a protocol with any of those
+ * names. Crash if there is, as that's an error in the code
+ * or an inappropriate plugin.
+ * This situation has to be fixed to not register more than one
+ * protocol with the same name.
+ *
+ * This is done by reducing the number of strcmp (and alike) calls as much as possible,
+ * as this significally slows down startup time.
+ *
+ * Drawback: As a hash value is used to reduce insert time,
+ * this might lead to a hash collision.
+ * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
+ * very unlikely.
+ */
+
+ key = g_malloc (sizeof(gint));
+ *key = g_str_hash(name);
+ existing_name = g_hash_table_lookup(proto_names, key);
+ if (existing_name != NULL) {
+ /* g_error will terminate the program */
+ g_error("Duplicate protocol name \"%s\"!"
+ " This might be caused by an inappropriate plugin or a development error.", name);
+ }
+ g_hash_table_insert(proto_names, key, (gpointer)name);
+
+ key = g_malloc (sizeof(gint));
+ *key = g_str_hash(short_name);
+ existing_name = g_hash_table_lookup(proto_short_names, key);
+ if (existing_name != NULL) {
+ g_error("Duplicate protocol short_name \"%s\"!"
+ " This might be caused by an inappropriate plugin or a development error.", short_name);
+ }
+ g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
+
+ found_invalid = FALSE;
+ for (i = 0; i < strlen(filter_name); i++) {
+ c = filter_name[i];
+ if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
+ found_invalid = TRUE;
+ }
+ }
+ if (found_invalid) {
+ g_error("Protocol filter name \"%s\" has one or more invalid characters."
+ " Allowed are lower characters, digits, '-', '_' and '.'."
+ " This might be caused by an inappropriate plugin or a development error.", filter_name);
+ }
+ key = g_malloc (sizeof(gint));
+ *key = g_str_hash(filter_name);
+ existing_name = g_hash_table_lookup(proto_filter_names, key);
+ if (existing_name != NULL) {
+ g_error("Duplicate protocol filter_name \"%s\"!"
+ " This might be caused by an inappropriate plugin or a development error.", filter_name);
+ }
+ g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
+
+ /* Add this protocol to the list of known protocols; the list
+ is sorted by protocol short name. */
+ protocol = g_malloc(sizeof (protocol_t));
+ protocol->name = name;
+ protocol->short_name = short_name;
+ protocol->filter_name = filter_name;
+ protocol->fields = NULL;
+ protocol->is_enabled = TRUE; /* protocol is enabled by default */
+ protocol->can_toggle = TRUE;
+ /* list will be sorted later by name, when all protocols completed registering */
+ protocols = g_list_append(protocols, protocol);
+
+ /* Here we do allocate a new header_field_info struct */
+ hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
+ hfinfo->name = name;
+ hfinfo->abbrev = filter_name;
+ hfinfo->type = FT_PROTOCOL;
+ hfinfo->strings = protocol;
+ hfinfo->bitmask = 0;
+ hfinfo->bitshift = 0;
+ hfinfo->ref_count = 0;
+ hfinfo->blurb = NULL;
+ hfinfo->parent = -1; /* this field differentiates protos and fields */
+
+ proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
+ protocol->proto_id = proto_id;
+ return proto_id;
}
/*
return &ptr->hfinfo;
}
-/*
- * Find the protocol list entry for a protocol given its field ID.
- */
-static gint
-compare_proto_id(gconstpointer proto_arg, gconstpointer id_arg)
-{
- const protocol_t *protocol = proto_arg;
- const int *id_ptr = id_arg;
-
- return (protocol->proto_id == *id_ptr) ? 0 : 1;
-}
-
protocol_t *
find_protocol_by_id(int proto_id)
{
- GList *list_entry;
+ header_field_info *hfinfo;
- list_entry = g_list_find_custom(protocols, &proto_id, compare_proto_id);
- if (list_entry == NULL)
+ if(proto_id<0)
return NULL;
- return list_entry->data;
+
+ PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
+ DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
+ return (protocol_t *)hfinfo->strings;
}
static gint compare_filter_name(gconstpointer proto_arg,
return protocol->proto_id;
}
-int proto_get_id_by_filter_name(gchar* filter_name)
+int proto_get_id_by_filter_name(const gchar* filter_name)
{
GList *list_entry;
protocol_t *protocol;
return protocol->proto_id;
}
-char *
+const char *
proto_get_protocol_name(int proto_id)
{
protocol_t *protocol;
return protocol->name;
}
-char *
+const char *
proto_get_protocol_short_name(protocol_t *protocol)
{
if (protocol == NULL)
return protocol->short_name;
}
-char *
+const char *
proto_get_protocol_filter_name(int proto_id)
{
protocol_t *protocol;
protocol_t *protocol;
protocol = find_protocol_by_id(proto_id);
- g_assert(protocol->can_toggle);
+ DISSECTOR_ASSERT(protocol->can_toggle);
protocol->is_enabled = enabled;
}
* 0 (which is unlikely to be the field ID we get back
* from "proto_register_field_init()").
*/
- g_assert(*ptr->p_id == -1 || *ptr->p_id == 0);
+ if (*ptr->p_id != -1 && *ptr->p_id != 0) {
+ fprintf(stderr,
+ "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
+ ptr->hfinfo.abbrev);
+ return;
+ }
if (proto != NULL) {
if (proto->fields == NULL) {
proto_register_field_init(header_field_info *hfinfo, int parent)
{
/* The field must have names */
- g_assert(hfinfo->name);
- g_assert(hfinfo->abbrev);
+ DISSECTOR_ASSERT(hfinfo->name);
+ DISSECTOR_ASSERT(hfinfo->abbrev);
- /* These types of fields are allowed to have value_strings or true_false_strings */
- g_assert((hfinfo->strings == NULL) || (
+ /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
+ DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
(hfinfo->type == FT_UINT8) ||
(hfinfo->type == FT_UINT16) ||
(hfinfo->type == FT_UINT24) ||
(hfinfo->type == FT_INT24) ||
(hfinfo->type == FT_INT32) ||
(hfinfo->type == FT_BOOLEAN) ||
+ (hfinfo->type == FT_PROTOCOL) ||
(hfinfo->type == FT_FRAMENUM) ));
switch (hfinfo->type) {
case FT_INT32:
/* Require integral types (other than frame number, which is
always displayed in decimal) to have a number base */
- g_assert(hfinfo->display != BASE_NONE);
+ DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
break;
case FT_FRAMENUM:
/* Don't allow bitfields or value strings for frame numbers */
- g_assert(hfinfo->bitmask == 0);
- g_assert(hfinfo->strings == NULL);
+ DISSECTOR_ASSERT(hfinfo->bitmask == 0);
+ DISSECTOR_ASSERT(hfinfo->strings == NULL);
break;
default:
if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
- char *p;
+ const char *p;
guchar c;
/* Check that the filter name (abbreviation) is legal;
* it must contain only alphanumerics, '-', "_", and ".". */
- for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
- g_assert(isalnum(c) || c == '-' || c == '_' ||
- c == '.');
-
+ for (p = hfinfo->abbrev; (c = *p) != '\0'; p++) {
+ if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) {
+ fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
+ DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
+ c == '.');
+ }
+ }
/* We allow multiple hfinfo's to be registered under the same
* abbreviation. This was done for X.25, as, depending
* on whether it's modulo-8 or modulo-128 operation,
same_name_hfinfo->same_name_next = hfinfo;
hfinfo->same_name_prev = same_name_hfinfo;
}
- g_tree_insert(gpa_name_tree, hfinfo->abbrev, hfinfo);
+ g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
}
return hfinfo->id;
}
void
-proto_register_subtree_array(gint **indices, int num_indices)
+proto_register_subtree_array(gint *const *indices, int num_indices)
{
int i;
- gint **ptr = indices;
+ gint *const *ptr = indices;
/*
- * Make sure we haven't already allocated the array of "tree is
- * expanded" flags.
- *
- * XXX - if it's *really* important to allow more ett_ values to
- * be given out after "proto_init()" is called, we could expand
- * the array.
+ * If we've already allocated the array of tree types, expand
+ * it; this lets plugins such as mate add tree types after
+ * the initial startup. (If we haven't already allocated it,
+ * we don't allocate it; on the first pass, we just assign
+ * ett values and keep track of how many we've assigned, and
+ * when we're finished registering all dissectors we allocate
+ * the array, so that we do only one allocation rather than
+ * wasting CPU time and memory by growing the array for each
+ * dissector that registers ett values.)
*/
- g_assert(tree_is_expanded == NULL);
+ if (tree_is_expanded != NULL) {
+ tree_is_expanded =
+ g_realloc(tree_is_expanded,
+ (num_tree_types+num_indices)*sizeof (gboolean));
+ memset(tree_is_expanded + num_tree_types, 0,
+ num_indices*sizeof (gboolean));
+ }
/*
* Assign "num_indices" subtree numbers starting at "num_tree_types",
guint8 *bytes;
guint32 integer;
ipv4_addr *ipv4;
+ e_guid_t *guid;
guint32 n_addr; /* network-order IPv4 address */
+ const gchar *name;
int ret; /*tmp return value */
switch(hfinfo->type) {
case FT_NONE:
case FT_PROTOCOL:
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s", hfinfo->name);
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
case FT_UINT_BYTES:
bytes = fvalue_get(&fi->value);
if (bytes) {
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s", hfinfo->name,
bytes_to_str(bytes, fvalue_length(&fi->value)));
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
}
else {
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: <MISSING>", hfinfo->name);
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
case FT_INT16:
case FT_INT24:
case FT_INT32:
- g_assert(!hfinfo->bitmask);
+ DISSECTOR_ASSERT(!hfinfo->bitmask);
if (hfinfo->strings) {
fill_label_enumerated_int(fi, label_str);
}
break;
case FT_FLOAT:
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %." STRINGIFY(FLT_DIG) "f",
hfinfo->name, fvalue_get_floating(&fi->value));
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
break;
case FT_DOUBLE:
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %." STRINGIFY(DBL_DIG) "g",
hfinfo->name, fvalue_get_floating(&fi->value));
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
break;
case FT_ABSOLUTE_TIME:
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s", hfinfo->name,
abs_time_to_str(fvalue_get(&fi->value)));
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
break;
case FT_RELATIVE_TIME:
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s seconds", hfinfo->name,
rel_time_to_secs_str(fvalue_get(&fi->value)));
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
case FT_IPXNET:
integer = fvalue_get_integer(&fi->value);
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
- "%s: 0x%08X (%s)", hfinfo->name,
- integer, get_ipxnet_name(integer));
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ "%s: %s (0x%08X)", hfinfo->name,
+ get_ipxnet_name(integer), integer);
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
break;
case FT_ETHER:
bytes = fvalue_get(&fi->value);
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s (%s)", hfinfo->name,
- ether_to_str(bytes),
- get_ether_name(bytes));
+ get_ether_name(bytes),
+ ether_to_str(bytes));
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
break;
case FT_IPv4:
ipv4 = fvalue_get(&fi->value);
n_addr = ipv4_get_net_order_addr(ipv4);
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s (%s)", hfinfo->name,
get_hostname(n_addr),
ip_to_str((guint8*)&n_addr));
case FT_IPv6:
bytes = fvalue_get(&fi->value);
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s (%s)", hfinfo->name,
get_hostname6((struct e_in6_addr *)bytes),
ip6_to_str((struct e_in6_addr*)bytes));
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
break;
+ case FT_GUID:
+ guid = fvalue_get(&fi->value);
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ "%s: %s", hfinfo->name,
+ guid_to_str(guid));
+ if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
+ label_str[ITEM_LABEL_LENGTH - 1] = '\0';
+ break;
+
+ case FT_OID:
+ bytes = fvalue_get(&fi->value);
+ name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
+ if (name) {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ "%s: %s (%s)", hfinfo->name,
+ oid_to_str(bytes, fvalue_length(&fi->value)), name);
+ } else {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ "%s: %s", hfinfo->name,
+ oid_to_str(bytes, fvalue_length(&fi->value)));
+ }
+ if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
+ label_str[ITEM_LABEL_LENGTH - 1] = '\0';
+ break;
+
case FT_STRING:
case FT_STRINGZ:
case FT_UINT_STRING:
bytes = fvalue_get(&fi->value);
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
- "%s: %s", hfinfo->name,
- format_text(bytes, strlen(bytes)));
+ if(strlen(bytes) > ITEM_LABEL_LENGTH) {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ "%s [truncated]: %s", hfinfo->name,
+ format_text(bytes, strlen(bytes)));
+ } else {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ "%s: %s", hfinfo->name,
+ format_text(bytes, strlen(bytes)));
+ }
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
break;
g_error("hfinfo->type %d (%s) not handled\n",
hfinfo->type,
ftype_name(hfinfo->type));
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
break;
}
}
}
/* Fill in the textual info */
- ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
+ ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
"%s: %s", hfinfo->name,
value ? tfstring->true_string : tfstring->false_string);
if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
static void
fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
{
- char *format = NULL, *p;
+ const char *format = NULL;
+ char *p;
int bitfield_byte_length, bitwidth;
guint32 unshifted_value;
guint32 value;
bitfield_byte_length = p - label_str;
/* Fill in the textual info using stored (shifted) value */
- ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
+ ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
format, hfinfo->name,
val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
static void
fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
{
- char *format = NULL, *p;
+ const char *format = NULL;
+ char *p;
int bitfield_byte_length, bitwidth;
guint32 unshifted_value;
guint32 value;
bitfield_byte_length = p - label_str;
/* Fill in the textual info using stored (shifted) value */
- ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
- format, hfinfo->name, value);
+ if (IS_BASE_DUAL(hfinfo->display)) {
+ ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
+ format, hfinfo->name, value, value);
+ } else {
+ ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
+ format, hfinfo->name, value);
+ }
if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
static void
fill_label_enumerated_uint(field_info *fi, gchar *label_str)
{
- char *format = NULL;
+ const char *format = NULL;
header_field_info *hfinfo = fi->hfinfo;
guint32 value;
int ret; /*tmp return value */
value = fvalue_get_integer(&fi->value);
/* Fill in the textual info */
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
format, hfinfo->name,
val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
static void
fill_label_uint(field_info *fi, gchar *label_str)
{
- char *format = NULL;
+ const char *format = NULL;
header_field_info *hfinfo = fi->hfinfo;
guint32 value;
int ret; /*tmp return value */
value = fvalue_get_integer(&fi->value);
/* Fill in the textual info */
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
- format, hfinfo->name, value);
+ if (IS_BASE_DUAL(hfinfo->display)) {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ format, hfinfo->name, value, value);
+ } else {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ format, hfinfo->name, value);
+ }
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
}
static void
fill_label_uint64(field_info *fi, gchar *label_str)
{
- char *format = NULL;
+ const char *format = NULL;
header_field_info *hfinfo = fi->hfinfo;
guint64 value;
int ret; /*tmp return value */
value = fvalue_get_integer64(&fi->value);
/* Fill in the textual info */
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
- format, hfinfo->name, value);
+ if (IS_BASE_DUAL(hfinfo->display)) {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ format, hfinfo->name, value, value);
+ } else {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ format, hfinfo->name, value);
+ }
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
}
static void
fill_label_enumerated_int(field_info *fi, gchar *label_str)
{
- char *format = NULL;
+ const char *format = NULL;
header_field_info *hfinfo = fi->hfinfo;
guint32 value;
int ret; /*tmp return value */
value = fvalue_get_integer(&fi->value);
/* Fill in the textual info */
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
format, hfinfo->name,
val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
static void
fill_label_int(field_info *fi, gchar *label_str)
{
- char *format = NULL;
+ const char *format = NULL;
header_field_info *hfinfo = fi->hfinfo;
guint32 value;
int ret; /*tmp return value */
value = fvalue_get_integer(&fi->value);
/* Fill in the textual info */
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
- format, hfinfo->name, value);
+ if (IS_BASE_DUAL(hfinfo->display)) {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ format, hfinfo->name, value, value);
+ } else {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ format, hfinfo->name, value);
+ }
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
}
static void
fill_label_int64(field_info *fi, gchar *label_str)
{
- char *format = NULL;
+ const char *format = NULL;
header_field_info *hfinfo = fi->hfinfo;
guint64 value;
int ret; /*tmp return value */
value = fvalue_get_integer64(&fi->value);
/* Fill in the textual info */
- ret = snprintf(label_str, ITEM_LABEL_LENGTH,
- format, hfinfo->name, value);
+ if (IS_BASE_DUAL(hfinfo->display)) {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ format, hfinfo->name, value, value);
+ } else {
+ ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ format, hfinfo->name, value);
+ }
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
}
bitwidth = hfinfo->display; /* hacky? :) */
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
return bitwidth;
}
-static char*
+static const char*
hfinfo_uint_vals_format(header_field_info *hfinfo)
{
- char *format = NULL;
+ const char *format = NULL;
switch(hfinfo->display) {
case BASE_DEC:
+ case BASE_DEC_HEX:
format = "%s: %s (%u)";
break;
case BASE_OCT: /* I'm lazy */
format = "%s: %s (%o)";
break;
case BASE_HEX:
+ case BASE_HEX_DEC:
switch(hfinfo->type) {
case FT_UINT8:
format = "%s: %s (0x%02x)";
format = "%s: %s (0x%08x)";
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
return format;
}
-static char*
+static const char*
hfinfo_uint_format(header_field_info *hfinfo)
{
- char *format = NULL;
+ const char *format = NULL;
/* Pick the proper format string */
if (hfinfo->type == FT_FRAMENUM) {
case BASE_DEC:
format = "%s: %u";
break;
+ case BASE_DEC_HEX:
+ switch(hfinfo->type) {
+ case FT_UINT8:
+ format = "%s: %u (0x%02x)";
+ break;
+ case FT_UINT16:
+ format = "%s: %u (0x%04x)";
+ break;
+ case FT_UINT24:
+ format = "%s: %u (0x%06x)";
+ break;
+ case FT_UINT32:
+ format = "%s: %u (0x%08x)";
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ ;
+ }
+ break;
case BASE_OCT: /* I'm lazy */
format = "%s: %o";
break;
format = "%s: 0x%08x";
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
+ ;
+ }
+ break;
+ case BASE_HEX_DEC:
+ switch(hfinfo->type) {
+ case FT_UINT8:
+ format = "%s: 0x%02x (%u)";
+ break;
+ case FT_UINT16:
+ format = "%s: 0x%04x (%u)";
+ break;
+ case FT_UINT24:
+ format = "%s: 0x%06x (%u)";
+ break;
+ case FT_UINT32:
+ format = "%s: 0x%08x (%u)";
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
}
return format;
}
-static char*
+static const char*
hfinfo_int_vals_format(header_field_info *hfinfo)
{
- char *format = NULL;
+ const char *format = NULL;
switch(hfinfo->display) {
case BASE_DEC:
+ case BASE_DEC_HEX:
format = "%s: %s (%d)";
break;
case BASE_OCT: /* I'm lazy */
format = "%s: %s (%o)";
break;
case BASE_HEX:
+ case BASE_HEX_DEC:
switch(hfinfo->type) {
case FT_INT8:
format = "%s: %s (0x%02x)";
format = "%s: %s (0x%08x)";
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
return format;
}
-static char*
+static const char*
hfinfo_uint64_format(header_field_info *hfinfo)
{
- char *format = NULL;
+ const char *format = NULL;
/* Pick the proper format string */
switch(hfinfo->display) {
case BASE_DEC:
format = "%s: %" PRIu64;
break;
+ case BASE_DEC_HEX:
+ format = "%s: %" PRIu64 " (%" PRIx64 ")";
+ break;
case BASE_OCT: /* I'm lazy */
format = "%s: %" PRIo64;
break;
case BASE_HEX:
format = "%s: 0x%016" PRIx64;
break;
+ case BASE_HEX_DEC:
+ format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
+ break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
return format;
}
-static char*
+static const char*
hfinfo_int_format(header_field_info *hfinfo)
{
- char *format = NULL;
+ const char *format = NULL;
/* Pick the proper format string */
switch(hfinfo->display) {
case BASE_DEC:
format = "%s: %d";
break;
+ case BASE_DEC_HEX:
+ switch(hfinfo->type) {
+ case FT_INT8:
+ format = "%s: %d (0x%02x)";
+ break;
+ case FT_INT16:
+ format = "%s: %d (0x%04x)";
+ break;
+ case FT_INT24:
+ format = "%s: %d (0x%06x)";
+ break;
+ case FT_INT32:
+ format = "%s: %d (0x%08x)";
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ ;
+ }
case BASE_OCT: /* I'm lazy */
format = "%s: %o";
break;
format = "%s: 0x%08x";
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
+ ;
+ }
+ break;
+ case BASE_HEX_DEC:
+ switch(hfinfo->type) {
+ case FT_INT8:
+ format = "%s: 0x%02x (%d)";
+ break;
+ case FT_INT16:
+ format = "%s: 0x%04x (%d)";
+ break;
+ case FT_INT24:
+ format = "%s: 0x%06x (%d)";
+ break;
+ case FT_INT32:
+ format = "%s: 0x%08x (%d)";
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
return format;
}
-static char*
+static const char*
hfinfo_int64_format(header_field_info *hfinfo)
{
- char *format = NULL;
+ const char *format = NULL;
/* Pick the proper format string */
switch(hfinfo->display) {
case BASE_DEC:
format = "%s: %" PRId64;
break;
+ case BASE_DEC_HEX:
+ format = "%s: %" PRId64 " (%" PRIx64 ")";
+ break;
case BASE_OCT: /* I'm lazy */
format = "%s: %" PRIo64;
break;
case BASE_HEX:
format = "%s: 0x%016" PRIx64;
break;
+ case BASE_HEX_DEC:
+ format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
+ break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
return format;
return gpa_hfinfo.len;
}
-char*
+const char*
proto_registrar_get_name(int n)
{
header_field_info *hfinfo;
return hfinfo->name;
}
-char*
+const char*
proto_registrar_get_abbrev(int n)
{
header_field_info *hfinfo;
}
-/* Helper struct and function for proto_find_info() */
+/* Helper struct for proto_find_info() and proto_all_finfos() */
typedef struct {
GPtrArray *array;
int id;
} ffdata_t;
+/* Helper function for proto_find_info() */
static gboolean
find_finfo(proto_node *node, gpointer data)
{
}
/* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
- * This works on any proto_tree, primed or unprimed, but actually searches
- * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
- * The caller does need to free the returned GPtrArray with
- * g_ptr_array_free(<array>, FALSE).
- */
+* This works on any proto_tree, primed or unprimed, but actually searches
+* the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
+* The caller does need to free the returned GPtrArray with
+* g_ptr_array_free(<array>, FALSE).
+*/
GPtrArray*
proto_find_finfo(proto_tree *tree, int id)
{
proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
return ffdata.array;
-}
+}
+
+/* Helper function for proto_all_finfos() */
+static gboolean
+every_finfo(proto_node *node, gpointer data)
+{
+ field_info *fi = PITEM_FINFO(node);
+ if (fi && fi->hfinfo) {
+ g_ptr_array_add(((ffdata_t*)data)->array, fi);
+ }
+
+ /* Don't stop traversing. */
+ return FALSE;
+}
+
+/* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
+GPtrArray*
+proto_all_finfos(proto_tree *tree)
+{
+ ffdata_t ffdata;
+
+ ffdata.array = g_ptr_array_new();
+ ffdata.id = 0;
+
+ proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
+
+ return ffdata.array;
+}
typedef struct {
{
protocol_t *protocol;
int i;
- void *cookie;
+ void *cookie = NULL;
for (i = proto_get_first_protocol(&cookie); i != -1;
i = proto_get_next_protocol(&cookie)) {
* Field 3 = field abbreviation
* Field 4 = type ( textual representation of the the ftenum type )
* Field 5 = parent protocol abbreviation
+ * Field 6 = blurb describing field
+ *
+ * (format 2)
+ * Field 1 = 'F'
+ * Field 2 = descriptive field name
+ * Field 3 = field abbreviation
+ * Field 4 = type ( textual representation of the the ftenum type )
+ * Field 5 = parent protocol abbreviation
+ * Field 6 = blurb describing field
+ * Field 7 = base for display (for integer types)
+ * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
*
- * (format 2 adds these fields:)
- * Field 6 = base for display (for integer types)
- * Field 7 = blurb describing field
+ * (format 3)
+ * Field 1 = 'F'
+ * Field 2 = descriptive field name
+ * Field 3 = field abbreviation
+ * Field 4 = type ( textual representation of the the ftenum type )
+ * Field 5 = parent protocol abbreviation
+ * Field 6 = blurb describing field
+ * Field 7 = base for display (for integer types)
+ * Field 8 = bitmask
*/
void
proto_registrar_dump_fields(int format)
int i, len;
const char *enum_name;
const char *base_name;
+ const char *blurb;
len = gpa_hfinfo.len;
for (i = 0; i < len ; i++) {
PROTO_REGISTRAR_GET_NTH(i, hfinfo);
/*
- * Skip fields with zero-length names or abbreviations;
- * the pseudo-field for "proto_tree_add_text()" is such
- * a field, and we don't want it in the list of filterable
- * fields.
- *
- *
- * XXX - perhaps the name and abbrev field should be null
- * pointers rather than null strings for that pseudo-field,
- * but we'd have to add checks for null pointers in some
- * places if we did that.
- *
- * Or perhaps protocol tree items added with
- * "proto_tree_add_text()" should have -1 as the field index,
- * with no pseudo-field being used, but that might also
- * require special checks for -1 to be added.
- */
- /* XXX - we could just skip the special text
- * pseudo-field by testing: if (hfinfo->id == hf_text_only)
- * */
- if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
+ * Skip the pseudo-field for "proto_tree_add_text()" since
+ * we don't want it in the list of filterable fields.
+ */
+ if (hfinfo->id == hf_text_only)
continue;
/* format for protocols */
hfinfo->type == FT_INT32 ||
hfinfo->type == FT_INT64) {
-
+
switch(hfinfo->display) {
case BASE_NONE:
base_name = "BASE_NONE";
case BASE_OCT:
base_name = "BASE_OCT";
break;
+ case BASE_DEC_HEX:
+ base_name = "BASE_DEC_HEX";
+ break;
+ case BASE_HEX_DEC:
+ base_name = "BASE_HEX_DEC";
+ break;
}
}
}
+ blurb = hfinfo->blurb;
+ if (blurb == NULL)
+ blurb = "";
if (format == 1) {
- printf("F\t%s\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
- enum_name,parent_hfinfo->abbrev, hfinfo->blurb);
+ printf("F\t%s\t%s\t%s\t%s\t%s\n",
+ hfinfo->name, hfinfo->abbrev, enum_name,
+ parent_hfinfo->abbrev, blurb);
}
else if (format == 2) {
printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
- hfinfo->name, hfinfo->abbrev,
- enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
- base_name, hfinfo->blurb);
+ hfinfo->name, hfinfo->abbrev, enum_name,
+ parent_hfinfo->abbrev, blurb,
+ base_name, blurb);
+ }
+ else if (format == 3) {
+ printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
+ hfinfo->name, hfinfo->abbrev, enum_name,
+ parent_hfinfo->abbrev, blurb,
+ base_name, hfinfo->bitmask);
+ }
+ else {
+ g_assert_not_reached();
}
}
}
}
-static char*
+static const char*
hfinfo_numeric_format(header_field_info *hfinfo)
{
- char *format = NULL;
+ const char *format = NULL;
/* Pick the proper format string */
if (hfinfo->type == FT_FRAMENUM) {
/* Pick the proper format string */
switch(hfinfo->display) {
case BASE_DEC:
+ case BASE_DEC_HEX:
case BASE_OCT: /* I'm lazy */
switch(hfinfo->type) {
case FT_UINT8:
format = "%s == %" PRId64;
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
break;
case BASE_HEX:
+ case BASE_HEX_DEC:
switch(hfinfo->type) {
case FT_UINT8:
format = "%s == 0x%02x";
format = "%s == 0x%016" PRIx64;
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
break;
default:
- g_assert_not_reached();
+ DISSECTOR_ASSERT_NOT_REACHED();
;
}
}
gint length;
hfinfo = finfo->hfinfo;
- g_assert(hfinfo);
+ DISSECTOR_ASSERT(hfinfo);
switch(hfinfo->type) {
case FT_BYTES:
case FT_UINT_BYTES:
case FT_PROTOCOL:
+ case FT_GUID:
+ case FT_OID:
/*
* These all have values, so we can match.
*/
return TRUE;
-
+ case FT_NONE:
+ /*
+ * Doesn't have a value, but may still want to test
+ * for its presence in a trace
+ */
+ return TRUE;
default:
/*
* This doesn't have a value, so we'd match
}
}
+/* This function returns a string allocated with packet lifetime scope.
+ * You do not need to [g_]free() this string since it will be automatically
+ * freed once the next packet is dissected.
+ */
char*
proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
{
header_field_info *hfinfo;
int abbrev_len;
- char *buf, *stringified, *format, *ptr;
+ char *buf, *ptr;
+ int buf_len;
+ const char *format;
int dfilter_len, i;
gint start, length, length_remaining;
guint8 c;
hfinfo = finfo->hfinfo;
- g_assert(hfinfo);
+ DISSECTOR_ASSERT(hfinfo);
abbrev_len = strlen(hfinfo->abbrev);
/*
- * XXX - we should add "val_to_string_repr" and "string_repr_len"
- * functions for more types, and use them whenever possible.
- *
- * The FT_UINT and FT_INT types are the only tricky ones, as
- * we choose the base in the string expression based on the
- * display base of the field.
+ * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
+ * functions for FT_UINT and FT_INT types, as we choose the base in
+ * the string expression based on the display base of the field.
*
* Note that the base does matter, as this is also used for
* the protocolinfo tap.
*
- * It might be nice to use that in "proto_item_fill_label()"
+ * It might be nice to use them in "proto_item_fill_label()"
* as well, although, there, you'd have to deal with the base
* *and* with resolved values for addresses.
*
* 1 byte for the trailing '\0'.
*/
dfilter_len = abbrev_len + 4 + 11 + 1;
- buf = g_malloc0(dfilter_len);
+ buf = ep_alloc0(dfilter_len);
format = hfinfo_numeric_format(hfinfo);
- snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
+ g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
break;
case FT_INT64:
* 1 byte for the trailing '\0'.
*/
dfilter_len = abbrev_len + 4 + 22 + 1;
- buf = g_malloc0(dfilter_len);
+ buf = ep_alloc0(dfilter_len);
format = hfinfo_numeric_format(hfinfo);
- snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
- break;
-
- case FT_IPXNET:
- /*
- * 4 bytes for " == ".
- * 2 bytes for "0x".
- * 8 bytes for 8 digits of 32-bit hex number.
- * 1 byte for the trailing '\0'.
- */
- dfilter_len = abbrev_len + 4 + 2 + 8 + 1;
- buf = g_malloc0(dfilter_len);
- snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
- fvalue_get_integer(&finfo->value));
- break;
-
- case FT_IPv6:
- /*
- * 4 bytes for " == ".
- * N bytes for the string for the address.
- * 1 byte for the trailing '\0'.
- */
- stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(&finfo->value));
- dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
- buf = g_malloc0(dfilter_len);
- snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
- stringified);
+ g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
break;
/* These use the fvalue's "to_string_repr" method. */
+ case FT_IPXNET:
case FT_BOOLEAN:
case FT_STRING:
+ case FT_STRINGZ:
case FT_ETHER:
case FT_BYTES:
case FT_UINT_BYTES:
+ case FT_UINT_STRING:
case FT_FLOAT:
case FT_DOUBLE:
case FT_ABSOLUTE_TIME:
case FT_RELATIVE_TIME:
case FT_IPv4:
+ case FT_IPv6:
+ case FT_GUID:
+ case FT_OID:
/* Figure out the string length needed.
* The ft_repr length.
* 4 bytes for " == ".
dfilter_len = fvalue_string_repr_len(&finfo->value,
FTREPR_DFILTER);
dfilter_len += abbrev_len + 4 + 1;
- buf = g_malloc0(dfilter_len);
+ buf = ep_alloc0(dfilter_len);
/* Create the string */
- snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
+ g_snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
fvalue_to_string_repr(&finfo->value,
FTREPR_DFILTER,
&buf[abbrev_len + 4]);
break;
case FT_PROTOCOL:
- buf = g_strdup(finfo->hfinfo->abbrev);
+ buf = ep_strdup(finfo->hfinfo->abbrev);
break;
default:
* If "edt" is NULL, the answer is "no".
*/
if (edt == NULL)
- return FALSE;
+ return NULL;
/*
* Is this field part of the raw frame tvbuff?
return NULL; /* you lose */
/*
- * If the length is 0, there's nothing to match, so
- * we can't match. (Also check for negative values,
+ * If the length is 0, just match the name of the field
+ * (Also check for negative values,
* just in case, as we'll cast it to an unsigned
* value later.)
*/
length = finfo->length;
- if (length <= 0)
+ if (length == 0)
+ {
+ buf = ep_strdup(finfo->hfinfo->abbrev);
+ break;
+ }
+ if (length < 0)
return NULL;
/*
length = length_remaining;
if (length <= 0)
return NULL;
-
+
start = finfo->start;
- buf = g_malloc0(32 + length * 3);
+ buf_len = 32 + length * 3;
+ buf = ep_alloc0(buf_len);
ptr = buf;
- sprintf(ptr, "frame[%d:%d] == ", finfo->start, length);
- ptr = buf+strlen(buf);
-
+ ptr += g_snprintf(ptr, buf_len-(ptr-buf), "frame[%d:%d] == ", finfo->start, length);
for (i=0;i<length; i++) {
c = tvb_get_guint8(finfo->ds_tvb, start);
start++;
if (i == 0 ) {
- sprintf(ptr, "%02x", c);
+ ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
}
else {
- sprintf(ptr, ":%02x", c);
+ ptr += g_snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);
}
- ptr = buf+strlen(buf);
}
break;
}