*
* $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
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 guint8* value_ptr);
+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);
+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
#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
- hfinfo=gpa_hfinfo.hfi[hfindex];
+ hfinfo=gpa_hfinfo.hfi[hfindex];
/* List which stores protocols and fields that have been registered */
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));
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
+ /* 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
*/
/* Assume dissector set only its protocol fields.
This function is called by dissectors and allowes to speed up filtering
- in ethereal, if this function returns FALSE it is safe to reset tree to NULL
+ 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.
case FT_GUID:
DISSECTOR_ASSERT(length == 16);
- proto_tree_set_guid_tvb(new_fi, tvb, start);
+ proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
break;
case FT_OID:
/* If the proto_tree wants to keep a record of this finfo
* for quick lookup, then record it. */
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) {
/* Add a FT_GUID to a proto_tree */
proto_item *
proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
- const guint8* value_ptr)
+ const e_guid_t *value_ptr)
{
proto_item *pi;
field_info *new_fi;
proto_item *
proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
- const guint8* value_ptr)
+ const e_guid_t *value_ptr)
{
proto_item *pi;
proto_item *
proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
- gint start, gint length, const guint8* value_ptr,
+ gint start, gint length, const e_guid_t *value_ptr,
const char *format, ...)
{
proto_item *pi;
proto_item *
proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
- const guint8* value_ptr, const char *format, ...)
+ const e_guid_t *value_ptr, const char *format, ...)
{
proto_item *pi;
va_list ap;
/* Set the FT_GUID value */
static void
-proto_tree_set_guid(field_info *fi, const guint8* value_ptr)
+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)
+proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
{
- proto_tree_set_guid(fi, tvb_get_ptr(tvb, start, 16));
+ 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 */
* 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()
+/* 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
+ * 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
+ * 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 :
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)
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 the proto_tree wants to keep a record of this finfo
* for quick lookup, then record it. */
if (fi->hfinfo->ref_count) {
+ /*HERE*/
hash = PTREE_DATA(tree)->interesting_hfids;
ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
if (ptrs) {
* 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
- * Ethereal, we don't highlight stuff past
+ * Wireshark, we don't highlight stuff past
* the end of the data.
*/
/* XXX - what to do, if we don't have a tvb? */
(fi->flags = (fi)->flags | (flags_in)); \
}
-gboolean
+gboolean
proto_item_set_expert_flags(proto_item *pi, int group, int severity)
{
if(pi == NULL || pi->finfo == NULL)
* 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;
}
}
-proto_item*
+proto_item*
proto_tree_get_parent(proto_tree *tree) {
/* dont bother if tree is not visible */
if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
return (proto_item*) tree;
}
+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;
+}
void
proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
/* fix last_child if required */
if(tree->last_child == item_to_move) {
tree->last_child = curr_item;
- }
+ }
}
/*** insert to_move after fixed ***/
* 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,
+ * 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.
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 */
break;
case FT_GUID:
- bytes = fvalue_get(&fi->value);
+ guid = fvalue_get(&fi->value);
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s", hfinfo->name,
- guid_to_str(bytes));
+ guid_to_str(guid));
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
break;
DISSECTOR_ASSERT_NOT_REACHED();
;
}
+ break;
case BASE_HEX_DEC:
switch(hfinfo->type) {
case FT_INT8:
}
-/* 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)) {
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";
* 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
+ * You do not need to [g_]free() this string since it will be automatically
* freed once the next packet is dissected.
*/
char*
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:
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_len = 32 + length * 3;
buf = ep_alloc0(buf_len);
ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
}
else {
- ptr += snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);
+ ptr += g_snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);
}
}
break;