From Shoichi Sakane via bug 5270: minor changes and remove an unused hf variable.
[obnox/wireshark/wip.git] / gtk / h225_counter.c
1 /* h225_counter.c
2  * H.225 message counter for Wireshark
3  * Copyright 2003 Lars Roland
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
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.h>
39 #include <epan/packet_info.h>
40 #include <epan/epan.h>
41 #include <epan/value_string.h>
42 #include <epan/tap.h>
43 #include <epan/dissectors/packet-h225.h>
44
45 #include "../simple_dialog.h"
46 #include "../file.h"
47 #include "../stat_menu.h"
48
49 #include "gtk/gui_stat_util.h"
50 #include "gtk/dlg_utils.h"
51 #include "gtk/tap_dfilter_dlg.h"
52 #include "gtk/gui_utils.h"
53 #include "gtk/main.h"
54
55
56 static void gtk_h225counter_init(const char *optarg, void *userdata);
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         GtkTreeView *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         }
292
293         return 1;
294 }
295
296 static void
297 h225counter_draw(void *phs)
298 {
299         h225counter_t *hs=(h225counter_t *)phs;
300         int i,j;
301         char str[256];
302         GtkListStore *store;
303         GtkTreeIter iter;
304
305         /* Now print Message and Reason Counter Table */
306         /* clear list before printing */
307         store = GTK_LIST_STORE(gtk_tree_view_get_model(hs->table));
308         gtk_list_store_clear(store);
309
310         for(i=0;i<=RAS_MSG_TYPES;i++) {
311                 if(hs->ras_msg[i]!=0) {
312                         g_snprintf(str, 256, "%s", val_to_str(i,h225_RasMessage_vals,"unknown ras-messages"));
313                         gtk_list_store_append(store, &iter);
314                         gtk_list_store_set(store, &iter,
315                                    0, val_to_str(i,h225_RasMessage_vals,"unknown ras-messages"),
316                                    1, hs->ras_msg[i], -1);
317
318                         /* reason counter */
319                         switch(i) {
320                         case 2: /* GRJ */
321                                 for(j=0;j<=GRJ_REASONS;j++) {
322                                         if(hs->grj_reason[j]!=0) {
323                                                 g_snprintf(str, 256,"    %s",
324                                                                 val_to_str(j,GatekeeperRejectReason_vals,"unknown reason"));
325                                                 gtk_list_store_append(store, &iter);
326                                                 gtk_list_store_set(store, &iter,
327                                                         0, str,
328                                                         1, hs->grj_reason[j], -1);
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, 256,"    %s",
336                                                                 val_to_str(j,RegistrationRejectReason_vals,"unknown reason"));
337                                                 gtk_list_store_append(store, &iter);
338                                                 gtk_list_store_set(store, &iter,
339                                                         0, str,
340                                                         1, hs->rrj_reason[j], -1);
341                                         }
342                                 }
343                                 break;
344                         case 6: /* URQ */
345                                 for(j=0;j<=URQ_REASONS;j++) {
346                                         if(hs->urq_reason[j]!=0) {
347                                                 g_snprintf(str, 256,"    %s",
348                                                                 val_to_str(j,UnregRequestReason_vals,"unknown reason"));
349                                                 gtk_list_store_append(store, &iter);
350                                                 gtk_list_store_set(store, &iter,
351                                                         0, str,
352                                                         1, hs->urq_reason[j], -1);
353                                         }
354                                 }
355                                 break;
356                         case 8: /* URJ */
357                                 for(j=0;j<=URJ_REASONS;j++) {
358                                         if(hs->urj_reason[j]!=0) {
359                                                 g_snprintf(str, 256,"    %s",
360                                                                 val_to_str(j,UnregRejectReason_vals,"unknown reason"));
361                                                 gtk_list_store_append(store, &iter);
362                                                 gtk_list_store_set(store, &iter,
363                                                         0, str,
364                                                         1, hs->urj_reason[j], -1);
365                                         }
366                                 }
367                                 break;
368                         case 11: /* ARJ */
369                                 for(j=0;j<=ARJ_REASONS;j++) {
370                                         if(hs->arj_reason[j]!=0) {
371                                                 g_snprintf(str, 256,"    %s",
372                                                                 val_to_str(j,AdmissionRejectReason_vals,"unknown reason"));
373                                                 gtk_list_store_append(store, &iter);
374                                                 gtk_list_store_set(store, &iter,
375                                                         0, str,
376                                                         1, hs->arj_reason[j], -1);
377                                         }
378                                 }
379                                 break;
380                         case 14: /* BRJ */
381                                 for(j=0;j<=BRJ_REASONS;j++) {
382                                         if(hs->brj_reason[j]!=0) {
383                                                 g_snprintf(str, 256,"    %s",
384                                                                 val_to_str(j,BandRejectReason_vals,"unknown reason"));
385                                                 gtk_list_store_append(store, &iter);
386                                                 gtk_list_store_set(store, &iter,
387                                                         0, str,
388                                                         1, hs->brj_reason[j], -1);
389                                         }
390                                 }
391                                 break;
392                         case 15: /* DRQ */
393                                 for(j=0;j<=DRQ_REASONS;j++) {
394                                         if(hs->drq_reason[j]!=0) {
395                                                 g_snprintf(str, 256,"    %s",
396                                                                 val_to_str(j,DisengageReason_vals,"unknown reason"));
397                                                 gtk_list_store_append(store, &iter);
398                                                 gtk_list_store_set(store, &iter,
399                                                         0, str,
400                                                         1, hs->drq_reason[j], -1);
401                                         }
402                                 }
403                                 break;
404                         case 17: /* DRJ */
405                                 for(j=0;j<=DRJ_REASONS;j++) {
406                                         if(hs->drj_reason[j]!=0) {
407                                                 g_snprintf(str, 256,"    %s",
408                                                                 val_to_str(j,DisengageRejectReason_vals,"unknown reason"));
409                                                 gtk_list_store_set(store, &iter,
410                                                         0, str,
411                                                         1, hs->drj_reason[j], -1);
412                                         }
413                                 }
414                                 break;
415                         case 20: /* LRJ */
416                                 for(j=0;j<=LRJ_REASONS;j++) {
417                                         if(hs->lrj_reason[j]!=0) {
418                                                 g_snprintf(str, 256,"    %s",
419                                                                 val_to_str(j,LocationRejectReason_vals,"unknown reason"));
420                                                 gtk_list_store_append(store, &iter);
421                                                 gtk_list_store_set(store, &iter,
422                                                         0, str,
423                                                         1, hs->lrj_reason[j], -1);
424                                         }
425                                 }
426                                 break;
427                         case 29: /* IRQNak */
428                                 for(j=0;j<=IRQNAK_REASONS;j++) {
429                                         if(hs->irqnak_reason[j]!=0) {
430                                                 g_snprintf(str, 256,"    %s",
431                                                                 val_to_str(j,InfoRequestNakReason_vals,"unknown reason"));
432                                                 gtk_list_store_append(store, &iter);
433                                                 gtk_list_store_set(store, &iter,
434                                                         0, str,
435                                                         1, hs->irqnak_reason[j], -1);
436                                         }
437                                 }
438                                 break;
439                         default:
440                                 break;
441                         }
442                         /* end of reason counter*/
443                 }
444         }
445
446         for(i=0;i<=CS_MSG_TYPES;i++) {
447                 if(hs->cs_msg[i]!=0) {
448                         gtk_list_store_append(store, &iter);
449                         gtk_list_store_set(store, &iter,
450                                    0, val_to_str(i,T_h323_message_body_vals,"unknown cs-messages"),
451                                    1, hs->cs_msg[i], -1);
452
453                         /* reason counter */
454                         switch(i) {
455                         case 5: /* ReleaseComplete */
456                                 for(j=0;j<=REL_CMP_REASONS;j++) {
457                                         if(hs->rel_cmp_reason[j]!=0) {
458                                                 g_snprintf(str, 256,"    %s",
459                                                                 val_to_str(j,h225_ReleaseCompleteReason_vals,"unknown reason"));
460                                                 gtk_list_store_append(store, &iter);
461                                                 gtk_list_store_set(store, &iter,
462                                                         0, str,
463                                                         1, hs->rel_cmp_reason[j], -1);
464                                         }
465                                 }
466                                 break;
467                         case 6: /* Facility */
468                                 for(j=0;j<=FACILITY_REASONS;j++) {
469                                         if(hs->facility_reason[j]!=0) {
470                                                 g_snprintf(str, 256,"    %s",
471                                                                 val_to_str(j,FacilityReason_vals,"unknown reason"));
472                                                 gtk_list_store_append(store, &iter);
473                                                 gtk_list_store_set(store, &iter,
474                                                         0, str,
475                                                         1, hs->facility_reason[j], -1);
476                                         }
477                                 }
478                                 break;
479                         default:
480                                 break;
481                         }
482                 }
483         }
484 }
485
486 static void
487 win_destroy_cb(GtkWindow *win _U_, gpointer data)
488 {
489         h225counter_t *hs=(h225counter_t *)data;
490
491         protect_thread_critical_region();
492         remove_tap_listener(hs);
493         unprotect_thread_critical_region();
494
495         if(hs->filter){
496                 g_free(hs->filter);
497                 hs->filter=NULL;
498         }
499         g_free(hs);
500 }
501
502 static const stat_column titles[]={
503   {G_TYPE_STRING, LEFT, "Message Type or Reason"},
504   {G_TYPE_UINT, RIGHT, "Count" }
505 };
506
507 static void
508 gtk_h225counter_init(const char *optarg, void *userdata _U_)
509 {
510         h225counter_t *hs;
511         GString *error_string;
512         GtkWidget *bbox;
513         GtkWidget *close_bt;
514
515         hs=g_malloc(sizeof(h225counter_t));
516
517         if(strncmp(optarg,"h225,counter,",13) == 0){
518                 hs->filter=g_strdup(optarg+13);
519         } else {
520                 hs->filter=NULL;
521         }
522
523         h225counter_reset(hs);
524
525         hs->win = dlg_window_new("Wireshark: H.225 counters");  /* transient_for top_level */
526         gtk_window_set_destroy_with_parent (GTK_WINDOW(hs->win), TRUE);
527
528         gtk_window_set_default_size(GTK_WINDOW(hs->win), 400, 200);
529
530         hs->vbox=gtk_vbox_new(FALSE, 3);
531         gtk_container_set_border_width(GTK_CONTAINER(hs->vbox), 12);
532
533         init_main_stat_window(hs->win, hs->vbox, "H.225 Message and Message Reason Counter", hs->filter);
534
535         /* init a scrolled window*/
536         hs->scrolled_window = scrolled_window_new(NULL, NULL);
537
538         hs->table = create_stat_table(hs->scrolled_window, hs->vbox, 2, titles);
539
540         error_string=register_tap_listener("h225", hs, hs->filter, 0, h225counter_reset, h225counter_packet, h225counter_draw);
541         if(error_string){
542                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
543                 g_string_free(error_string, TRUE);
544                 g_free(hs->filter);
545                 g_free(hs);
546                 return;
547         }
548
549         /* Button row. */
550         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
551         gtk_box_pack_end(GTK_BOX(hs->vbox), bbox, FALSE, FALSE, 0);
552
553         close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
554         window_set_cancel_button(hs->win, close_bt, window_cancel_button_cb);
555
556         g_signal_connect(hs->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
557         g_signal_connect(hs->win, "destroy", G_CALLBACK(win_destroy_cb), hs);
558
559         gtk_widget_show_all(hs->win);
560         window_present(hs->win);
561
562         cf_retap_packets(&cfile);
563         gdk_window_raise(hs->win->window);
564 }
565
566 void
567 register_tap_listener_gtk_h225counter(void)
568 {
569         register_dfilter_stat(&h225_counter_dlg, "_H.225",
570             REGISTER_STAT_GROUP_TELEPHONY);
571 }