forked from osmocom/wireshark
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
9.2 KiB
239 lines
9.2 KiB
tapping with stats_tree
|
|
|
|
Let's suppose that you want to write a tap only to keep counters, and you
|
|
don't want to get involved with GUI programming or maybe you'd like to make
|
|
it a plugin. A stats_tree might be the way to go. The stats_tree module takes
|
|
care of the representation (GUI for Wireshark and text for TShark) of the
|
|
tap data. So there's very little code to write to make a tap listener usable
|
|
from both Wireshark and TShark.
|
|
|
|
First, you should add the TAP to the dissector in question as described in
|
|
README.tapping .
|
|
|
|
Once the dissector in question is "tapped" you have to write the stats tree
|
|
code which is made of three parts:
|
|
|
|
The init callback routine:
|
|
which will be executed before any packet is passed to the tap. Here you
|
|
should create the "static" nodes of your tree. As well as initialize your
|
|
data.
|
|
|
|
The (per)packet callback routine:
|
|
As the tap_packet callback is going to be called for every packet, it
|
|
should be used to increment the counters.
|
|
|
|
The cleanup callback:
|
|
It is called at the destruction of the stats_tree and might be used to
|
|
free ....
|
|
|
|
Other than that the stats_tree should be registered.
|
|
|
|
If you want to make it a plugin, stats_tree_register() should be called by
|
|
plugin_register_tap_listener() read README.plugins for other information
|
|
regarding Wireshark plugins.
|
|
|
|
If you want it as part of the dissector stats_tree_register() can be called
|
|
either by proto_register_xxx() or if you prefer by proto_reg_handoff_xxx().
|
|
|
|
|
|
A small example of a very basic stats_tree plugin follows.
|
|
|
|
----- example stats_tree plugin ------
|
|
/* udpterm_stats_tree.c
|
|
* A small example of stats_tree plugin that counts udp packets by termination
|
|
* 2005, Luis E. G. Ontanon
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gmodule.h>
|
|
|
|
#include <epan/stats_tree.h>
|
|
#include <epan/dissectors/udp.h>
|
|
|
|
static int st_udp_term;
|
|
static gchar* st_str_udp_term = "UDP terminations";
|
|
|
|
/* this one initializes the tree, creating the root nodes */
|
|
extern void udp_term_stats_tree_init(stats_tree* st) {
|
|
/* we create a node under which we'll add every termination */
|
|
st_udp_term = stats_tree_create_node(st, st_str_udp_term, 0, STAT_DT_INT, TRUE);
|
|
}
|
|
|
|
/* this one will be called with every udp packet */
|
|
extern tap_packet_status
|
|
udp_term_stats_tree_packet(stats_tree *st, /* st as it was passed to us */
|
|
packet_info *pinfo, /* we'll fetch the addresses from here */
|
|
epan_dissect_t *edt _U_, /* unused */
|
|
const void *p) /* we'll use this to fetch the ports */
|
|
{
|
|
static guint8 str[128];
|
|
e_udphdr* udphdr = (e_udphdr*) p;
|
|
|
|
/* we increment by one (tick) the root node */
|
|
tick_stat_node(st, st_str_udp_term, 0, FALSE);
|
|
|
|
/* we then tick a node for this src_addr:src_port
|
|
if the node doesn't exists it will be created */
|
|
snprintf(str, sizeof(str),"%s:%u",address_to_str(&pinfo->net_src),udphdr->sport);
|
|
tick_stat_node(st, str, st_udp_term, FALSE);
|
|
|
|
/* same thing for dst */
|
|
snprintf(str, sizeof(str),"%s:%u",address_to_str(&pinfo->net_dst),udphdr->dport);
|
|
tick_stat_node(st, str, st_udp_term, FALSE);
|
|
|
|
return 1;
|
|
}
|
|
|
|
WS_DLL_PUBLIC_DEF const gchar version[] = "0.0";
|
|
|
|
WS_DLL_PUBLIC_DEF void plugin_register_tap_listener(void) {
|
|
|
|
stats_tree_register_plugin("udp", /* the proto we are going to "tap" */
|
|
"udp_terms", /* the abbreviation for this tree (to be used as -z udp_terms,tree) */
|
|
st_str_udp_term, /* the name of the menu and window (use "/" for sub menus)*/
|
|
0, /* tap listener flags for per-packet callback */
|
|
udp_term_stats_tree_packet, /* the per packet callback */
|
|
udp_term_stats_tree_init, /* the init callback */
|
|
NULL ); /* the cleanup callback (in this case there isn't) */
|
|
|
|
}
|
|
|
|
----- END ------
|
|
|
|
the stats_tree API
|
|
==================
|
|
every stats_tree callback has a stats_tree* parameter (st), stats_tree is an obscure
|
|
data structure which should be passed to the api functions.
|
|
|
|
stats_tree_register(tapname, abbr, name, flags, packet_cb, init_cb, cleanup_cb);
|
|
registers a new stats tree with default group REGISTER_STAT_GROUP_UNSORTED
|
|
|
|
stats_tree_register_plugin(tapname, abbr, name, flags, packet_cb, init_cb, cleanup_cb);
|
|
registers a new stats tree from a plugin with the default group
|
|
|
|
stats_tree_register_with_group(tapname, abbr, name, flags, packet_cb, init_cb, cleanup_cb, stat_group);
|
|
registers a new stats tree under a particular stat group
|
|
|
|
stats_tree_parent_id_by_name( st, parent_name)
|
|
returns the id of a candidate parent node given its name
|
|
|
|
|
|
Node functions
|
|
==============
|
|
|
|
All the functions that operate on nodes return a parent_id
|
|
|
|
stats_tree_create_node(st, name, parent_id, datatype, with_children)
|
|
Creates a node in the tree (to be used in the in init_cb)
|
|
name: the name of the new node
|
|
parent_id: the id of the parent_node (NULL for root)
|
|
datatype: datatype of the new node, STAT_DT_INT or STAT_DT_FLOAT. The only
|
|
methods implemented for floats are averages.
|
|
with_children: TRUE if this node will have "dynamically created" children
|
|
(i.e. it will be a candidate parent)
|
|
|
|
|
|
stats_tree_create_node_by_pname(st, name, parent_name, datatype, with_children);
|
|
As before but creates a node using its parent's name
|
|
|
|
|
|
stats_tree_create_range_node(st, name, parent_id, ...)
|
|
stats_tree_create_range_node_string(st, name, parent_id, num_str_ranges, str_ranges)
|
|
stats_tree_range_node_with_pname(st, name, parent_name, ...)
|
|
Creates a node in the tree, that will contain a ranges list.
|
|
example:
|
|
stats_tree_create_range_node(st,name,parent_id,
|
|
"-99","100-199","200-299","300-399","400-", NULL);
|
|
|
|
stats_tree_tick_range(st, name, parent_id, value_in_range);
|
|
stats_tree_tick_range_by_pname(st, name, parent_name, value_in_range)
|
|
Increases by one the ranged node and the sub node to whose range the value belongs
|
|
|
|
|
|
stats_tree_create_pivot(st, name, parent_id);
|
|
stats_tree_create_pivot_by_pname(st, name, parent_name);
|
|
Creates a "pivot node"
|
|
|
|
stats_tree_tick_pivot(st, pivot_id, pivoted_string);
|
|
Each time a pivot node will be ticked it will get increased, and, it will
|
|
increase (or create) the children named as pivoted_string
|
|
|
|
the following will either increase or create a node (with value 1) when called
|
|
|
|
tick_stat_node(st, name, parent_id, with_children)
|
|
increases by one a stat_node
|
|
|
|
increase_stat_node(st, name, parent_id, with_children, value)
|
|
increases by value a stat_node
|
|
|
|
set_stat_node(st, name, parent_id, with_children, value)
|
|
sets the value of a stat_node
|
|
|
|
zero_stat_node(st, name, parent_id, with_children)
|
|
resets to zero a stat_node
|
|
|
|
Averages work by tracking both the number of items added to node (the ticking
|
|
action) and the value of each item added to the node. This is done
|
|
automatically for ranged nodes; for other node types you need to call one of
|
|
the functions below to associate item values with each tick.
|
|
|
|
avg_stat_node_add_value_notick(st, name, parent_id, with_children, value)
|
|
avg_stat_node_add_value_int(st, name, parent_id, with_children, value)
|
|
avg_stat_node_add_value_float(st, name, parent_id, with_children, value)
|
|
|
|
The difference between the above functions is whether the item count is
|
|
increased or not. To properly compute the average you need to either call
|
|
avg_stat_node_add_value or avg_stat_node_add_value_notick combined
|
|
tick_stat_node. The later sequence allows for plug-ins which are compatible
|
|
with older Wireshark versions which ignores avg_stat_node_add_value because
|
|
it does not understand the command. This would result in 0 counts for all
|
|
nodes. It is preferred to use avg_stat_node_add_value if you are not writing
|
|
a plug-in.
|
|
|
|
avg_stat_node_add_value_int is used the same way as tick_stat_node with the
|
|
exception that you now specify an additional value associated with the tick.
|
|
|
|
avg_stat_node_add_value_float is used to compute averages of floats, for nodes
|
|
with the STAT_DT_FLOAT datatype.
|
|
|
|
Do not mix increase_stat_node, set_stat_node or zero_stat_node
|
|
with avg_stat_node_add_value_int as this will lead to incorrect results for the
|
|
average value.
|
|
|
|
stats_tree now also support setting flags per node to control the behaviour
|
|
of these nodes. This can be done using the stat_node_set_flags and
|
|
stat_node_clear_flags functions. Currently these flags are defined:
|
|
|
|
ST_FLG_DEF_NOEXPAND: By default the top-level nodes in a tree are
|
|
automatically expanded in the GUI. Setting this flag on
|
|
such a node prevents the node from automatically
|
|
expanding.
|
|
ST_FLG_SORT_TOP: Nodes with this flag is sorted separately from nodes
|
|
without this flag (in effect partitioning tree into a top
|
|
and bottom half. Each half is sorted normally. Top always
|
|
appear first :)
|
|
|
|
The same node manipulations can also be performed via generic functions:
|
|
|
|
stats_tree_manip_node_int(mode, st, name, parent_id, with_children, value);
|
|
stats_tree_manip_node_float(mode, st, name, parent_id, with_children, value);
|
|
|
|
mode is an enum with the following set of values:
|
|
MN_INCREASE
|
|
MN_SET
|
|
MN_AVERAGE
|
|
MN_AVERAGE_NOTICK
|
|
MN_SET_FLAGS
|
|
MN_CLEAR_FLAGS
|
|
|
|
You can find more examples of these in $srcdir/plugins/epan/stats_tree/pinfo_stats_tree.c
|
|
|
|
Luis E. G. Ontanon.
|