summaryrefslogtreecommitdiff
path: root/epan
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>2001-12-18 19:09:08 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>2001-12-18 19:09:08 +0000
commit791f5774d0fdabdb706bfd7056e534713cc4e4d6 (patch)
tree35f987f9914fead0fb5fefe79df280b7340831b4 /epan
parent4e013a44de86f8146cfd7d440adb67366e37273a (diff)
downloadwireshark-791f5774d0fdabdb706bfd7056e534713cc4e4d6.tar.gz
Provide for per-protocol-tree data in the proto_tree code.
Put a hash-table of "interesting" fields in the per-proto-tree data. The dfilter code records which fields/protocols are "interesting" (by which I mean, their value or existence is checked). Thus, the proto_tree routines can create special arrays of field_info*'s that are ready for the dfilter engine to use during a filter operation. Also store the "proto_tree_is_visible" boolean, renamed "visible", in the per-proto-tree data. Move epan_dissect_t to its own header file to make #include dependencies easier to handle. Provide epan_dissect_fill_in_columns(), which accepts just the epan_dissect_t* as an argument. epan_dissect_new() needs to be followed by epan_dissect_run() for the dissection to actually take place. Between those two calls, epan_dissect_prime_dfilter() can be run 0, 1, or multiple times in order to prime the empty proto_tree with the "intersesting" fields from the dfilter_t. svn path=/trunk/; revision=4422
Diffstat (limited to 'epan')
-rw-r--r--epan/Makefile.am3
-rw-r--r--epan/dfilter/dfilter-int.h5
-rw-r--r--epan/dfilter/dfilter.c27
-rw-r--r--epan/dfilter/dfilter.h12
-rw-r--r--epan/dfilter/dfvm.c6
-rw-r--r--epan/dfilter/gencode.c50
-rw-r--r--epan/dfilter/gencode.h3
-rw-r--r--epan/dfilter/semcheck.c3
-rw-r--r--epan/epan.c61
-rw-r--r--epan/epan.h50
-rw-r--r--epan/epan_dissect.h44
-rw-r--r--epan/packet.c3
-rw-r--r--epan/packet.h4
-rw-r--r--epan/proto.c349
-rw-r--r--epan/proto.h39
15 files changed, 441 insertions, 218 deletions
diff --git a/epan/Makefile.am b/epan/Makefile.am
index 02e2c2b782..cefe353d0d 100644
--- a/epan/Makefile.am
+++ b/epan/Makefile.am
@@ -2,7 +2,7 @@
# Automake file for the EPAN library
# (Ethereal Protocol ANalyzer Library)
#
-# $Id: Makefile.am,v 1.29 2001/11/22 03:07:06 hagbard Exp $
+# $Id: Makefile.am,v 1.30 2001/12/18 19:09:03 gram Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@zing.org>
@@ -46,6 +46,7 @@ libethereal_a_SOURCES = \
column-utils.h \
epan.c \
epan.h \
+ epan_dissect.h \
except.c \
except.h \
exceptions.h \
diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h
index c1e6774438..89e1857f8f 100644
--- a/epan/dfilter/dfilter-int.h
+++ b/epan/dfilter/dfilter-int.h
@@ -1,5 +1,5 @@
/*
- * $Id: dfilter-int.h,v 1.3 2001/02/15 06:22:45 guy Exp $
+ * $Id: dfilter-int.h,v 1.4 2001/12/18 19:09:06 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -35,6 +35,8 @@ struct _dfilter_t {
int num_registers;
GList **registers;
gboolean *attempted_load;
+ int *interesting_fields;
+ int num_interesting_fields;
};
typedef struct {
@@ -43,6 +45,7 @@ typedef struct {
gboolean syntax_error;
GPtrArray *insns;
GHashTable *loaded_fields;
+ GHashTable *interesting_fields;
int next_insn_id;
int next_register;
} dfwork_t;
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c
index 0380f15662..1f5743d23e 100644
--- a/epan/dfilter/dfilter.c
+++ b/epan/dfilter/dfilter.c
@@ -1,5 +1,5 @@
/*
- * $Id: dfilter.c,v 1.5 2001/07/13 00:55:54 guy Exp $
+ * $Id: dfilter.c,v 1.6 2001/12/18 19:09:06 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -37,6 +37,7 @@
#include "gencode.h"
#include "semcheck.h"
#include "dfvm.h"
+#include "epan_dissect.h"
/* Balanced tree of abbreviations and IDs */
@@ -228,6 +229,10 @@ dfilter_free(dfilter_t *df)
free_insns(df->insns);
}
+ if (df->interesting_fields) {
+ g_free(df->interesting_fields);
+ }
+
g_free(df->registers);
g_free(df->attempted_load);
g_free(df);
@@ -245,6 +250,7 @@ dfwork_new(void)
dfw->syntax_error = FALSE;
dfw->insns = NULL;
dfw->loaded_fields = NULL;
+ dfw->interesting_fields = NULL;
dfw->next_insn_id = 0;
dfw->next_register = 0;
@@ -262,10 +268,15 @@ dfwork_free(dfwork_t *dfw)
g_hash_table_destroy(dfw->loaded_fields);
}
+ if (dfw->interesting_fields) {
+ g_hash_table_destroy(dfw->interesting_fields);
+ }
+
if (dfw->insns) {
free_insns(dfw->insns);
}
+
g_free(dfw);
}
@@ -333,6 +344,8 @@ dfilter_compile(gchar *text, dfilter_t **dfp)
dfilter = dfilter_new();
dfilter->insns = dfw->insns;
dfw->insns = NULL;
+ dfilter->interesting_fields = dfw_interesting_fields(dfw,
+ &dfilter->num_interesting_fields);
/* Initialize run-time space */
dfilter->num_registers = dfw->next_register;
@@ -378,6 +391,18 @@ dfilter_apply_edt(dfilter_t *df, epan_dissect_t* edt)
void
+dfilter_foreach_interesting_field(dfilter_t *df, GFunc func,
+ gpointer user_data)
+{
+ int i;
+
+ for (i = 0; i < df->num_interesting_fields; i++) {
+ func(GINT_TO_POINTER(df->interesting_fields[i]), user_data);
+ }
+}
+
+
+void
dfilter_dump(dfilter_t *df)
{
dfvm_dump(stdout, df->insns);
diff --git a/epan/dfilter/dfilter.h b/epan/dfilter/dfilter.h
index afd93fb824..49eba9c5db 100644
--- a/epan/dfilter/dfilter.h
+++ b/epan/dfilter/dfilter.h
@@ -1,5 +1,5 @@
/*
- * $Id: dfilter.h,v 1.2 2001/02/01 20:31:18 gram Exp $
+ * $Id: dfilter.h,v 1.3 2001/12/18 19:09:06 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -25,12 +25,14 @@
#define DFILTER_H
#include <glib.h>
-#include "epan.h"
-#include "proto.h"
/* Passed back to user */
typedef struct _dfilter_t dfilter_t;
+#include "epan.h"
+#include "proto.h"
+
+
/* Module-level initialization */
void
dfilter_init(void);
@@ -75,6 +77,10 @@ dfilter_apply_edt(dfilter_t *df, epan_dissect_t* edt);
gboolean
dfilter_apply(dfilter_t *df, tvbuff_t *tvb, proto_tree *tree);
+/* Run a callback for each interesting field in the dfilter. */
+void
+dfilter_foreach_interesting_field(dfilter_t *df, GFunc func,
+ gpointer user_data);
/* Print bytecode of dfilter to stdout */
void
diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c
index bc1c48c21d..02bf948a5c 100644
--- a/epan/dfilter/dfvm.c
+++ b/epan/dfilter/dfvm.c
@@ -1,5 +1,5 @@
/*
- * $Id: dfvm.c,v 1.4 2001/12/13 05:55:23 gram Exp $
+ * $Id: dfvm.c,v 1.5 2001/12/18 19:09:06 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -211,6 +211,9 @@ read_tree(dfilter_t *df, proto_tree *tree, int field_id, int reg)
if (!finfos) {
return FALSE;
}
+ else if (g_ptr_array_len(finfos) == 0) {
+ return FALSE;
+ }
len = finfos->len;
for (i = 0; i < len; i++) {
@@ -218,7 +221,6 @@ read_tree(dfilter_t *df, proto_tree *tree, int field_id, int reg)
fvalues = g_list_prepend(fvalues, finfo->value);
}
fvalues = g_list_reverse(fvalues);
- g_ptr_array_free(finfos, TRUE);
df->registers[reg] = fvalues;
return TRUE;
diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c
index cf3e1d5787..d8d0119005 100644
--- a/epan/dfilter/gencode.c
+++ b/epan/dfilter/gencode.c
@@ -1,5 +1,5 @@
/*
- * $Id: gencode.c,v 1.3 2001/02/27 19:23:28 gram Exp $
+ * $Id: gencode.c,v 1.4 2001/12/18 19:09:06 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -57,7 +57,7 @@ dfw_append_read_tree(dfwork_t *dfw, int field_id)
* can re-use registers. */
reg = GPOINTER_TO_UINT(
g_hash_table_lookup(dfw->loaded_fields,
- GUINT_TO_POINTER(field_id)));
+ GINT_TO_POINTER(field_id)));
if (reg) {
/* Reg's are stored in has as reg+1, so
* that the non-existence of a field_id in
@@ -70,6 +70,10 @@ dfw_append_read_tree(dfwork_t *dfw, int field_id)
g_hash_table_insert(dfw->loaded_fields,
GUINT_TO_POINTER(field_id),
GUINT_TO_POINTER(reg + 1));
+
+ /* Record the FIELD_ID in hash of interesting fields. */
+ g_hash_table_insert(dfw->interesting_fields,
+ GINT_TO_POINTER(field_id), GUINT_TO_POINTER(TRUE));
}
insn = dfvm_insn_new(READ_TREE);
@@ -232,6 +236,11 @@ gen_test(dfwork_t *dfw, stnode_t *st_node)
insn = dfvm_insn_new(CHECK_EXISTS);
insn->arg1 = val1;
dfw_append_insn(dfw, insn);
+
+ /* Record the FIELD_ID in hash of interesting fields. */
+ g_hash_table_insert(dfw->interesting_fields,
+ GINT_TO_POINTER(hfinfo->id), GUINT_TO_POINTER(TRUE));
+
break;
case TEST_OP_NOT:
@@ -312,7 +321,44 @@ dfw_gencode(dfwork_t *dfw)
{
dfw->insns = g_ptr_array_new();
dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
+ dfw->interesting_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
gencode(dfw, dfw->st_root);
dfw_append_insn(dfw, dfvm_insn_new(RETURN));
}
+
+
+typedef struct {
+ int i;
+ int *fields;
+} hash_key_iterator;
+
+static void
+get_hash_key(gpointer key, gpointer value, gpointer user_data)
+{
+ int field_id = GPOINTER_TO_INT(key);
+ hash_key_iterator *hki = user_data;
+
+ hki->fields[hki->i] = field_id;
+ hki->i++;
+}
+
+int*
+dfw_interesting_fields(dfwork_t *dfw, int *caller_num_fields)
+{
+ int num_fields = g_hash_table_size(dfw->interesting_fields);
+
+ hash_key_iterator hki;
+
+ if (num_fields == 0) {
+ *caller_num_fields = 0;
+ return NULL;
+ }
+
+ hki.fields = g_new(int, num_fields);
+ hki.i = 0;
+
+ g_hash_table_foreach(dfw->interesting_fields, get_hash_key, &hki);
+ *caller_num_fields = num_fields;
+ return hki.fields;
+}
diff --git a/epan/dfilter/gencode.h b/epan/dfilter/gencode.h
index db56b9082c..2148b2be58 100644
--- a/epan/dfilter/gencode.h
+++ b/epan/dfilter/gencode.h
@@ -4,4 +4,7 @@
void
dfw_gencode(dfwork_t *dfw);
+int*
+dfw_interesting_fields(dfwork_t *dfw, int *caller_num_fields);
+
#endif
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c
index 025d471baa..5afb7b6b0a 100644
--- a/epan/dfilter/semcheck.c
+++ b/epan/dfilter/semcheck.c
@@ -1,5 +1,5 @@
/*
- * $Id: semcheck.c,v 1.6 2001/11/02 10:09:49 guy Exp $
+ * $Id: semcheck.c,v 1.7 2001/12/18 19:09:06 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -32,6 +32,7 @@
#include "sttype-test.h"
#include "exceptions.h"
+#include "packet.h"
static void
semcheck(dfwork_t *dfw, stnode_t *st_node);
diff --git a/epan/epan.c b/epan/epan.c
index 20edfb4b42..4be784e8b2 100644
--- a/epan/epan.c
+++ b/epan/epan.c
@@ -1,6 +1,6 @@
/* epan.h
*
- * $Id: epan.c,v 1.14 2001/12/16 22:16:13 guy Exp $
+ * $Id: epan.c,v 1.15 2001/12/18 19:09:03 gram Exp $
*
* Ethereal Protocol Analyzer Library
*
@@ -11,14 +11,13 @@
#endif
#include <glib.h>
-#include <epan.h>
+#include "epan.h"
+#include "epan_dissect.h"
#include "conversation.h"
-#include "dfilter/dfilter.h"
#include "except.h"
#include "packet.h"
-#include "proto.h"
-#include "tvbuff.h"
+#include "column-utils.h"
/*
* XXX - this takes the plugin directory as an argument, because
@@ -74,37 +73,34 @@ epan_conversation_init(void)
epan_dissect_t*
-epan_dissect_new(void* pseudo_header, const guint8* data, frame_data *fd,
- gboolean create_proto_tree, gboolean proto_tree_visible,
- column_info *cinfo)
+epan_dissect_new(gboolean create_proto_tree, gboolean proto_tree_visible)
{
epan_dissect_t *edt;
edt = g_new(epan_dissect_t, 1);
- /* start with empty data source list */
- if ( fd->data_src)
- g_slist_free( fd->data_src);
- fd->data_src = 0;
-
- /*
- * Set the global "proto_tree_is_visible" to control whether
- * to fill in the text representation field in the protocol
- * tree fields.
- */
- proto_tree_is_visible = proto_tree_visible;
if (create_proto_tree) {
edt->tree = proto_tree_create_root();
+ proto_tree_set_visible(edt->tree, proto_tree_visible);
}
else {
edt->tree = NULL;
}
- dissect_packet(edt, pseudo_header, data, fd, cinfo);
+ return edt;
+}
- proto_tree_is_visible = FALSE;
+void
+epan_dissect_run(epan_dissect_t *edt, void* pseudo_header,
+ const guint8* data, frame_data *fd, column_info *cinfo)
+{
+ /* start with empty data source list */
+ if (fd->data_src) {
+ g_slist_free(fd->data_src);
+ }
+ fd->data_src = NULL;
- return edt;
+ dissect_packet(edt, pseudo_header, data, fd, cinfo);
}
@@ -122,3 +118,24 @@ epan_dissect_free(epan_dissect_t* edt)
g_free(edt);
}
+
+static void
+prime_dfilter(gpointer data, gpointer user_data)
+{
+ int hfid = GPOINTER_TO_INT(data);
+ proto_tree *tree = user_data;
+
+ proto_tree_prime_hfid(tree, hfid);
+}
+
+void
+epan_dissect_prime_dfilter(epan_dissect_t *edt, dfilter_t* dfcode)
+{
+ dfilter_foreach_interesting_field(dfcode, prime_dfilter, edt->tree);
+}
+
+void
+epan_dissect_fill_in_columns(epan_dissect_t *edt)
+{
+ fill_in_columns(&edt->pi);
+}
diff --git a/epan/epan.h b/epan/epan.h
index f33cb1034e..3a3197f540 100644
--- a/epan/epan.h
+++ b/epan/epan.h
@@ -1,21 +1,37 @@
/* epan.h
*
- * $Id: epan.h,v 1.11 2001/12/16 22:16:13 guy Exp $
+ * $Id: epan.h,v 1.12 2001/12/18 19:09:03 gram Exp $
*
* Ethereal Protocol Analyzer Library
*
+ * Copyright (c) 2001 by Gerald Combs <gerald@ethereal.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
*/
#ifndef EPAN_H
#define EPAN_H
#include <glib.h>
+#include "frame_data.h"
+#include "column_info.h"
-struct _epan_dissect_t;
+typedef struct _epan_dissect_t epan_dissect_t;
-/* XXX - for now */
-#include "packet.h"
-#include "packet_info.h"
+#include "dfilter/dfilter.h"
void epan_init(const char * plugindir, void (register_all_protocols)(void),
void (register_all_handoffs)(void));
@@ -40,24 +56,18 @@ void
epan_free(epan_t*);
+epan_dissect_t*
+epan_dissect_new(gboolean create_proto_tree, gboolean proto_tree_visible);
+void
+epan_dissect_run(epan_dissect_t *edt, void* pseudo_header,
+ const guint8* data, frame_data *fd, column_info *cinfo);
-/* Dissection of a single byte array. Holds tvbuff info as
- * well as proto_tree info. As long as the epan_dissect_t for a byte
- * array is in existence, you must not free or move that byte array,
- * as the structures that the epan_dissect_t contains might have pointers
- * to addresses in your byte array.
- */
-typedef struct _epan_dissect_t {
- tvbuff_t *tvb;
- proto_tree *tree;
- packet_info pi;
-} epan_dissect_t;
+void
+epan_dissect_prime_dfilter(epan_dissect_t *edt, dfilter_t*);
-epan_dissect_t*
-epan_dissect_new(void* pseudo_header, const guint8* data, frame_data *fd,
- gboolean create_proto_tree, gboolean proto_tree_visible,
- column_info *cinfo);
+void
+epan_dissect_fill_in_columns(epan_dissect_t *edt);
void
epan_dissect_free(epan_dissect_t* edt);
diff --git a/epan/epan_dissect.h b/epan/epan_dissect.h
new file mode 100644
index 0000000000..424ea60484
--- /dev/null
+++ b/epan/epan_dissect.h
@@ -0,0 +1,44 @@
+/* epan_dissect.h
+ *
+ * $Id: epan_dissect.h,v 1.1 2001/12/18 19:09:03 gram Exp $
+ *
+ * Ethereal Protocol Analyzer Library
+ *
+ * Copyright (c) 2001 by Gerald Combs <gerald@ethereal.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EPAN_DISSECT_H
+#define EPAN_DISSECT_H
+
+#include "tvbuff.h"
+#include "proto.h"
+#include "packet_info.h"
+
+/* Dissection of a single byte array. Holds tvbuff info as
+ * well as proto_tree info. As long as the epan_dissect_t for a byte
+ * array is in existence, you must not free or move that byte array,
+ * as the structures that the epan_dissect_t contains might have pointers
+ * to addresses in your byte array.
+ */
+struct _epan_dissect_t {
+ tvbuff_t *tvb;
+ proto_tree *tree;
+ packet_info pi;
+};
+
+
+#endif /* EPAN_DISSECT_H */
diff --git a/epan/packet.c b/epan/packet.c
index b6f299a0a1..6ef976a430 100644
--- a/epan/packet.c
+++ b/epan/packet.c
@@ -1,7 +1,7 @@
/* packet.c
* Routines for packet disassembly
*
- * $Id: packet.c,v 1.54 2001/12/10 00:26:16 guy Exp $
+ * $Id: packet.c,v 1.55 2001/12/18 19:09:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -79,6 +79,7 @@
#include "resolv.h"
#include "tvbuff.h"
#include "plugins.h"
+#include "epan_dissect.h"
static gint proto_malformed = -1;
static dissector_handle_t frame_handle = NULL;
diff --git a/epan/packet.h b/epan/packet.h
index 812e653cbf..5d4a048c75 100644
--- a/epan/packet.h
+++ b/epan/packet.h
@@ -1,7 +1,7 @@
/* packet.h
* Definitions for packet disassembly structures and routines
*
- * $Id: packet.h,v 1.47 2001/12/10 00:26:16 guy Exp $
+ * $Id: packet.h,v 1.48 2001/12/18 19:09:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -226,7 +226,7 @@ extern void init_all_protocols(void);
/*
* Dissectors should never modify the packet data.
*/
-extern void dissect_packet(struct _epan_dissect_t *edt,
+extern void dissect_packet(epan_dissect_t *edt,
union wtap_pseudo_header *pseudo_header, const u_char *pd,
frame_data *fd, column_info *cinfo);
diff --git a/epan/proto.c b/epan/proto.c
index 0db8366551..56e68454b2 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -1,7 +1,7 @@
/* proto.c
* Routines for protocol tree
*
- * $Id: proto.c,v 1.47 2001/12/07 03:39:26 gram Exp $
+ * $Id: proto.c,v 1.48 2001/12/18 19:09:04 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -73,11 +73,12 @@ static proto_item*
proto_tree_add_node(proto_tree *tree, field_info *fi);
static field_info *
-alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length);
+alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length);
static proto_item *
-proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
- field_info **pfi);
+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(proto_item *pi, const char *format, va_list ap);
@@ -138,6 +139,12 @@ typedef struct {
/* List of all protocols */
static GList *protocols;
+#define INITIAL_NUM_PROTOCOL_HFINFO 200
+#define INITIAL_NUM_FIELD_INFO 100
+#define INITIAL_NUM_PROTO_NODE 100
+#define INITIAL_NUM_ITEM_LABEL 100
+
+
/* Contains information about protocols and header fields. Used when
* dissectors register their data */
static GMemChunk *gmc_hfinfo = NULL;
@@ -146,6 +153,9 @@ static GMemChunk *gmc_hfinfo = NULL;
* proto_tree_add_item. */
static GMemChunk *gmc_field_info = NULL;
+/* Contains the space for proto_nodes. */
+static GMemChunk *gmc_proto_node = NULL;
+
/* String space for protocol and field items for the GUI */
static GMemChunk *gmc_item_labels = NULL;
@@ -160,12 +170,6 @@ gboolean *tree_is_expanded;
/* Number of elements in that array. */
int num_tree_types;
-/* 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.
- */
-gboolean proto_tree_is_visible = FALSE;
-
/* initialize data structures and register protocols and fields */
void
proto_init(const char *plugin_dir,void (register_all_protocols)(void),
@@ -181,6 +185,8 @@ proto_init(const char *plugin_dir,void (register_all_protocols)(void),
g_mem_chunk_destroy(gmc_hfinfo);
if (gmc_field_info)
g_mem_chunk_destroy(gmc_field_info);
+ if (gmc_proto_node)
+ g_mem_chunk_destroy(gmc_proto_node);
if (gmc_item_labels)
g_mem_chunk_destroy(gmc_item_labels);
if (gpa_hfinfo)
@@ -189,13 +195,25 @@ proto_init(const char *plugin_dir,void (register_all_protocols)(void),
g_free(tree_is_expanded);
gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
- sizeof(header_field_info), 50 * sizeof(header_field_info), G_ALLOC_ONLY);
+ sizeof(header_field_info),
+ INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
+ G_ALLOC_ONLY);
+
gmc_field_info = g_mem_chunk_new("gmc_field_info",
- sizeof(struct field_info), 200 * sizeof(struct field_info),
+ sizeof(field_info),
+ INITIAL_NUM_FIELD_INFO * sizeof(field_info),
G_ALLOC_AND_FREE);
+
+ gmc_proto_node = g_mem_chunk_new("gmc_proto_node",
+ sizeof(proto_node),
+ INITIAL_NUM_PROTO_NODE * sizeof(proto_node),
+ G_ALLOC_AND_FREE);
+
gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
- ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
+ ITEM_LABEL_LENGTH,
+ INITIAL_NUM_ITEM_LABEL* ITEM_LABEL_LENGTH,
G_ALLOC_AND_FREE);
+
gpa_hfinfo = g_ptr_array_new();
/* Allocate "tree_is_expanded", with one element for ETT_NONE,
@@ -248,10 +266,14 @@ proto_cleanup(void)
g_mem_chunk_destroy(gmc_hfinfo);
if (gmc_field_info)
g_mem_chunk_destroy(gmc_field_info);
+ if (gmc_proto_node)
+ g_mem_chunk_destroy(gmc_proto_node);
if (gmc_item_labels)
g_mem_chunk_destroy(gmc_item_labels);
if (gpa_hfinfo)
g_ptr_array_free(gpa_hfinfo, TRUE);
+ if (tree_is_expanded != NULL)
+ g_free(tree_is_expanded);
/* Cleanup the ftype subsystem */
ftypes_cleanup();
@@ -261,8 +283,11 @@ proto_cleanup(void)
void
proto_tree_free(proto_tree *tree)
{
+ /* Free all the data pointed to by the tree. */
g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
proto_tree_free_node, NULL);
+
+ /* Then free the tree. */
g_node_destroy((GNode*)tree);
}
@@ -273,20 +298,69 @@ free_field_info(void *fi)
g_mem_chunk_free(gmc_field_info, (field_info*)fi);
}
-static gboolean
-proto_tree_free_node(GNode *node, gpointer data)
+static void
+free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data)
{
- field_info *fi = (field_info*) (node->data);
+ GPtrArray *ptrs = value;
- if (fi != NULL) {
- if (fi->representation) {
- g_mem_chunk_free(gmc_item_labels, fi->representation);
+ g_ptr_array_free(ptrs, TRUE);
+}
+
+static void
+free_node_tree_data(tree_data_t *tree_data)
+{
+ /* Free all the GPtrArray's in the interesting_hfids hash. */
+ g_hash_table_foreach(tree_data->interesting_hfids,
+ free_GPtrArray_value, NULL);
+
+ /* And then destroy the hash. */
+ g_hash_table_destroy(tree_data->interesting_hfids);
+
+ /* And finally the tree_data_t itself. */
+ g_free(tree_data);
+}
+
+static void
+free_node_field_info(field_info* finfo)
+{
+ if (finfo->representation) {
+ g_mem_chunk_free(gmc_item_labels, finfo->representation);
}
- fvalue_free(fi->value);
- free_field_info(fi);
+ fvalue_free(finfo->value);
+ free_field_info(finfo);
+}
+
+static gboolean
+proto_tree_free_node(GNode *node, gpointer data)
+{
+ field_info *finfo = PITEM_FINFO(node);
+
+ if (finfo == NULL) {
+ /* This is the root GNode. Destroy the per-tree data.
+ * There is no field_info to destroy. */
+ free_node_tree_data(PTREE_DATA(node));
+ }
+ else {
+ /* This is a child GNode. Don't free the per-tree data, but
+ * do free the field_info data. */
+ free_node_field_info(finfo);
}
+
+ /* Free the proto_node. */
+ g_mem_chunk_free(gmc_proto_node, GNODE_PNODE(node));
+
return FALSE; /* FALSE = do not end traversal of GNode tree */
-}
+}
+
+/* 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.
+ */
+void
+proto_tree_set_visible(proto_tree *tree, gboolean visible)
+{
+ PTREE_DATA(tree)->visible = visible;
+}
/* Finds a record in the hf_info_records array by id. */
header_field_info*
@@ -451,11 +525,13 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
guint32 value, n;
char *string;
int found_length;
+ GHashTable *hash;
+ GPtrArray *ptrs;
if (!tree)
return(NULL);
- new_fi = alloc_field_info(hfindex, tvb, start, length);
+ new_fi = alloc_field_info(tree, hfindex, tvb, start, length);
if (new_fi == NULL)
return(NULL);
@@ -574,6 +650,14 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
* raised by a tvbuff access method doesn't leave junk in the proto_tree. */
pi = proto_tree_add_node(tree, new_fi);
+ /* 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);
+ }
+
return pi;
}
@@ -588,7 +672,7 @@ proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
if (pi == NULL)
return(NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -691,7 +775,7 @@ proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -767,7 +851,7 @@ proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -830,7 +914,7 @@ proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -893,7 +977,7 @@ proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -956,7 +1040,7 @@ proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -1047,7 +1131,7 @@ proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -1122,7 +1206,7 @@ proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -1191,7 +1275,7 @@ proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -1254,7 +1338,7 @@ proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -1326,7 +1410,7 @@ proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -1413,7 +1497,7 @@ proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint sta
if (pi == NULL)
return (NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->visible = FALSE;
return pi;
@@ -1464,12 +1548,17 @@ proto_tree_set_int(field_info *fi, gint32 value)
static proto_item *
proto_tree_add_node(proto_tree *tree, field_info *fi)
{
- proto_item *pi;
+ GNode *new_gnode;
+ proto_node *pnode;
- pi = (proto_item*) g_node_new(fi);
- g_node_append((GNode*)tree, (GNode*)pi);
+ pnode = g_mem_chunk_alloc(gmc_proto_node);
+ pnode->finfo = fi;
+ pnode->tree_data = PTREE_DATA(tree);
- return pi;
+ new_gnode = g_node_new(pnode);
+ g_node_append((GNode*)tree, new_gnode);
+
+ return (proto_item*) new_gnode;
}
@@ -1481,13 +1570,24 @@ proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint
{
proto_item *pi;
field_info *fi;
+ GHashTable *hash;
+ GPtrArray *ptrs;
if (!tree)
return(NULL);
- fi = alloc_field_info(hfindex, tvb, start, length);
+ fi = alloc_field_info(tree, hfindex, tvb, start, length);
pi = proto_tree_add_node(tree, fi);
+ /* 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);
+ }
+
+ /* Does the caller want to know the fi pointer? */
if (pfi) {
*pfi = fi;
}
@@ -1496,7 +1596,7 @@ proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint
}
static field_info *
-alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length)
+alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length)
{
field_info *fi;
@@ -1517,7 +1617,7 @@ alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length)
}
fi->length = length;
fi->tree_type = ETT_NONE;
- fi->visible = proto_tree_is_visible;
+ fi->visible = PTREE_DATA(tree)->visible;
fi->representation = NULL;
fi->value = fvalue_new(fi->hfinfo->type);
@@ -1537,7 +1637,7 @@ alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length)
static void
proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
{
- field_info *fi = (field_info*) (((GNode*)pi)->data);
+ field_info *fi = PITEM_FINFO(pi);
if (fi->visible) {
fi->representation = g_mem_chunk_alloc(gmc_item_labels);
@@ -1556,7 +1656,7 @@ proto_item_set_text(proto_item *pi, const char *format, ...)
return;
}
- fi = (field_info *)(((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
if (fi->representation)
g_mem_chunk_free(gmc_item_labels, fi->representation);
@@ -1578,7 +1678,7 @@ proto_item_append_text(proto_item *pi, const char *format, ...)
return;
}
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
if (fi->visible) {
va_start(ap, format);
@@ -1603,21 +1703,45 @@ proto_item_set_len(proto_item *pi, gint length)
if (pi == NULL)
return;
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
fi->length = length;
}
int
proto_item_get_len(proto_item *pi)
{
- field_info *fi = (field_info*) (((GNode*)pi)->data);
+ field_info *fi = PITEM_FINFO(pi);
return fi->length;
}
proto_tree*
proto_tree_create_root(void)
{
- return (proto_tree*) g_node_new(NULL);
+ proto_node *pnode;
+
+ /* Initialize the proto_node */
+ pnode = g_mem_chunk_alloc(gmc_proto_node);
+ pnode->finfo = NULL;
+ pnode->tree_data = g_new(tree_data_t, 1);
+
+ /* Initialize the tree_data_t */
+ pnode->tree_data->interesting_hfids =
+ g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ /* Set the default to FALSE so it's easier to
+ * find errors; if we expect to see the protocol tree
+ * but for some reason the default 'visible' is not
+ * changed, then we'll find out very quickly. */
+ pnode->tree_data->visible = FALSE;
+
+ return (proto_tree*) g_node_new(pnode);
+}
+
+void
+proto_tree_prime_hfid(proto_tree *tree, int hfid)
+{
+ g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
+ GINT_TO_POINTER(hfid), g_ptr_array_new());
}
proto_tree*
@@ -1627,7 +1751,7 @@ proto_item_add_subtree(proto_item *pi, gint idx) {
if (!pi)
return(NULL);
- fi = (field_info*) (((GNode*)pi)->data);
+ fi = PITEM_FINFO(pi);
g_assert(idx >= 0 && idx < num_tree_types);
fi->tree_type = idx;
return (proto_tree*) pi;
@@ -2594,7 +2718,7 @@ proto_find_protocol_multi(proto_tree* tree, GNodeTraverseFunc callback,
static gboolean
traverse_subtree_for_field(GNode *node, gpointer data)
{
- field_info *fi = (field_info*) (node->data);
+ field_info *fi = PITEM_FINFO(node);
proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
if (fi) { /* !fi == the top most container node which holds nothing */
@@ -2606,126 +2730,37 @@ traverse_subtree_for_field(GNode *node, gpointer data)
return FALSE; /* keep traversing */
}
-static gboolean
-check_for_protocol_or_field_id(GNode *node, gpointer data)
-{
- field_info *fi = (field_info*) (node->data);
- proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
- header_field_info *hfinfo;
-
- if (fi) { /* !fi == the top most container node which holds nothing */
- /* Is this field one of the fields in the specified list
- * of fields? */
- for (hfinfo = sinfo->target; hfinfo != NULL;
- hfinfo = hfinfo->same_name_next) {
- if (fi->hfinfo == hfinfo) {
- sinfo->result.node = node;
- return TRUE; /* halt traversal */
- }
- }
- }
- return FALSE; /* keep traversing */
-}
-
/* Looks for a protocol or a field in a proto_tree. Returns TRUE if
* it exists anywhere, or FALSE if it exists nowhere. */
gboolean
proto_check_for_protocol_or_field(proto_tree* tree, int id)
{
- proto_tree_search_info sinfo;
- header_field_info *hfinfo;
-
- hfinfo = proto_registrar_get_nth(id);
-
- /* Find the first entry on the list of fields with the same
- * name as this field. */
- while (hfinfo->same_name_prev != NULL)
- hfinfo = hfinfo->same_name_prev;
-
- sinfo.target = hfinfo;
- sinfo.result.node = NULL;
- sinfo.traverse_func = check_for_protocol_or_field_id;
- sinfo.halt_on_first_hit = TRUE;
-
- /* do a quicker check if target is a protocol */
- if (proto_registrar_is_protocol(id) == TRUE) {
- proto_find_protocol_multi(tree, check_for_protocol_or_field_id, &sinfo);
- }
- else {
- /* Go through each protocol subtree. */
- g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
- traverse_subtree_for_field, &sinfo);
- }
-
- if (sinfo.result.node)
- return TRUE;
- else
- return FALSE;
-}
-
-
-
-static gboolean
-get_finfo_ptr_array(GNode *node, gpointer data)
-{
- field_info *fi = (field_info*) (node->data);
- proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
- header_field_info *hfinfo;
+ GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
- if (fi) { /* !fi == the top most container node which holds nothing */
- /* Is this field one of the fields in the specified list
- * of fields? */
- for (hfinfo = sinfo->target; hfinfo != NULL;
- hfinfo = hfinfo->same_name_next) {
- if (fi->hfinfo == hfinfo) {
- if (!sinfo->result.ptr_array) {
- sinfo->result.ptr_array = g_ptr_array_new();
- }
- g_ptr_array_add(sinfo->result.ptr_array,
- (gpointer)fi);
- return FALSE; /* keep traversing */
- }
- }
- }
- return FALSE; /* keep traversing */
+ if (!ptrs) {
+ return FALSE;
+ }
+ else if (g_ptr_array_len(ptrs) > 0) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
}
-/* Return GPtrArray* of field_info pointers for all hfindex that appear in tree
- * (we assume that a field will only appear under its registered parent's subtree) */
+/* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
+ * This only works if the hfindex was "primed" before the dissection
+ * took place, as we just pass back the already-created GPtrArray*.
+ * The caller should *not* free the GPtrArray*; proto_tree_free_node()
+ * handles that. */
GPtrArray*
proto_get_finfo_ptr_array(proto_tree *tree, int id)
{
- proto_tree_search_info sinfo;
- header_field_info *hfinfo;
-
- hfinfo = proto_registrar_get_nth(id);
-
- /* Find the first entry on the list of fields with the same
- * name as this field. */
- while (hfinfo->same_name_prev != NULL)
- hfinfo = hfinfo->same_name_prev;
-
- sinfo.target = hfinfo;
- sinfo.result.ptr_array = NULL;
- sinfo.traverse_func = get_finfo_ptr_array;
- sinfo.halt_on_first_hit = FALSE;
-
- /* do a quicker check if target is a protocol */
- if (proto_registrar_is_protocol(id) == TRUE) {
- proto_find_protocol_multi(tree, get_finfo_ptr_array, &sinfo);
- }
- else {
- /* Go through each protocol subtree. */
- sinfo.traverse_func = get_finfo_ptr_array;
- g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
- traverse_subtree_for_field, &sinfo);
- }
-
- return sinfo.result.ptr_array;
+ return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
+ GINT_TO_POINTER(id));
}
-
typedef struct {
guint offset;
field_info *finfo;
@@ -2735,7 +2770,7 @@ typedef struct {
static gboolean
check_for_offset(GNode *node, gpointer data)
{
- field_info *fi = node->data;
+ field_info *fi = PITEM_FINFO(node);
offset_search_t *offsearch = data;
/* !fi == the top most container node which holds nothing */
diff --git a/epan/proto.h b/epan/proto.h
index 57ed884705..6d86378ff8 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -1,7 +1,7 @@
/* proto.h
* Definitions for protocol display
*
- * $Id: proto.h,v 1.24 2001/12/07 03:39:26 gram Exp $
+ * $Id: proto.h,v 1.25 2001/12/18 19:09:04 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -42,9 +42,6 @@
#include "tvbuff.h"
#include "ftypes/ftypes.h"
-
-typedef GNode proto_tree;
-typedef GNode proto_item;
struct value_string;
#define ITEM_LABEL_LENGTH 240
@@ -107,7 +104,7 @@ typedef struct hf_register_info {
} hf_register_info;
-/* Info stored in each proto_item GNode */
+/* Contains the field information for the proto_item. */
typedef struct field_info {
header_field_info *hfinfo;
gint start;
@@ -119,6 +116,31 @@ typedef struct field_info {
gchar *ds_name; /* data source name */
} field_info;
+/* One of these exists for the entire protocol tree. Each proto_node
+ * in the protocol tree points to the same copy. */
+typedef struct {
+ GHashTable *interesting_hfids;
+ gboolean visible;
+} tree_data_t;
+
+/* Each GNode (proto_tree, proto_item) points to one of
+ * these. */
+typedef struct {
+ field_info *finfo;
+ tree_data_t *tree_data;
+} proto_node;
+
+typedef GNode proto_tree;
+typedef GNode proto_item;
+
+/* Retrieve the proto_node from a GNode. */
+#define GNODE_PNODE(t) ((proto_node*)((GNode*)(t))->data)
+
+/* Retrieve the field_info from a proto_item */
+#define PITEM_FINFO(t) (GNODE_PNODE(t)->finfo)
+
+/* Retrieve the tree_data_t from a proto_tree */
+#define PTREE_DATA(t) (GNODE_PNODE(t)->tree_data)
/* Sets up memory used by proto routines. Called at program startup */
extern void proto_init(const char *plugin_dir,
@@ -153,6 +175,10 @@ extern int proto_item_get_len(proto_item *ti);
/* Creates new proto_tree root */
extern proto_tree* proto_tree_create_root(void);
+/* Mark a field/protocol ID as "interesting". */
+void
+proto_tree_prime_hfid(proto_tree *tree, int hfid);
+
/* Clear memory for entry proto_tree. Clears proto_tree struct also. */
extern void proto_tree_free(proto_tree *tree);
@@ -457,6 +483,9 @@ proto_tree_add_debug_text(proto_tree *tree, const char *format, ...);
extern void
proto_item_fill_label(field_info *fi, gchar *label_str);
+extern void
+proto_tree_set_visible(proto_tree *tree, gboolean visible);
+
/* Returns number of items (protocols or header fields) registered. */
extern int proto_registrar_n(void);