Pass ESD_BTN_OK rather than NULL as a second argument to
[obnox/wireshark/wip.git] / gtk / h225_counter.c
1 /* h225_counter.c
2  * h225 message counter for ethereal
3  * Copyright 2003 Lars Roland
4  *
5  * $Id: h225_counter.c,v 1.8 2004/01/31 03:22:41 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #include <gtk/gtk.h>
37 #include <string.h>
38 #include "../epan/packet_info.h"
39 #include "../epan/epan.h"
40 #include "menu.h"
41 #include "../tap.h"
42 #include "../epan/value_string.h"
43 #include "../register.h"
44 #include "../packet-h225.h"
45 #include "gtk_stat_util.h"
46 #include "compat_macros.h"
47 #include "../simple_dialog.h"
48 #include "dlg_utils.h"
49 #include "../file.h"
50 #include "../globals.h"
51 #include "../tap_dfilter_dlg.h"
52 #include "tap_dfilter_dlg.h"
53
54 extern GtkWidget *main_display_filter_widget;
55
56 void gtk_h225counter_init(char *optarg);
57
58 tap_dfilter_dlg h225_counter_dlg = {"H.225 Messages and Message Reasons", "h225,counter", gtk_h225counter_init, -1};
59
60 /* following values represent the size of their valuestring arrays */
61
62 #define RAS_MSG_TYPES 33
63 #define CS_MSG_TYPES 13
64
65 #define GRJ_REASONS 8
66 #define RRJ_REASONS 18
67 #define URQ_REASONS 6
68 #define URJ_REASONS 6
69 #define ARJ_REASONS 22
70 #define BRJ_REASONS 8
71 #define DRQ_REASONS 3
72 #define DRJ_REASONS 4
73 #define LRJ_REASONS 16
74 #define IRQNAK_REASONS 4
75 #define REL_CMP_REASONS 26
76 #define FACILITY_REASONS 11
77
78
79 /* used to keep track of the statistics for an entire program interface */
80 typedef struct _h225counter_t {
81         GtkWidget *win;
82         GtkWidget *vbox;
83         char *filter;
84         GtkWidget *scrolled_window;
85         GtkCList *table;
86         guint32 ras_msg[RAS_MSG_TYPES + 1];
87         guint32 cs_msg[CS_MSG_TYPES + 1];
88         guint32 grj_reason[GRJ_REASONS + 1];
89         guint32 rrj_reason[RRJ_REASONS + 1];
90         guint32 urq_reason[URQ_REASONS + 1];
91         guint32 urj_reason[URJ_REASONS + 1];
92         guint32 arj_reason[ARJ_REASONS + 1];
93         guint32 brj_reason[BRJ_REASONS + 1];
94         guint32 drq_reason[DRQ_REASONS + 1];
95         guint32 drj_reason[DRJ_REASONS + 1];
96         guint32 lrj_reason[LRJ_REASONS + 1];
97         guint32 irqnak_reason[IRQNAK_REASONS + 1];
98         guint32 rel_cmp_reason[REL_CMP_REASONS + 1];
99         guint32 facility_reason[FACILITY_REASONS + 1];
100 } h225counter_t;
101
102
103 static void
104 h225counter_reset(void *phs)
105 {
106         h225counter_t *hs=(h225counter_t *)phs;
107         int i;
108
109         for(i=0;i<=RAS_MSG_TYPES;i++) {
110                 hs->ras_msg[i] = 0;
111         }
112         for(i=0;i<=CS_MSG_TYPES;i++) {
113                 hs->cs_msg[i] = 0;
114         }
115         for(i=0;i<=GRJ_REASONS;i++) {
116                 hs->grj_reason[i] = 0;
117         }
118         for(i=0;i<=RRJ_REASONS;i++) {
119                 hs->rrj_reason[i] = 0;
120         }
121         for(i=0;i<=URQ_REASONS;i++) {
122                 hs->urq_reason[i] = 0;
123         }
124         for(i=0;i<=URJ_REASONS;i++) {
125                 hs->urj_reason[i] = 0;
126         }
127         for(i=0;i<=ARJ_REASONS;i++) {
128                 hs->arj_reason[i] = 0;
129         }
130         for(i=0;i<=BRJ_REASONS;i++) {
131                 hs->brj_reason[i] = 0;
132         }
133         for(i=0;i<=DRQ_REASONS;i++) {
134                 hs->drq_reason[i] = 0;
135         }
136         for(i=0;i<=DRJ_REASONS;i++) {
137                 hs->drj_reason[i] = 0;
138         }
139         for(i=0;i<=LRJ_REASONS;i++) {
140                 hs->lrj_reason[i] = 0;
141         }
142         for(i=0;i<=IRQNAK_REASONS;i++) {
143                 hs->irqnak_reason[i] = 0;
144         }
145         for(i=0;i<=REL_CMP_REASONS;i++) {
146                 hs->rel_cmp_reason[i] = 0;
147         }
148         for(i=0;i<=FACILITY_REASONS;i++) {
149                 hs->facility_reason[i] = 0;
150         }
151 }
152
153 static int
154 h225counter_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *phi)
155 {
156         h225counter_t *hs=(h225counter_t *)phs;
157         h225_packet_info *pi=phi;
158
159         switch (pi->msg_type) {
160
161         case H225_RAS:
162                 if(pi->msg_tag==-1) { /* uninitialized */
163                         return 0;
164                 }
165                 else if (pi->msg_tag >= RAS_MSG_TYPES) { /* unknown */
166                         hs->ras_msg[RAS_MSG_TYPES]++;
167                 }
168                 else {
169                         hs->ras_msg[pi->msg_tag]++;
170                 }
171
172                 /* Look for reason tag */
173                 if(pi->reason==-1) { /* uninitialized */
174                         break;
175                 }
176
177                 switch(pi->msg_tag) {
178
179                 case 2: /* GRJ */
180                         if(pi->reason < GRJ_REASONS)
181                                 hs->grj_reason[pi->reason]++;
182                         else
183                                 hs->grj_reason[GRJ_REASONS]++;
184                         break;
185                 case 5: /* RRJ */
186                         if(pi->reason < RRJ_REASONS)
187                                 hs->rrj_reason[pi->reason]++;
188                         else
189                                 hs->rrj_reason[RRJ_REASONS]++;
190                         break;
191                 case 6: /* URQ */
192                         if(pi->reason < URQ_REASONS)
193                                 hs->urq_reason[pi->reason]++;
194                         else
195                                 hs->urq_reason[URQ_REASONS]++;
196                         break;
197                 case 8: /* URJ */
198                         if(pi->reason < URJ_REASONS)
199                                 hs->urj_reason[pi->reason]++;
200                         else
201                                 hs->urj_reason[URJ_REASONS]++;
202                         break;
203                 case 11: /* ARJ */
204                         if(pi->reason < ARJ_REASONS)
205                                 hs->arj_reason[pi->reason]++;
206                         else
207                                 hs->arj_reason[ARJ_REASONS]++;
208                         break;
209                 case 14: /* BRJ */
210                         if(pi->reason < BRJ_REASONS)
211                                 hs->brj_reason[pi->reason]++;
212                         else
213                                 hs->brj_reason[BRJ_REASONS]++;
214                         break;
215                 case 15: /* DRQ */
216                         if(pi->reason < DRQ_REASONS)
217                                 hs->drq_reason[pi->reason]++;
218                         else
219                                 hs->drq_reason[DRQ_REASONS]++;
220                         break;
221                 case 17: /* DRJ */
222                         if(pi->reason < DRJ_REASONS)
223                                 hs->drj_reason[pi->reason]++;
224                         else
225                                 hs->drj_reason[DRJ_REASONS]++;
226                         break;
227                 case 20: /* LRJ */
228                         if(pi->reason < LRJ_REASONS)
229                                 hs->lrj_reason[pi->reason]++;
230                         else
231                                 hs->lrj_reason[LRJ_REASONS]++;
232                         break;
233                 case 29: /* IRQ Nak */
234                         if(pi->reason < IRQNAK_REASONS)
235                                 hs->irqnak_reason[pi->reason]++;
236                         else
237                                 hs->irqnak_reason[IRQNAK_REASONS]++;
238                         break;
239
240                 default:
241                         /* do nothing */
242                         break;
243                 }
244
245                 break;
246
247         case H225_CS:
248                 if(pi->msg_tag==-1) { /* uninitialized */
249                         return 0;
250                 }
251                 else if (pi->msg_tag >= CS_MSG_TYPES) { /* unknown */
252                         hs->cs_msg[CS_MSG_TYPES]++;
253                 }
254                 else {
255                         hs->cs_msg[pi->msg_tag]++;
256                 }
257
258                 /* Look for reason tag */
259                 if(pi->reason==-1) { /* uninitialized */
260                         break;
261                 }
262
263                 switch(pi->msg_tag) {
264
265                 case 5: /* ReleaseComplete */
266                         if(pi->reason < REL_CMP_REASONS)
267                                 hs->rel_cmp_reason[pi->reason]++;
268                         else
269                                 hs->rel_cmp_reason[REL_CMP_REASONS]++;
270                         break;
271                 case 6: /* Facility */
272                         if(pi->reason < FACILITY_REASONS)
273                                 hs->facility_reason[pi->reason]++;
274                         else
275                                 hs->facility_reason[FACILITY_REASONS]++;
276                         break;
277                 default:
278                         /* do nothing */
279                         break;
280                 }
281
282                 break;
283
284         default:
285                 return 0;
286                 break;
287         }
288
289         return 1;
290 }
291
292 static void
293 h225counter_draw(void *phs)
294 {
295         h225counter_t *hs=(h225counter_t *)phs;
296         int i,j;
297         char *str[2];
298
299         for(i=0;i<2;i++) {
300                 str[i]=g_malloc(sizeof(char[256]));
301         }
302         /* Now print Message and Reason Counter Table */
303         /* clear list before printing */
304         gtk_clist_clear(hs->table);
305
306         for(i=0;i<=RAS_MSG_TYPES;i++) {
307                 if(hs->ras_msg[i]!=0) {
308                         sprintf(str[0], "%s", val_to_str(i,RasMessage_vals,"unknown ras-messages  "));
309                         sprintf(str[1], "%d", hs->ras_msg[i]);
310                         gtk_clist_append(hs->table, str);
311
312                         /* reason counter */
313                         switch(i) {
314                         case 2: /* GRJ */
315                                 for(j=0;j<=GRJ_REASONS;j++) {
316                                         if(hs->grj_reason[j]!=0) {
317                                                 sprintf(str[0], "    %s", val_to_str(j,GatekeeperRejectReason_vals,"unknown reason   "));
318                                                 sprintf(str[1], "%d", hs->grj_reason[j]);
319                                                 gtk_clist_append(hs->table, str);
320                                         }
321                                 }
322                                 break;
323                         case 5: /* RRJ */
324                                 for(j=0;j<=RRJ_REASONS;j++) {
325                                         if(hs->rrj_reason[j]!=0) {
326                                                 sprintf(str[0], "    %s", val_to_str(j,RegistrationRejectReason_vals,"unknown reason   "));
327                                                 sprintf(str[1], "%d", hs->rrj_reason[j]);
328                                                 gtk_clist_append(hs->table, str);
329                                         }
330                                 }
331                                 break;
332                         case 6: /* URQ */
333                                 for(j=0;j<=URQ_REASONS;j++) {
334                                         if(hs->urq_reason[j]!=0) {
335                                                 sprintf(str[0], "    %s", val_to_str(j,UnregRequestReason_vals,"unknown reason   "));
336                                                 sprintf(str[1], "%d", hs->urq_reason[j]);
337                                                 gtk_clist_append(hs->table, str);
338                                         }
339                                 }
340                                 break;
341                         case 8: /* URJ */
342                                 for(j=0;j<=URJ_REASONS;j++) {
343                                         if(hs->urj_reason[j]!=0) {
344                                                 sprintf(str[0], "    %s", val_to_str(j,UnregRejectReason_vals,"unknown reason   "));
345                                                 sprintf(str[1], "%d", hs->urj_reason[j]);
346                                                 gtk_clist_append(hs->table, str);
347                                         }
348                                 }
349                                 break;
350                         case 11: /* ARJ */
351                                 for(j=0;j<=ARJ_REASONS;j++) {
352                                         if(hs->arj_reason[j]!=0) {
353                                                 sprintf(str[0], "    %s", val_to_str(j,AdmissionRejectReason_vals,"unknown reason   "));
354                                                 sprintf(str[1], "%d", hs->arj_reason[j]);
355                                                 gtk_clist_append(hs->table, str);
356                                         }
357                                 }
358                                 break;
359                         case 14: /* BRJ */
360                                 for(j=0;j<=BRJ_REASONS;j++) {
361                                         if(hs->brj_reason[j]!=0) {
362                                                 sprintf(str[0], "    %s", val_to_str(j,BandRejectReason_vals,"unknown reason   "));
363                                                 sprintf(str[1], "%d", hs->brj_reason[j]);
364                                                 gtk_clist_append(hs->table, str);
365                                         }
366                                 }
367                                 break;
368                         case 15: /* DRQ */
369                                 for(j=0;j<=DRQ_REASONS;j++) {
370                                         if(hs->drq_reason[j]!=0) {
371                                                 sprintf(str[0], "    %s", val_to_str(j,DisengageReason_vals,"unknown reason   "));
372                                                 sprintf(str[1], "%d", hs->drq_reason[j]);
373                                                 gtk_clist_append(hs->table, str);
374                                         }
375                                 }
376                                 break;
377                         case 17: /* DRJ */
378                                 for(j=0;j<=DRJ_REASONS;j++) {
379                                         if(hs->drj_reason[j]!=0) {
380                                                 sprintf(str[0], "    %s", val_to_str(j,DisengageRejectReason_vals,"unknown reason   "));
381                                                 sprintf(str[1], "%d", hs->drj_reason[j]);
382                                                 gtk_clist_append(hs->table, str);
383                                         }
384                                 }
385                                 break;
386                         case 20: /* LRJ */
387                                 for(j=0;j<=LRJ_REASONS;j++) {
388                                         if(hs->lrj_reason[j]!=0) {
389                                                 sprintf(str[0], "    %s", val_to_str(j,LocationRejectReason_vals,"unknown reason   "));
390                                                 sprintf(str[1], "%d", hs->lrj_reason[j]);
391                                                 gtk_clist_append(hs->table, str);
392                                         }
393                                 }
394                                 break;
395                         case 29: /* IRQNak */
396                                 for(j=0;j<=IRQNAK_REASONS;j++) {
397                                         if(hs->irqnak_reason[j]!=0) {
398                                                 sprintf(str[0], "    %s", val_to_str(j,InfoRequestNakReason_vals,"unknown reason   "));
399                                                 sprintf(str[1], "%d", hs->irqnak_reason[j]);
400                                                 gtk_clist_append(hs->table, str);
401                                         }
402                                 }
403                                 break;
404                         default:
405                                 break;
406                         }
407                         /* end of reason counter*/
408                 }
409         }
410
411         for(i=0;i<=CS_MSG_TYPES;i++) {
412                 if(hs->cs_msg[i]!=0) {
413                         sprintf(str[0], "%s", val_to_str(i,h323_message_body_vals,"unknown cs-messages   "));
414                         sprintf(str[1], "%d", hs->cs_msg[i]);
415                         gtk_clist_append(hs->table, str);
416
417                         /* reason counter */
418                         switch(i) {
419                         case 5: /* ReleaseComplete */
420                                 for(j=0;j<=REL_CMP_REASONS;j++) {
421                                         if(hs->rel_cmp_reason[j]!=0) {
422                                                 sprintf(str[0], "    %s", val_to_str(j,ReleaseCompleteReason_vals,"unknown reason   "));
423                                                 sprintf(str[1], "%d", hs->rel_cmp_reason[j]);
424                                                 gtk_clist_append(hs->table, str);
425                                         }
426                                 }
427                                 break;
428                         case 6: /* Facility */
429                                 for(j=0;j<=FACILITY_REASONS;j++) {
430                                         if(hs->facility_reason[j]!=0) {
431                                                 sprintf(str[0], "    %s", val_to_str(j,FacilityReason_vals,"unknown reason   "));
432                                                 sprintf(str[1], "%d", hs->facility_reason[j]);
433                                                 gtk_clist_append(hs->table, str);
434                                         }
435                                 }
436                                 break;
437                         default:
438                                 break;
439                         }
440                 }
441         }
442
443         gtk_widget_show(GTK_WIDGET(hs->table));
444
445 }
446
447 void protect_thread_critical_region(void);
448 void unprotect_thread_critical_region(void);
449 static void
450 win_destroy_cb(GtkWindow *win _U_, gpointer data)
451 {
452         h225counter_t *hs=(h225counter_t *)data;
453
454         protect_thread_critical_region();
455         remove_tap_listener(hs);
456         unprotect_thread_critical_region();
457
458         if(hs->filter){
459                 g_free(hs->filter);
460                 hs->filter=NULL;
461         }
462         g_free(hs);
463 }
464
465
466 static gchar *titles[]={"Message Type or Reason",
467                         "Count" };
468
469 void
470 gtk_h225counter_init(char *optarg)
471 {
472         h225counter_t *hs;
473         char *filter=NULL;
474         GString *error_string;
475
476         if(strncmp(optarg,"h225,counter,",13) == 0){
477                 filter=optarg+13;
478         } else {
479                 filter=g_malloc(1);
480                 *filter='\0';
481         }
482
483         hs=g_malloc(sizeof(h225counter_t));
484         hs->filter=g_malloc(strlen(filter)+1);
485         strcpy(hs->filter, filter);
486
487         h225counter_reset(hs);
488
489         hs->win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
490         SIGNAL_CONNECT(hs->win, "destroy", win_destroy_cb, hs);
491
492         hs->vbox=gtk_vbox_new(FALSE, 0);
493
494         init_main_stat_window(hs->win, hs->vbox, "ITU-T H.225 Message and Message Reason Counter", filter);
495
496         /* init a scrolled window*/
497         hs->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
498         WIDGET_SET_SIZE(hs->scrolled_window, 400, 200);
499
500         hs->table = create_stat_table(hs->scrolled_window, hs->vbox, 2, titles);
501
502         error_string=register_tap_listener("h225", hs, filter, h225counter_reset, h225counter_packet, h225counter_draw);
503         if(error_string){
504                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
505                 g_string_free(error_string, TRUE);
506                 g_free(hs->filter);
507                 g_free(hs);
508                 return;
509         }
510
511         gtk_widget_show_all(hs->win);
512         redissect_packets(&cfile);
513 }
514
515 void
516 register_tap_listener_gtk_h225counter(void)
517 {
518         register_ethereal_tap("h225,counter", gtk_h225counter_init);
519 }
520
521 void
522 register_tap_menu_gtk_h225counter(void)
523 {
524         register_tap_menu_item("_Statistics/Watch protocol/ITU-T H.225...",
525             gtk_tap_dfilter_dlg_cb, NULL, NULL, &(h225_counter_dlg));
526 }