tshark: Add endpoints statistics

"stat name" has been official changed to "endpoints" for all dissectors, rather than a mixture of "host"/"endpoints" based on dissector.

Change-Id: If34bcb5165b493948e784ba038ab202803a59843
Reviewed-on: https://code.wireshark.org/review/6154
Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Michael Mann 2014-12-30 23:26:19 -05:00 committed by Anders Broman
parent 07c9492b8d
commit 860cb393d8
26 changed files with 205 additions and 54 deletions

View File

@ -1017,6 +1017,7 @@ set(TSHARK_TAP_SRC
ui/cli/tap-dcerpcstat.c
ui/cli/tap-diameter-avp.c
ui/cli/tap-expert.c
ui/cli/tap-endpoints.c
ui/cli/tap-follow.c
ui/cli/tap-funnel.c
ui/cli/tap-gsm_astat.c

View File

@ -660,7 +660,6 @@ libwireshark.so.0 libwireshark0 #MINVER#
get_host_ipaddr@Base 1.9.1
get_hostlist_filter@Base 1.99.0
get_hostlist_packet_func@Base 1.99.0
get_hostlist_prefix_func@Base 1.99.0
get_hostname6@Base 1.9.1
get_hostname@Base 1.9.1
get_ipv4_hash_table@Base 1.12.0~rc1

View File

@ -873,15 +873,22 @@ Create a table that lists all conversations that could be seen in the
capture. I<type> specifies the conversation endpoint types for which we
want to generate the statistics; currently the supported ones are:
"bluetooth" Bluetooth addresses
"eth" Ethernet addresses
"fc" Fibre Channel addresses
"fddi" FDDI addresses
"ip" IPv4 addresses
"ipv6" IPv6 addresses
"ipx" IPX addresses
"jxta" JXTA message addresses
"ncp" NCP connections
"rsvp" RSVP connections
"sctp" SCTP addresses
"tcp" TCP/IP socket pairs Both IPv4 and IPv6 are supported
"tr" Token Ring addresses
"usb" USB addresses
"udp" UDP/IP socket pairs Both IPv4 and IPv6 are supported
"wlan" IEEE 802.11 addresses
If the optional I<filter> is specified, only those packets that match the
filter will be used in the calculations.
@ -951,6 +958,37 @@ Several fields with same name within one diameter message are supported, e.g. I<
Note: B<tshark -q> option is recommended to suppress default B<tshark> output.
=item B<-z> endpoints,I<type>[,I<filter>]
Create a table that lists all endpoints that could be seen in the
capture. I<type> specifies the endpoint types for which we
want to generate the statistics; currently the supported ones are:
"bluetooth" Bluetooth addresses
"eth" Ethernet addresses
"fc" Fibre Channel addresses
"fddi" FDDI addresses
"ip" IPv4 addresses
"ipv6" IPv6 addresses
"ipx" IPX addresses
"jxta" JXTA message addresses
"ncp" NCP connections
"rsvp" RSVP connections
"sctp" SCTP addresses
"tcp" TCP/IP socket pairs Both IPv4 and IPv6 are supported
"tr" Token Ring addresses
"usb" USB addresses
"udp" UDP/IP socket pairs Both IPv4 and IPv6 are supported
"wlan" IEEE 802.11 addresses
If the optional I<filter> is specified, only those packets that match the
filter will be used in the calculations.
The table is presented with one line for each conversation and displays
the number of packets/bytes in each direction as well as the total
number of packets/bytes. The table is sorted according to the total
number of frames.
=item B<-z> expert[I<,error|,warn|,note|,chat>][I<,filter>]
Collects information about all expert info, and will display them in order,

View File

@ -40,7 +40,6 @@ struct register_ct {
int proto_id; /* protocol id (0-indexed) */
tap_packet_cb conv_func; /* function to be called for new incoming packets for conversation*/
tap_packet_cb host_func; /* function to be called for new incoming packets for hostlist */
host_tap_prefix prefix_func; /* function to provide prefix if different than default (host) */
conv_gui_init_cb conv_gui_init; /* GUI specific function to initialize conversation */
host_gui_init_cb host_gui_init; /* GUI specific function to initialize hostlist */
};
@ -68,12 +67,6 @@ tap_packet_cb get_hostlist_packet_func(register_ct_t* ct)
return ct->host_func;
}
host_tap_prefix get_hostlist_prefix_func(register_ct_t* ct)
{
return ct->prefix_func;
}
static GSList *registered_ct_tables = NULL;
void
@ -102,7 +95,7 @@ dissector_hostlist_init(const char *opt_arg, void* userdata)
GString *cmd_str = g_string_new("");
const char *filter=NULL;
g_string_printf(cmd_str, "%s,%s,", (table->prefix_func != NULL) ? table->prefix_func() : "host", proto_get_protocol_filter_name(table->proto_id));
g_string_printf(cmd_str, "%s,%s,", HOSTLIST_TAP_PREFIX, proto_get_protocol_filter_name(table->proto_id));
if(!strncmp(opt_arg, cmd_str->str, cmd_str->len)){
if (opt_arg[cmd_str->len] == ',') {
filter = opt_arg + cmd_str->len + 1;
@ -145,7 +138,7 @@ insert_sorted_by_table_name(gconstpointer aparam, gconstpointer bparam)
}
void
register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_cb conv_packet_func, tap_packet_cb hostlist_func, host_tap_prefix prefix_func)
register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_cb conv_packet_func, tap_packet_cb hostlist_func)
{
register_ct_t *table;
@ -157,7 +150,6 @@ register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_
table->host_func = hostlist_func;
table->conv_gui_init = NULL;
table->host_gui_init = NULL;
table->prefix_func = prefix_func;
registered_ct_tables = g_slist_insert_sorted(registered_ct_tables, table, insert_sorted_by_table_name);
}
@ -199,8 +191,7 @@ set_host_gui_data(gpointer data, gpointer user_data)
table->host_gui_init = (host_gui_init_cb)user_data;
g_string_printf(host_cmd_str, "%s,%s", (get_hostlist_prefix_func(table) != NULL) ? get_hostlist_prefix_func(table)() : "host",
proto_get_protocol_filter_name(table->proto_id));
g_string_printf(host_cmd_str, "%s,%s", HOSTLIST_TAP_PREFIX, proto_get_protocol_filter_name(table->proto_id));
ui_info.group = REGISTER_STAT_GROUP_ENDPOINT_LIST;
ui_info.title = NULL; /* construct this from the protocol info? */
ui_info.cli_string = host_cmd_str->str;

View File

@ -101,7 +101,6 @@ struct register_ct;
typedef void (*conv_gui_init_cb)(struct register_ct* ct, const char *filter);
typedef void (*host_gui_init_cb)(struct register_ct* host, const char *filter);
typedef const char* (*host_tap_prefix)(void);
/** Structure for information about a registered conversation */
typedef struct register_ct register_ct_t;
@ -144,15 +143,16 @@ typedef struct _hostlist_talker_t {
} hostlist_talker_t;
#define HOSTLIST_TAP_PREFIX "endpoints"
/** Register the conversation table for the conversation and endpoint windows.
*
* @param proto_id is the protocol with conversation
* @param hide_ports hide the port columns
* @param conv_packet_func the registered conversation tap name
* @param hostlist_func the registered hostlist tap name
* @param prefix_func the function if hostlist tap has diffent name than default ("host")
*/
extern void register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_cb conv_packet_func, tap_packet_cb hostlist_func, host_tap_prefix prefix_func);
extern void register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_cb conv_packet_func, tap_packet_cb hostlist_func);
/** Should port columns be hidden?
*
@ -182,13 +182,6 @@ WS_DLL_PUBLIC tap_packet_cb get_conversation_packet_func(register_ct_t* ct);
*/
WS_DLL_PUBLIC tap_packet_cb get_hostlist_packet_func(register_ct_t* ct);
/** Get tap function handler from hostlist
*
* @param ct Registered conversation
* @return tap function handler of conversation
*/
WS_DLL_PUBLIC host_tap_prefix get_hostlist_prefix_func(register_ct_t* ct);
/** get conversation from protocol ID
*
* @param proto_id protocol ID

View File

@ -887,7 +887,7 @@ proto_register_bluetooth(void)
bluetooth_tap = register_tap("bluetooth");
register_conversation_table(proto_bluetooth, TRUE, bluetooth_conversation_packet, bluetooth_hostlist_packet, NULL);
register_conversation_table(proto_bluetooth, TRUE, bluetooth_conversation_packet, bluetooth_hostlist_packet);
}
void

View File

@ -1011,7 +1011,7 @@ proto_register_eth(void)
register_dissector("eth", dissect_eth_maybefcs, proto_eth);
eth_tap = register_tap("eth");
register_conversation_table(proto_eth, TRUE, eth_conversation_packet, eth_hostlist_packet, NULL);
register_conversation_table(proto_eth, TRUE, eth_conversation_packet, eth_hostlist_packet);
register_color_conversation_filter("eth", "Ethernet", eth_color_filter_valid, eth_build_color_filter);
}

View File

@ -1640,7 +1640,7 @@ proto_register_fc(void)
fcsof_handle = register_dissector("fcsof", dissect_fcsof, proto_fcsof);
register_conversation_table(proto_fc, TRUE, fc_conversation_packet, fc_hostlist_packet, NULL);
register_conversation_table(proto_fc, TRUE, fc_conversation_packet, fc_hostlist_packet);
}

View File

@ -523,7 +523,7 @@ proto_register_fddi(void)
&fddi_padding);
fddi_tap = register_tap("fddi");
register_conversation_table(proto_fddi, TRUE, fddi_conversation_packet, fddi_hostlist_packet, NULL);
register_conversation_table(proto_fddi, TRUE, fddi_conversation_packet, fddi_hostlist_packet);
}
void

View File

@ -26521,7 +26521,7 @@ proto_register_ieee80211 (void)
register_init_routine(ieee80211_gas_reassembly_init);
wlan_tap = register_tap("wlan");
register_conversation_table(proto_wlan, TRUE, wlan_conversation_packet, wlan_hostlist_packet, NULL);
register_conversation_table(proto_wlan, TRUE, wlan_conversation_packet, wlan_hostlist_packet);
/* Register configuration options */
wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);

View File

@ -3089,7 +3089,7 @@ proto_register_ip(void)
ip_tap = register_tap("ip");
register_decode_as(&ip_da);
register_conversation_table(proto_ip, TRUE, ip_conversation_packet, ip_hostlist_packet, NULL);
register_conversation_table(proto_ip, TRUE, ip_conversation_packet, ip_hostlist_packet);
register_color_conversation_filter("ip", "IPv4", ip_color_filter_valid, ip_build_color_filter);
}

View File

@ -3028,7 +3028,7 @@ proto_register_ipv6(void)
register_decode_as(&ipv6_da);
register_decode_as(&ipv6_next_header_da);
register_conversation_table(proto_ipv6, TRUE, ipv6_conversation_packet, ipv6_hostlist_packet, NULL);
register_conversation_table(proto_ipv6, TRUE, ipv6_conversation_packet, ipv6_hostlist_packet);
register_color_conversation_filter("ipv6", "IPv6", ipv6_color_filter_valid, ipv6_build_color_filter);
}

View File

@ -1611,7 +1611,7 @@ proto_register_ipx(void)
register_postseq_cleanup_routine(&spx_postseq_cleanup);
ipx_tap=register_tap("ipx");
register_conversation_table(proto_ipx, TRUE, ipx_conversation_packet, ipx_hostlist_packet, NULL);
register_conversation_table(proto_ipx, TRUE, ipx_conversation_packet, ipx_hostlist_packet);
}
void

View File

@ -2367,7 +2367,7 @@ void proto_register_jxta(void)
prefs_register_bool_preference(jxta_module, "sctp.heuristic", "Try to discover JXTA in SCTP connections",
"Enable to inspect SCTP connections for JXTA conversations.", &gSCTP_HEUR);
register_conversation_table(proto_jxta, TRUE, jxta_conversation_packet, jxta_hostlist_packet, NULL);
register_conversation_table(proto_jxta, TRUE, jxta_conversation_packet, jxta_hostlist_packet);
}

View File

@ -1136,7 +1136,7 @@ proto_register_ncp(void)
ncp_tap.hdr=register_tap("ncp");
register_postseq_cleanup_routine(&mncp_postseq_cleanup);
register_conversation_table(proto_ncp, FALSE, ncp_conversation_packet, ncp_hostlist_packet, NULL);
register_conversation_table(proto_ncp, FALSE, ncp_conversation_packet, ncp_hostlist_packet);
}
void

View File

@ -9234,7 +9234,7 @@ proto_register_rsvp(void)
/* Initialization routine for RSVP conversations */
register_init_routine(&rsvp_init_protocol);
register_conversation_table(proto_rsvp, TRUE, rsvp_conversation_packet, rsvp_hostlist_packet, NULL);
register_conversation_table(proto_rsvp, TRUE, rsvp_conversation_packet, rsvp_hostlist_packet);
}
void

View File

@ -4959,7 +4959,7 @@ proto_register_sctp(void)
register_decode_as(&sctp_da_port);
register_decode_as(&sctp_da_ppi);
register_conversation_table(proto_sctp, FALSE, sctp_conversation_packet, sctp_hostlist_packet, NULL);
register_conversation_table(proto_sctp, FALSE, sctp_conversation_packet, sctp_hostlist_packet);
}
void

View File

@ -625,12 +625,6 @@ tcpip_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, co
return 1;
}
static const char*
tcpip_hostlist_prefix(void)
{
return "endpoints";
}
static gboolean
tcp_color_filter_valid(packet_info *pinfo)
{
@ -6001,7 +5995,7 @@ proto_register_tcp(void)
register_decode_as(&tcp_da);
register_conversation_table(proto_tcp, FALSE, tcpip_conversation_packet, tcpip_hostlist_packet, tcpip_hostlist_prefix);
register_conversation_table(proto_tcp, FALSE, tcpip_conversation_packet, tcpip_hostlist_packet);
register_color_conversation_filter("tcp", "TCP", tcp_color_filter_valid, tcp_build_color_filter);
}

View File

@ -803,7 +803,7 @@ proto_register_tr(void)
register_dissector("tr", dissect_tr, proto_tr);
tr_tap=register_tap("tr");
register_conversation_table(proto_tr, TRUE, tr_conversation_packet, tr_hostlist_packet, NULL);
register_conversation_table(proto_tr, TRUE, tr_conversation_packet, tr_hostlist_packet);
}
void

View File

@ -371,12 +371,6 @@ udpip_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, co
return 1;
}
static const char*
udpip_hostlist_prefix(void)
{
return "endpoints";
}
static gboolean
udp_color_filter_valid(packet_info *pinfo)
{
@ -1012,7 +1006,7 @@ proto_register_udp(void)
&udplite_check_checksum);
register_decode_as(&udp_da);
register_conversation_table(proto_udp, FALSE, udpip_conversation_packet, udpip_hostlist_packet, udpip_hostlist_prefix);
register_conversation_table(proto_udp, FALSE, udpip_conversation_packet, udpip_hostlist_packet);
register_color_conversation_filter("udp", "UDP", udp_color_filter_valid, udp_build_color_filter);
register_init_routine(udp_init);

View File

@ -4319,7 +4319,7 @@ proto_register_usb(void)
register_decode_as(&usb_product_da);
register_decode_as(&usb_device_da);
register_conversation_table(proto_usb, TRUE, usb_conversation_packet, usb_hostlist_packet, NULL);
register_conversation_table(proto_usb, TRUE, usb_conversation_packet, usb_hostlist_packet);
}
void

View File

@ -1210,7 +1210,7 @@ main(int argc, char *argv[])
#endif
register_all_tap_listeners();
conversation_table_set_gui_info(init_iousers);
/* hostlist_table_set_gui_info(NULL); XXX - TODO: Provide "GUI" function for TShark */
hostlist_table_set_gui_info(init_hostlists);
/* If invoked with the "-G" flag, we dump out information based on
the argument to the "-G" flag; if no argument is specified,

View File

@ -49,6 +49,7 @@ TSHARK_TAP_SRC = \
tap-comparestat.c \
tap-dcerpcstat.c \
tap-diameter-avp.c \
tap-endpoints.c \
tap-expert.c \
tap-follow.c \
tap-funnel.c \

140
ui/cli/tap-endpoints.c Normal file
View File

@ -0,0 +1,140 @@
/* tap-endpoints.c
* endpoints 2014 Michael Mann
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <epan/packet.h>
#include <epan/tap.h>
#include <epan/stat_tap_ui.h>
#include <epan/conversation_table.h>
#include <ui/cli/tshark-tap.h>
typedef struct _endpoints_t {
const char *type;
const char *filter;
conv_hash_t hash;
} endpoints_t;
static void
endpoints_draw(void *arg)
{
conv_hash_t *hash = (conv_hash_t*)arg;
endpoints_t *iu = (endpoints_t *)hash->user_data;
hostlist_talker_t *host;
guint64 last_frames, max_frames;
guint i;
gboolean display_port = (!strncmp(iu->type, "TCP", 3) || !strncmp(iu->type, "UDP", 3)) ? TRUE : FALSE;
printf("================================================================================\n");
printf("%s Endpoints\n", iu->type);
printf("Filter:%s\n", iu->filter ? iu->filter : "<No Filter>");
printf(" | %sPackets | | Bytes | | Tx Packets | | Tx Bytes | | Rx Packets | | Rx Bytes |\n",
display_port ? "Port || " : "");
max_frames = UINT_MAX;
do {
last_frames = 0;
for (i=0; (iu->hash.conv_array && i < iu->hash.conv_array->len); i++) {
guint64 tot_frames;
host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i);
tot_frames = host->rx_frames + host->tx_frames;
if ((tot_frames > last_frames) && (tot_frames < max_frames)) {
last_frames = tot_frames;
}
}
for (i=0; (iu->hash.conv_array && i < iu->hash.conv_array->len); i++) {
guint64 tot_frames;
host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i);
tot_frames = host->rx_frames + host->tx_frames;
if (tot_frames == last_frames) {
if (display_port) {
printf("%-20s %5s %6" G_GINT64_MODIFIER "u %9" G_GINT64_MODIFIER
"u %6" G_GINT64_MODIFIER "u %9" G_GINT64_MODIFIER "u %6"
G_GINT64_MODIFIER "u %9" G_GINT64_MODIFIER "u \n",
/* XXX - TODO: make name resolution configurable (through gbl_resolv_flags?) */
get_conversation_address(&host->myaddress, TRUE),
/* XXX - TODO: make port resolution configurable (through gbl_resolv_flags?) */
get_conversation_port(host->port, host->ptype, TRUE),
host->tx_frames+host->rx_frames, host->tx_bytes+host->rx_bytes,
host->tx_frames, host->tx_bytes,
host->rx_frames, host->rx_bytes);
} else {
printf("%-20s %6" G_GINT64_MODIFIER "u %9" G_GINT64_MODIFIER
"u %6" G_GINT64_MODIFIER "u %9" G_GINT64_MODIFIER "u %6"
G_GINT64_MODIFIER "u %9" G_GINT64_MODIFIER "u \n",
/* XXX - TODO: make name resolution configurable (through gbl_resolv_flags?) */
get_conversation_address(&host->myaddress, TRUE),
host->tx_frames+host->rx_frames, host->tx_bytes+host->rx_bytes,
host->tx_frames, host->tx_bytes,
host->rx_frames, host->rx_bytes);
}
}
}
max_frames = last_frames;
} while (last_frames);
printf("================================================================================\n");
}
void init_hostlists(struct register_ct *ct, const char *filter)
{
endpoints_t *iu;
GString *error_string;
iu = g_new0(endpoints_t, 1);
iu->type = proto_get_protocol_short_name(find_protocol_by_id(get_conversation_proto_id(ct)));
iu->filter = g_strdup(filter);
iu->hash.user_data = iu;
error_string = register_tap_listener(proto_get_protocol_filter_name(get_conversation_proto_id(ct)), &iu->hash, filter, 0, NULL, get_hostlist_packet_func(ct), endpoints_draw);
if (error_string) {
g_free(iu);
fprintf(stderr, "tshark: Couldn't register endpoint tap: %s\n",
error_string->str);
g_string_free(error_string, TRUE);
exit(1);
}
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: t
* End:
*
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/

View File

@ -25,5 +25,6 @@
#include <epan/conversation_table.h>
extern void init_iousers(struct register_ct* ct, const char *filter);
extern void init_hostlists(struct register_ct* ct, const char *filter);
#endif /* __TSHARK_TAP_H__ */

View File

@ -1353,8 +1353,7 @@ void hostlist_endpoint_cb(register_ct_t* table)
{
char cmd_str[50];
g_snprintf(cmd_str, 50, "%s,%s", (get_hostlist_prefix_func(table) != NULL) ? get_hostlist_prefix_func(table)() : "host",
proto_get_protocol_filter_name(get_conversation_proto_id(table)));
g_snprintf(cmd_str, 50, "%s,%s", HOSTLIST_TAP_PREFIX, proto_get_protocol_filter_name(get_conversation_proto_id(table)));
dissector_hostlist_init(cmd_str, table);
}