Have cf_retap_packets() take an argument that indicates whether 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$
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 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <string.h>
35
36 #include <gtk/gtk.h>
37
38 #include <epan/packet_info.h>
39 #include <epan/epan.h>
40 #include <epan/value_string.h>
41
42 #include <epan/tap.h>
43 #include "../register.h"
44 #include <epan/dissectors/packet-h225.h>
45 #include "gui_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 "../stat_menu.h"
52 #include "../tap_dfilter_dlg.h"
53 #include "gui_utils.h"
54
55
56 static void gtk_h225counter_init(const char *optarg);
57
58 static tap_dfilter_dlg h225_counter_dlg = {
59         "H.225 Messages and Message Reasons",
60         "h225,counter",
61         gtk_h225counter_init,
62         -1
63 };
64
65 /* following values represent the size of their valuestring arrays */
66
67 #define RAS_MSG_TYPES 33
68 #define CS_MSG_TYPES 13
69
70 #define GRJ_REASONS 8
71 #define RRJ_REASONS 18
72 #define URQ_REASONS 6
73 #define URJ_REASONS 6
74 #define ARJ_REASONS 22
75 #define BRJ_REASONS 8
76 #define DRQ_REASONS 3
77 #define DRJ_REASONS 4
78 #define LRJ_REASONS 16
79 #define IRQNAK_REASONS 4
80 #define REL_CMP_REASONS 26
81 #define FACILITY_REASONS 11
82
83
84 /* used to keep track of the statistics for an entire program interface */
85 typedef struct _h225counter_t {
86         GtkWidget *win;
87         GtkWidget *vbox;
88         char *filter;
89         GtkWidget *scrolled_window;
90         GtkCList *table;
91         guint32 ras_msg[RAS_MSG_TYPES + 1];
92         guint32 cs_msg[CS_MSG_TYPES + 1];
93         guint32 grj_reason[GRJ_REASONS + 1];
94         guint32 rrj_reason[RRJ_REASONS + 1];
95         guint32 urq_reason[URQ_REASONS + 1];
96         guint32 urj_reason[URJ_REASONS + 1];
97         guint32 arj_reason[ARJ_REASONS + 1];
98         guint32 brj_reason[BRJ_REASONS + 1];
99         guint32 drq_reason[DRQ_REASONS + 1];
100         guint32 drj_reason[DRJ_REASONS + 1];
101         guint32 lrj_reason[LRJ_REASONS + 1];
102         guint32 irqnak_reason[IRQNAK_REASONS + 1];
103         guint32 rel_cmp_reason[REL_CMP_REASONS + 1];
104         guint32 facility_reason[FACILITY_REASONS + 1];
105 } h225counter_t;
106
107
108 static void
109 h225counter_reset(void *phs)
110 {
111         h225counter_t *hs=(h225counter_t *)phs;
112         int i;
113
114         for(i=0;i<=RAS_MSG_TYPES;i++) {
115                 hs->ras_msg[i] = 0;
116         }
117         for(i=0;i<=CS_MSG_TYPES;i++) {
118                 hs->cs_msg[i] = 0;
119         }
120         for(i=0;i<=GRJ_REASONS;i++) {
121                 hs->grj_reason[i] = 0;
122         }
123         for(i=0;i<=RRJ_REASONS;i++) {
124                 hs->rrj_reason[i] = 0;
125         }
126         for(i=0;i<=URQ_REASONS;i++) {
127                 hs->urq_reason[i] = 0;
128         }
129         for(i=0;i<=URJ_REASONS;i++) {
130                 hs->urj_reason[i] = 0;
131         }
132         for(i=0;i<=ARJ_REASONS;i++) {
133                 hs->arj_reason[i] = 0;
134         }
135         for(i=0;i<=BRJ_REASONS;i++) {
136                 hs->brj_reason[i] = 0;
137         }
138         for(i=0;i<=DRQ_REASONS;i++) {
139                 hs->drq_reason[i] = 0;
140         }
141         for(i=0;i<=DRJ_REASONS;i++) {
142                 hs->drj_reason[i] = 0;
143         }
144         for(i=0;i<=LRJ_REASONS;i++) {
145                 hs->lrj_reason[i] = 0;
146         }
147         for(i=0;i<=IRQNAK_REASONS;i++) {
148                 hs->irqnak_reason[i] = 0;
149         }
150         for(i=0;i<=REL_CMP_REASONS;i++) {
151                 hs->rel_cmp_reason[i] = 0;
152         }
153         for(i=0;i<=FACILITY_REASONS;i++) {
154                 hs->facility_reason[i] = 0;
155         }
156 }
157
158 static int
159 h225counter_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi)
160 {
161         h225counter_t *hs=(h225counter_t *)phs;
162         const h225_packet_info *pi=phi;
163
164         switch (pi->msg_type) {
165
166         case H225_RAS:
167                 if(pi->msg_tag==-1) { /* uninitialized */
168                         return 0;
169                 }
170                 else if (pi->msg_tag >= RAS_MSG_TYPES) { /* unknown */
171                         hs->ras_msg[RAS_MSG_TYPES]++;
172                 }
173                 else {
174                         hs->ras_msg[pi->msg_tag]++;
175                 }
176
177                 /* Look for reason tag */
178                 if(pi->reason==-1) { /* uninitialized */
179                         break;
180                 }
181
182                 switch(pi->msg_tag) {
183
184                 case 2: /* GRJ */
185                         if(pi->reason < GRJ_REASONS)
186                                 hs->grj_reason[pi->reason]++;
187                         else
188                                 hs->grj_reason[GRJ_REASONS]++;
189                         break;
190                 case 5: /* RRJ */
191                         if(pi->reason < RRJ_REASONS)
192                                 hs->rrj_reason[pi->reason]++;
193                         else
194                                 hs->rrj_reason[RRJ_REASONS]++;
195                         break;
196                 case 6: /* URQ */
197                         if(pi->reason < URQ_REASONS)
198                                 hs->urq_reason[pi->reason]++;
199                         else
200                                 hs->urq_reason[URQ_REASONS]++;
201                         break;
202                 case 8: /* URJ */
203                         if(pi->reason < URJ_REASONS)
204                                 hs->urj_reason[pi->reason]++;
205                         else
206                                 hs->urj_reason[URJ_REASONS]++;
207                         break;
208                 case 11: /* ARJ */
209                         if(pi->reason < ARJ_REASONS)
210                                 hs->arj_reason[pi->reason]++;
211                         else
212                                 hs->arj_reason[ARJ_REASONS]++;
213                         break;
214                 case 14: /* BRJ */
215                         if(pi->reason < BRJ_REASONS)
216                                 hs->brj_reason[pi->reason]++;
217                         else
218                                 hs->brj_reason[BRJ_REASONS]++;
219                         break;
220                 case 15: /* DRQ */
221                         if(pi->reason < DRQ_REASONS)
222                                 hs->drq_reason[pi->reason]++;
223                         else
224                                 hs->drq_reason[DRQ_REASONS]++;
225                         break;
226                 case 17: /* DRJ */
227                         if(pi->reason < DRJ_REASONS)
228                                 hs->drj_reason[pi->reason]++;
229                         else
230                                 hs->drj_reason[DRJ_REASONS]++;
231                         break;
232                 case 20: /* LRJ */
233                         if(pi->reason < LRJ_REASONS)
234                                 hs->lrj_reason[pi->reason]++;
235                         else
236                                 hs->lrj_reason[LRJ_REASONS]++;
237                         break;
238                 case 29: /* IRQ Nak */
239                         if(pi->reason < IRQNAK_REASONS)
240                                 hs->irqnak_reason[pi->reason]++;
241                         else
242                                 hs->irqnak_reason[IRQNAK_REASONS]++;
243                         break;
244
245                 default:
246                         /* do nothing */
247                         break;
248                 }
249
250                 break;
251
252         case H225_CS:
253                 if(pi->msg_tag==-1) { /* uninitialized */
254                         return 0;
255                 }
256                 else if (pi->msg_tag >= CS_MSG_TYPES) { /* unknown */
257                         hs->cs_msg[CS_MSG_TYPES]++;
258                 }
259                 else {
260                         hs->cs_msg[pi->msg_tag]++;
261                 }
262
263                 /* Look for reason tag */
264                 if(pi->reason==-1) { /* uninitialized */
265                         break;
266                 }
267
268                 switch(pi->msg_tag) {
269
270                 case 5: /* ReleaseComplete */
271                         if(pi->reason < REL_CMP_REASONS)
272                                 hs->rel_cmp_reason[pi->reason]++;
273                         else
274                                 hs->rel_cmp_reason[REL_CMP_REASONS]++;
275                         break;
276                 case 6: /* Facility */
277                         if(pi->reason < FACILITY_REASONS)
278                                 hs->facility_reason[pi->reason]++;
279                         else
280                                 hs->facility_reason[FACILITY_REASONS]++;
281                         break;
282                 default:
283                         /* do nothing */
284                         break;
285                 }
286
287                 break;
288
289         default:
290                 return 0;
291                 break;
292         }
293
294         return 1;
295 }
296
297 static void
298 h225counter_draw(void *phs)
299 {
300         h225counter_t *hs=(h225counter_t *)phs;
301         int i,j;
302         char *str[2];
303
304         for(i=0;i<2;i++) {
305                 str[i]=g_malloc(sizeof(char[256]));
306         }
307         /* Now print Message and Reason Counter Table */
308         /* clear list before printing */
309         gtk_clist_clear(hs->table);
310
311         for(i=0;i<=RAS_MSG_TYPES;i++) {
312                 if(hs->ras_msg[i]!=0) {
313                         g_snprintf(str[0], sizeof(char[256]), 
314                 "%s", val_to_str(i,RasMessage_vals,"unknown ras-messages  "));
315                         g_snprintf(str[1], sizeof(char[256]),
316                 "%d", hs->ras_msg[i]);
317                         gtk_clist_append(hs->table, str);
318
319                         /* reason counter */
320                         switch(i) {
321                         case 2: /* GRJ */
322                                 for(j=0;j<=GRJ_REASONS;j++) {
323                                         if(hs->grj_reason[j]!=0) {
324                                                 g_snprintf(str[0], sizeof(char[256]),
325                             "    %s", val_to_str(j,GatekeeperRejectReason_vals,"unknown reason   "));
326                                                 g_snprintf(str[1], sizeof(char[256]),
327                             "%d", hs->grj_reason[j]);
328                                                 gtk_clist_append(hs->table, str);
329                                         }
330                                 }
331                                 break;
332                         case 5: /* RRJ */
333                                 for(j=0;j<=RRJ_REASONS;j++) {
334                                         if(hs->rrj_reason[j]!=0) {
335                                                 g_snprintf(str[0], sizeof(char[256]),
336                             "    %s", val_to_str(j,RegistrationRejectReason_vals,"unknown reason   "));
337                                                 g_snprintf(str[1], sizeof(char[256]),
338                             "%d", hs->rrj_reason[j]);
339                                                 gtk_clist_append(hs->table, str);
340                                         }
341                                 }
342                                 break;
343                         case 6: /* URQ */
344                                 for(j=0;j<=URQ_REASONS;j++) {
345                                         if(hs->urq_reason[j]!=0) {
346                                                 g_snprintf(str[0], sizeof(char[256]),
347                             "    %s", val_to_str(j,UnregRequestReason_vals,"unknown reason   "));
348                                                 g_snprintf(str[1], sizeof(char[256]),
349                             "%d", hs->urq_reason[j]);
350                                                 gtk_clist_append(hs->table, str);
351                                         }
352                                 }
353                                 break;
354                         case 8: /* URJ */
355                                 for(j=0;j<=URJ_REASONS;j++) {
356                                         if(hs->urj_reason[j]!=0) {
357                                                 g_snprintf(str[0], sizeof(char[256]),
358                             "    %s", val_to_str(j,UnregRejectReason_vals,"unknown reason   "));
359                                                 g_snprintf(str[1], sizeof(char[256]),
360                             "%d", hs->urj_reason[j]);
361                                                 gtk_clist_append(hs->table, str);
362                                         }
363                                 }
364                                 break;
365                         case 11: /* ARJ */
366                                 for(j=0;j<=ARJ_REASONS;j++) {
367                                         if(hs->arj_reason[j]!=0) {
368                                                 g_snprintf(str[0], sizeof(char[256]),
369                             "    %s", val_to_str(j,AdmissionRejectReason_vals,"unknown reason   "));
370                                                 g_snprintf(str[1], sizeof(char[256]),
371                             "%d", hs->arj_reason[j]);
372                                                 gtk_clist_append(hs->table, str);
373                                         }
374                                 }
375                                 break;
376                         case 14: /* BRJ */
377                                 for(j=0;j<=BRJ_REASONS;j++) {
378                                         if(hs->brj_reason[j]!=0) {
379                                                 g_snprintf(str[0], sizeof(char[256]),
380                             "    %s", val_to_str(j,BandRejectReason_vals,"unknown reason   "));
381                                                 g_snprintf(str[1], sizeof(char[256]),
382                             "%d", hs->brj_reason[j]);
383                                                 gtk_clist_append(hs->table, str);
384                                         }
385                                 }
386                                 break;
387                         case 15: /* DRQ */
388                                 for(j=0;j<=DRQ_REASONS;j++) {
389                                         if(hs->drq_reason[j]!=0) {
390                                                 g_snprintf(str[0], sizeof(char[256]),
391                             "    %s", val_to_str(j,DisengageReason_vals,"unknown reason   "));
392                                                 g_snprintf(str[1], sizeof(char[256]),
393                             "%d", hs->drq_reason[j]);
394                                                 gtk_clist_append(hs->table, str);
395                                         }
396                                 }
397                                 break;
398                         case 17: /* DRJ */
399                                 for(j=0;j<=DRJ_REASONS;j++) {
400                                         if(hs->drj_reason[j]!=0) {
401                                                 g_snprintf(str[0], sizeof(char[256]),
402                             "    %s", val_to_str(j,DisengageRejectReason_vals,"unknown reason   "));
403                                                 g_snprintf(str[1], sizeof(char[256]),
404                             "%d", hs->drj_reason[j]);
405                                                 gtk_clist_append(hs->table, str);
406                                         }
407                                 }
408                                 break;
409                         case 20: /* LRJ */
410                                 for(j=0;j<=LRJ_REASONS;j++) {
411                                         if(hs->lrj_reason[j]!=0) {
412                                                 g_snprintf(str[0], sizeof(char[256]),
413                             "    %s", val_to_str(j,LocationRejectReason_vals,"unknown reason   "));
414                                                 g_snprintf(str[1], sizeof(char[256]),
415                             "%d", hs->lrj_reason[j]);
416                                                 gtk_clist_append(hs->table, str);
417                                         }
418                                 }
419                                 break;
420                         case 29: /* IRQNak */
421                                 for(j=0;j<=IRQNAK_REASONS;j++) {
422                                         if(hs->irqnak_reason[j]!=0) {
423                                                 g_snprintf(str[0], sizeof(char[256]),
424                             "    %s", val_to_str(j,InfoRequestNakReason_vals,"unknown reason   "));
425                                                 g_snprintf(str[1], sizeof(char[256]),
426                             "%d", hs->irqnak_reason[j]);
427                                                 gtk_clist_append(hs->table, str);
428                                         }
429                                 }
430                                 break;
431                         default:
432                                 break;
433                         }
434                         /* end of reason counter*/
435                 }
436         }
437
438         for(i=0;i<=CS_MSG_TYPES;i++) {
439                 if(hs->cs_msg[i]!=0) {
440                         g_snprintf(str[0], sizeof(char[256]),
441                 "%s", val_to_str(i,T_h323_message_body_vals,"unknown cs-messages   "));
442                         g_snprintf(str[1], sizeof(char[256]),
443                 "%d", hs->cs_msg[i]);
444                         gtk_clist_append(hs->table, str);
445
446                         /* reason counter */
447                         switch(i) {
448                         case 5: /* ReleaseComplete */
449                                 for(j=0;j<=REL_CMP_REASONS;j++) {
450                                         if(hs->rel_cmp_reason[j]!=0) {
451                                                 g_snprintf(str[0], sizeof(char[256]),
452                             "    %s", val_to_str(j,ReleaseCompleteReason_vals,"unknown reason   "));
453                                                 g_snprintf(str[1], sizeof(char[256]),
454                             "%d", hs->rel_cmp_reason[j]);
455                                                 gtk_clist_append(hs->table, str);
456                                         }
457                                 }
458                                 break;
459                         case 6: /* Facility */
460                                 for(j=0;j<=FACILITY_REASONS;j++) {
461                                         if(hs->facility_reason[j]!=0) {
462                                                 g_snprintf(str[0], sizeof(char[256]),
463                             "    %s", val_to_str(j,FacilityReason_vals,"unknown reason   "));
464                                                 g_snprintf(str[1], sizeof(char[256]),
465                             "%d", hs->facility_reason[j]);
466                                                 gtk_clist_append(hs->table, str);
467                                         }
468                                 }
469                                 break;
470                         default:
471                                 break;
472                         }
473                 }
474         }
475
476         gtk_widget_show(GTK_WIDGET(hs->table));
477
478 }
479
480 void protect_thread_critical_region(void);
481 void unprotect_thread_critical_region(void);
482 static void
483 win_destroy_cb(GtkWindow *win _U_, gpointer data)
484 {
485         h225counter_t *hs=(h225counter_t *)data;
486
487         protect_thread_critical_region();
488         remove_tap_listener(hs);
489         unprotect_thread_critical_region();
490
491         if(hs->filter){
492                 g_free(hs->filter);
493                 hs->filter=NULL;
494         }
495         g_free(hs);
496 }
497
498
499 static const gchar *titles[]={
500                         "Message Type or Reason",
501                         "Count" };
502
503 static void
504 gtk_h225counter_init(const char *optarg)
505 {
506         h225counter_t *hs;
507         const char *filter=NULL;
508         GString *error_string;
509         GtkWidget *bbox;
510         GtkWidget *close_bt;
511
512         if(strncmp(optarg,"h225,counter,",13) == 0){
513                 filter=optarg+13;
514         } else {
515                 filter="";
516         }
517
518         hs=g_malloc(sizeof(h225counter_t));
519         hs->filter=g_strdup(filter);
520
521         h225counter_reset(hs);
522
523         hs->win=window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: H225 counters");
524         gtk_window_set_default_size(GTK_WINDOW(hs->win), 400, 200);
525
526         hs->vbox=gtk_vbox_new(FALSE, 3);
527         gtk_container_set_border_width(GTK_CONTAINER(hs->vbox), 12);
528
529         init_main_stat_window(hs->win, hs->vbox, "H.225 Message and Message Reason Counter", filter);
530
531         /* init a scrolled window*/
532         hs->scrolled_window = scrolled_window_new(NULL, NULL);
533
534         hs->table = create_stat_table(hs->scrolled_window, hs->vbox, 2, titles);
535
536         error_string=register_tap_listener("h225", hs, filter, h225counter_reset, h225counter_packet, h225counter_draw);
537         if(error_string){
538                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
539                 g_string_free(error_string, TRUE);
540                 g_free(hs->filter);
541                 g_free(hs);
542                 return;
543         }
544
545         /* Button row. */
546         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
547         gtk_box_pack_end(GTK_BOX(hs->vbox), bbox, FALSE, FALSE, 0);
548
549         close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
550         window_set_cancel_button(hs->win, close_bt, window_cancel_button_cb);
551
552         SIGNAL_CONNECT(hs->win, "delete_event", window_delete_event_cb, NULL);
553         SIGNAL_CONNECT(hs->win, "destroy", win_destroy_cb, hs);
554
555         gtk_widget_show_all(hs->win);
556         window_present(hs->win);
557
558         cf_retap_packets(&cfile, FALSE);
559 }
560
561 void
562 register_tap_listener_gtk_h225counter(void)
563 {
564         register_dfilter_stat(&h225_counter_dlg, "H.225",
565             REGISTER_STAT_GROUP_TELEPHONY);
566 }