forked from osmocom/wireshark
epan: Add more bookkeeping for layers
Packet info already contains the notion of layer depth for the current protocol, among all the protocols in the frame. This adds an extra layer number for the protocols that are the same as the current one. Obviously this will only go above one if the protocol is repeated in the stack, such as with IP tunneling. Adds extra logic to track numbers for each protocol in the frame and update them when calling a dissector. The total layer number and protocol layer number are store in the field info structure so they can be used after dissection, namely by display filters.
This commit is contained in:
parent
b53d349583
commit
d517feee74
110
epan/packet.c
110
epan/packet.c
|
@ -729,6 +729,67 @@ struct dissector_handle {
|
|||
protocol_t *protocol;
|
||||
};
|
||||
|
||||
static void
|
||||
add_layer(packet_info *pinfo, int proto_id)
|
||||
{
|
||||
int *proto_layer_num_ptr;
|
||||
|
||||
pinfo->curr_layer_num++;
|
||||
wmem_list_append(pinfo->layers, GINT_TO_POINTER(proto_id));
|
||||
|
||||
/* Increment layer number for this proto id. */
|
||||
if (pinfo->proto_layers == NULL) {
|
||||
pinfo->proto_layers = wmem_map_new(pinfo->pool, g_direct_hash, g_direct_equal);
|
||||
}
|
||||
|
||||
proto_layer_num_ptr = wmem_map_lookup(pinfo->proto_layers, GINT_TO_POINTER(proto_id));
|
||||
if (proto_layer_num_ptr == NULL) {
|
||||
/* Insert new layer */
|
||||
proto_layer_num_ptr = wmem_new(pinfo->pool, int);
|
||||
*proto_layer_num_ptr = 1;
|
||||
wmem_map_insert(pinfo->proto_layers, GINT_TO_POINTER(proto_id), proto_layer_num_ptr);
|
||||
}
|
||||
else {
|
||||
/* Increment layer number */
|
||||
(*proto_layer_num_ptr)++;
|
||||
}
|
||||
pinfo->curr_proto_layer_num = *proto_layer_num_ptr;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_last_layer(packet_info *pinfo, gboolean reduce_count)
|
||||
{
|
||||
int *proto_layer_num_ptr;
|
||||
wmem_list_frame_t *frame;
|
||||
int proto_id;
|
||||
|
||||
if (reduce_count) {
|
||||
pinfo->curr_layer_num--;
|
||||
}
|
||||
|
||||
frame = wmem_list_tail(pinfo->layers);
|
||||
proto_id = GPOINTER_TO_INT(wmem_list_frame_data(frame));
|
||||
wmem_list_remove_frame(pinfo->layers, frame);
|
||||
|
||||
if (reduce_count) {
|
||||
/* Reduce count for removed protocol layer. */
|
||||
proto_layer_num_ptr = wmem_map_lookup(pinfo->proto_layers, GINT_TO_POINTER(proto_id));
|
||||
if (proto_layer_num_ptr && *proto_layer_num_ptr > 0) {
|
||||
(*proto_layer_num_ptr)--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore count for new last (protocol) layer. */
|
||||
frame = wmem_list_tail(pinfo->layers);
|
||||
if (frame) {
|
||||
proto_id = GPOINTER_TO_INT(wmem_list_frame_data(frame));
|
||||
proto_layer_num_ptr = wmem_map_lookup(pinfo->proto_layers, GINT_TO_POINTER(proto_id));
|
||||
ws_assert(proto_layer_num_ptr);
|
||||
pinfo->curr_proto_layer_num = *proto_layer_num_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function will return
|
||||
* old style dissector :
|
||||
* length of the payload or 1 of the payload is empty
|
||||
|
@ -788,10 +849,9 @@ call_dissector_work_error(dissector_handle_t handle, tvbuff_t *tvb,
|
|||
#define PINFO_LAYER_MAX_RECURSION_DEPTH 500
|
||||
|
||||
static int
|
||||
call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo_arg,
|
||||
call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo,
|
||||
proto_tree *tree, gboolean add_proto_name, void *data)
|
||||
{
|
||||
packet_info *pinfo = pinfo_arg;
|
||||
const char *saved_proto;
|
||||
guint16 saved_can_desegment;
|
||||
int len;
|
||||
|
@ -836,8 +896,7 @@ call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo
|
|||
*/
|
||||
/* XXX Should we check for a duplicate layer here? */
|
||||
if (add_proto_name) {
|
||||
pinfo->curr_layer_num++;
|
||||
wmem_list_append(pinfo->layers, GINT_TO_POINTER(proto_get_id(handle->protocol)));
|
||||
add_layer(pinfo, proto_get_id(handle->protocol));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -857,16 +916,13 @@ call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo
|
|||
* tree. Remove it.
|
||||
*/
|
||||
while (wmem_list_count(pinfo->layers) > saved_layers_len) {
|
||||
if (len == 0) {
|
||||
/*
|
||||
* Only reduce the layer number if the dissector
|
||||
* rejected the data. Since tree can be NULL on
|
||||
* the first pass, we cannot check it or it will
|
||||
* break dissectors that rely on a stable value.
|
||||
*/
|
||||
pinfo->curr_layer_num--;
|
||||
}
|
||||
wmem_list_remove_frame(pinfo->layers, wmem_list_tail(pinfo->layers));
|
||||
/*
|
||||
* Only reduce the layer number if the dissector
|
||||
* rejected the data. Since tree can be NULL on
|
||||
* the first pass, we cannot check it or it will
|
||||
* break dissectors that rely on a stable value.
|
||||
*/
|
||||
remove_last_layer(pinfo, len == 0);
|
||||
}
|
||||
}
|
||||
pinfo->current_proto = saved_proto;
|
||||
|
@ -2875,8 +2931,7 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
|
|||
* Add the protocol name to the layers; we'll remove it
|
||||
* if the dissector fails.
|
||||
*/
|
||||
pinfo->curr_layer_num++;
|
||||
wmem_list_append(pinfo->layers, GINT_TO_POINTER(proto_id));
|
||||
add_layer(pinfo, proto_id);
|
||||
}
|
||||
|
||||
pinfo->heur_list_name = hdtbl_entry->list_name;
|
||||
|
@ -2890,16 +2945,13 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
|
|||
* items to the tree so remove it from the list.
|
||||
*/
|
||||
while (wmem_list_count(pinfo->layers) > saved_layers_len) {
|
||||
if (len == 0) {
|
||||
/*
|
||||
* Only reduce the layer number if the dissector
|
||||
* rejected the data. Since tree can be NULL on
|
||||
* the first pass, we cannot check it or it will
|
||||
* break dissectors that rely on a stable value.
|
||||
*/
|
||||
pinfo->curr_layer_num--;
|
||||
}
|
||||
wmem_list_remove_frame(pinfo->layers, wmem_list_tail(pinfo->layers));
|
||||
/*
|
||||
* Only reduce the layer number if the dissector
|
||||
* rejected the data. Since tree can be NULL on
|
||||
* the first pass, we cannot check it or it will
|
||||
* break dissectors that rely on a stable value.
|
||||
*/
|
||||
remove_last_layer(pinfo, len == 0);
|
||||
}
|
||||
}
|
||||
if (len) {
|
||||
|
@ -3368,8 +3420,7 @@ void call_heur_dissector_direct(heur_dtbl_entry_t *heur_dtbl_entry, tvbuff_t *tv
|
|||
/* do NOT change this behavior - wslua uses the protocol short name set here in order
|
||||
to determine which Lua-based heuristic dissector to call */
|
||||
pinfo->current_proto = proto_get_protocol_short_name(heur_dtbl_entry->protocol);
|
||||
pinfo->curr_layer_num++;
|
||||
wmem_list_append(pinfo->layers, GINT_TO_POINTER(proto_get_id(heur_dtbl_entry->protocol)));
|
||||
add_layer(pinfo, proto_get_id(heur_dtbl_entry->protocol));
|
||||
}
|
||||
|
||||
pinfo->heur_list_name = heur_dtbl_entry->list_name;
|
||||
|
@ -3384,8 +3435,7 @@ void call_heur_dissector_direct(heur_dtbl_entry_t *heur_dtbl_entry, tvbuff_t *tv
|
|||
* items to the tree so remove it from the list.
|
||||
*/
|
||||
while (wmem_list_count(pinfo->layers) > saved_layers_len) {
|
||||
pinfo->curr_layer_num--;
|
||||
wmem_list_remove_frame(pinfo->layers, wmem_list_tail(pinfo->layers));
|
||||
remove_last_layer(pinfo, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -132,8 +132,10 @@ typedef struct _packet_info {
|
|||
|
||||
GHashTable *private_table; /**< a hash table passed from one dissector to another */
|
||||
|
||||
wmem_list_t *layers; /**< layers of each protocol */
|
||||
guint8 curr_layer_num; /**< The current "depth" or layer number in the current frame */
|
||||
wmem_list_t *layers; /**< layers of each protocol */
|
||||
wmem_map_t *proto_layers; /** map of proto_id to curr_layer_num. */
|
||||
guint8 curr_layer_num; /**< The current "depth" or layer number in the current frame */
|
||||
guint8 curr_proto_layer_num; /**< The current "depth" or layer number for this dissector in the current frame */
|
||||
guint16 link_number;
|
||||
|
||||
guint16 clnp_srcref; /**< clnp/cotp source reference (can't use srcport, this would confuse tpkt) */
|
||||
|
|
|
@ -6309,6 +6309,9 @@ new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
|
|||
fi->appendix_start = 0;
|
||||
fi->appendix_length = 0;
|
||||
|
||||
fi->total_layer_num = tree->tree_data->pinfo->curr_layer_num;
|
||||
fi->proto_layer_num = tree->tree_data->pinfo->curr_proto_layer_num;
|
||||
|
||||
return fi;
|
||||
}
|
||||
|
||||
|
|
|
@ -798,6 +798,8 @@ typedef struct field_info {
|
|||
item_label_t *rep; /**< string for GUI tree */
|
||||
tvbuff_t *ds_tvb; /**< data source tvbuff */
|
||||
fvalue_t value;
|
||||
int total_layer_num; /**< Hierarchical layer number, for all protocols in the tree. */
|
||||
int proto_layer_num; /**< Protocol layer number, so 1st, 2nd, 3rd, ... for protocol X. */
|
||||
} field_info;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue