More constification of arrays.
[obnox/wireshark/wip.git] / tap-dcerpcstat.c
index 8c392dc46c98ef2904fec0b45ca01d3439b2066a..1b824dc89fbe94a7f54d84e933429d5f8c9f560e 100644 (file)
@@ -1,7 +1,7 @@
 /* tap-dcerpcstat.c
  * dcerpcstat   2002 Ronnie Sahlberg
  *
- * $Id: tap-dcerpcstat.c,v 1.1 2002/10/23 03:49:10 guy Exp $
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -34,9 +34,9 @@
 
 #include <string.h>
 #include "epan/packet_info.h"
-#include "tap.h"
-#include "packet-dcerpc.h"
-#include "tap-dcerpcstat.h"
+#include <epan/tap.h>
+#include <epan/dissectors/packet-dcerpc.h>
+#include "register.h"
 
 /* used to keep track of statistics for a specific procedure */
 typedef struct _rpc_procedure_t {
@@ -60,21 +60,27 @@ typedef struct _rpcstat_t {
 
 
 static int
-dcerpcstat_packet(rpcstat_t *rs, packet_info *pinfo, dcerpc_info *ri)
+dcerpcstat_packet(void *prs, packet_info *pinfo, epan_dissect_t *edt _U_, void *pri)
 {
+       dcerpc_info *ri=pri;
+       rpcstat_t *rs=prs;
        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){
+       if(ri->ptype != PDU_RESP){
                return 0;
        }
 
@@ -104,14 +110,12 @@ dcerpcstat_packet(rpcstat_t *rs, packet_info *pinfo, dcerpc_info *ri)
                delta.secs--;
        }
 
-       if((rp->max.secs==0)
-       && (rp->max.nsecs==0) ){
+       if(rp->num==0){
                rp->max.secs=delta.secs;
                rp->max.nsecs=delta.nsecs;
        }
 
-       if((rp->min.secs==0)
-       && (rp->min.nsecs==0) ){
+       if(rp->num==0){
                rp->min.secs=delta.secs;
                rp->min.nsecs=delta.nsecs;
        }
@@ -136,14 +140,16 @@ dcerpcstat_packet(rpcstat_t *rs, packet_info *pinfo, dcerpc_info *ri)
                rp->tot.nsecs-=1000000000;
                rp->tot.secs++;
        }
+
        rp->num++;
 
        return 1;
 }
 
 static void
-dcerpcstat_draw(rpcstat_t *rs)
+dcerpcstat_draw(void *prs)
 {
+       rpcstat_t *rs=prs;
        guint32 i;
 #ifdef G_HAVE_UINT64
        guint64 td;
@@ -152,7 +158,7 @@ dcerpcstat_draw(rpcstat_t *rs)
 #endif
        printf("\n");
        printf("===================================================================\n");
-       printf("%s Version %d.%d RTT Statistics:\n", rs->prog, rs->ver&0xff,rs->ver>>8);
+       printf("%s Major Version %u RTT Statistics:\n", rs->prog, rs->ver);
        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++){
@@ -179,23 +185,77 @@ dcerpcstat_draw(rpcstat_t *rs)
 
 
 
-void
-dcerpcstat_init(e_uuid_t *uuid, int major, int minor, char *filter)
+static void
+dcerpcstat_init(char *optarg)
 {
        rpcstat_t *rs;
        guint32 i, max_procs;
        dcerpc_sub_dissector *procs;
+       e_uuid_t uuid;
+       guint d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
+       int major, minor;
+       guint16 ver;
+       int pos=0;
+        char *filter=NULL;
+        GString *error_string;
+    
+       /*
+        * XXX - DCE RPC statistics are maintained only by major version,
+        * not by major and minor version, so the minor version number is
+        * ignored.
+        *
+        * Should we just stop supporting minor version numbers here?
+        * Or should we allow it to be omitted?  Or should we keep
+        * separate statistics for different minor version numbers,
+        * and allow the minor version number to be omitted, and
+        * report aggregate statistics for all minor version numbers
+        * if it's omitted?
+        *
+        * XXX - should this be called "srt" rather than "rtt"?  The
+        * equivalent tap for Ethereal calls it "srt", for "Service
+        * Response Time", rather than "rtt" for "Round-Trip Time".
+        */
+       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){
+                       filter=optarg+pos;
+               } else {
+                       filter=NULL;
+               }
+       } else {
+               fprintf(stderr, "tethereal: invalid \"-z dcerpc,rtt,<uuid>,<major version>.<minor version>[,<filter>]\" argument\n");
+               exit(1);
+       }
+       if (major < 0 || major > 65535) {
+               fprintf(stderr,"tethereal: dcerpcstat_init() Major version number %d is invalid - must be positive and <= 65535\n", major);
+               exit(1);
+       }
+       if (minor < 0 || minor > 65535) {
+               fprintf(stderr,"tethereal: dcerpcstat_init() Minor version number %d is invalid - must be positive and <= 65535\n", minor);
+               exit(1);
+       }
+       ver = major;
 
        rs=g_malloc(sizeof(rpcstat_t));
-       rs->prog=dcerpc_get_proto_name(uuid, (minor<<8)|(major&0xff) );
+       rs->prog=dcerpc_get_proto_name(&uuid, ver);
        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);
+               fprintf(stderr,"tethereal: dcerpcstat_init() Protocol with uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x v%u 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],ver);
                exit(1);
        }
-       procs=dcerpc_get_proto_sub_dissector(uuid, (minor<<8)|(major&0xff) );
-       rs->uuid=*uuid;
-       rs->ver=(minor<<8)|(major&0xff);
+       procs=dcerpc_get_proto_sub_dissector(&uuid, ver);
+       rs->uuid=uuid;
+       rs->ver=ver;
 
        if(filter){
                rs->filter=g_malloc(strlen(filter)+1);
@@ -228,14 +288,22 @@ dcerpcstat_init(e_uuid_t *uuid, int major, int minor, char *filter)
                rs->procedures[i].tot.nsecs=0;
        }
 
-       if(register_tap_listener("dcerpc", rs, filter, NULL, (void*)dcerpcstat_packet, (void*)dcerpcstat_draw)){
+       error_string=register_tap_listener("dcerpc", rs, filter, NULL, dcerpcstat_packet, dcerpcstat_draw);
+       if(error_string){
                /* 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");
+               fprintf(stderr, "tethereal: Couldn't register dcerpc,rtt tap: %s\n",
+                   error_string->str);
+               g_string_free(error_string, TRUE);
                exit(1);
        }
 }
 
+void
+register_tap_listener_dcerpcstat(void)
+{
+       register_ethereal_tap("dcerpc,rtt,", dcerpcstat_init);
+}