diff options
-rw-r--r-- | epan/dissectors/packet-eth.c | 27 | ||||
-rw-r--r-- | epan/dissectors/packet-frame.c | 28 | ||||
-rw-r--r-- | epan/dissectors/packet-ip.c | 19 | ||||
-rw-r--r-- | epan/dissectors/packet-kerberos.c | 2 | ||||
-rw-r--r-- | epan/proto.c | 158 | ||||
-rw-r--r-- | epan/proto.h | 23 |
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. |