New tap extension for tethereal : ProtocolHierarchyStatistics.
authorsahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 1 Nov 2002 05:29:36 +0000 (05:29 +0000)
committersahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 1 Nov 2002 05:29:36 +0000 (05:29 +0000)
Similar to what is available on ethereal:/Tools/ProtocolHierarchyStatistics
but this one can handle ALL protocols that tethereal has dissectors for.

Maybe a gtk/gtk2 version of this should replace the existing one in ethereal?

Try -z io,phs   or -z io,phs,<filter>  to test it.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@6532 f5534014-38df-0310-8fa8-9805f1628bb7

Makefile.am
Makefile.nmake
doc/tethereal.pod.template
tap-protohierstat.c [new file with mode: 0644]

index 5f36de3a14dd84e3766176813e78695518ab5a0e..0b96bfa2b733466a44534ee2e936ff2355759bad 100644 (file)
@@ -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
 
index dc4b9caba055357c8eaf08a0c1bd2da289215973..9d472616f453bfb703380eae703fa5ceddd49ce6 100644 (file)
@@ -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
 
index 44d1ad2cc68606e6f64cc3d9afc7fca59a4bd9fb..ec2742d8ab80c09998b65327c88e685081136454 100644 (file)
@@ -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 (file)
index 0000000..a919d51
--- /dev/null
@@ -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);
+}
+