aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2002-10-23 03:49:13 +0000
committerGuy Harris <guy@alum.mit.edu>2002-10-23 03:49:13 +0000
commita71d1d910e21a9dbec9caef3d404b1626ee5ad0c (patch)
tree9988bb31bedf5fe12f8168ae54c0da9f8c908f31
parentc65515848941a8a4e42a4f48b13bdd78312e5985 (diff)
From Ronnie Sahlberg: add a tap for statistics for DCERPC interfaces.
svn path=/trunk/; revision=6479
-rw-r--r--AUTHORS2
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.nmake3
-rw-r--r--doc/tethereal.pod.template16
-rw-r--r--packet-dcerpc.c41
-rw-r--r--packet-dcerpc.h7
-rw-r--r--tap-dcerpcstat.c241
-rw-r--r--tap-dcerpcstat.h28
-rw-r--r--tethereal.c39
9 files changed, 372 insertions, 9 deletions
diff --git a/AUTHORS b/AUTHORS
index 9c9d63739a..214932aaef 100644
--- 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> {
diff --git a/Makefile.am b/Makefile.am
index 5fd62c9ff6..35835594ba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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 \
diff --git a/Makefile.nmake b/Makefile.nmake
index 38c0213d7b..ec5e877c02 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.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 \
diff --git a/doc/tethereal.pod.template b/doc/tethereal.pod.template
index 5f58f409d1..50d28c6124 100644
--- a/doc/tethereal.pod.template
+++ b/doc/tethereal.pod.template
@@ -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
diff --git a/packet-dcerpc.c b/packet-dcerpc.c
index 61a2fd7573..2d78e52b48 100644
--- a/packet-dcerpc.c
+++ b/packet-dcerpc.c
@@ -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
diff --git a/packet-dcerpc.h b/packet-dcerpc.h
index feae1d7aff..04ab146ec2 100644
--- a/packet-dcerpc.h
+++ b/packet-dcerpc.h
@@ -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
index 0000000000..8c392dc46c
--- /dev/null
+++ b/tap-dcerpcstat.c
@@ -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
index 0000000000..afe5d65441
--- /dev/null
+++ b/tap-dcerpcstat.h
@@ -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);
+
+
+
diff --git a/tethereal.c b/tethereal.c
index 3d7e9fa3e4..c842a277f2 100644
--- a/tethereal.c
+++ b/tethereal.c
@@ -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;