From Ronnie Sahlberg: add a tap for statistics for DCERPC interfaces.
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 23 Oct 2002 03:49:13 +0000 (03:49 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 23 Oct 2002 03:49:13 +0000 (03:49 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@6479 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
Makefile.am
Makefile.nmake
doc/tethereal.pod.template
packet-dcerpc.c
packet-dcerpc.h
tap-dcerpcstat.c [new file with mode: 0644]
tap-dcerpcstat.h [new file with mode: 0644]
tethereal.c

diff --git a/AUTHORS b/AUTHORS
index 9c9d63739a22baf89e379c480b2274e1cf9d378b..214932aaefd4bd0d4031d69ac7bbd8d68f4bc781 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -618,7 +618,7 @@ Ronnie Sahlberg <sahlberg[AT]optushome.com.au> {
        MAPI skeleton dissector
        DCE/RPC fragment reassembly
        TCP ACK/SEQ number analysis and relative sequence numbers
-       TAP system and RPCSTAT example for tethereal and Gtk2
+       TAP system and ONC RPC and DCE RPC examples
 }
 
 Borosa Tomislav <tomislav.borosa[AT]SIEMENS.HR> {
index 5fd62c9ff60cfbccd349c9879cdd547680c42fa5..35835594bafc65952197a63306845e38e4d53dfd 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.509 2002/10/22 08:47:44 guy Exp $
+# $Id: Makefile.am,v 1.510 2002/10/23 03:49:10 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@ethereal.com>
@@ -637,6 +637,8 @@ ETHEREAL_COMMON_SRC = \
        smb.h          \
        tap.c           \
        tap.h           \
+       tap-dcerpcstat.c        \
+       tap-dcerpcstat.h        \
        tap-rpcstat.c   \
        tap-rpcstat.h   \
        tap-rpcprogs.c  \
index 38c0213d7b756fd2730669bce35fff5de5ed24e3..ec5e877c02d3368506736a87cc960cb5a92e2216 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.244 2002/10/22 08:47:45 guy Exp $
+# $Id: Makefile.nmake,v 1.245 2002/10/23 03:49:10 guy Exp $
 
 include config.nmake
 include <win32.mak>
@@ -341,6 +341,7 @@ ETHEREAL_COMMON_OBJECTS = \
        register.obj     \
        ringbuffer.obj   \
        tap.obj         \
+       tap-dcerpcstat.obj      \
        tap-rpcstat.obj \
        tap-rpcprogs.obj        \
        util.obj         \
index 5f58f409d1f8151e5a207c4118a3919a445840e7..50d28c6124adad4ae61a00ee0be80495918d6b48 100644 (file)
@@ -309,6 +309,21 @@ Get B<Tethereal> to collect various types of statistics and display the result
 after finishing reading the capture file.
 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>[,I<filter>]
 
 Collect call/reply RTT data for I<program>/I<version>.  Data collected
@@ -329,6 +344,7 @@ Data collected is number of calls for each protocol/version, MinRTT,
 MaxRTT and AvgRTT. 
 This option can only be used once on the command line.
 
+
 =back
 
 =head1 CAPTURE FILTER SYNTAX
index 61a2fd7573a0cc72c11727eda0bac74ae48961eb..2d78e52b48e67c8dbbd4c9b670b22d43c6f625a3 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for DCERPC packet disassembly
  * Copyright 2001, Todd Sabin <tas@webspan.net>
  *
- * $Id: packet-dcerpc.c,v 1.80 2002/10/22 00:59:24 guy Exp $
+ * $Id: packet-dcerpc.c,v 1.81 2002/10/23 03:49:10 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -36,6 +36,9 @@
 #include <epan/conversation.h>
 #include "prefs.h"
 #include "reassemble.h"
+#include "tap.h"
+
+static int dcerpc_tap = -1;
 
 static const value_string pckt_vals[] = {
     { PDU_REQ,        "Request"},
@@ -495,6 +498,40 @@ dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
     g_hash_table_insert (dcerpc_uuids, key, value);
 }
 
+/* Function to find the name of a registered protocol
+ * or NULL if the protocol/version is not known to ethereal.
+ */
+char *
+dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
+{
+    dcerpc_uuid_key key;
+    dcerpc_uuid_value *sub_proto;
+
+    key.uuid = *uuid;
+    key.ver = ver;
+    if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
+        return NULL;
+    }
+    return sub_proto->name;
+}
+
+/* Function to find the subdissector table of a registered protocol
+ * or NULL if the protocol/version is not known to ethereal.
+ */
+dcerpc_sub_dissector *
+dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver)
+{
+    dcerpc_uuid_key key;
+    dcerpc_uuid_value *sub_proto;
+
+    key.uuid = *uuid;
+    key.ver = ver;
+    if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
+        return NULL;
+    }
+    return sub_proto->procs;
+}
+
 
 /*
  * To keep track of ctx_id mappings.
@@ -1399,6 +1436,7 @@ dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
             }
         }
     }
+    tap_queue_packet(dcerpc_tap, pinfo, info);
     return 0;
 }
 
@@ -3698,6 +3736,7 @@ proto_register_dcerpc (void)
                                     &dcerpc_reassemble);
     register_init_routine(dcerpc_reassemble_init);
     dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
+    dcerpc_tap=register_tap("dcerpc");
 }
 
 void
index feae1d7afff540087b96ac77f374291e6b39fe14..04ab146ec25776a9d4a9d44512c91f323c5ee104 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-dcerpc.h
  * Copyright 2001, Todd Sabin <tas@webspan.net>
  *
- * $Id: packet-dcerpc.h,v 1.22 2002/10/22 00:59:25 guy Exp $
+ * $Id: packet-dcerpc.h,v 1.23 2002/10/23 03:49:10 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -124,8 +124,6 @@ int dissect_dcerpc_double (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 int dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                            proto_tree *tree, char *drep, 
                            int hfindex, guint32 *pdata);
-
-
 /*
  * NDR routines for subdissectors.
  */
@@ -189,6 +187,9 @@ typedef struct _dcerpc_sub_dissector {
 
 /* registration function for subdissectors */
 void dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver, dcerpc_sub_dissector *procs, int opnum_hf);
+char *dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver);
+dcerpc_sub_dissector *dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver);
+
 
 /* Private data structure to pass to DCERPC dissector. This is used to
    pass transport specific information down to the dissector from the
diff --git a/tap-dcerpcstat.c b/tap-dcerpcstat.c
new file mode 100644 (file)
index 0000000..8c392dc
--- /dev/null
@@ -0,0 +1,241 @@
+/* tap-dcerpcstat.c
+ * dcerpcstat   2002 Ronnie Sahlberg
+ *
+ * $Id: tap-dcerpcstat.c,v 1.1 2002/10/23 03:49:10 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.
+ */
+
+#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 "tap.h"
+#include "packet-dcerpc.h"
+#include "tap-dcerpcstat.h"
+
+/* used to keep track of statistics for a specific procedure */
+typedef struct _rpc_procedure_t {
+       char *proc;
+       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 {
+       char *prog;
+       char *filter;
+       e_uuid_t uuid;
+       guint16 ver;
+       guint32 num_procedures;
+       rpc_procedure_t *procedures;
+} rpcstat_t;
+
+
+
+static int
+dcerpcstat_packet(rpcstat_t *rs, packet_info *pinfo, dcerpc_info *ri)
+{
+       nstime_t delta;
+       rpc_procedure_t *rp;
+
+       if(!ri->call_data){
+               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( (ri->call_data->uuid.Data1!=rs->uuid.Data1)
+          ||(ri->call_data->uuid.Data2!=rs->uuid.Data2)
+          ||(ri->call_data->uuid.Data3!=rs->uuid.Data3)
+          ||(ri->call_data->uuid.Data4[0]!=rs->uuid.Data4[0])
+          ||(ri->call_data->uuid.Data4[1]!=rs->uuid.Data4[1])
+          ||(ri->call_data->uuid.Data4[2]!=rs->uuid.Data4[2])
+          ||(ri->call_data->uuid.Data4[3]!=rs->uuid.Data4[3])
+          ||(ri->call_data->uuid.Data4[4]!=rs->uuid.Data4[4])
+          ||(ri->call_data->uuid.Data4[5]!=rs->uuid.Data4[5])
+          ||(ri->call_data->uuid.Data4[6]!=rs->uuid.Data4[6])
+          ||(ri->call_data->uuid.Data4[7]!=rs->uuid.Data4[7])
+         ||(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
+       printf("\n");
+       printf("===================================================================\n");
+       printf("%s Version %d.%d RTT Statistics:\n", rs->prog, rs->ver&0xff,rs->ver>>8);
+       printf("Filter: %s\n",rs->filter?rs->filter:"");
+       printf("Procedure                  Calls   Min RTT   Max RTT   Avg RTT\n");
+       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;
+               }
+
+               printf("%-25s %6d %3d.%05d %3d.%05d %3d.%05d\n",
+                       rs->procedures[i].proc,
+                       rs->procedures[i].num,
+                       (int)rs->procedures[i].min.secs,rs->procedures[i].min.nsecs/10000,
+                       (int)rs->procedures[i].max.secs,rs->procedures[i].max.nsecs/10000,
+                       td/100000, td%100000
+               );
+       }
+       printf("===================================================================\n");
+}
+
+
+
+void
+dcerpcstat_init(e_uuid_t *uuid, int major, int minor, char *filter)
+{
+       rpcstat_t *rs;
+       guint32 i, max_procs;
+       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);
+
+       if(filter){
+               rs->filter=g_malloc(strlen(filter)+1);
+               strcpy(rs->filter, filter);
+       } else {
+               rs->filter=NULL;
+       }
+
+       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));
+       for(i=0;i<rs->num_procedures;i++){
+               int j;
+               rs->procedures[i].proc="unknown";
+               for(j=0;procs[j].name;j++){
+                       if(procs[j].num==i){
+                               rs->procedures[i].proc=procs[j].name;
+                       }
+               }
+               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;
+       }
+
+       if(register_tap_listener("dcerpc", rs, filter, NULL, (void*)dcerpcstat_packet, (void*)dcerpcstat_draw)){
+               /* error, we failed to attach to the tap. clean up */
+               g_free(rs->procedures);
+               g_free(rs->filter);
+               g_free(rs);
+
+               fprintf(stderr,"tethereal: dcerpcstat_init() failed to attach to tap.\n");
+               exit(1);
+       }
+}
+
diff --git a/tap-dcerpcstat.h b/tap-dcerpcstat.h
new file mode 100644 (file)
index 0000000..afe5d65
--- /dev/null
@@ -0,0 +1,28 @@
+/* tap-dcerpcstat.h
+ * dcerpcstat   2002 Ronnie Sahlberg
+ *
+ * $Id: tap-dcerpcstat.h,v 1.1 2002/10/23 03:49:10 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.
+ */
+
+void dcerpcstat_init(e_uuid_t *program, int major, int minor, char *filter);
+
+
+
index 3d7e9fa3e4929c7ea6ecb822c0736246e86f7894..c842a277f2208c5c5bbbc3cabb8dcfde5ecdf760 100644 (file)
@@ -1,6 +1,6 @@
 /* tethereal.c
  *
- * $Id: tethereal.c,v 1.161 2002/10/17 02:11:20 guy Exp $
+ * $Id: tethereal.c,v 1.162 2002/10/23 03:49:10 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -98,6 +98,8 @@
 #include "tap.h"
 #include "tap-rpcstat.h"
 #include "tap-rpcprogs.h"
+#include "packet-dcerpc.h"
+#include "tap-dcerpcstat.h"
 
 #ifdef HAVE_LIBPCAP
 #include <wiretap/wtap-capture.h>
@@ -658,9 +660,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){
+                dcerpcstat_init(&uuid,major,minor,optarg+pos);
+              } else {
+                dcerpcstat_init(&uuid,major,minor,NULL);
+              }
+            } else {
+              fprintf(stderr, "tethereal: 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, "tethereal: invalid -z argument. Argument must be:\n");
+          fprintf(stderr, "tethereal: invalid -z argument. Argument must be one of:\n");
           fprintf(stderr, "   \"-z rpc,...\"\n");
+          fprintf(stderr, "   \"-z dcerpc,...\"\n");
           exit(1);
         }
         break;