From Ronnie Sahlberg: Ethereal support for DCERPCSTAT.
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 25 Oct 2002 01:08:49 +0000 (01:08 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 25 Oct 2002 01:08:49 +0000 (01:08 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@6499 f5534014-38df-0310-8fa8-9805f1628bb7

14 files changed:
doc/ethereal.pod.template
gtk/Makefile.am
gtk/Makefile.nmake
gtk/dcerpc_stat.c [new file with mode: 0644]
gtk/dcerpc_stat.h [new file with mode: 0644]
gtk/main.c
gtk/menu.c
gtk2/Makefile.am
gtk2/dcerpc_stat.c [new file with mode: 0644]
gtk2/dcerpc_stat.h [new file with mode: 0644]
gtk2/main.c
gtk2/menu.c
packet-dcerpc.c
packet-dcerpc.h

index 1db146213f038d42af9353aba052004c8d80aa56..054d2f48cab1fbf7a6b242e83ba162922bd0806a 100644 (file)
@@ -272,6 +272,20 @@ Get B<Ethereal> to collect various types of statistics and display the result
 in a window that updates in semi-real time.
 Currently implemented statistics are:
 
+B<-z> dcerpc,rtt,I<uuid>,I<major>.I<minor>[,I<filter>]
+
+Collect call/reply RTT data for DCERPC interface I<uuid>, 
+version I<major>.I<minor>.
+Data collected is number of calls for each procedure, MinRTT, MaxRTT 
+and AvgRTT. 
+Example: use B<-z dcerpc,rtt,12345778-1234-abcd-ef00-0123456789ac,1.0> to collect data for CIFS SAMR Interface.  
+This option can be used multiple times on the command line. 
+
+If the optional filterstring is provided, the stats will only be calculated
+on those calls that match that filter.
+Example: use B<-z dcerpc,rtt,12345778-1234-abcd-ef00-0123456789ac,1.0,ip.addr==1.2.3.4> to collect SAMR
+RTT statistics for a specific host.
+
 B<-z> rpc,rtt,I<program>,I<version>[,<filter>]
 
 Collect call/reply RTT data for I<program>/I<version>.  Data collected
@@ -551,14 +565,22 @@ If an optional filter string is used only such ONC-RPC request/response pairs
 that match that filter will be used to calculate the statistics. If no filter 
 string is specified all request/response pairs will be used.
 
-Before the statistics are recalculated you must reread the capture file or start a new capture. You can also regenerate the statistics by just applying an empty display filter causing ethereal to reread the packet list.
-
 =item Tools:Statistics:ONC-RPC:Programs
 
 This dialog will open a window showing aggregated RTT statistics for all
 ONC-RPC Programs/versions that exist in the capture file.
 
-Before the statistics are recalculated you must reread the capture file or start a new capture. You can also regenerate the statistics by just applying an empty display filter causing ethereal to reread the packet list.
+=item Tools:Statistics:DCE-RPC:RTT
+
+Open a window to display statistics for an arbitrary DCE-RPC program interface
+and display B<Procedure>, B<Number of Calls>, B<Minimum RTT>, B<Maximum RTT> and B<Average RTT> for all procedures for that program/version.
+These windows opened will update in semi-real time to reflect changes when
+doing live captures or when reading new capture files into B<Ethereal>.
+
+This dialog will also allow an optional filter string to be used.
+If an optional filter string is used only such DCE-RPC request/response pairs 
+that match that filter will be used to calculate the statistics. If no filter 
+string is specified all request/response pairs will be used.
 
 =head2 WINDOWS
 
index 023c9e67c2e60073d02cd3a63dadcb837e85ff9a..7d524a33402fdf49c068ea1616690955032d7b40 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for the GTK interface routines for Ethereal
 #
-# $Id: Makefile.am,v 1.42 2002/09/21 11:36:27 oabad Exp $
+# $Id: Makefile.am,v 1.43 2002/10/25 01:08:46 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@ethereal.com>
@@ -40,6 +40,8 @@ libui_a_SOURCES = \
        color_utils.h   \
        column_prefs.c  \
        column_prefs.h  \
+       dcerpc_stat.c   \
+       dcerpc_stat.h   \
        decode_as_dlg.c \
        decode_as_dlg.h \
        dfilter_expr_dlg.c \
index 4edefe0e00a37af86ee0583085b2eb44efd94de6..8216f889dae083945a2315b010aa3f6fb7ee529a 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.32 2002/10/24 07:08:24 guy Exp $
+# $Id: Makefile.nmake,v 1.33 2002/10/25 01:08:46 guy Exp $
 
 include ..\config.nmake
 
@@ -31,6 +31,7 @@ OBJECTS=capture_dlg.obj \
        colors.obj       \
        color_utils.obj  \
        column_prefs.obj \
+       dcerpc_stat.obj \
        decode_as_dlg.obj \
        dfilter_expr_dlg.obj \
        display_opts.obj \
diff --git a/gtk/dcerpc_stat.c b/gtk/dcerpc_stat.c
new file mode 100644 (file)
index 0000000..2952724
--- /dev/null
@@ -0,0 +1,576 @@
+/* dcerpc_stat.c
+ * dcerpc_stat   2002 Ronnie Sahlberg
+ *
+ * $Id: dcerpc_stat.c,v 1.1 2002/10/25 01:08:46 guy 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 rpc call/reply RTT statistics to tethereal.
+ * It is only used by tethereal and not ethereal
+ *
+ * It serves as an example on how to use the tap api.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include "epan/packet_info.h"
+#include "simple_dialog.h"
+#include "tap.h"
+#include "packet-dcerpc.h"
+#include "dcerpc_stat.h"
+#include "../globals.h"
+
+/* used to keep track of statistics for a specific procedure */
+typedef struct _rpc_procedure_t {
+       GtkWidget *wnum;
+       GtkWidget *wmin;
+       GtkWidget *wmax;
+       GtkWidget *wavg;
+       gchar snum[8];
+       gchar smin[16];
+       gchar smax[16];
+       gchar savg[16];
+       int num;
+       nstime_t min;
+       nstime_t max;
+       nstime_t tot;
+} rpc_procedure_t;
+
+/* used to keep track of the statistics for an entire program interface */
+typedef struct _rpcstat_t {
+       GtkWidget *win;
+       GtkWidget *table;
+       char *prog;
+       e_uuid_t uuid;
+       guint16 ver;
+       guint32 num_procedures;
+       rpc_procedure_t *procedures;
+} rpcstat_t;
+
+
+static int
+uuid_equal(e_uuid_t *uuid1, e_uuid_t *uuid2)
+{
+       if( (uuid1->Data1!=uuid2->Data1)
+         ||(uuid1->Data2!=uuid2->Data2)
+         ||(uuid1->Data3!=uuid2->Data3)
+         ||(uuid1->Data4[0]!=uuid2->Data4[0])
+         ||(uuid1->Data4[1]!=uuid2->Data4[1])
+         ||(uuid1->Data4[2]!=uuid2->Data4[2])
+         ||(uuid1->Data4[3]!=uuid2->Data4[3])
+         ||(uuid1->Data4[4]!=uuid2->Data4[4])
+         ||(uuid1->Data4[5]!=uuid2->Data4[5])
+         ||(uuid1->Data4[6]!=uuid2->Data4[6])
+         ||(uuid1->Data4[7]!=uuid2->Data4[7]) ){
+               return 0;
+       }
+       return 1;
+}
+       
+
+static void
+dcerpcstat_reset(rpcstat_t *rs)
+{
+       guint32 i;
+
+       for(i=0;i<rs->num_procedures;i++){
+               rs->procedures[i].num=0;        
+               rs->procedures[i].min.secs=0;
+               rs->procedures[i].min.nsecs=0;
+               rs->procedures[i].max.secs=0;
+               rs->procedures[i].max.nsecs=0;
+               rs->procedures[i].tot.secs=0;
+               rs->procedures[i].tot.nsecs=0;
+       }
+}
+
+
+static int
+dcerpcstat_packet(rpcstat_t *rs, packet_info *pinfo, epan_dissect_t *edt _U_, dcerpc_info *ri)
+{
+       nstime_t delta;
+       rpc_procedure_t *rp;
+
+       if(!ri->call_data){
+               return 0;
+       }
+       if(!ri->call_data->req_frame){
+               /* we have not seen the request so we dont know the delta*/
+               return 0;
+       }
+       if(ri->call_data->opnum>=rs->num_procedures){
+               /* dont handle this since its outside of known table */
+               return 0;
+       }
+
+       /* we are only interested in reply packets */
+       if(ri->request){
+               return 0;
+       }
+
+       /* we are only interested in certain program/versions */
+       if( (!uuid_equal( (&ri->call_data->uuid), (&rs->uuid)))
+         ||(ri->call_data->ver!=rs->ver)){
+               return 0;
+       }
+
+       rp=&(rs->procedures[ri->call_data->opnum]);
+
+       /* calculate time delta between request and reply */
+       delta.secs=pinfo->fd->abs_secs-ri->call_data->req_time.secs;
+       delta.nsecs=pinfo->fd->abs_usecs*1000-ri->call_data->req_time.nsecs;
+       if(delta.nsecs<0){
+               delta.nsecs+=1000000000;
+               delta.secs--;
+       }
+
+       if((rp->max.secs==0)
+       && (rp->max.nsecs==0) ){
+               rp->max.secs=delta.secs;
+               rp->max.nsecs=delta.nsecs;
+       }
+
+       if((rp->min.secs==0)
+       && (rp->min.nsecs==0) ){
+               rp->min.secs=delta.secs;
+               rp->min.nsecs=delta.nsecs;
+       }
+
+       if( (delta.secs<rp->min.secs)
+       ||( (delta.secs==rp->min.secs)
+         &&(delta.nsecs<rp->min.nsecs) ) ){
+               rp->min.secs=delta.secs;
+               rp->min.nsecs=delta.nsecs;
+       }
+
+       if( (delta.secs>rp->max.secs)
+       ||( (delta.secs==rp->max.secs)
+         &&(delta.nsecs>rp->max.nsecs) ) ){
+               rp->max.secs=delta.secs;
+               rp->max.nsecs=delta.nsecs;
+       }
+       
+       rp->tot.secs += delta.secs;
+       rp->tot.nsecs += delta.nsecs;
+       if(rp->tot.nsecs>1000000000){
+               rp->tot.nsecs-=1000000000;
+               rp->tot.secs++;
+       }
+       rp->num++;
+
+       return 1;
+}
+
+static void
+dcerpcstat_draw(rpcstat_t *rs)
+{
+       guint32 i;
+#ifdef G_HAVE_UINT64
+       guint64 td;
+#else
+       guint32 td;
+#endif
+
+       for(i=0;i<rs->num_procedures;i++){
+               /* scale it to units of 10us.*/
+               /* for long captures with a large tot time, this can overflow on 32bit */
+               td=(int)rs->procedures[i].tot.secs;
+               td=td*100000+(int)rs->procedures[i].tot.nsecs/10000;
+               if(rs->procedures[i].num){
+                       td/=rs->procedures[i].num;
+               } else {
+                       td=0;
+               }
+
+               sprintf(rs->procedures[i].snum,"%d", rs->procedures[i].num);
+               gtk_label_set_text(GTK_LABEL(rs->procedures[i].wnum), rs->procedures[i].snum);
+
+               sprintf(rs->procedures[i].smin,"%3d.%05d", (int)rs->procedures[i].min.secs,rs->procedures[i].min.nsecs/10000);
+               gtk_label_set_text(GTK_LABEL(rs->procedures[i].wmin), rs->procedures[i].smin);
+
+               sprintf(rs->procedures[i].smax,"%3d.%05d", (int)rs->procedures[i].max.secs,rs->procedures[i].max.nsecs/10000);
+               gtk_label_set_text(GTK_LABEL(rs->procedures[i].wmax), rs->procedures[i].smax);
+
+               sprintf(rs->procedures[i].savg,"%3d.%05d", td/100000, td%100000);
+               gtk_label_set_text(GTK_LABEL(rs->procedures[i].wavg), rs->procedures[i].savg);
+
+       }
+}
+
+
+/* since the gtk2 implementation of tap is multithreaded we must protect
+ * remove_tap_listener() from modifying the list while draw_tap_listener()
+ * is running.  the other protected block is in main.c
+ *
+ * there should not be any other critical regions in gtk2
+ */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+static void
+win_destroy_cb(GtkWindow *win _U_, gpointer data)
+{
+       rpcstat_t *rs=(rpcstat_t *)data;
+
+       protect_thread_critical_region();
+       remove_tap_listener(rs);
+       unprotect_thread_critical_region();
+
+       g_free(rs->procedures);
+       g_free(rs);
+}
+
+
+
+/* When called, this function will create a new instance of gtk-dcerpcstat.
+ */
+void
+gtk_dcerpcstat_init(e_uuid_t *uuid, int major, int minor, char *filter)
+{
+       rpcstat_t *rs;
+       guint32 i, max_procs;
+       char title_string[60];
+       char filter_string[256];
+       GtkWidget *vbox;
+       GtkWidget *stat_label;
+       GtkWidget *filter_label;
+       GtkWidget *tmp;
+       dcerpc_sub_dissector *procs;
+
+       rs=g_malloc(sizeof(rpcstat_t));
+       rs->prog=dcerpc_get_proto_name(uuid, (minor<<8)|(major&0xff) );
+       if(!rs->prog){
+               g_free(rs);
+               fprintf(stderr,"tethereal: dcerpcstat_init() Protocol with uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x v%d.%d not supported\n",uuid->Data1,uuid->Data2,uuid->Data3,uuid->Data4[0],uuid->Data4[1],uuid->Data4[2],uuid->Data4[3],uuid->Data4[4],uuid->Data4[5],uuid->Data4[6],uuid->Data4[7],major,minor);
+               exit(1);
+       }
+       procs=dcerpc_get_proto_sub_dissector(uuid, (minor<<8)|(major&0xff) );
+       rs->uuid=*uuid;
+       rs->ver=(minor<<8)|(major&0xff);
+
+       rs->win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       sprintf(title_string,"DCE-RPC RTT Stat for %s version %d.%d", rs->prog, rs->ver&0xff,rs->ver>>8);
+       gtk_window_set_title(GTK_WINDOW(rs->win), title_string);
+       gtk_signal_connect(GTK_OBJECT(rs->win), "destroy", GTK_SIGNAL_FUNC(win_destroy_cb), rs);
+
+       vbox=gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(rs->win), vbox);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+       gtk_widget_show(vbox);
+
+       stat_label=gtk_label_new(title_string);
+       gtk_box_pack_start(GTK_BOX(vbox), stat_label, FALSE, FALSE, 0);
+       gtk_widget_show(stat_label);
+
+       snprintf(filter_string,255,"Filter:%s",filter?filter:"");
+       filter_label=gtk_label_new(filter_string);
+       gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
+       gtk_widget_show(filter_label);
+
+
+       for(i=0,max_procs=0;procs[i].name;i++){
+               if(procs[i].num>max_procs){
+                       max_procs=procs[i].num;
+               }
+       }
+       rs->num_procedures=max_procs+1;
+       rs->procedures=g_malloc(sizeof(rpc_procedure_t)*(rs->num_procedures+1));
+
+       rs->table=gtk_table_new(rs->num_procedures+1, 5, TRUE);
+       gtk_container_add(GTK_CONTAINER(vbox), rs->table);
+
+       tmp=gtk_label_new("Procedure");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 0,1,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
+       gtk_widget_show(tmp);
+
+       tmp=gtk_label_new("Calls");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 1,2,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
+       gtk_widget_show(tmp);
+
+       tmp=gtk_label_new("Min RTT");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 2,3,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
+       gtk_widget_show(tmp);
+
+       tmp=gtk_label_new("Max RTT");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 3,4,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
+       gtk_widget_show(tmp);
+
+       tmp=gtk_label_new("Avg RTT");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 4,5,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
+       gtk_widget_show(tmp);
+
+               for(i=0;i<rs->num_procedures;i++){
+               GtkWidget *tmp;
+               int j;
+               char *proc_name;
+
+               proc_name="unknown";
+               for(j=0;procs[j].name;j++){
+                       if(procs[j].num==i){
+                               proc_name=procs[j].name;
+                       }
+               }
+
+               tmp=gtk_label_new(proc_name);
+               gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 0,1,i+1,i+2);
+               gtk_widget_show(tmp);
+
+               rs->procedures[i].wnum=gtk_label_new("0");
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), rs->procedures[i].wnum, 1,2,i+1,i+2);
+               gtk_label_set_justify(GTK_LABEL(rs->procedures[i].wnum), GTK_JUSTIFY_RIGHT);
+               gtk_widget_show(rs->procedures[i].wnum);
+
+               rs->procedures[i].wmin=gtk_label_new("0");
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), rs->procedures[i].wmin, 2,3,i+1,i+2);
+               gtk_label_set_justify(GTK_LABEL(rs->procedures[i].wmin), GTK_JUSTIFY_RIGHT);
+               gtk_widget_show(rs->procedures[i].wmin);
+
+               rs->procedures[i].wmax=gtk_label_new("0");
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), rs->procedures[i].wmax, 3,4,i+1,i+2);
+               gtk_label_set_justify(GTK_LABEL(rs->procedures[i].wmax), GTK_JUSTIFY_RIGHT);
+               gtk_widget_show(rs->procedures[i].wmax);
+
+               rs->procedures[i].wavg=gtk_label_new("0");
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), rs->procedures[i].wavg, 4,5,i+1,i+2);
+               gtk_label_set_justify(GTK_LABEL(rs->procedures[i].wavg), GTK_JUSTIFY_RIGHT);
+               gtk_widget_show(rs->procedures[i].wavg);
+
+               rs->procedures[i].num=0;        
+               rs->procedures[i].min.secs=0;
+               rs->procedures[i].min.nsecs=0;
+               rs->procedures[i].max.secs=0;
+               rs->procedures[i].max.nsecs=0;
+               rs->procedures[i].tot.secs=0;
+               rs->procedures[i].tot.nsecs=0;
+       }
+
+       gtk_widget_show(rs->table);
+
+
+       if(register_tap_listener("dcerpc", rs, filter, (void*)dcerpcstat_reset, (void*)dcerpcstat_packet, (void*)dcerpcstat_draw)){
+               char str[256];
+               /* error, we failed to attach to the tap. clean up */
+               snprintf(str,255,"Could not attach to tap using filter:%s",filter?filter:"");
+               simple_dialog(ESD_TYPE_WARN, NULL, str);
+               g_free(rs->procedures);
+               g_free(rs);
+               return;
+       }
+
+
+       gtk_widget_show_all(rs->win);
+       redissect_packets(&cfile);
+}
+
+
+
+static e_uuid_t *dcerpc_uuid_program=NULL;
+static guint16 dcerpc_version;
+static GtkWidget *dlg=NULL, *dlg_box;
+static GtkWidget *prog_box;
+static GtkWidget *prog_label, *prog_opt, *prog_menu;
+static GtkWidget *vers_label, *vers_opt, *vers_menu;
+static GtkWidget *filter_box;
+static GtkWidget *filter_label, *filter_entry;
+static GtkWidget *start_button;
+
+
+static void
+dcerpcstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
+{
+       char *filter;
+
+       filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
+       if(filter[0]==0){
+               filter=NULL;
+       }
+       gtk_dcerpcstat_init(dcerpc_uuid_program, dcerpc_version&0xff, dcerpc_version>>8, filter);
+}
+
+
+static void
+dcerpcstat_version_select(GtkWidget *item _U_, gpointer key)
+{
+       int vers=(int)key;
+
+       dcerpc_version=vers;
+}
+
+
+
+
+static void *
+dcerpcstat_find_vers(gpointer *key, gpointer *value _U_, gpointer *user_data _U_)
+{
+       dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
+       GtkWidget *menu_item;
+       char vs[5];
+
+       if(!uuid_equal((&k->uuid), dcerpc_uuid_program)){
+               return NULL;
+       }
+
+       sprintf(vs,"%d.%d",k->ver&0xff,k->ver>>8);
+       menu_item=gtk_menu_item_new_with_label(vs);
+       gtk_signal_connect(GTK_OBJECT(menu_item), "activate", 
+                       GTK_SIGNAL_FUNC(dcerpcstat_version_select), (gpointer)((int)k->ver));
+       gtk_widget_show(menu_item);
+       gtk_menu_append(GTK_MENU(vers_menu), menu_item);
+
+       if(dcerpc_version==0xffff){
+               dcerpc_version=k->ver;
+       }
+
+       return NULL;
+}
+
+
+static void
+dcerpcstat_program_select(GtkWidget *item _U_, gpointer key)
+{
+       dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
+
+       dcerpc_uuid_program=&k->uuid;
+
+       /* change version menu */
+       dcerpc_version=0xffff;
+       gtk_object_destroy(GTK_OBJECT(vers_menu));
+       vers_menu=gtk_menu_new();
+       g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
+       gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
+}
+
+
+static void *
+dcerpcstat_list_programs(gpointer *key, gpointer *value, gpointer *user_data _U_)
+{
+       dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
+       dcerpc_uuid_value *v=(dcerpc_uuid_value *)value;
+       GtkWidget *menu_item;
+
+       menu_item=gtk_menu_item_new_with_label(v->name);
+       gtk_signal_connect(GTK_OBJECT(menu_item), "activate", 
+                       GTK_SIGNAL_FUNC(dcerpcstat_program_select), (gpointer)k);
+
+       gtk_widget_show(menu_item);
+       gtk_menu_append(GTK_MENU(prog_menu), menu_item);
+
+       if(!dcerpc_uuid_program){
+               dcerpc_uuid_program=&k->uuid;
+       }
+
+       return NULL;
+}
+
+
+static void
+dlg_destroy_cb(void)
+{
+       dlg=NULL;
+}
+
+
+void
+gtk_dcerpcstat_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+       /* if the window is already open, bring it to front */
+       if(dlg){
+               gdk_window_raise(dlg->window);
+               return;
+       }
+
+       dlg=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       gtk_window_set_title(GTK_WINDOW(dlg), "DCE-RPC RTT Statistics");
+       gtk_signal_connect(GTK_OBJECT(dlg), "destroy", GTK_SIGNAL_FUNC(dlg_destroy_cb), NULL);
+       dlg_box=gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
+       gtk_widget_show(dlg_box);
+
+
+       prog_box=gtk_hbox_new(FALSE, 10);
+       /* Program label */
+       gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
+       prog_label=gtk_label_new("Program:");
+       gtk_box_pack_start(GTK_BOX(prog_box), prog_label, FALSE, FALSE, 0);
+       gtk_widget_show(prog_label);
+
+       /* Program menu */
+       prog_opt=gtk_option_menu_new();
+       prog_menu=gtk_menu_new();
+       g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_list_programs, NULL);
+       gtk_option_menu_set_menu(GTK_OPTION_MENU(prog_opt), prog_menu);
+       gtk_box_pack_start(GTK_BOX(prog_box), prog_opt, TRUE, TRUE, 0);
+       gtk_widget_show(prog_opt);
+
+       /* Version label */
+       gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
+       vers_label=gtk_label_new("Version:");
+       gtk_box_pack_start(GTK_BOX(prog_box), vers_label, FALSE, FALSE, 0);
+       gtk_widget_show(vers_label);
+
+       /* Version menu */
+       vers_opt=gtk_option_menu_new();
+       vers_menu=gtk_menu_new();
+       dcerpc_version=0xffff;
+       g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
+       gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
+       gtk_box_pack_start(GTK_BOX(prog_box), vers_opt, TRUE, TRUE, 0);
+       gtk_widget_show(vers_opt);
+
+       gtk_box_pack_start(GTK_BOX(dlg_box), prog_box, TRUE, TRUE, 0);
+       gtk_widget_show(prog_box);
+
+
+       /* filter box */
+       filter_box=gtk_hbox_new(FALSE, 10);
+       /* Filter label */
+       gtk_container_set_border_width(GTK_CONTAINER(filter_box), 10);
+       filter_label=gtk_label_new("Filter:");
+       gtk_box_pack_start(GTK_BOX(filter_box), filter_label, FALSE, FALSE, 0);
+       gtk_widget_show(filter_label);
+
+       filter_entry=gtk_entry_new_with_max_length(250);
+       gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, FALSE, FALSE, 0);
+       gtk_widget_show(filter_entry);
+       
+       gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
+       gtk_widget_show(filter_box);
+
+
+       /* the start button */
+       start_button=gtk_button_new_with_label("Create Stat");
+       gtk_signal_connect_object(GTK_OBJECT(start_button), "clicked", 
+                       GTK_SIGNAL_FUNC(dcerpcstat_start_button_clicked),
+                       NULL);
+
+       gtk_box_pack_start(GTK_BOX(dlg_box), start_button, TRUE, TRUE, 0);
+       gtk_widget_show(start_button);
+
+       gtk_widget_show_all(dlg);
+}
+
diff --git a/gtk/dcerpc_stat.h b/gtk/dcerpc_stat.h
new file mode 100644 (file)
index 0000000..2767c0a
--- /dev/null
@@ -0,0 +1,31 @@
+/* dcerpc_stat.h
+ * dcerpc_stat   2002 Ronnie Sahlberg
+ *
+ * $Id: dcerpc_stat.h,v 1.1 2002/10/25 01:08:46 guy 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.
+ */
+
+#ifndef __DCERPCSTAT_H__
+#define __DCERPCSTAT_H__
+
+void gtk_dcerpcstat_init(e_uuid_t *uuid, int major, int minor, char *filter);
+void gtk_dcerpcstat_cb(GtkWidget *w, gpointer d);
+
+#endif
index 395db6b34027db144bccfe6b3d10dda45afc81d7..67fb06a3f1d2271e31b7ed23615e75c4fd5cff74 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.269 2002/10/25 00:29:10 guy Exp $
+ * $Id: main.c,v 1.270 2002/10/25 01:08:46 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "../tap.h"
 #include "rpc_stat.h"
 #include "rpc_progs.h"
+#include "../packet-dcerpc.h"
+#include "dcerpc_stat.h"
 
 #ifdef WIN32
 #include "capture-wpcap.h"
@@ -1691,8 +1693,42 @@ main(int argc, char *argv[])
                 fprintf(stderr, "   \"-z rpc,programs\"\n");
                 exit(1);
               }
+            } else if(!strncmp(optarg,"dcerpc,",7)){
+              if(!strncmp(optarg,"dcerpc,rtt,",11)){
+                e_uuid_t uuid;
+                int d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
+                int major, minor;
+                int pos=0;
+                if(sscanf(optarg,"dcerpc,rtt,%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d%n", &d1,&d2,&d3,&d40,&d41,&d42,&d43,&d44,&d45,&d46,&d47,&major,&minor,&pos)==13){
+                  uuid.Data1=d1;
+                  uuid.Data2=d2;
+                  uuid.Data3=d3;
+                  uuid.Data4[0]=d40;
+                  uuid.Data4[1]=d41;
+                  uuid.Data4[2]=d42;
+                  uuid.Data4[3]=d43;
+                  uuid.Data4[4]=d44;
+                  uuid.Data4[5]=d45;
+                  uuid.Data4[6]=d46;
+                  uuid.Data4[7]=d47;
+                  if(pos){
+                    gtk_dcerpcstat_init(&uuid,major,minor,optarg+pos);
+                  } else {
+                    gtk_dcerpcstat_init(&uuid,major,minor,NULL);
+                  }
+                } else {
+                  fprintf(stderr, "ethereal: invalid \"-z dcerpc,rtt,<uuid>,<major version>.<minor version>[,<filter>]\" argument\n");
+                  exit(1);
+                }
+              } else {
+                fprintf(stderr, "tethereal: invalid -z argument. Argument must be one of:\n");
+                fprintf(stderr, "   \"-z dcerpc,rtt,<uuid>,<major version>.<minor version>[,<filter>]\"\n");
+                exit(1);
+              }
             } else {
-              fprintf(stderr, "ethereal: invalid -z argument. Argument must be \"-z rpc,...\"\n");
+              fprintf(stderr, "ethereal: invalid -z argument. Argument must be one of:\n");
+              fprintf(stderr, "   \"-z rpc,...\"\n");
+              fprintf(stderr, "   \"-z dcerpc,...\"\n");
               exit(1);
             }
             break;
index 51364d1eb97e8cfa31350240157c6585eacd6e2f..5b767af9143d2e61eab59d7ec9a2020e99b2b0da 100644 (file)
@@ -1,7 +1,7 @@
 /* menu.c
  * Menu routines
  *
- * $Id: menu.c,v 1.68 2002/09/07 10:02:31 sahlberg Exp $
+ * $Id: menu.c,v 1.69 2002/10/25 01:08:46 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -59,6 +59,8 @@
 #include <epan/epan_dissect.h>
 #include "rpc_stat.h"
 #include "rpc_progs.h"
+#include "../packet-dcerpc.h"
+#include "dcerpc_stat.h"
 
 GtkWidget *popup_menu_object;
 
@@ -176,6 +178,8 @@ static GtkItemFactoryEntry menu_items[] =
   {"/Tools/Statistics/ONC-RPC", NULL, NULL, 0, "<Branch>", },
   {"/Tools/Statistics/ONC-RPC/RTT", NULL, GTK_MENU_FUNC(gtk_rpcstat_cb), 0, NULL, },
   {"/Tools/Statistics/ONC-RPC/Programs", NULL, GTK_MENU_FUNC(gtk_rpcprogs_init), 0, NULL, },
+  {"/Tools/Statistics/DCE-RPC", NULL, NULL, 0, "<Branch>", },
+  {"/Tools/Statistics/DCE-RPC/RTT", NULL, GTK_MENU_FUNC(gtk_dcerpcstat_cb), 0, NULL, },
   {"/_Help", NULL, NULL, 0, "<LastBranch>" },
   {"/Help/_Help", NULL, GTK_MENU_FUNC(help_cb), 0, NULL},
   {"/Help/<separator>", NULL, NULL, 0, "<Separator>"},
index d553a2a7984df583777d47ce7b133988c4a220d8..edf098587aae67870cf2ba77ee1c7948a98b8b42 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for the GTK2 interface routines for Ethereal
 #
-# $Id: Makefile.am,v 1.5 2002/09/21 11:36:30 oabad Exp $
+# $Id: Makefile.am,v 1.6 2002/10/25 01:08:48 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@ethereal.com>
@@ -40,6 +40,8 @@ libui_a_SOURCES = \
        color_utils.h   \
        column_prefs.c  \
        column_prefs.h  \
+       dcerpc_stat.c   \
+       dcerpc_stat.h   \
        decode_as_dlg.c \
        decode_as_dlg.h \
        dfilter_expr_dlg.c \
diff --git a/gtk2/dcerpc_stat.c b/gtk2/dcerpc_stat.c
new file mode 100644 (file)
index 0000000..93d0c02
--- /dev/null
@@ -0,0 +1,576 @@
+/* dcerpc_stat.c
+ * dcerpc_stat   2002 Ronnie Sahlberg
+ *
+ * $Id: dcerpc_stat.c,v 1.1 2002/10/25 01:08:48 guy 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 rpc call/reply RTT statistics to tethereal.
+ * It is only used by tethereal and not ethereal
+ *
+ * It serves as an example on how to use the tap api.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include "epan/packet_info.h"
+#include "simple_dialog.h"
+#include "tap.h"
+#include "packet-dcerpc.h"
+#include "dcerpc_stat.h"
+#include "../globals.h"
+
+/* used to keep track of statistics for a specific procedure */
+typedef struct _rpc_procedure_t {
+       GtkWidget *wnum;
+       GtkWidget *wmin;
+       GtkWidget *wmax;
+       GtkWidget *wavg;
+       gchar snum[8];
+       gchar smin[16];
+       gchar smax[16];
+       gchar savg[16];
+       int num;
+       nstime_t min;
+       nstime_t max;
+       nstime_t tot;
+} rpc_procedure_t;
+
+/* used to keep track of the statistics for an entire program interface */
+typedef struct _rpcstat_t {
+       GtkWidget *win;
+       GtkWidget *table;
+       char *prog;
+       e_uuid_t uuid;
+       guint16 ver;
+       guint32 num_procedures;
+       rpc_procedure_t *procedures;
+} rpcstat_t;
+
+
+static int
+uuid_equal(e_uuid_t *uuid1, e_uuid_t *uuid2)
+{
+       if( (uuid1->Data1!=uuid2->Data1)
+         ||(uuid1->Data2!=uuid2->Data2)
+         ||(uuid1->Data3!=uuid2->Data3)
+         ||(uuid1->Data4[0]!=uuid2->Data4[0])
+         ||(uuid1->Data4[1]!=uuid2->Data4[1])
+         ||(uuid1->Data4[2]!=uuid2->Data4[2])
+         ||(uuid1->Data4[3]!=uuid2->Data4[3])
+         ||(uuid1->Data4[4]!=uuid2->Data4[4])
+         ||(uuid1->Data4[5]!=uuid2->Data4[5])
+         ||(uuid1->Data4[6]!=uuid2->Data4[6])
+         ||(uuid1->Data4[7]!=uuid2->Data4[7]) ){
+               return 0;
+       }
+       return 1;
+}
+       
+
+static void
+dcerpcstat_reset(rpcstat_t *rs)
+{
+       guint32 i;
+
+       for(i=0;i<rs->num_procedures;i++){
+               rs->procedures[i].num=0;        
+               rs->procedures[i].min.secs=0;
+               rs->procedures[i].min.nsecs=0;
+               rs->procedures[i].max.secs=0;
+               rs->procedures[i].max.nsecs=0;
+               rs->procedures[i].tot.secs=0;
+               rs->procedures[i].tot.nsecs=0;
+       }
+}
+
+
+static int
+dcerpcstat_packet(rpcstat_t *rs, packet_info *pinfo, epan_dissect_t *edt _U_, dcerpc_info *ri)
+{
+       nstime_t delta;
+       rpc_procedure_t *rp;
+
+       if(!ri->call_data){
+               return 0;
+       }
+       if(!ri->call_data->req_frame){
+               /* we have not seen the request so we dont know the delta*/
+               return 0;
+       }
+       if(ri->call_data->opnum>=rs->num_procedures){
+               /* dont handle this since its outside of known table */
+               return 0;
+       }
+
+       /* we are only interested in reply packets */
+       if(ri->request){
+               return 0;
+       }
+
+       /* we are only interested in certain program/versions */
+       if( (!uuid_equal( (&ri->call_data->uuid), (&rs->uuid)))
+         ||(ri->call_data->ver!=rs->ver)){
+               return 0;
+       }
+
+       rp=&(rs->procedures[ri->call_data->opnum]);
+
+       /* calculate time delta between request and reply */
+       delta.secs=pinfo->fd->abs_secs-ri->call_data->req_time.secs;
+       delta.nsecs=pinfo->fd->abs_usecs*1000-ri->call_data->req_time.nsecs;
+       if(delta.nsecs<0){
+               delta.nsecs+=1000000000;
+               delta.secs--;
+       }
+
+       if((rp->max.secs==0)
+       && (rp->max.nsecs==0) ){
+               rp->max.secs=delta.secs;
+               rp->max.nsecs=delta.nsecs;
+       }
+
+       if((rp->min.secs==0)
+       && (rp->min.nsecs==0) ){
+               rp->min.secs=delta.secs;
+               rp->min.nsecs=delta.nsecs;
+       }
+
+       if( (delta.secs<rp->min.secs)
+       ||( (delta.secs==rp->min.secs)
+         &&(delta.nsecs<rp->min.nsecs) ) ){
+               rp->min.secs=delta.secs;
+               rp->min.nsecs=delta.nsecs;
+       }
+
+       if( (delta.secs>rp->max.secs)
+       ||( (delta.secs==rp->max.secs)
+         &&(delta.nsecs>rp->max.nsecs) ) ){
+               rp->max.secs=delta.secs;
+               rp->max.nsecs=delta.nsecs;
+       }
+       
+       rp->tot.secs += delta.secs;
+       rp->tot.nsecs += delta.nsecs;
+       if(rp->tot.nsecs>1000000000){
+               rp->tot.nsecs-=1000000000;
+               rp->tot.secs++;
+       }
+       rp->num++;
+
+       return 1;
+}
+
+static void
+dcerpcstat_draw(rpcstat_t *rs)
+{
+       guint32 i;
+#ifdef G_HAVE_UINT64
+       guint64 td;
+#else
+       guint32 td;
+#endif
+
+       for(i=0;i<rs->num_procedures;i++){
+               /* scale it to units of 10us.*/
+               /* for long captures with a large tot time, this can overflow on 32bit */
+               td=(int)rs->procedures[i].tot.secs;
+               td=td*100000+(int)rs->procedures[i].tot.nsecs/10000;
+               if(rs->procedures[i].num){
+                       td/=rs->procedures[i].num;
+               } else {
+                       td=0;
+               }
+
+               sprintf(rs->procedures[i].snum,"%d", rs->procedures[i].num);
+               gtk_label_set_text(GTK_LABEL(rs->procedures[i].wnum), rs->procedures[i].snum);
+
+               sprintf(rs->procedures[i].smin,"%3d.%05d", (int)rs->procedures[i].min.secs,rs->procedures[i].min.nsecs/10000);
+               gtk_label_set_text(GTK_LABEL(rs->procedures[i].wmin), rs->procedures[i].smin);
+
+               sprintf(rs->procedures[i].smax,"%3d.%05d", (int)rs->procedures[i].max.secs,rs->procedures[i].max.nsecs/10000);
+               gtk_label_set_text(GTK_LABEL(rs->procedures[i].wmax), rs->procedures[i].smax);
+
+               sprintf(rs->procedures[i].savg,"%3d.%05d", td/100000, td%100000);
+               gtk_label_set_text(GTK_LABEL(rs->procedures[i].wavg), rs->procedures[i].savg);
+
+       }
+}
+
+
+/* since the gtk2 implementation of tap is multithreaded we must protect
+ * remove_tap_listener() from modifying the list while draw_tap_listener()
+ * is running.  the other protected block is in main.c
+ *
+ * there should not be any other critical regions in gtk2
+ */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+static void
+win_destroy_cb(GtkWindow *win _U_, gpointer data)
+{
+       rpcstat_t *rs=(rpcstat_t *)data;
+
+       protect_thread_critical_region();
+       remove_tap_listener(rs);
+       unprotect_thread_critical_region();
+
+       g_free(rs->procedures);
+       g_free(rs);
+}
+
+
+
+/* When called, this function will create a new instance of gtk-dcerpcstat.
+ */
+void
+gtk_dcerpcstat_init(e_uuid_t *uuid, int major, int minor, char *filter)
+{
+       rpcstat_t *rs;
+       guint32 i, max_procs;
+       char title_string[60];
+       char filter_string[256];
+       GtkWidget *vbox;
+       GtkWidget *stat_label;
+       GtkWidget *filter_label;
+       GtkWidget *tmp;
+       dcerpc_sub_dissector *procs;
+
+       rs=g_malloc(sizeof(rpcstat_t));
+       rs->prog=dcerpc_get_proto_name(uuid, (minor<<8)|(major&0xff) );
+       if(!rs->prog){
+               g_free(rs);
+               fprintf(stderr,"tethereal: dcerpcstat_init() Protocol with uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x v%d.%d not supported\n",uuid->Data1,uuid->Data2,uuid->Data3,uuid->Data4[0],uuid->Data4[1],uuid->Data4[2],uuid->Data4[3],uuid->Data4[4],uuid->Data4[5],uuid->Data4[6],uuid->Data4[7],major,minor);
+               exit(1);
+       }
+       procs=dcerpc_get_proto_sub_dissector(uuid, (minor<<8)|(major&0xff) );
+       rs->uuid=*uuid;
+       rs->ver=(minor<<8)|(major&0xff);
+
+       rs->win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       sprintf(title_string,"DCE-RPC RTT Stat for %s version %d.%d", rs->prog, rs->ver&0xff,rs->ver>>8);
+       gtk_window_set_title(GTK_WINDOW(rs->win), title_string);
+       gtk_signal_connect(GTK_OBJECT(rs->win), "destroy", GTK_SIGNAL_FUNC(win_destroy_cb), rs);
+
+       vbox=gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(rs->win), vbox);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+       gtk_widget_show(vbox);
+
+       stat_label=gtk_label_new(title_string);
+       gtk_box_pack_start(GTK_BOX(vbox), stat_label, FALSE, FALSE, 0);
+       gtk_widget_show(stat_label);
+
+       snprintf(filter_string,255,"Filter:%s",filter?filter:"");
+       filter_label=gtk_label_new(filter_string);
+       gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
+       gtk_widget_show(filter_label);
+
+
+       for(i=0,max_procs=0;procs[i].name;i++){
+               if(procs[i].num>max_procs){
+                       max_procs=procs[i].num;
+               }
+       }
+       rs->num_procedures=max_procs+1;
+       rs->procedures=g_malloc(sizeof(rpc_procedure_t)*(rs->num_procedures+1));
+
+       rs->table=gtk_table_new(rs->num_procedures+1, 5, TRUE);
+       gtk_container_add(GTK_CONTAINER(vbox), rs->table);
+
+       tmp=gtk_label_new("Procedure");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 0,1,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
+       gtk_widget_show(tmp);
+
+       tmp=gtk_label_new("Calls");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 1,2,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
+       gtk_widget_show(tmp);
+
+       tmp=gtk_label_new("Min RTT");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 2,3,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
+       gtk_widget_show(tmp);
+
+       tmp=gtk_label_new("Max RTT");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 3,4,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
+       gtk_widget_show(tmp);
+
+       tmp=gtk_label_new("Avg RTT");
+       gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 4,5,0,1);
+       gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
+       gtk_widget_show(tmp);
+
+               for(i=0;i<rs->num_procedures;i++){
+               GtkWidget *tmp;
+               int j;
+               char *proc_name;
+
+               proc_name="unknown";
+               for(j=0;procs[j].name;j++){
+                       if(procs[j].num==i){
+                               proc_name=procs[j].name;
+                       }
+               }
+
+               tmp=gtk_label_new(proc_name);
+               gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), tmp, 0,1,i+1,i+2);
+               gtk_widget_show(tmp);
+
+               rs->procedures[i].wnum=gtk_label_new("0");
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), rs->procedures[i].wnum, 1,2,i+1,i+2);
+               gtk_label_set_justify(GTK_LABEL(rs->procedures[i].wnum), GTK_JUSTIFY_RIGHT);
+               gtk_widget_show(rs->procedures[i].wnum);
+
+               rs->procedures[i].wmin=gtk_label_new("0");
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), rs->procedures[i].wmin, 2,3,i+1,i+2);
+               gtk_label_set_justify(GTK_LABEL(rs->procedures[i].wmin), GTK_JUSTIFY_RIGHT);
+               gtk_widget_show(rs->procedures[i].wmin);
+
+               rs->procedures[i].wmax=gtk_label_new("0");
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), rs->procedures[i].wmax, 3,4,i+1,i+2);
+               gtk_label_set_justify(GTK_LABEL(rs->procedures[i].wmax), GTK_JUSTIFY_RIGHT);
+               gtk_widget_show(rs->procedures[i].wmax);
+
+               rs->procedures[i].wavg=gtk_label_new("0");
+               gtk_table_attach_defaults(GTK_TABLE(rs->table), rs->procedures[i].wavg, 4,5,i+1,i+2);
+               gtk_label_set_justify(GTK_LABEL(rs->procedures[i].wavg), GTK_JUSTIFY_RIGHT);
+               gtk_widget_show(rs->procedures[i].wavg);
+
+               rs->procedures[i].num=0;        
+               rs->procedures[i].min.secs=0;
+               rs->procedures[i].min.nsecs=0;
+               rs->procedures[i].max.secs=0;
+               rs->procedures[i].max.nsecs=0;
+               rs->procedures[i].tot.secs=0;
+               rs->procedures[i].tot.nsecs=0;
+       }
+
+       gtk_widget_show(rs->table);
+
+
+       if(register_tap_listener("dcerpc", rs, filter, (void*)dcerpcstat_reset, (void*)dcerpcstat_packet, (void*)dcerpcstat_draw)){
+               char str[256];
+               /* error, we failed to attach to the tap. clean up */
+               snprintf(str,255,"Could not attach to tap using filter:%s",filter?filter:"");
+               simple_dialog(ESD_TYPE_WARN, NULL, str);
+               g_free(rs->procedures);
+               g_free(rs);
+               return;
+       }
+
+
+       gtk_widget_show_all(rs->win);
+       redissect_packets(&cfile);
+}
+
+
+
+static e_uuid_t *dcerpc_uuid_program=NULL;
+static guint16 dcerpc_version;
+static GtkWidget *dlg=NULL, *dlg_box;
+static GtkWidget *prog_box;
+static GtkWidget *prog_label, *prog_opt, *prog_menu;
+static GtkWidget *vers_label, *vers_opt, *vers_menu;
+static GtkWidget *filter_box;
+static GtkWidget *filter_label, *filter_entry;
+static GtkWidget *start_button;
+
+
+static void
+dcerpcstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
+{
+       char *filter;
+
+       filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
+       if(filter[0]==0){
+               filter=NULL;
+       }
+       gtk_dcerpcstat_init(dcerpc_uuid_program, dcerpc_version&0xff, dcerpc_version>>8, filter);
+}
+
+
+static void
+dcerpcstat_version_select(GtkWidget *item _U_, gpointer key)
+{
+       int vers=(int)key;
+
+       dcerpc_version=vers;
+}
+
+
+
+
+static void *
+dcerpcstat_find_vers(gpointer *key, gpointer *value _U_, gpointer *user_data _U_)
+{
+       dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
+       GtkWidget *menu_item;
+       char vs[5];
+
+       if(!uuid_equal((&k->uuid), dcerpc_uuid_program)){
+               return NULL;
+       }
+
+       sprintf(vs,"%d.%d",k->ver&0xff,k->ver>>8);
+       menu_item=gtk_menu_item_new_with_label(vs);
+       gtk_signal_connect(GTK_OBJECT(menu_item), "activate", 
+                       GTK_SIGNAL_FUNC(dcerpcstat_version_select), (gpointer)((int)k->ver));
+       gtk_widget_show(menu_item);
+       gtk_menu_append(GTK_MENU(vers_menu), menu_item);
+
+       if(dcerpc_version==0xffff){
+               dcerpc_version=k->ver;
+       }
+
+       return NULL;
+}
+
+
+static void
+dcerpcstat_program_select(GtkWidget *item _U_, gpointer key)
+{
+       dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
+
+       dcerpc_uuid_program=&k->uuid;
+
+       /* change version menu */
+       dcerpc_version=0xffff;
+       gtk_object_destroy(GTK_OBJECT(vers_menu));
+       vers_menu=gtk_menu_new();
+       g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
+       gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
+}
+
+
+static void *
+dcerpcstat_list_programs(gpointer *key, gpointer *value, gpointer *user_data _U_)
+{
+       dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
+       dcerpc_uuid_value *v=(dcerpc_uuid_value *)value;
+       GtkWidget *menu_item;
+
+       menu_item=gtk_menu_item_new_with_label(v->name);
+       gtk_signal_connect(GTK_OBJECT(menu_item), "activate", 
+                       GTK_SIGNAL_FUNC(dcerpcstat_program_select), (gpointer)k);
+
+       gtk_widget_show(menu_item);
+       gtk_menu_append(GTK_MENU(prog_menu), menu_item);
+
+       if(!dcerpc_uuid_program){
+               dcerpc_uuid_program=&k->uuid;
+       }
+
+       return NULL;
+}
+
+
+static void
+dlg_destroy_cb(void)
+{
+       dlg=NULL;
+}
+
+
+void
+gtk_dcerpcstat_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+       /* if the window is already open, bring it to front */
+       if(dlg){
+               gdk_window_raise(dlg->window);
+               return;
+       }
+
+       dlg=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       gtk_window_set_title(GTK_WINDOW(dlg), "DCE-RPC RTT Statistics");
+       gtk_signal_connect(GTK_OBJECT(dlg), "destroy", GTK_SIGNAL_FUNC(dlg_destroy_cb), NULL);
+       dlg_box=gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
+       gtk_widget_show(dlg_box);
+
+
+       prog_box=gtk_hbox_new(FALSE, 10);
+       /* Program label */
+       gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
+       prog_label=gtk_label_new("Program:");
+       gtk_box_pack_start(GTK_BOX(prog_box), prog_label, FALSE, FALSE, 0);
+       gtk_widget_show(prog_label);
+
+       /* Program menu */
+       prog_opt=gtk_option_menu_new();
+       prog_menu=gtk_menu_new();
+       g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_list_programs, NULL);
+       gtk_option_menu_set_menu(GTK_OPTION_MENU(prog_opt), prog_menu);
+       gtk_box_pack_start(GTK_BOX(prog_box), prog_opt, TRUE, TRUE, 0);
+       gtk_widget_show(prog_opt);
+
+       /* Version label */
+       gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
+       vers_label=gtk_label_new("Version:");
+       gtk_box_pack_start(GTK_BOX(prog_box), vers_label, FALSE, FALSE, 0);
+       gtk_widget_show(vers_label);
+
+       /* Version menu */
+       vers_opt=gtk_option_menu_new();
+       vers_menu=gtk_menu_new();
+       dcerpc_version=0xffff;
+       g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
+       gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
+       gtk_box_pack_start(GTK_BOX(prog_box), vers_opt, TRUE, TRUE, 0);
+       gtk_widget_show(vers_opt);
+
+       gtk_box_pack_start(GTK_BOX(dlg_box), prog_box, TRUE, TRUE, 0);
+       gtk_widget_show(prog_box);
+
+
+       /* filter box */
+       filter_box=gtk_hbox_new(FALSE, 10);
+       /* Filter label */
+       gtk_container_set_border_width(GTK_CONTAINER(filter_box), 10);
+       filter_label=gtk_label_new("Filter:");
+       gtk_box_pack_start(GTK_BOX(filter_box), filter_label, FALSE, FALSE, 0);
+       gtk_widget_show(filter_label);
+
+       filter_entry=gtk_entry_new_with_max_length(250);
+       gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, FALSE, FALSE, 0);
+       gtk_widget_show(filter_entry);
+       
+       gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
+       gtk_widget_show(filter_box);
+
+
+       /* the start button */
+       start_button=gtk_button_new_with_label("Create Stat");
+       gtk_signal_connect_object(GTK_OBJECT(start_button), "clicked", 
+                       GTK_SIGNAL_FUNC(dcerpcstat_start_button_clicked),
+                       NULL);
+
+       gtk_box_pack_start(GTK_BOX(dlg_box), start_button, TRUE, TRUE, 0);
+       gtk_widget_show(start_button);
+
+       gtk_widget_show_all(dlg);
+}
+
diff --git a/gtk2/dcerpc_stat.h b/gtk2/dcerpc_stat.h
new file mode 100644 (file)
index 0000000..0919307
--- /dev/null
@@ -0,0 +1,31 @@
+/* dcerpc_stat.h
+ * dcerpc_stat   2002 Ronnie Sahlberg
+ *
+ * $Id: dcerpc_stat.h,v 1.1 2002/10/25 01:08:48 guy 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.
+ */
+
+#ifndef __DCERPCSTAT_H__
+#define __DCERPCSTAT_H__
+
+void gtk_dcerpcstat_init(e_uuid_t *uuid, int major, int minor, char *filter);
+void gtk_dcerpcstat_cb(GtkWidget *w, gpointer d);
+
+#endif
index 484e9b6bef4a0f3563419cc344c175c96491248b..431b37030107a6c9c7b44428457508fdaa78bb4d 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.17 2002/10/25 00:29:12 guy Exp $
+ * $Id: main.c,v 1.18 2002/10/25 01:08:48 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "../tap.h"
 #include "rpc_stat.h"
 #include "rpc_progs.h"
+#include "../packet-dcerpc.h"
+#include "dcerpc_stat.h"
 
 #ifdef WIN32
 #include "capture-wpcap.h"
@@ -1776,8 +1778,42 @@ main(int argc, char *argv[])
                 fprintf(stderr, "   \"-z rpc,programs\"\n");
                 exit(1);
               }
+            } else if(!strncmp(optarg,"dcerpc,",7)){
+              if(!strncmp(optarg,"dcerpc,rtt,",11)){
+                e_uuid_t uuid;
+                int d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
+                int major, minor;
+                int pos=0;
+                if(sscanf(optarg,"dcerpc,rtt,%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d%n", &d1,&d2,&d3,&d40,&d41,&d42,&d43,&d44,&d45,&d46,&d47,&major,&minor,&pos)==13){
+                  uuid.Data1=d1;
+                  uuid.Data2=d2;
+                  uuid.Data3=d3;
+                  uuid.Data4[0]=d40;
+                  uuid.Data4[1]=d41;
+                  uuid.Data4[2]=d42;
+                  uuid.Data4[3]=d43;
+                  uuid.Data4[4]=d44;
+                  uuid.Data4[5]=d45;
+                  uuid.Data4[6]=d46;
+                  uuid.Data4[7]=d47;
+                  if(pos){
+                    gtk_dcerpcstat_init(&uuid,major,minor,optarg+pos);
+                  } else {
+                    gtk_dcerpcstat_init(&uuid,major,minor,NULL);
+                  }
+                } else {
+                  fprintf(stderr, "ethereal: invalid \"-z dcerpc,rtt,<uuid>,<major version>.<minor version>[,<filter>]\" argument\n");
+                  exit(1);
+                }
+              } else {
+                fprintf(stderr, "tethereal: invalid -z argument. Argument must be one of:\n");
+                fprintf(stderr, "   \"-z dcerpc,rtt,<uuid>,<major version>.<minor version>[,<filter>]\"\n");
+                exit(1);
+              }
             } else {
-              fprintf(stderr, "ethereal: invalid -z argument. Argument must be \"-z rpc,...\"\n");
+              fprintf(stderr, "ethereal: invalid -z argument. Argument must be one of:\n");
+              fprintf(stderr, "   \"-z rpc,...\"\n");
+              fprintf(stderr, "   \"-z dcerpc,...\"\n");
               exit(1);
             }
             break;
index 3a71b3ccdadd35427059295a69f321825cce1080..b8c3574fcb9f196ce0d722427fc64cd8035e1073 100644 (file)
@@ -1,7 +1,7 @@
 /* menu.c
  * Menu routines
  *
- * $Id: menu.c,v 1.5 2002/09/07 09:28:05 sahlberg Exp $
+ * $Id: menu.c,v 1.6 2002/10/25 01:08:49 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -59,6 +59,8 @@
 #include <epan/epan_dissect.h>
 #include "rpc_stat.h"
 #include "rpc_progs.h"
+#include "../packet-dcerpc.h"
+#include "dcerpc_stat.h"
 
 GtkWidget *popup_menu_object;
 
@@ -176,6 +178,8 @@ static GtkItemFactoryEntry menu_items[] =
   {"/Tools/Statistics/ONC-RPC", NULL, NULL, 0, "<Branch>", NULL },
   {"/Tools/Statistics/ONC-RPC/RTT", NULL, GTK_MENU_FUNC(gtk_rpcstat_cb), 0, NULL, NULL },
   {"/Tools/Statistics/ONC-RPC/Programs", NULL, GTK_MENU_FUNC(gtk_rpcprogs_init), 0, NULL, NULL },
+  {"/Tools/Statistics/DCE-RPC", NULL, NULL, 0, "<Branch>", NULL },
+  {"/Tools/Statistics/DCE-RPC/RTT", NULL, GTK_MENU_FUNC(gtk_dcerpcstat_cb), 0, NULL, NULL },
   {"/_Help", NULL, NULL, 0, "<LastBranch>", NULL  },
   {"/Help/_Help", NULL, GTK_MENU_FUNC(help_cb), 0, "<StockItem>", GTK_STOCK_HELP },
   {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL },
index d18d440087d71ffd5eff1faa2d00906a291134cf..572cdf5668e4a64501423086766ce7d46922f2bd 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for DCERPC packet disassembly
  * Copyright 2001, Todd Sabin <tas@webspan.net>
  *
- * $Id: packet-dcerpc.c,v 1.82 2002/10/24 06:17:34 guy Exp $
+ * $Id: packet-dcerpc.c,v 1.83 2002/10/25 01:08:42 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -446,20 +446,7 @@ dcerpc_reassemble_init(void)
  */
 
 /* the registered subdissectors */
-static GHashTable *dcerpc_uuids;
-
-typedef struct _dcerpc_uuid_key {
-    e_uuid_t uuid;
-    guint16 ver;
-} dcerpc_uuid_key;
-
-typedef struct _dcerpc_uuid_value {
-    int proto;
-    int ett;
-    gchar *name;
-    dcerpc_sub_dissector *procs;
-    int opnum_hf;
-} dcerpc_uuid_value;
+GHashTable *dcerpc_uuids=NULL;
 
 static gint
 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
index 04ab146ec25776a9d4a9d44512c91f323c5ee104..d0a17624434c493ddceddb3be330b61d249488e6 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-dcerpc.h
  * Copyright 2001, Todd Sabin <tas@webspan.net>
  *
- * $Id: packet-dcerpc.h,v 1.23 2002/10/23 03:49:10 guy Exp $
+ * $Id: packet-dcerpc.h,v 1.24 2002/10/25 01:08:42 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -95,6 +95,7 @@ typedef struct _e_dce_dg_common_hdr_t {
 #define PDU_CO_CANCEL  18
 #define PDU_ORPHANED   19
 
+
 /*
  * helpers for packet-dcerpc.c and packet-dcerpc-ndr.c
  * If you're writing a subdissector, you almost certainly want the
@@ -238,4 +239,22 @@ typedef struct _dcerpc_info {
        void *private_data;
 } dcerpc_info;
 
+
+/* the registered subdissectors */
+extern GHashTable *dcerpc_uuids;
+
+typedef struct _dcerpc_uuid_key {
+    e_uuid_t uuid;
+    guint16 ver;
+} dcerpc_uuid_key;
+
+typedef struct _dcerpc_uuid_value {
+    int proto;
+    int ett;
+    gchar *name;
+    dcerpc_sub_dissector *procs;
+    int opnum_hf;
+} dcerpc_uuid_value;
+
+
 #endif /* packet-dcerpc.h */