diff options
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | Makefile.nmake | 3 | ||||
-rw-r--r-- | doc/ethereal.pod.template | 12 | ||||
-rw-r--r-- | gtk/Makefile.am | 4 | ||||
-rw-r--r-- | gtk/Makefile.nmake | 1 | ||||
-rw-r--r-- | gtk/menu.c | 5 | ||||
-rw-r--r-- | gtk/proto_hier_stats_dlg.c | 213 | ||||
-rw-r--r-- | gtk/proto_hier_stats_dlg.h | 27 | ||||
-rw-r--r-- | proto_hier_stats.c | 203 | ||||
-rw-r--r-- | proto_hier_stats.h | 27 |
10 files changed, 495 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am index 92151a4bfe..cfbe9ebbdc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.293 2001/03/18 03:34:22 guy Exp $ +# $Id: Makefile.am,v 1.294 2001/03/22 23:54:44 gram Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@zing.org> @@ -371,6 +371,8 @@ ethereal_SOURCES = \ filters.h \ globals.h \ menu.h \ + proto_hier_stats.h \ + proto_hier_stats.c \ simple_dialog.h \ summary.c \ summary.h \ diff --git a/Makefile.nmake b/Makefile.nmake index 9f2307fcd8..d80e50ccc8 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -1,7 +1,7 @@ ## Makefile for building ethereal.exe with Microsoft C and nmake ## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake # -# $Id: Makefile.nmake,v 1.87 2001/03/18 02:13:32 guy Exp $ +# $Id: Makefile.nmake,v 1.88 2001/03/22 23:54:44 gram Exp $ include config.nmake @@ -207,6 +207,7 @@ ethereal_OBJECTS = \ capture.obj \ file.obj \ filters.obj \ + proto_hier_stats.obj \ summary.obj \ tethereal_OBJECTS = \ diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template index 803ce43496..e8b0ef08c5 100644 --- a/doc/ethereal.pod.template +++ b/doc/ethereal.pod.template @@ -401,6 +401,18 @@ packet is a TCP packet to port 12345, using this dialog you can instruct Ethereal to decode all packets to or from that TCP port as HTTP packets. +=item Tools:Protocol Hierarchy Statistics + +This shows the number of packets, and the number of bytes +in those packets, for each protocol in the trace. It +organizes the protocols in the same hierarchy in which +they were found in the trace. Besides counting the packets +in which the protocol exists, a count is also made +for packets in which the protocol is the last protocol in +the stack. These "Last Protocol" counts show you how many packets +(and the byte count associated with those packets) B<ended> in a particular +protocol. + =head2 WINDOWS =over 4 diff --git a/gtk/Makefile.am b/gtk/Makefile.am index acf76f2947..68c3c5d768 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for the GTK interface routines for Ethereal # -# $Id: Makefile.am,v 1.33 2001/02/01 07:34:33 guy Exp $ +# $Id: Makefile.am,v 1.34 2001/03/22 23:54:47 gram Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@zing.org> @@ -82,6 +82,8 @@ libui_a_SOURCES = \ proto_dlg.h \ proto_draw.c \ proto_draw.h \ + proto_hier_stats_dlg.h \ + proto_hier_stats_dlg.c \ simple_dialog.c \ stream_prefs.c \ stream_prefs.h \ diff --git a/gtk/Makefile.nmake b/gtk/Makefile.nmake index c69428bc5a..dfbbb83527 100644 --- a/gtk/Makefile.nmake +++ b/gtk/Makefile.nmake @@ -40,6 +40,7 @@ OBJECTS=capture_dlg.obj \ progress_dlg.obj \ proto_dlg.obj \ proto_draw.obj \ + proto_hier_stats_dlg.obj \ simple_dialog.obj \ stream_prefs.obj \ summary_dlg.obj \ diff --git a/gtk/menu.c b/gtk/menu.c index 443cd06cee..2083b29845 100644 --- a/gtk/menu.c +++ b/gtk/menu.c @@ -1,7 +1,7 @@ /* menu.c * Menu routines * - * $Id: menu.c,v 1.49 2001/02/11 23:02:05 guy Exp $ + * $Id: menu.c,v 1.50 2001/03/22 23:54:47 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -58,6 +58,7 @@ #include "decode_as_dlg.h" #include "help_dlg.h" #include "proto_dlg.h" +#include "proto_hier_stats_dlg.h" #include "keys.h" #include "plugins.h" @@ -150,6 +151,7 @@ static GtkItemFactoryEntry menu_items[] = {"/Tools/_Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, NULL}, /* {"/Tools/Graph", NULL, NULL, 0, NULL}, future use */ {"/Tools/_Summary", NULL, GTK_MENU_FUNC(summary_open_cb), 0, NULL}, + {"/Tools/Protocol Hierarchy Statistics", NULL, GTK_MENU_FUNC(proto_hier_stats_cb), 0, NULL}, {"/_Help", NULL, NULL, 0, "<LastBranch>" }, {"/Help/_Help", NULL, GTK_MENU_FUNC(help_cb), 0, NULL}, {"/Help/<separator>", NULL, NULL, 0, "<Separator>"}, @@ -379,6 +381,7 @@ set_menus_for_captured_packets(gboolean have_captured_packets) set_menu_sensitivity("/Display/Match Selected", have_captured_packets); set_menu_sensitivity("/Display/Colorize Display...", have_captured_packets); set_menu_sensitivity("/Tools/Summary", have_captured_packets); + set_menu_sensitivity("/Tools/Protocol Hierarchy Statistics", have_captured_packets); } /* Enable or disable menu items based on whether a packet is selected. */ diff --git a/gtk/proto_hier_stats_dlg.c b/gtk/proto_hier_stats_dlg.c new file mode 100644 index 0000000000..aceec24b78 --- /dev/null +++ b/gtk/proto_hier_stats_dlg.c @@ -0,0 +1,213 @@ +/* proto_hier_stats_dlg.c + * + * $Id: proto_hier_stats_dlg.c,v 1.1 2001/03/22 23:54:47 gram Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gtk/gtk.h> + +#include "proto_hier_stats.h" +#include "dlg_utils.h" +#include "main.h" + +#define NUM_STAT_COLUMNS 6 + +typedef struct { + + GtkCTree *tree; + GtkCTreeNode *parent; + ph_stats_t *ps; + +} draw_info_t; + + +#define PCT(x,y) (100.0 * (float)(x) / (float)(y)) + +static void +fill_in_ctree_node(GNode *node, gpointer data) +{ + ph_stats_node_t *stats = node->data; + draw_info_t *di = data; + + GtkCTree *tree = di->tree; + GtkCTreeNode *parent = di->parent; + ph_stats_t *ps = di->ps; + + gchar *text[NUM_STAT_COLUMNS]; + gboolean is_leaf; + GtkCTreeNode *new_node; + + draw_info_t child_di; + + if (g_node_n_children(node) > 0) { + is_leaf = FALSE; + } + else { + is_leaf = TRUE; + } + + text[0] = stats->hfinfo->name; + text[1] = g_strdup_printf("%6.2f%%", + PCT(stats->num_pkts_total, ps->tot_packets)); + text[2] = g_strdup_printf("%u", stats->num_pkts_total); + text[3] = g_strdup_printf("%u", stats->num_bytes_total); + text[4] = g_strdup_printf("%u", stats->num_pkts_last); + text[5] = g_strdup_printf("%u", stats->num_bytes_last); + + new_node = gtk_ctree_insert_node(tree, parent, NULL, text, + 5, NULL, NULL, NULL, NULL, + is_leaf, TRUE); + + + g_free(text[1]); + g_free(text[2]); + g_free(text[3]); + g_free(text[4]); + g_free(text[5]); + + child_di.tree = tree; + child_di.parent = new_node; + child_di.ps = ps; + + g_node_children_foreach(node, G_TRAVERSE_ALL, + fill_in_ctree_node, &child_di); + +} + + + +static void +fill_in_ctree(GtkWidget *tree, ph_stats_t *ps) +{ + draw_info_t di; + + di.tree = GTK_CTREE(tree); + di.parent = NULL; + di.ps = ps; + + g_node_children_foreach(ps->stats_tree, G_TRAVERSE_ALL, + fill_in_ctree_node, &di); +} + +static void +create_tree(GtkWidget *container) +{ + GtkWidget *sw, *tree; + ph_stats_t *ps; + int i, height; + gchar *column_titles[NUM_STAT_COLUMNS] = { + "Protocol", + "Percentage Packets", + "Packets", + "Bytes", + "Last-Protocol Packets", + "Last-Protocol Bytes", + }; + + ps = ph_stats_new(); + + /* Scrolled Window */ + sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(container), sw); + + tree = gtk_ctree_new_with_titles(NUM_STAT_COLUMNS, 0, column_titles); + + /* XXX - get 'pos' to set vertical scroll-bar placement. */ + /* XXX - set line style from preferences ???. */ + + /* The titel bars do nothing. */ + gtk_clist_column_titles_passive(GTK_CLIST(tree)); + + /* Auto Resize all columns */ + for (i = 0; i < NUM_STAT_COLUMNS; i++) { + gtk_clist_set_column_auto_resize(GTK_CLIST(tree), i, TRUE); + } + + + /* Right justify numeric columns */ + for (i = 1; i <= 5; i++) { + gtk_clist_set_column_justification(GTK_CLIST(tree), i, + GTK_JUSTIFY_RIGHT); + } + + /* Fill in the data. */ + fill_in_ctree(tree, ps); + + /* Try to size the CTree to a good initial size. + * 5 is a magic number that I pulled out off my hat. + * Using DEF_WIDTH is pretty bogus, too. */ + height = GTK_CLIST(tree)->rows * (GTK_CLIST(tree)->row_height + 5); + gtk_widget_set_usize(tree, DEF_WIDTH, height); + + + gtk_container_add(GTK_CONTAINER(sw), tree); + ph_stats_free(ps); +} + +void +proto_hier_stats_cb(GtkWidget *w, gpointer d) +{ + GtkWidget *dlg, *bt, *vbox, *frame, *bbox; + const gchar *wname = "Protocol Hierarchy Statistics"; + + dlg = dlg_window_new(wname); + + vbox = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(dlg), vbox); + + frame = gtk_frame_new(wname); + /*gtk_container_add(GTK_CONTAINER(vbox), frame);*/ + gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); + + + /* Data section */ + create_tree(frame); + + /* Button row. We put it in an HButtonBox to + * keep it from expanding to the width of the window. */ + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); + /*gtk_container_add(GTK_CONTAINER(vbox), bbox);*/ + gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); + + /* Close button */ + bt = gtk_button_new_with_label("Close"); + gtk_signal_connect_object(GTK_OBJECT(bt), "clicked", + GTK_SIGNAL_FUNC(gtk_widget_destroy), + GTK_OBJECT(dlg)); + gtk_container_add(GTK_CONTAINER(bbox), bt); + GTK_WIDGET_SET_FLAGS(bt, GTK_CAN_DEFAULT); + gtk_widget_grab_default(bt); + dlg_set_cancel(dlg, bt); + + gtk_widget_show_all(dlg); + +} + diff --git a/gtk/proto_hier_stats_dlg.h b/gtk/proto_hier_stats_dlg.h new file mode 100644 index 0000000000..dc124ffec1 --- /dev/null +++ b/gtk/proto_hier_stats_dlg.h @@ -0,0 +1,27 @@ +/* proto_hier_stats_dlg.h + * + * $Id: proto_hier_stats_dlg.h,v 1.1 2001/03/22 23:54:47 gram Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +void +proto_hier_stats_cb(GtkWidget *w, gpointer d); diff --git a/proto_hier_stats.c b/proto_hier_stats.c new file mode 100644 index 0000000000..303d14ee6f --- /dev/null +++ b/proto_hier_stats.c @@ -0,0 +1,203 @@ +/* proto_hier_stats.c + * Routines for calculating statistics based on protocol. + * + * $Id: proto_hier_stats.c,v 1.1 2001/03/22 23:54:44 gram Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "globals.h" +#include "proto_hier_stats.h" +#include <wtap.h> + +#include <stdio.h> +#include <glib.h> + +static GNode* +find_stat_node(GNode *parent_node, header_field_info *needle_hfinfo) +{ + GNode *needle_node; + field_info *finfo; + ph_stats_node_t *stats; + + needle_node = g_node_first_child(parent_node); + + while (needle_node) { + finfo = needle_node->data; + if (finfo && finfo->hfinfo && finfo->hfinfo->id == needle_hfinfo->id) { + return needle_node; + } + needle_node = g_node_next_sibling(needle_node); + } + + /* None found. Create one. */ + stats = g_new(ph_stats_node_t, 1); + + /* Intialize counters */ + stats->hfinfo = needle_hfinfo; + stats->num_pkts_total = 0; + stats->num_pkts_last = 0; + stats->num_bytes_total = 0; + stats->num_bytes_last = 0; + + needle_node = g_node_new(stats); + g_node_append(parent_node, needle_node); + return needle_node; +} + + +static void +process_node(proto_item *proto_node, GNode *parent_stat_node, ph_stats_t *ps, guint pkt_len) +{ + field_info *finfo; + ph_stats_node_t *stats; + proto_item *proto_sibling_node; + GNode *stat_node; + + finfo = proto_node->data; + g_assert(finfo); + + stat_node = find_stat_node(parent_stat_node, finfo->hfinfo); + + /* Assert that the finfo is related to a protocol, not a field. */ + g_assert(finfo->hfinfo->parent == -1); + + stats = stat_node->data; + stats->num_pkts_total++; + stats->num_bytes_total += pkt_len; + + proto_sibling_node = g_node_next_sibling(proto_node); + + if (proto_sibling_node) { + process_node(proto_sibling_node, stat_node, ps, pkt_len); + } + else { + stats->num_pkts_last++; + stats->num_bytes_last += pkt_len; + } +} + + + +static void +process_tree(proto_tree *protocol_tree, ph_stats_t* ps, guint pkt_len) +{ + proto_item *proto_node; + + proto_node = g_node_first_child(protocol_tree); + if (!proto_node) { + return; + } + + process_node(proto_node, ps->stats_tree, ps, pkt_len); +} + +static void +process_frame(frame_data *frame, ph_stats_t* ps) +{ + epan_dissect_t *edt; + union wtap_pseudo_header phdr; + proto_tree *protocol_tree; + guint8 pd[WTAP_MAX_PACKET_SIZE]; + + protocol_tree = proto_tree_create_root(); + + /* Load the frame from the capture file */ + wtap_seek_read(cfile.wth, frame->file_off, &phdr, + pd, frame->cap_len); + + /* Dissect the frame */ + edt = epan_dissect_new(&phdr, pd, frame, protocol_tree); + + /* Get stats from this protocol tree */ + process_tree(protocol_tree, ps, frame->pkt_len); + + /* Free our memory. */ + epan_dissect_free(edt); + proto_tree_free(protocol_tree); +} + + + +ph_stats_t* +ph_stats_new(void) +{ + ph_stats_t *ps; + frame_data *frame; + guint tot_packets, tot_bytes; + + /* Initialize the data */ + ps = g_new(ph_stats_t, 1); + ps->tot_packets = 0; + ps->tot_bytes = 0; + ps->stats_tree = g_node_new(NULL); + + frame = cfile.plist; + tot_packets = 0; + tot_bytes = 0; + + while (frame) { + /* Skip frames that are hidden due to the display filter */ + if (!frame->flags.passed_dfilter) { + continue; + } + + process_frame(frame, ps); + + tot_packets++; + tot_bytes += frame->pkt_len; + + frame = frame->next; + } + + ps->tot_packets = tot_packets; + ps->tot_bytes = tot_bytes; + + return ps; +} + +static gboolean +stat_node_free(GNode *node, gpointer data) +{ + ph_stats_node_t *stats = node->data; + + if (stats) { + g_free(stats); + } +} + +void +ph_stats_free(ph_stats_t *ps) +{ + + if (ps->stats_tree) { + g_node_traverse(ps->stats_tree, G_IN_ORDER, + G_TRAVERSE_ALL, -1, + stat_node_free, NULL); + g_node_destroy(ps->stats_tree); + } + + g_free(ps); +} diff --git a/proto_hier_stats.h b/proto_hier_stats.h new file mode 100644 index 0000000000..257c9e19eb --- /dev/null +++ b/proto_hier_stats.h @@ -0,0 +1,27 @@ + +#ifndef PROTO_HIER_STATS_H +#define PROTO_HIER_STATS_H + +#include "proto.h" + +typedef struct { + header_field_info *hfinfo; + guint num_pkts_total; + guint num_pkts_last; + guint num_bytes_total; + guint num_bytes_last; +} ph_stats_node_t; + + +typedef struct { + guint tot_packets; + guint tot_bytes; + GNode *stats_tree; +} ph_stats_t; + + +ph_stats_t* ph_stats_new(void); + +void ph_stats_free(ph_stats_t *ps); + +#endif |