aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/packet-eth.c27
-rw-r--r--epan/dissectors/packet-frame.c28
-rw-r--r--epan/dissectors/packet-ip.c19
-rw-r--r--epan/dissectors/packet-kerberos.c2
-rw-r--r--epan/proto.c158
-rw-r--r--epan/proto.h23
6 files changed, 221 insertions, 36 deletions
diff --git a/epan/dissectors/packet-eth.c b/epan/dissectors/packet-eth.c
index 6f903cc1e1..2e11e6a124 100644
--- a/epan/dissectors/packet-eth.c
+++ b/epan/dissectors/packet-eth.c
@@ -160,7 +160,7 @@ capture_eth(const guchar *pd, int offset, int len, packet_counts *ld)
}
static void
-dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
int fcs_len)
{
proto_item *ti;
@@ -170,6 +170,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
const char *src_addr, *dst_addr;
static eth_hdr ehdrs[4];
static int ehdr_num=0;
+ proto_tree *tree;
ehdr_num++;
if(ehdr_num>=4){
@@ -177,6 +178,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
}
ehdr=&ehdrs[ehdr_num];
+ tree=parent_tree;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Ethernet");
@@ -198,7 +200,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
* a first look before we assume that it's actually an
* Ethernet packet.
*/
- if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree))
+ if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, parent_tree))
goto end_of_eth;
if (ehdr->type <= IEEE_802_3_MAX_LEN) {
@@ -212,7 +214,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
tvb_get_guint8(tvb, 2) == 0x0C &&
tvb_get_guint8(tvb, 3) == 0x00 &&
tvb_get_guint8(tvb, 4) == 0x00 ) {
- dissect_isl(tvb, pinfo, tree, fcs_len);
+ dissect_isl(tvb, pinfo, parent_tree, fcs_len);
goto end_of_eth;
}
}
@@ -263,6 +265,15 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
fh_tree = proto_item_add_subtree(ti, ett_ieee8023);
}
+ /* if IP is not referenced from any filters we dont need to worry about
+ generating any tree items. We must do this after we created the actual
+ protocol above so that proto hier stat still works though.
+ */
+ if(!proto_field_is_referenced(parent_tree, proto_eth)){
+ tree=NULL;
+ fh_tree=NULL;
+ }
+
proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr);
@@ -270,21 +281,21 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 6, 6, src_addr);
- dissect_802_3(ehdr->type, is_802_2, tvb, ETH_HEADER_SIZE, pinfo, tree, fh_tree,
+ dissect_802_3(ehdr->type, is_802_2, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree,
hf_eth_len, hf_eth_trailer, fcs_len);
} else {
if (eth_interpret_as_fw1_monitor) {
if ((dst_addr[0] == 'i') || (dst_addr[0] == 'I') ||
(dst_addr[0] == 'o') || (dst_addr[0] == 'O')) {
- call_dissector(fw1_handle, tvb, pinfo, tree);
+ call_dissector(fw1_handle, tvb, pinfo, parent_tree);
goto end_of_eth;
}
}
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "Ethernet II");
- if (tree) {
- ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
+ if (parent_tree) {
+ ti = proto_tree_add_protocol_format(parent_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
"Ethernet II, Src: %s, Dst: %s",
ether_to_str(src_addr), ether_to_str(dst_addr));
@@ -297,7 +308,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 6, 6, src_addr);
- ethertype(ehdr->type, tvb, ETH_HEADER_SIZE, pinfo, tree, fh_tree, hf_eth_type,
+ ethertype(ehdr->type, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree, hf_eth_type,
hf_eth_trailer, fcs_len);
}
diff --git a/epan/dissectors/packet-frame.c b/epan/dissectors/packet-frame.c
index 2dbe49c286..3630d8aa43 100644
--- a/epan/dissectors/packet-frame.c
+++ b/epan/dissectors/packet-frame.c
@@ -73,12 +73,15 @@ static const value_string p2p_dirs[] = {
static dissector_table_t wtap_encap_dissector_table;
static void
-dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
- proto_tree *fh_tree;
+ proto_tree *fh_tree=NULL;
proto_item *volatile ti = NULL;
nstime_t ts;
int cap_len, pkt_len;
+ proto_tree *tree;
+
+ tree=parent_tree;
pinfo->current_proto = "Frame";
@@ -123,7 +126,6 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* Put in frame header information. */
if (tree) {
-
cap_len = tvb_length(tvb);
pkt_len = tvb_reported_length(tvb);
@@ -131,7 +133,19 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
"Frame %u (%u bytes on wire, %u bytes captured)", pinfo->fd->num, pkt_len, cap_len);
fh_tree = proto_item_add_subtree(ti, ett_frame);
+ }
+
+ /* if IP is not referenced from any filters we dont need to worry about
+ generating any tree items. We must do this after we created the actual
+ protocol above so that proto hier stat still works though.
+ */
+ if(!proto_field_is_referenced(tree, proto_frame)){
+ tree=NULL;
+ fh_tree = NULL;
+ }
+
+ if (fh_tree) {
proto_tree_add_boolean_hidden(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked);
if(pinfo->fd->flags.ref_time){
@@ -187,18 +201,18 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
TRY {
if (!dissector_try_port(wtap_encap_dissector_table, pinfo->fd->lnk_t,
- tvb, pinfo, tree)) {
+ tvb, pinfo, parent_tree)) {
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %u",
pinfo->fd->lnk_t);
- call_dissector(data_handle,tvb, pinfo, tree);
+ call_dissector(data_handle,tvb, pinfo, parent_tree);
}
}
CATCH_ALL {
- show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
+ show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
}
ENDTRY;
@@ -210,7 +224,7 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tap_queue_packet(frame_tap, pinfo, NULL);
- if (mate_handle) call_dissector(mate_handle,tvb, pinfo, tree);
+ if (mate_handle) call_dissector(mate_handle,tvb, pinfo, parent_tree);
}
diff --git a/epan/dissectors/packet-ip.c b/epan/dissectors/packet-ip.c
index 2292eeeb15..f762edb76f 100644
--- a/epan/dissectors/packet-ip.c
+++ b/epan/dissectors/packet-ip.c
@@ -814,7 +814,7 @@ static guint16 ip_checksum(const guint8 *ptr, int len)
}
static void
-dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
proto_tree *ip_tree = NULL, *field_tree;
proto_item *ti = NULL, *tf;
@@ -833,6 +833,9 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
e_ip *iph;
const guchar *src_addr, *dst_addr;
guint32 src32, dst32;
+ proto_tree *tree;
+
+ tree=parent_tree;
eip_current++;
if(eip_current==4){
@@ -856,6 +859,14 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
hi_nibble(iph->ip_v_hl));
}
+ /* if IP is not referenced from any filters we dont need to worry about
+ generating any tree items. We must do this after we created the actual
+ protocol above so that proto hier stat still works though.
+ */
+ if(!proto_field_is_referenced(parent_tree, proto_ip)){
+ tree=NULL;
+ }
+
if (hlen < IPH_MIN_LEN) {
if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
@@ -1088,7 +1099,7 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
- tree);
+ parent_tree);
pinfo->fragmented = save_fragmented;
goto end_of_ip;
}
@@ -1100,13 +1111,13 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
even be labelled as an IP frame; ideally, if a frame being dissected
throws an exception, it'll be labelled as a mangled frame of the
type in question. */
- if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
+ if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, parent_tree)) {
/* Unknown protocol */
if (update_col_info) {
if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
}
- call_dissector(data_handle,next_tvb, pinfo, tree);
+ call_dissector(data_handle,next_tvb, pinfo, parent_tree);
}
pinfo->fragmented = save_fragmented;
diff --git a/epan/dissectors/packet-kerberos.c b/epan/dissectors/packet-kerberos.c
index 3145c066e2..aeaaa9b955 100644
--- a/epan/dissectors/packet-kerberos.c
+++ b/epan/dissectors/packet-kerberos.c
@@ -3673,7 +3673,7 @@ static ber_sequence_t ERROR_sequence[] = {
dissect_krb5_e_checksum }, /* used by PacketCable */
{ 0, 0, 0, NULL }
};
-static int
+int
dissect_krb5_ERROR(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
{
offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, ERROR_sequence, -1, -1);
diff --git a/epan/proto.c b/epan/proto.c
index e45a77e963..eba7cb41ac 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -48,6 +48,35 @@
#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);
@@ -187,6 +216,10 @@ static SLAB_FREE_LIST_DEFINE(item_label_t)
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 {
@@ -426,6 +459,23 @@ static void
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);
}
@@ -483,9 +533,32 @@ proto_tree_set_visible(proto_tree *tree, gboolean visible)
PTREE_DATA(tree)->visible = visible;
}
-#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
- DISSECTOR_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 ethereal, 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*
@@ -667,6 +740,8 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
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)
@@ -891,10 +966,12 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
/* 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) {
+ 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;
@@ -992,6 +1069,8 @@ proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
@@ -1065,6 +1144,8 @@ proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
hfinfo->type == FT_RELATIVE_TIME);
@@ -1127,6 +1208,8 @@ proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
@@ -1188,6 +1271,8 @@ proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
@@ -1249,6 +1334,8 @@ proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
@@ -1334,6 +1421,8 @@ proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
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);
@@ -1436,6 +1525,8 @@ proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
@@ -1503,6 +1594,8 @@ proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
@@ -1564,6 +1657,8 @@ proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
@@ -1625,6 +1720,8 @@ proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
@@ -1686,6 +1783,8 @@ proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
switch(hfinfo->type) {
case FT_UINT8:
@@ -1772,6 +1871,8 @@ proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
@@ -1811,6 +1912,8 @@ proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gin
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
switch(hfinfo->type) {
case FT_INT8:
@@ -1896,6 +1999,8 @@ proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
if (!tree)
return (NULL);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
@@ -1988,10 +2093,12 @@ proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
/* 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) {
+ 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? */
@@ -2299,10 +2406,26 @@ proto_tree_create_root(void)
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) {
@@ -2314,6 +2437,7 @@ proto_item_add_subtree(proto_item *pi, gint idx) {
fi = PITEM_FINFO(pi);
DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
fi->tree_type = idx;
+
return (proto_tree*) pi;
}
@@ -2331,14 +2455,16 @@ proto_item_get_subtree(proto_item *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;
@@ -2351,7 +2477,8 @@ proto_item_get_parent_nth(proto_item *ti, int gen) {
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;
}
@@ -2445,6 +2572,7 @@ proto_register_protocol(char *name, char *short_name, char *filter_name)
hfinfo->strings = protocol;
hfinfo->bitmask = 0;
hfinfo->bitshift = 0;
+ hfinfo->ref_count = 0;
hfinfo->blurb = "";
hfinfo->parent = -1; /* this field differentiates protos and fields */
diff --git a/epan/proto.h b/epan/proto.h
index db01f62935..30564b23da 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -154,6 +154,12 @@ struct _header_field_info {
/* ------- set by proto routines (prefilled by HFILL macro, see below) ------ */
int id; /**< Field ID */
int parent; /**< parent protocol tree */
+ /* This field keeps track of whether a field is
+ * referenced in any filter or not and if so how
+ * many times. If a filter is being referenced the
+ * refcount for the parent protocol is updated as well
+ */
+ int ref_count; /**< is this field referenced by a filter or not */
int bitshift; /**< bits to shift (FT_BOOLEAN only) */
header_field_info *same_name_next; /**< Link to next hfinfo with same abbrev*/
header_field_info *same_name_prev; /**< Link to previous hfinfo with same abbrev*/
@@ -164,7 +170,7 @@ struct _header_field_info {
* _header_field_info. If new fields are added or removed, it should
* be changed as necessary.
*/
-#define HFILL 0, 0, 0, NULL, NULL
+#define HFILL 0, 0, 0, 0, NULL, NULL
/** Used when registering many fields at once, using proto_register_field_array() */
typedef struct hf_register_info {
@@ -265,6 +271,21 @@ extern void proto_init(const char *plugin_dir,
/** Frees memory used by proto routines. Called at program shutdown */
extern void proto_cleanup(void);
+/** This function takes a tree and a protocol id as parameter and
+ will return TRUE/FALSE for whether the protocol or any of the filterable
+ fields in the protocol is referenced by any fitlers.
+ If this function returns FALSE then it is safe to skip any
+ proto_tree_add_...() calls and just treat the call as if the
+ dissector was called with tree==NULL.
+ If you reset the tree to NULL by this dissector returning FALSE,
+ you will still need to call any subdissector with the original value of
+ tree or filtering will break.
+
+ The purpose of this is to optimize ethereal for speed and make it
+ faster for when filters are being used.
+*/
+extern gboolean proto_field_is_referenced(proto_tree *tree, int proto_id);
+
/** Create a subtree under an existing item.