Bump date and version number
[obnox/wireshark/wip.git] / tap-h225counter.c
1 /* tap_h225counter.c
2  * h225 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 #include <stdio.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #include <string.h>
37 #include "epan/packet_info.h"
38 #include <epan/tap.h>
39 #include <epan/stat_cmd_args.h>
40 #include "epan/value_string.h"
41 #include "register.h"
42 #include <epan/dissectors/packet-h225.h>
43
44 /* following values represent the size of their valuestring arrays */
45
46 #define RAS_MSG_TYPES 33
47 #define CS_MSG_TYPES 13
48
49 #define GRJ_REASONS 8
50 #define RRJ_REASONS 18
51 #define URQ_REASONS 6
52 #define URJ_REASONS 6
53 #define ARJ_REASONS 22
54 #define BRJ_REASONS 8
55 #define DRQ_REASONS 3
56 #define DRJ_REASONS 4
57 #define LRJ_REASONS 16
58 #define IRQNAK_REASONS 4
59 #define REL_CMP_REASONS 26
60 #define FACILITY_REASONS 11
61
62
63 /* used to keep track of the statistics for an entire program interface */
64 typedef struct _h225counter_t {
65         char *filter;
66         guint32 ras_msg[RAS_MSG_TYPES + 1];
67         guint32 cs_msg[CS_MSG_TYPES + 1];
68         guint32 grj_reason[GRJ_REASONS + 1];
69         guint32 rrj_reason[RRJ_REASONS + 1];
70         guint32 urq_reason[URQ_REASONS + 1];
71         guint32 urj_reason[URJ_REASONS + 1];
72         guint32 arj_reason[ARJ_REASONS + 1];
73         guint32 brj_reason[BRJ_REASONS + 1];
74         guint32 drq_reason[DRQ_REASONS + 1];
75         guint32 drj_reason[DRJ_REASONS + 1];
76         guint32 lrj_reason[LRJ_REASONS + 1];
77         guint32 irqnak_reason[IRQNAK_REASONS + 1];
78         guint32 rel_cmp_reason[REL_CMP_REASONS + 1];
79         guint32 facility_reason[FACILITY_REASONS + 1];
80 } h225counter_t;
81
82
83 static void
84 h225counter_reset(void *phs)
85 {
86         h225counter_t *hs=(h225counter_t *)phs;
87         int i;
88
89         for(i=0;i<=RAS_MSG_TYPES;i++) {
90                 hs->ras_msg[i] = 0;
91         }
92         for(i=0;i<=CS_MSG_TYPES;i++) {
93                 hs->cs_msg[i] = 0;
94         }
95         for(i=0;i<=GRJ_REASONS;i++) {
96                 hs->grj_reason[i] = 0;
97         }
98         for(i=0;i<=RRJ_REASONS;i++) {
99                 hs->rrj_reason[i] = 0;
100         }
101         for(i=0;i<=URQ_REASONS;i++) {
102                 hs->urq_reason[i] = 0;
103         }
104         for(i=0;i<=URJ_REASONS;i++) {
105                 hs->urj_reason[i] = 0;
106         }
107         for(i=0;i<=ARJ_REASONS;i++) {
108                 hs->arj_reason[i] = 0;
109         }
110         for(i=0;i<=BRJ_REASONS;i++) {
111                 hs->brj_reason[i] = 0;
112         }
113         for(i=0;i<=DRQ_REASONS;i++) {
114                 hs->drq_reason[i] = 0;
115         }
116         for(i=0;i<=DRJ_REASONS;i++) {
117                 hs->drj_reason[i] = 0;
118         }
119         for(i=0;i<=LRJ_REASONS;i++) {
120                 hs->lrj_reason[i] = 0;
121         }
122         for(i=0;i<=IRQNAK_REASONS;i++) {
123                 hs->irqnak_reason[i] = 0;
124         }
125         for(i=0;i<=REL_CMP_REASONS;i++) {
126                 hs->rel_cmp_reason[i] = 0;
127         }
128         for(i=0;i<=FACILITY_REASONS;i++) {
129                 hs->facility_reason[i] = 0;
130         }
131 }
132
133 static int
134 h225counter_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi)
135 {
136         h225counter_t *hs=(h225counter_t *)phs;
137         const h225_packet_info *pi=phi;
138
139         switch (pi->msg_type) {
140
141         case H225_RAS:
142                 if(pi->msg_tag==-1) { /* uninitialized */
143                         return 0;
144                 }
145                 else if (pi->msg_tag >= RAS_MSG_TYPES) { /* unknown */
146                         hs->ras_msg[RAS_MSG_TYPES]++;
147                 }
148                 else {
149                         hs->ras_msg[pi->msg_tag]++;
150                 }
151
152                 /* Look for reason tag */
153                 if(pi->reason==-1) { /* uninitialized */
154                         break;
155                 }
156
157                 switch(pi->msg_tag) {
158
159                 case 2: /* GRJ */
160                         if(pi->reason < GRJ_REASONS)
161                                 hs->grj_reason[pi->reason]++;
162                         else
163                                 hs->grj_reason[GRJ_REASONS]++;
164                         break;
165                 case 5: /* RRJ */
166                         if(pi->reason < RRJ_REASONS)
167                                 hs->rrj_reason[pi->reason]++;
168                         else
169                                 hs->rrj_reason[RRJ_REASONS]++;
170                         break;
171                 case 6: /* URQ */
172                         if(pi->reason < URQ_REASONS)
173                                 hs->urq_reason[pi->reason]++;
174                         else
175                                 hs->urq_reason[URQ_REASONS]++;
176                         break;
177                 case 8: /* URJ */
178                         if(pi->reason < URJ_REASONS)
179                                 hs->urj_reason[pi->reason]++;
180                         else
181                                 hs->urj_reason[URJ_REASONS]++;
182                         break;
183                 case 11: /* ARJ */
184                         if(pi->reason < ARJ_REASONS)
185                                 hs->arj_reason[pi->reason]++;
186                         else
187                                 hs->arj_reason[ARJ_REASONS]++;
188                         break;
189                 case 14: /* BRJ */
190                         if(pi->reason < BRJ_REASONS)
191                                 hs->brj_reason[pi->reason]++;
192                         else
193                                 hs->brj_reason[BRJ_REASONS]++;
194                         break;
195                 case 15: /* DRQ */
196                         if(pi->reason < DRQ_REASONS)
197                                 hs->drq_reason[pi->reason]++;
198                         else
199                                 hs->drq_reason[DRQ_REASONS]++;
200                         break;
201                 case 17: /* DRJ */
202                         if(pi->reason < DRJ_REASONS)
203                                 hs->drj_reason[pi->reason]++;
204                         else
205                                 hs->drj_reason[DRJ_REASONS]++;
206                         break;
207                 case 20: /* LRJ */
208                         if(pi->reason < LRJ_REASONS)
209                                 hs->lrj_reason[pi->reason]++;
210                         else
211                                 hs->lrj_reason[LRJ_REASONS]++;
212                         break;
213                 case 29: /* IRQ Nak */
214                         if(pi->reason < IRQNAK_REASONS)
215                                 hs->irqnak_reason[pi->reason]++;
216                         else
217                                 hs->irqnak_reason[IRQNAK_REASONS]++;
218                         break;
219
220                 default:
221                         /* do nothing */
222                         break;
223                 }
224
225                 break;
226
227         case H225_CS:
228                 if(pi->msg_tag==-1) { /* uninitialized */
229                         return 0;
230                 }
231                 else if (pi->msg_tag >= CS_MSG_TYPES) { /* unknown */
232                         hs->cs_msg[CS_MSG_TYPES]++;
233                 }
234                 else {
235                         hs->cs_msg[pi->msg_tag]++;
236                 }
237
238                 /* Look for reason tag */
239                 if(pi->reason==-1) { /* uninitialized */
240                         break;
241                 }
242
243                 switch(pi->msg_tag) {
244
245                 case 5: /* ReleaseComplete */
246                         if(pi->reason < REL_CMP_REASONS)
247                                 hs->rel_cmp_reason[pi->reason]++;
248                         else
249                                 hs->rel_cmp_reason[REL_CMP_REASONS]++;
250                         break;
251                 case 6: /* Facility */
252                         if(pi->reason < FACILITY_REASONS)
253                                 hs->facility_reason[pi->reason]++;
254                         else
255                                 hs->facility_reason[FACILITY_REASONS]++;
256                         break;
257                 default:
258                         /* do nothing */
259                         break;
260                 }
261
262                 break;
263
264         default:
265                 return 0;
266                 break;
267         }
268
269         return 1;
270 }
271
272
273 static void
274 h225counter_draw(void *phs)
275 {
276         h225counter_t *hs=(h225counter_t *)phs;
277         int i,j;
278
279         printf("================== H225 Message and Reason Counter ==================\n");
280         printf("RAS-Messages:\n");
281         for(i=0;i<=RAS_MSG_TYPES;i++) {
282                 if(hs->ras_msg[i]!=0) {
283                         printf("  %s : %u\n", val_to_str(i,RasMessage_vals,"unknown ras-messages  "), hs->ras_msg[i]);
284                         /* reason counter */
285                         switch(i) {
286                         case 2: /* GRJ */
287                                 for(j=0;j<=GRJ_REASONS;j++) {
288                                         if(hs->grj_reason[j]!=0) {
289                                                 printf("    %s : %u\n", val_to_str(j,GatekeeperRejectReason_vals,"unknown reason   "), hs->grj_reason[j]);
290                                         }
291                                 }
292                                 break;
293                         case 5: /* RRJ */
294                                 for(j=0;j<=RRJ_REASONS;j++) {
295                                         if(hs->rrj_reason[j]!=0) {
296                                                 printf("    %s : %u\n", val_to_str(j,RegistrationRejectReason_vals,"unknown reason   "), hs->rrj_reason[j]);
297                                         }
298                                 }
299                                 break;
300                         case 6: /* URQ */
301                                 for(j=0;j<=URQ_REASONS;j++) {
302                                         if(hs->urq_reason[j]!=0) {
303                                                 printf("    %s : %u\n", val_to_str(j,UnregRequestReason_vals,"unknown reason   "), hs->urq_reason[j]);
304                                         }
305                                 }
306                                 break;
307                         case 8: /* URJ */
308                                 for(j=0;j<=URJ_REASONS;j++) {
309                                         if(hs->urj_reason[j]!=0) {
310                                                 printf("    %s : %u\n", val_to_str(j,UnregRejectReason_vals,"unknown reason   "), hs->urj_reason[j]);
311                                         }
312                                 }
313                                 break;
314                         case 11: /* ARJ */
315                                 for(j=0;j<=ARJ_REASONS;j++) {
316                                         if(hs->arj_reason[j]!=0) {
317                                                 printf("    %s : %u\n", val_to_str(j,AdmissionRejectReason_vals,"unknown reason   "), hs->arj_reason[j]);
318                                         }
319                                 }
320                                 break;
321                         case 14: /* BRJ */
322                                 for(j=0;j<=BRJ_REASONS;j++) {
323                                         if(hs->brj_reason[j]!=0) {
324                                                 printf("    %s : %u\n", val_to_str(j,BandRejectReason_vals,"unknown reason   "), hs->brj_reason[j]);
325                                         }
326                                 }
327                                 break;
328                         case 15: /* DRQ */
329                                 for(j=0;j<=DRQ_REASONS;j++) {
330                                         if(hs->drq_reason[j]!=0) {
331                                                 printf("    %s : %u\n", val_to_str(j,DisengageReason_vals,"unknown reason   "), hs->drq_reason[j]);
332                                         }
333                                 }
334                                 break;
335                         case 17: /* DRJ */
336                                 for(j=0;j<=DRJ_REASONS;j++) {
337                                         if(hs->drj_reason[j]!=0) {
338                                                 printf("    %s : %u\n", val_to_str(j,DisengageRejectReason_vals,"unknown reason   "), hs->drj_reason[j]);
339                                         }
340                                 }
341                                 break;
342                         case 20: /* LRJ */
343                                 for(j=0;j<=LRJ_REASONS;j++) {
344                                         if(hs->lrj_reason[j]!=0) {
345                                                 printf("    %s : %u\n", val_to_str(j,LocationRejectReason_vals,"unknown reason   "), hs->lrj_reason[j]);
346                                         }
347                                 }
348                         case 29: /* IRQNak */
349                                 for(j=0;j<=IRQNAK_REASONS;j++) {
350                                         if(hs->irqnak_reason[j]!=0) {
351                                                 printf("    %s : %u\n", val_to_str(j,InfoRequestNakReason_vals,"unknown reason   "), hs->irqnak_reason[j]);
352                                         }
353                                 }
354                                 break;
355                         default:
356                                 break;
357                         }
358                         /* end of reason counter*/
359                 }
360         }
361         printf("Call Signalling:\n");
362         for(i=0;i<=CS_MSG_TYPES;i++) {
363                 if(hs->cs_msg[i]!=0) {
364                         printf("  %s : %u\n", val_to_str(i,T_h323_message_body_vals,"unknown cs-messages   "), hs->cs_msg[i]);
365                         /* reason counter */
366                         switch(i) {
367                         case 5: /* ReleaseComplete */
368                                 for(j=0;j<=REL_CMP_REASONS;j++) {
369                                         if(hs->rel_cmp_reason[j]!=0) {
370                                                 printf("    %s : %u\n", val_to_str(j,ReleaseCompleteReason_vals,"unknown reason   "), hs->rel_cmp_reason[j]);
371                                         }
372                                 }
373                                 break;
374                         case 6: /* Facility */
375                                 for(j=0;j<=FACILITY_REASONS;j++) {
376                                         if(hs->facility_reason[j]!=0) {
377                                                 printf("    %s : %u\n", val_to_str(j,FacilityReason_vals,"unknown reason   "), hs->facility_reason[j]);
378                                         }
379                                 }
380                                 break;
381                         default:
382                                 break;
383                         }
384                 }
385         }
386         printf("=====================================================================\n");
387 }
388
389
390 static void
391 h225counter_init(const char *optarg, void* userdata _U_)
392 {
393         h225counter_t *hs;
394         const char *filter=NULL;
395         GString *error_string;
396
397         if(!strncmp(optarg,"h225,counter,",13)){
398                 filter=optarg+13;
399         } else {
400                 filter="";
401         }
402
403         hs = g_malloc(sizeof(h225counter_t));
404         hs->filter=g_malloc(strlen(filter)+1);
405         strcpy(hs->filter, filter);
406
407         h225counter_reset(hs);
408
409         error_string=register_tap_listener("h225", hs, filter, NULL, h225counter_packet, h225counter_draw);
410         if(error_string){
411                 /* error, we failed to attach to the tap. clean up */
412                 g_free(hs->filter);
413                 g_free(hs);
414
415                 fprintf(stderr, "tshark: Couldn't register h225,counter tap: %s\n",
416                     error_string->str);
417                 g_string_free(error_string, TRUE);
418                 exit(1);
419         }
420 }
421
422
423 void
424 register_tap_listener_h225counter(void)
425 {
426         register_stat_cmd_arg("h225,counter", h225counter_init,NULL);
427 }