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