aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.nmake3
-rw-r--r--doc/tethereal.pod.template10
-rw-r--r--tap-protohierstat.c217
4 files changed, 231 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index 5f36de3a14..0b96bfa2b7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal
#
-# $Id: Makefile.am,v 1.514 2002/11/01 01:49:38 sahlberg Exp $
+# $Id: Makefile.am,v 1.515 2002/11/01 05:29:34 sahlberg Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@ethereal.com>
@@ -773,6 +773,7 @@ ethereal_static_LDFLAGS = -Wl,-static
TETHEREAL_TAP_SRC = \
tap-dcerpcstat.c \
tap-iostat.c \
+ tap-protohierstat.c \
tap-rpcstat.c \
tap-rpcprogs.c
diff --git a/Makefile.nmake b/Makefile.nmake
index dc4b9caba0..9d472616f4 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.249 2002/11/01 01:49:38 sahlberg Exp $
+# $Id: Makefile.nmake,v 1.250 2002/11/01 05:29:34 sahlberg Exp $
include config.nmake
include <win32.mak>
@@ -325,6 +325,7 @@ DISSECTOR_OBJECTS = $(DISSECTOR_SRC:.c=.obj)
TETHEREAL_TAP_SRC = \
tap-dcerpcstat.c \
tap-iostat.c \
+ tap-protohierstat.c \
tap-rpcstat.c \
tap-rpcprogs.c
diff --git a/doc/tethereal.pod.template b/doc/tethereal.pod.template
index 44d1ad2cc6..ec2742d8ab 100644
--- a/doc/tethereal.pod.template
+++ b/doc/tethereal.pod.template
@@ -324,6 +324,16 @@ Example: use B<-z dcerpc,rtt,12345778-1234-abcd-ef00-0123456789ac,1.0,ip.addr==1
RTT statistics for a specific host.
+B<-z> io,phs[,I<filter>]
+
+Create Protocol Hierarchy Statistics listing both number of frames and bytes.
+If no I<filter> is specified the statistics will be calculated for all frames.
+If a I<filters> is specified statistics will be only calculated for those
+packets that match the filter.
+
+This option can be used multiple times on the command line.
+
+
B<-z> io,stat,I<interval>[,I<filter>][,I<filter>][,I<filter>]...
Collect frame/bytes statistics for the capture in intervals of I<interval>
diff --git a/tap-protohierstat.c b/tap-protohierstat.c
new file mode 100644
index 0000000000..a919d5110f
--- /dev/null
+++ b/tap-protohierstat.c
@@ -0,0 +1,217 @@
+/* tap-protohierstat.c
+ * protohierstat 2002 Ronnie Sahlberg
+ *
+ * $Id: tap-protohierstat.c,v 1.1 2002/11/01 05:29:34 sahlberg Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * 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.
+ */
+
+/* This module provides ProtocolHierarchyStatistics for tethereal */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+#include "epan/packet_info.h"
+#include "epan/epan_dissect.h"
+#include "epan/proto.h"
+#include "tap.h"
+#include "register.h"
+
+typedef struct _phs_t {
+ struct _phs_t *sibling;
+ struct _phs_t *child;
+ struct _phs_t *parent;
+ char *filter;
+ int protocol;
+ char *proto_name;
+ guint32 frames;
+ guint32 bytes;
+} phs_t;
+
+
+static phs_t *
+new_phs_t(phs_t *parent)
+{
+ phs_t *rs;
+ rs=g_malloc(sizeof(phs_t));
+ rs->sibling=NULL;
+ rs->child=NULL;
+ rs->parent=parent;
+ rs->filter=NULL;
+ rs->protocol=-1;
+ rs->proto_name=NULL;
+ rs->frames=0;
+ rs->bytes=0;
+ return rs;
+}
+
+
+static int
+protohierstat_packet(void *prs, packet_info *pinfo, epan_dissect_t *edt, void *dummy _U_)
+{
+ phs_t *rs=prs;
+ phs_t *tmprs;
+ proto_tree *tree;
+ field_info *fi;
+
+ if(!edt){
+ return 0;
+ }
+ if(!edt->tree){
+ return 0;
+ }
+ if(!edt->tree->children){
+ return 0;
+ }
+
+ for(tree=edt->tree->children;tree;tree=tree->next){
+ fi=PITEM_FINFO(tree);
+
+ /* first time we saw a protocol at this leaf */
+ if(rs->protocol==-1){
+ rs->protocol=fi->hfinfo->id;
+ rs->proto_name=fi->hfinfo->abbrev;
+ rs->frames=1;
+ rs->bytes=pinfo->fd->pkt_len;
+ rs->child=new_phs_t(rs);
+ rs=rs->child;
+ continue;
+ }
+
+ /* find this protocol in the list of siblings */
+ for(tmprs=rs;tmprs;tmprs=tmprs->sibling){
+ if(tmprs->protocol==fi->hfinfo->id){
+ break;
+ }
+ }
+
+ /* not found, then we must add it to the end of the list */
+ if(!tmprs){
+ for(tmprs=rs;tmprs->sibling;tmprs=tmprs->sibling)
+ ;
+ tmprs->sibling=new_phs_t(rs->parent);
+ rs=tmprs->sibling;
+ rs->protocol=fi->hfinfo->id;
+ rs->proto_name=fi->hfinfo->abbrev;
+ } else {
+ rs=tmprs;
+ }
+
+ rs->frames++;
+ rs->bytes+=pinfo->fd->pkt_len;
+
+ if(!rs->child){
+ rs->child=new_phs_t(rs);
+ }
+ rs=rs->child;
+ }
+ return 1;
+}
+
+static void
+phs_draw(phs_t *rs, int indentation)
+{
+ int i;
+ char str[80];
+ for(;rs;rs=rs->sibling){
+ if(rs->protocol==-1){
+ return;
+ }
+ str[0]=0;
+ for(i=0;i<indentation;i++){
+ strcat(str," ");
+ }
+ strcat(str, rs->proto_name);
+ printf("%-40s frames:%d bytes:%d\n",str, rs->frames, rs->bytes);
+ phs_draw(rs->child, indentation+1);
+ }
+}
+
+static void
+protohierstat_draw(void *prs)
+{
+ phs_t *rs=prs;
+
+ printf("\n");
+ printf("===================================================================\n");
+ printf("Protocol Hierarchy Statistics\n");
+ printf("Filter: %s\n\n",rs->filter?rs->filter:"");
+ phs_draw(rs,0);
+ printf("===================================================================\n");
+}
+
+
+static void
+protohierstat_init(char *optarg)
+{
+ phs_t *rs;
+ int pos=0;
+ char *filter=NULL;
+
+ if(!strcmp("io,phs",optarg)){
+ filter="frame";
+ } else if(sscanf(optarg,"io,phs,%n",&pos)==0){
+ if(pos){
+ filter=optarg+pos;
+ } else {
+ /* We must use a filter to guarantee that edt->tree
+ will be populated. "frame" matches everything so
+ that one is used instead of no filter.
+ */
+ filter="frame";
+ }
+ } else {
+ fprintf(stderr, "tethereal: invalid \"-z io,phs[,<filter>]\" argument\n");
+ exit(1);
+ }
+
+ rs=new_phs_t(NULL);
+
+ if(filter){
+ rs->filter=g_malloc(strlen(filter)+1);
+ strcpy(rs->filter, filter);
+ } else {
+ rs->filter=NULL;
+ }
+
+ if(register_tap_listener("frame", rs, filter, NULL, protohierstat_packet, protohierstat_draw)){
+ /* error, we failed to attach to the tap. clean up */
+ g_free(rs->filter);
+ g_free(rs);
+
+ fprintf(stderr,"tethereal: protohierstat_init() failed to attach to tap.\n");
+ exit(1);
+ }
+}
+
+
+void
+register_tap_listener_protohierstat(void)
+{
+ register_ethereal_tap("io,phs", protohierstat_init, NULL, NULL);
+}
+