]> git.samba.org - obnox/wireshark/wip.git/blob - gtk/dcerpc_stat.c
Put back "menu.h" - it's needed to declare "register_tap_menu_item()".
[obnox/wireshark/wip.git] / gtk / dcerpc_stat.c
1 /* dcerpc_stat.c
2  * dcerpc_stat   2002 Ronnie Sahlberg
3  *
4  * $Id: dcerpc_stat.c,v 1.33 2003/12/13 22:23:18 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 /* This module provides rpc call/reply SRT statistics to ethereal,
26  * and displays them graphically.
27  * It is only used by ethereal and not tethereal
28  *
29  * It serves as an example on how to use the tap api.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <gtk/gtk.h>
37 #include <stdio.h>
38 #include <string.h>
39
40 #include "epan/packet_info.h"
41 #include "epan/epan.h"
42 #include "menu.h"
43 #include "simple_dialog.h"
44 #include "dlg_utils.h"
45 #include "ui_util.h"
46 #include "tap.h"
47 #include "../register.h"
48 #include "packet-dcerpc.h"
49 #include "../globals.h"
50 #include "filter_prefs.h"
51 #include "compat_macros.h"
52 #include "service_response_time_table.h"
53
54
55 extern GtkWidget   *main_display_filter_widget;
56
57 /* used to keep track of the statistics for an entire program interface */
58 typedef struct _rpcstat_t {
59         GtkWidget *win;
60         srt_stat_table srt_table;
61         char *prog;
62         e_uuid_t uuid;
63         guint16 ver;
64         int num_procedures;
65 } rpcstat_t;
66
67
68 static int
69 uuid_equal(e_uuid_t *uuid1, e_uuid_t *uuid2)
70 {
71         if( (uuid1->Data1!=uuid2->Data1)
72           ||(uuid1->Data2!=uuid2->Data2)
73           ||(uuid1->Data3!=uuid2->Data3)
74           ||(uuid1->Data4[0]!=uuid2->Data4[0])
75           ||(uuid1->Data4[1]!=uuid2->Data4[1])
76           ||(uuid1->Data4[2]!=uuid2->Data4[2])
77           ||(uuid1->Data4[3]!=uuid2->Data4[3])
78           ||(uuid1->Data4[4]!=uuid2->Data4[4])
79           ||(uuid1->Data4[5]!=uuid2->Data4[5])
80           ||(uuid1->Data4[6]!=uuid2->Data4[6])
81           ||(uuid1->Data4[7]!=uuid2->Data4[7]) ){
82                 return 0;
83         }
84         return 1;
85 }
86
87 static char *
88 dcerpcstat_gen_title(rpcstat_t *rs)
89 {
90         char *title;
91
92         title = g_strdup_printf("DCE-RPC Service Response Time statistics for %s version %d.%d: %s", rs->prog, rs->ver&0xff, rs->ver>>8, cf_get_display_name(&cfile));
93         return title;
94 }
95
96 static void
97 dcerpcstat_set_title(rpcstat_t *rs)
98 {
99         char *title;
100
101         title = dcerpcstat_gen_title(rs);
102         gtk_window_set_title(GTK_WINDOW(rs->win), title);
103         g_free(title);
104 }
105
106 static void
107 dcerpcstat_reset(rpcstat_t *rs)
108 {
109         reset_srt_table_data(&rs->srt_table);
110         dcerpcstat_set_title(rs);
111 }
112
113
114 static int
115 dcerpcstat_packet(rpcstat_t *rs, packet_info *pinfo, epan_dissect_t *edt _U_, dcerpc_info *ri)
116 {
117         if(!ri->call_data){
118                 return 0;
119         }
120         if(!ri->call_data->req_frame){
121                 /* we have not seen the request so we dont know the delta*/
122                 return 0;
123         }
124         if(ri->call_data->opnum>=rs->num_procedures){
125                 /* dont handle this since its outside of known table */
126                 return 0;
127         }
128
129         /* we are only interested in reply packets */
130         if(ri->request){
131                 return 0;
132         }
133
134         /* we are only interested in certain program/versions */
135         if( (!uuid_equal( (&ri->call_data->uuid), (&rs->uuid)))
136           ||(ri->call_data->ver!=rs->ver)){
137                 return 0;
138         }
139
140
141         add_srt_table_data(&rs->srt_table, ri->call_data->opnum, &ri->call_data->req_time, pinfo);
142
143
144         return 1;
145 }
146
147 static void
148 dcerpcstat_draw(rpcstat_t *rs)
149 {
150         draw_srt_table_data(&rs->srt_table);
151 }
152
153
154 /* since the gtk2 implementation of tap is multithreaded we must protect
155  * remove_tap_listener() from modifying the list while draw_tap_listener()
156  * is running.  the other protected block is in main.c
157  *
158  * there should not be any other critical regions in gtk2
159  */
160 void protect_thread_critical_region(void);
161 void unprotect_thread_critical_region(void);
162 static void
163 win_destroy_cb(GtkWindow *win _U_, gpointer data)
164 {
165         rpcstat_t *rs=(rpcstat_t *)data;
166
167         protect_thread_critical_region();
168         remove_tap_listener(rs);
169         unprotect_thread_critical_region();
170
171         free_srt_table_data(&rs->srt_table);
172         g_free(rs);
173 }
174
175
176
177 /* When called, this function will create a new instance of gtk-dcerpcstat.
178  */
179 static void
180 gtk_dcerpcstat_init(char *optarg)
181 {
182         rpcstat_t *rs;
183         guint32 i, max_procs;
184         char *title_string;
185         char filter_string[256];
186         GtkWidget *vbox;
187         GtkWidget *stat_label;
188         GtkWidget *filter_label;
189         dcerpc_sub_dissector *procs;
190         e_uuid_t uuid;
191         int d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
192         int major, minor;
193         int pos=0;
194         char *filter=NULL;
195         GString *error_string;
196         int hf_opnum;
197
198         if(sscanf(optarg,"dcerpc,srt,%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){
199                 uuid.Data1=d1;
200                 uuid.Data2=d2;
201                 uuid.Data3=d3;
202                 uuid.Data4[0]=d40;
203                 uuid.Data4[1]=d41;
204                 uuid.Data4[2]=d42;
205                 uuid.Data4[3]=d43;
206                 uuid.Data4[4]=d44;
207                 uuid.Data4[5]=d45;
208                 uuid.Data4[6]=d46;
209                 uuid.Data4[7]=d47;
210                 if(pos){
211                         filter=optarg+pos;
212                 } else {
213                         filter=NULL;
214                 }
215         } else {
216                 fprintf(stderr, "ethereal: invalid \"-z dcerpc,srt,<uuid>,<major version>.<minor version>[,<filter>]\" argument\n");
217                 exit(1);
218         }
219
220
221         rs=g_malloc(sizeof(rpcstat_t));
222         if (major < 0 || major > 255 || minor < 0 || minor > 255)
223                 rs->prog = NULL;        /* bogus major or minor */
224         else
225                 rs->prog=dcerpc_get_proto_name(&uuid, (guint16) ((minor<<8)|(major&0xff)) );
226         if(!rs->prog){
227                 g_free(rs);
228                 fprintf(stderr,"ethereal: 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);
229                 exit(1);
230         }
231         hf_opnum=dcerpc_get_proto_hf_opnum(&uuid, (guint16) ((minor<<8)|(major&0xff)) );
232         procs=dcerpc_get_proto_sub_dissector(&uuid, (guint16) ((minor<<8)|(major&0xff)) );
233         rs->uuid=uuid;
234         rs->ver=(minor<<8)|(major&0xff);
235
236         rs->win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
237         gtk_window_set_default_size(GTK_WINDOW(rs->win), 550, 400);
238         dcerpcstat_set_title(rs);
239         SIGNAL_CONNECT(rs->win, "destroy", win_destroy_cb, rs);
240
241         vbox=gtk_vbox_new(FALSE, 0);
242         gtk_container_add(GTK_CONTAINER(rs->win), vbox);
243         gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
244         gtk_widget_show(vbox);
245
246         title_string=dcerpcstat_gen_title(rs);
247         stat_label=gtk_label_new(title_string);
248         g_free(title_string);
249         gtk_box_pack_start(GTK_BOX(vbox), stat_label, FALSE, FALSE, 0);
250         gtk_widget_show(stat_label);
251
252         snprintf(filter_string,255,"Filter:%s",filter?filter:"");
253         filter_label=gtk_label_new(filter_string);
254         gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
255         gtk_widget_show(filter_label);
256
257         for(i=0,max_procs=0;procs[i].name;i++){
258                 if(procs[i].num>max_procs){
259                         max_procs=procs[i].num;
260                 }
261         }
262         rs->num_procedures=max_procs+1;
263
264         /* We must display TOP LEVEL Widget before calling init_srt_table() */
265         gtk_widget_show(rs->win);
266
267         if(hf_opnum!=-1){
268                 init_srt_table(&rs->srt_table, max_procs+1, vbox, proto_registrar_get_nth(hf_opnum)->abbrev);
269         } else {
270                 init_srt_table(&rs->srt_table, max_procs+1, vbox, NULL);
271         }
272
273         for(i=0;i<(max_procs+1);i++){
274                 int j;
275                 char *proc_name;
276
277                 proc_name="unknown";
278                 for(j=0;procs[j].name;j++){
279                         if(procs[j].num==i){
280                                 proc_name=procs[j].name;
281                         }
282                 }
283
284                 init_srt_table_row(&rs->srt_table, i, proc_name);
285         }
286
287
288         error_string=register_tap_listener("dcerpc", rs, filter, (void*)dcerpcstat_reset, (void*)dcerpcstat_packet, (void*)dcerpcstat_draw);
289         if(error_string){
290                 /* error, we failed to attach to the tap. clean up */
291                 simple_dialog(ESD_TYPE_WARN, NULL, error_string->str);
292                 g_string_free(error_string, TRUE);
293                 free_srt_table_data(&rs->srt_table);
294                 g_free(rs);
295                 return;
296         }
297
298
299         gtk_widget_show_all(rs->win);
300         redissect_packets(&cfile);
301 }
302
303
304
305 static e_uuid_t *dcerpc_uuid_program=NULL;
306 static guint16 dcerpc_version;
307 static GtkWidget *dlg=NULL;
308 static GtkWidget *prog_menu;
309 static GtkWidget *vers_opt, *vers_menu;
310 static GtkWidget *filter_entry;
311 static dcerpc_uuid_key *current_uuid_key=NULL;
312 static dcerpc_uuid_value *current_uuid_value=NULL;
313 static dcerpc_uuid_key *new_uuid_key=NULL;
314 static dcerpc_uuid_value *new_uuid_value=NULL;
315
316
317 static void
318 dcerpcstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
319 {
320         GString *str;
321         char *filter;
322
323         str = g_string_new("dcerpc,srt");
324         g_string_sprintfa(str,
325             ",%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d",
326             dcerpc_uuid_program->Data1, dcerpc_uuid_program->Data2,
327             dcerpc_uuid_program->Data3,
328             dcerpc_uuid_program->Data4[0], dcerpc_uuid_program->Data4[1],
329             dcerpc_uuid_program->Data4[2], dcerpc_uuid_program->Data4[3],
330             dcerpc_uuid_program->Data4[4], dcerpc_uuid_program->Data4[5],
331             dcerpc_uuid_program->Data4[6], dcerpc_uuid_program->Data4[7],
332             dcerpc_version&0xff, dcerpc_version>>8);
333         filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
334         if(filter[0]!=0){
335                 g_string_sprintfa(str, ",%s", filter);
336         }
337
338         gtk_dcerpcstat_init(str->str);
339         g_string_free(str, TRUE);
340 }
341
342
343 static void
344 dcerpcstat_version_select(GtkWidget *item _U_, gpointer key)
345 {
346         int vers=(int)key;
347
348         dcerpc_version=vers;
349 }
350
351
352
353
354 static void *
355 dcerpcstat_find_vers(gpointer *key, gpointer *value _U_, gpointer *user_data _U_)
356 {
357         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
358         GtkWidget *menu_item;
359         char vs[5];
360
361         if(!uuid_equal((&k->uuid), dcerpc_uuid_program)){
362                 return NULL;
363         }
364
365         sprintf(vs,"%d.%d",k->ver&0xff,k->ver>>8);
366         menu_item=gtk_menu_item_new_with_label(vs);
367         SIGNAL_CONNECT(menu_item, "activate", dcerpcstat_version_select,
368                        ((int)k->ver));
369         gtk_widget_show(menu_item);
370         gtk_menu_append(GTK_MENU(vers_menu), menu_item);
371
372         if(dcerpc_version==0xffff){
373                 dcerpc_version=k->ver;
374         }
375
376         return NULL;
377 }
378
379
380 static void
381 dcerpcstat_program_select(GtkWidget *item _U_, gpointer key)
382 {
383         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
384
385         dcerpc_uuid_program=&k->uuid;
386
387         /* change version menu */
388         dcerpc_version=0xffff;
389         gtk_object_destroy(GTK_OBJECT(vers_menu));
390         vers_menu=gtk_menu_new();
391         g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
392         gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
393 }
394
395
396 static GtkWidget *program_submenu_menu;
397 static GtkWidget *program_submenu_item;
398 static GtkWidget *program_submenu_label;
399 static int program_subitem_index;
400 static char *first_menu_name;
401 static void 
402 dcerpcstat_add_program_to_menu(dcerpc_uuid_key *k, dcerpc_uuid_value *v)
403 {
404         GtkWidget *program_menu_item;
405         GtkWidget *box;
406         char str[64];
407
408         switch(program_subitem_index%15){
409         case 0:
410
411                 first_menu_name=v->name;
412                 snprintf(str,63,"%s ...",v->name);
413                 program_submenu_item=gtk_menu_item_new();
414                 box=gtk_hbox_new(TRUE,0);
415                 gtk_container_add(GTK_CONTAINER(program_submenu_item), box);
416                 
417                 program_submenu_label=gtk_label_new(str);
418                 gtk_box_pack_start(GTK_BOX(box), program_submenu_label, TRUE, TRUE, 0);
419                 gtk_widget_show(program_submenu_label);
420                 gtk_widget_show(box);
421
422                 gtk_menu_append(GTK_MENU(prog_menu), program_submenu_item);
423                 gtk_widget_show(program_submenu_item);
424
425                 program_submenu_menu=gtk_menu_new();
426                 gtk_menu_item_set_submenu(GTK_MENU_ITEM(program_submenu_item), program_submenu_menu);
427                 break;
428         case 14:
429                 snprintf(str,63,"%s - %s",first_menu_name,v->name);
430                 gtk_label_set_text(GTK_LABEL(program_submenu_label), str);
431                 break;
432 /*qqq*/
433         }
434         program_subitem_index++;                
435
436         program_menu_item=gtk_menu_item_new_with_label(v->name);
437         SIGNAL_CONNECT(program_menu_item, "activate", dcerpcstat_program_select, k);
438
439         gtk_widget_show(program_menu_item);
440         gtk_menu_append(GTK_MENU(program_submenu_menu), program_menu_item);
441
442         if(!dcerpc_uuid_program){
443                 dcerpc_uuid_program=&k->uuid;
444         }
445
446         return;
447 }
448
449 static void *
450 dcerpcstat_find_next_program(gpointer *key, gpointer *value, gpointer *user_data _U_)
451 {
452         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
453         dcerpc_uuid_value *v=(dcerpc_uuid_value *)value;
454
455         /* first time called, just set new_uuid to this one */
456         if((current_uuid_key==NULL)&&(new_uuid_key==NULL)){
457                 new_uuid_key=k;
458                 new_uuid_value=v;
459                 return NULL;
460         }
461
462         /* if we havent got a current one yet, just check the new
463            and scan for the first one alphabetically  */
464         if(current_uuid_key==NULL){
465                 if(strcmp(new_uuid_value->name, v->name)>0){
466                         new_uuid_key=k;
467                         new_uuid_value=v;
468                         return NULL;
469                 }
470                 return NULL;
471         }
472
473         /* searching for the next one we are only interested in those
474            that sorts alphabetically after the current one */
475         if(strcmp(current_uuid_value->name, v->name)>=0){
476                 /* this one doesnt so just skip it */
477                 return NULL;
478         }
479
480         /* is it the first potential new entry? */
481         if(new_uuid_key==NULL){
482                 new_uuid_key=k;
483                 new_uuid_value=v;
484                 return NULL;
485         }
486
487         /* does it sort before the current new one? */
488         if(strcmp(new_uuid_value->name, v->name)>0){
489                 new_uuid_key=k;
490                 new_uuid_value=v;
491                 return NULL;
492         }
493
494         return NULL;
495 }
496
497
498 static void
499 dlg_destroy_cb(void)
500 {
501         dlg=NULL;
502 }
503
504
505 static void
506 dlg_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
507 {
508         gtk_widget_destroy(GTK_WIDGET(parent_w));
509 }
510
511
512 static void
513 gtk_dcerpcstat_cb(GtkWidget *w _U_, gpointer d _U_)
514 {
515         GtkWidget *dlg_box;
516         GtkWidget *prog_box, *prog_label, *prog_opt;
517         GtkWidget *vers_label;
518         GtkWidget *filter_box, *filter_bt;
519         GtkWidget *bbox, *start_button, *cancel_button;
520         const char *filter;
521         static construct_args_t args = {
522           "Service Response Time Statistics Filter",
523           TRUE,
524           FALSE
525         };
526
527         /* if the window is already open, bring it to front and
528            un-minimize it, as necessary */
529         if(dlg){
530                 reactivate_window(dlg);
531                 return;
532         }
533
534         dlg=dlg_window_new("Ethereal: Compute DCE-RPC SRT statistics");
535         SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
536
537         dlg_box=gtk_vbox_new(FALSE, 10);
538         gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
539         gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
540         gtk_widget_show(dlg_box);
541
542         /* Program box */
543         prog_box=gtk_hbox_new(FALSE, 3);
544
545         /* Program label */
546         gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
547         prog_label=gtk_label_new("Program:");
548         gtk_box_pack_start(GTK_BOX(prog_box), prog_label, FALSE, FALSE, 0);
549         gtk_widget_show(prog_label);
550
551         /* Program menu */
552         prog_opt=gtk_option_menu_new();
553         prog_menu=gtk_menu_new();
554         current_uuid_key=NULL;
555         current_uuid_value=NULL;
556 /*qqq*/
557         program_submenu_item=NULL;
558         program_submenu_menu=NULL;
559         program_subitem_index=0;
560         do {
561                 new_uuid_key=NULL;
562                 new_uuid_value=NULL;
563                 g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_next_program, NULL);
564                 if(new_uuid_key){
565                         dcerpcstat_add_program_to_menu(new_uuid_key, new_uuid_value);
566                 }
567                 current_uuid_key=new_uuid_key;
568                 current_uuid_value=new_uuid_value;
569         } while(new_uuid_key!=NULL);
570
571         gtk_option_menu_set_menu(GTK_OPTION_MENU(prog_opt), prog_menu);
572         gtk_box_pack_start(GTK_BOX(prog_box), prog_opt, TRUE, TRUE, 0);
573         gtk_widget_show(prog_opt);
574
575         /* Version label */
576         gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
577         vers_label=gtk_label_new("Version:");
578         gtk_box_pack_start(GTK_BOX(prog_box), vers_label, FALSE, FALSE, 0);
579         gtk_widget_show(vers_label);
580
581         /* Version menu */
582         vers_opt=gtk_option_menu_new();
583         vers_menu=gtk_menu_new();
584         dcerpc_version=0xffff;
585         g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
586         gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
587         gtk_box_pack_start(GTK_BOX(prog_box), vers_opt, TRUE, TRUE, 0);
588         gtk_widget_show(vers_opt);
589
590         gtk_box_pack_start(GTK_BOX(dlg_box), prog_box, TRUE, TRUE, 0);
591         gtk_widget_show(prog_box);
592
593         /* Filter box */
594         filter_box=gtk_hbox_new(FALSE, 3);
595
596         /* Filter label */
597         filter_bt=gtk_button_new_with_label("Filter:");
598         SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
599         gtk_box_pack_start(GTK_BOX(filter_box), filter_bt, FALSE, FALSE, 0);
600         gtk_widget_show(filter_bt);
601
602         /* Filter entry */
603         filter_entry=gtk_entry_new();
604         gtk_widget_set_usize(filter_entry, 300, -2);
605
606         /* Filter entry */
607         filter_entry=gtk_entry_new();
608         gtk_widget_set_usize(filter_entry, 300, -2);
609
610         gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
611         filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
612         if(filter){
613                 gtk_entry_set_text(GTK_ENTRY(filter_entry), filter);
614         }
615         gtk_widget_show(filter_entry);
616         
617         gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
618         gtk_widget_show(filter_box);
619
620         /* button box */
621         bbox=gtk_hbutton_box_new();
622         gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_DEFAULT_STYLE);
623         gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
624         gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
625         gtk_widget_show(bbox);
626
627         /* the start button */
628         start_button=gtk_button_new_with_label("Create Stat");
629         SIGNAL_CONNECT_OBJECT(start_button, "clicked", 
630                               dcerpcstat_start_button_clicked, NULL);
631         gtk_box_pack_start(GTK_BOX(bbox), start_button, TRUE, TRUE, 0);
632         GTK_WIDGET_SET_FLAGS(start_button, GTK_CAN_DEFAULT);
633         gtk_widget_grab_default(start_button);
634         gtk_widget_show(start_button);
635
636 #if GTK_MAJOR_VERSION < 2
637         cancel_button=gtk_button_new_with_label("Cancel");
638 #else
639         cancel_button=gtk_button_new_from_stock(GTK_STOCK_CANCEL);
640 #endif
641         SIGNAL_CONNECT(cancel_button, "clicked", dlg_cancel_cb, dlg);
642         GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT);
643         gtk_box_pack_start(GTK_BOX(bbox), cancel_button, TRUE, TRUE, 0);
644         gtk_widget_show(cancel_button);
645
646         /* Catch the "activate" signal on the filter text entry, so that
647            if the user types Return there, we act as if the "Create Stat"
648            button had been selected, as happens if Return is typed if some
649            widget that *doesn't* handle the Return key has the input
650            focus. */
651         dlg_set_activate(filter_entry, start_button);
652
653         /* Catch the "key_press_event" signal in the window, so that we can
654            catch the ESC key being pressed and act as if the "Cancel" button
655            had been selected. */
656         dlg_set_cancel(dlg, cancel_button);
657
658         /* Give the initial focus to the "Filter" entry box. */
659         gtk_widget_grab_focus(filter_entry);
660
661         gtk_widget_show_all(dlg);
662 }
663
664 void
665 register_tap_listener_gtkdcerpcstat(void)
666 {
667         register_ethereal_tap("dcerpc,srt,", gtk_dcerpcstat_init);
668 }
669
670 void
671 register_tap_menu_gtkdcerpcstat(void)
672 {
673         register_tap_menu_item("Statistics/Service Response Time/DCE-RPC...",
674             gtk_dcerpcstat_cb, NULL, NULL);
675 }