Replace a handful of tabs with spaces.
[obnox/wireshark/wip.git] / gtk / voip_calls.c
1 /* voip_calls.c
2  * VoIP calls summary addition for Wireshark
3  *
4  * $Id$
5  *
6  * Copyright 2004, Ericsson, Spain
7  * By Francisco Alcoba <francisco.alcoba@ericsson.com>
8  *
9  * based on h323_calls.c
10  * Copyright 2004, Iskratel, Ltd, Kranj
11  * By Miha Jemec <m.jemec@iskratel.si>
12  * 
13  * H323, RTP, RTP Event, MGCP, AudioCodes (ISDN PRI and CAS), T38 and Graph Support
14  * By Alejandro Vaquero, alejandro.vaquero@verso.com
15  * Copyright 2005, Verso Technologies Inc.
16  *
17  * Wireshark - Network traffic analyzer
18  * By Gerald Combs <gerald@wireshark.org>
19  * Copyright 1998 Gerald Combs
20  *
21  * This program is free software; you can redistribute it and/or
22  * modify it under the terms of the GNU General Public License
23  * as published by the Free Software Foundation; either version 2
24  * of the License, or (at your option) any later version.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with this program; if not, write to the Free Software
33  * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
34  */
35
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #endif
39
40 #include <string.h>
41
42 #include "graph_analysis.h"
43 #include "voip_calls.h"
44 #include "voip_calls_dlg.h"
45
46 #include "main.h"
47 #include "globals.h"
48
49 #include <epan/tap.h>
50 #include <epan/tap-voip.h>
51 #include <epan/dissectors/packet-sip.h>
52 #include <epan/dissectors/packet-mtp3.h>
53 #include <epan/dissectors/packet-isup.h>
54 #include <epan/dissectors/packet-h225.h>
55 #include <epan/dissectors/packet-h245.h>
56 #include <epan/dissectors/packet-q931.h>
57 #include <epan/dissectors/packet-sdp.h>
58 #include <epan/dissectors/packet-mgcp.h>
59 #include <epan/dissectors/packet-actrace.h>
60 #include <epan/dissectors/packet-rtp.h>
61 #include <epan/dissectors/packet-rtp-events.h>
62 #include <epan/dissectors/packet-t38.h>
63 #include <epan/dissectors/packet-t30.h>
64 #include <epan/dissectors/packet-h248.h>
65 #include <epan/dissectors/packet-sccp.h>
66 #include <plugins/unistim/packet-unistim.h>
67 #include <epan/conversation.h>
68 #include <epan/rtp_pt.h>
69 #include <epan/ws_strsplit.h>
70
71 #include "alert_box.h"
72 #include "simple_dialog.h"
73
74 #ifdef HAVE_LIBPORTAUDIO
75 #if GTK_MAJOR_VERSION >= 2
76 #include "rtp_player.h"
77 #endif /* GTK_MAJOR_VERSION >= 2 */
78 #endif /* HAVE_LIBPORTAUDIO */
79
80 #ifdef NEED_G_ASCII_STRCASECMP_H
81 #include "../epan/g_ascii_strcasecmp.h"
82 #endif
83
84 const char *voip_call_state_name[8]={
85         "",
86         "CALL SETUP",
87         "RINGING",
88         "IN CALL",
89         "CANCELLED",
90         "COMPLETED",
91         "REJECTED",
92         "UNKNOWN"
93         };
94
95 /* defines whether we can consider the call active */
96 const char *voip_protocol_name[]={
97         "SIP",
98         "ISUP",
99         "H.323",
100         "MGCP",
101         "AC_ISDN",
102         "AC_CAS",
103         "T.38",
104         "H.248",
105         "SCCP",
106         "BSSMAP",
107         "RANAP",
108         "UNISTIM",
109         "VoIP"
110 };
111
112 typedef struct {
113         gchar *frame_label;
114         gchar *comment;
115 } graph_str;
116
117 #define H245_MAX 6
118
119 typedef struct {
120         guint32 frame_num;
121         gint8 labels_count;
122         graph_str labels[H245_MAX];
123 } h245_labels_t;
124
125 static h245_labels_t h245_labels;
126
127 /****************************************************************************/
128 /* the one and only global voip_calls_tapinfo_t structure */
129 static voip_calls_tapinfo_t the_tapinfo_struct =
130         {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
131
132 /* the one and only global voip_rtp_tapinfo_t structure */
133 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
134         {0, NULL, 0, 0};
135
136 /****************************************************************************/
137 /* when there is a [re]reading of packet's */
138 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
139 {
140         voip_calls_info_t *callsinfo;
141         voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
142         voip_rtp_stream_info_t *strinfo;
143         graph_analysis_item_t *graph_item;
144         GList* list;
145
146 #ifdef HAVE_LIBPORTAUDIO
147 #if GTK_MAJOR_VERSION >= 2
148         /* reset the RTP player */
149         reset_rtp_player();
150 #endif
151 #endif
152
153         /* free the data items first */
154         list = g_list_first(tapinfo->callsinfo_list);
155         while (list)
156         {
157                 callsinfo = list->data;
158                 if (callsinfo->call_id) 
159                         g_free(callsinfo->call_id);
160                 g_free(callsinfo->from_identity);
161                 g_free(callsinfo->to_identity);
162                 g_free((void *)(callsinfo->initial_speaker.data));
163                 if (callsinfo->protocol_name) 
164                         g_free(callsinfo->protocol_name);
165                 if (callsinfo->call_comment) 
166                         g_free(callsinfo->call_comment);
167                 
168                 if (callsinfo->free_prot_info && callsinfo->prot_info)
169                         callsinfo->free_prot_info(callsinfo->prot_info);
170
171                 g_free(list->data);
172                 list = g_list_next(list);
173         }
174         g_list_free(tapinfo->callsinfo_list);
175         tapinfo->callsinfo_list = NULL;
176         tapinfo->ncalls = 0;
177         tapinfo->npackets = 0;
178         tapinfo->start_packets = 0;
179         tapinfo->completed_calls = 0;
180         tapinfo->rejected_calls = 0;
181
182         /* free the graph data items first */
183         list = g_list_first(tapinfo->graph_analysis->list);
184         while (list)
185         {
186                 graph_item = list->data;
187                 g_free(graph_item->frame_label);
188                 g_free(graph_item->comment);
189                 g_free((void *)graph_item->src_addr.data);
190                 g_free((void *)graph_item->dst_addr.data);
191                 g_free(list->data);
192                 list = g_list_next(list);
193         }
194         g_list_free(tapinfo->graph_analysis->list);
195         tapinfo->graph_analysis->nconv = 0;
196         tapinfo->graph_analysis->list = NULL;
197
198         ++(tapinfo->launch_count);
199
200         /* free the strinfo data items first */
201         list = g_list_first(rtp_tapinfo->list);
202         while(list)
203         {
204                 strinfo = list->data;
205                 g_free(strinfo->pt_str);
206                 list = g_list_next(list);
207
208         }
209         g_list_free(rtp_tapinfo->list);
210         rtp_tapinfo->list = NULL;
211
212         return;
213 }
214
215 /****************************************************************************/
216 void graph_analysis_data_init(void){
217         the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
218         the_tapinfo_struct.graph_analysis->nconv = 0;
219         the_tapinfo_struct.graph_analysis->list = NULL;
220 }
221
222 /****************************************************************************/
223 /* Add a new item into the graph */
224 static int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style)
225 {
226         graph_analysis_item_t *gai;
227
228         gai = g_malloc(sizeof(graph_analysis_item_t));
229         gai->frame_num = pinfo->fd->num;
230         gai->time= nstime_to_sec(&pinfo->fd->rel_ts);
231         COPY_ADDRESS(&(gai->src_addr),src_addr);
232         COPY_ADDRESS(&(gai->dst_addr),dst_addr);
233
234         gai->port_src=pinfo->srcport;
235         gai->port_dst=pinfo->destport;
236         if (frame_label != NULL)
237                 gai->frame_label = g_strdup(frame_label);
238         else
239                 gai->frame_label = g_strdup("");
240
241         if (comment != NULL)
242                 gai->comment = g_strdup(comment);
243         else
244                 gai->comment = g_strdup("");
245         gai->conv_num=call_num;
246         gai->line_style=line_style;
247         gai->display=FALSE;
248
249         tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
250
251         return 1;
252
253 }
254
255 /****************************************************************************/
256 /* Append str to frame_label and comment in a graph item */
257 /* return 0 if the frame_num is not in the graph list */
258 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
259 {
260         graph_analysis_item_t *gai;
261         GList* list;
262         gchar *tmp_str = NULL;
263         gchar *tmp_str2 = NULL;
264
265         list = g_list_first(tapinfo->graph_analysis->list);
266         while (list)
267         {
268                 gai = list->data;
269                 if (gai->frame_num == frame_num){
270                         tmp_str = gai->frame_label;
271                         tmp_str2 = gai->comment;
272
273                         if (new_frame_label != NULL){
274                                 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
275                                 g_free(tmp_str);
276                         }
277
278
279                         if (new_comment != NULL){
280                                 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
281                                 g_free(tmp_str2);
282                         }
283                         break;
284                 }
285                 list = g_list_next (list);
286         }
287         if (tmp_str == NULL) return 0;          /* it is not in the list */
288         return 1;
289
290 }
291
292 /****************************************************************************/
293 /* Change the frame_label and comment in a graph item if not NULL*/
294 /* return 0 if the frame_num is not in the graph list */
295 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
296 {
297         graph_analysis_item_t *gai;
298         GList* list;
299         gchar *tmp_str = NULL;
300         gchar *tmp_str2 = NULL;
301
302         list = g_list_first(tapinfo->graph_analysis->list);
303         while (list)
304         {
305                 gai = list->data;
306                 if (gai->frame_num == frame_num){
307                         tmp_str = gai->frame_label;
308                         tmp_str2 = gai->comment;
309
310                         if (new_frame_label != NULL){
311                                 gai->frame_label = g_strdup(new_frame_label);
312                                 g_free(tmp_str);
313                         }
314
315                         if (new_comment != NULL){
316                                 gai->comment = g_strdup(new_comment);
317                                 g_free(tmp_str2);
318                         }
319                         break;
320                 }
321                 list = g_list_next (list);
322         }
323         if (tmp_str == NULL) return 0;          /* it is not in the list */
324         return 1;
325
326 }
327
328 /****************************************************************************/
329 /* Change all the graph items with call_num to new_call_num */
330 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
331 {
332         graph_analysis_item_t *gai;
333         GList* list;
334         guint items_changed;
335
336         items_changed = 0;
337         list = g_list_first(tapinfo->graph_analysis->list);
338         while (list)
339         {
340                 gai = list->data;
341                 if (gai->conv_num == call_num){
342                         gai->conv_num = new_call_num;
343                         items_changed++;
344                 }
345                 list = g_list_next (list);
346         }
347         return items_changed;
348 }
349
350
351
352
353 /****************************************************************************/
354 /* Insert the item in the graph list */
355 void insert_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style, double time, guint32 frame_num)
356 {
357         graph_analysis_item_t *gai, *new_gai;
358         GList* list;
359         guint item_num;
360         gboolean inserted;
361
362         new_gai = g_malloc(sizeof(graph_analysis_item_t));
363         new_gai->frame_num = frame_num;
364         new_gai->time= time;
365         COPY_ADDRESS(&(new_gai->src_addr),src_addr);
366         COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
367
368         new_gai->port_src=pinfo->srcport;
369         new_gai->port_dst=pinfo->destport;
370         if (frame_label != NULL)
371                 new_gai->frame_label = g_strdup(frame_label);
372         else
373                 new_gai->frame_label = g_strdup("");
374
375         if (comment != NULL)
376                 new_gai->comment = g_strdup(comment);
377         else
378                 new_gai->comment = g_strdup("");
379         new_gai->conv_num=call_num;
380         new_gai->line_style=line_style;
381         new_gai->display=FALSE;
382
383         item_num = 0; 
384         inserted = FALSE;
385         list = g_list_first(tapinfo->graph_analysis->list);
386         while (list)
387         {
388                 gai = list->data;
389                 if (gai->frame_num > frame_num){
390                         the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
391                         inserted = TRUE;
392                         break;
393                 }
394                 list = g_list_next (list);
395                 item_num++;
396         }
397
398         if ( !inserted) tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, new_gai);
399 }
400
401 /****************************************************************************/
402 /* ***************************TAP for RTP Events*****************************/
403 /****************************************************************************/
404
405 static guint32 rtp_evt_frame_num = 0;
406 static guint8 rtp_evt = 0;
407 static gboolean rtp_evt_end = FALSE;
408 /*static guint32 rtp_evt_setup_frame_num = 0;*/
409
410 /****************************************************************************/
411 /* whenever a rtp event packet is seen by the tap listener */
412 static int 
413 rtp_event_packet(void *ptr _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rtp_event_info)
414 {
415         const struct _rtp_event_info *pi = rtp_event_info;
416
417         /* do not consider RTP events packets without a setup frame */
418         if (pi->info_setup_frame_num == 0){
419                 return 0;
420         }
421
422         rtp_evt_frame_num = pinfo->fd->num;
423         rtp_evt = pi->info_rtp_evt;
424         rtp_evt_end = pi->info_end;
425
426         return 0;
427 }
428
429 /****************************************************************************/
430 static gboolean have_rtp_event_tap_listener=FALSE;
431
432 void
433 rtp_event_init_tap(void)
434 {
435         GString *error_string;
436
437
438         if(have_rtp_event_tap_listener==FALSE)
439         {
440                 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
441                         NULL,
442                         NULL,
443                         rtp_event_packet,
444                         NULL
445                         );
446                         
447                 if (error_string != NULL) {
448                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
449                                       error_string->str);
450                         g_string_free(error_string, TRUE);
451                         exit(1);
452                 }
453                 have_rtp_event_tap_listener=TRUE;
454         }
455 }
456
457 /****************************************************************************/
458
459 void
460 remove_tap_listener_rtp_event(void)
461 {
462         protect_thread_critical_region();
463         remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
464         unprotect_thread_critical_region();
465
466         have_rtp_event_tap_listener=FALSE;
467 }
468
469 /****************************************************************************/
470 /* ***************************TAP for RTP **********************************/
471 /****************************************************************************/
472
473 /****************************************************************************/
474 /* when there is a [re]reading of RTP packet's */
475 static void voip_rtp_reset(void *ptr _U_)
476 {
477         voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
478         GList* list;
479         /* free the data items first */
480         list = g_list_first(tapinfo->list);
481         while (list)
482         {
483                 g_free(list->data);
484                 list = g_list_next(list);
485         }
486         g_list_free(tapinfo->list);
487         tapinfo->list = NULL;
488         tapinfo->nstreams = 0;
489         return;
490 }
491
492 /****************************************************************************/
493 /* whenever a RTP packet is seen by the tap listener */
494 static int 
495 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
496 {
497         voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
498         voip_rtp_stream_info_t *tmp_listinfo;
499         voip_rtp_stream_info_t *strinfo = NULL;
500         GList* list;
501         struct _rtp_conversation_info *p_conv_data = NULL;
502
503         const struct _rtp_info *pi = RTPinfo;
504
505         /* do not consider RTP packets without a setup frame */
506         if (pi->info_setup_frame_num == 0){
507                 return 0;
508         }
509
510         /* add this RTP for future listening using the RTP Player*/
511 #if GTK_MAJOR_VERSION >= 2
512 #ifdef HAVE_LIBPORTAUDIO
513         add_rtp_packet(pi, pinfo);
514 #endif
515 #endif
516         
517         /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
518         list = g_list_first(tapinfo->list);
519         while (list)
520         {
521                 tmp_listinfo=list->data;
522                 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) 
523                         && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
524                         /* if the payload type has changed, we mark the stream as finished to create a new one
525                            this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */           
526                         if ( tmp_listinfo->pt != pi->info_payload_type ) {
527                                 tmp_listinfo->end_stream = TRUE;
528                         } else {
529                                 strinfo = (voip_rtp_stream_info_t*)(list->data);
530                                 break;
531                         }
532                 }
533                 list = g_list_next (list);
534         }
535
536         /* if this is a duplicated RTP Event End, just return */
537         if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
538                 return 0;
539         }
540
541         /* not in the list? then create a new entry */
542         if (strinfo==NULL){
543                 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
544                 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
545                 strinfo->src_port = pinfo->srcport;
546                 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
547                 strinfo->dest_port = pinfo->destport;
548                 strinfo->ssrc = pi->info_sync_src;
549                 strinfo->end_stream = FALSE;
550                 strinfo->pt = pi->info_payload_type;
551                 strinfo->pt_str = NULL;
552                 strinfo->is_srtp = pi->info_is_srtp;
553                 /* if it is dynamic payload, let use the conv data to see if it is defined */
554                 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
555                         /* Use existing packet info if available */
556                         p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
557                         if (p_conv_data)
558                                 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
559                 }
560                 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
561                 strinfo->npackets = 0;
562                 strinfo->first_frame_num = pinfo->fd->num;
563                 strinfo->start_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
564                 strinfo->start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
565                 strinfo->setup_frame_number = pi->info_setup_frame_num;
566                 strinfo->rtp_event = -1;
567                 tapinfo->list = g_list_append(tapinfo->list, strinfo);
568         }
569
570         if (strinfo!=NULL){
571                 /* Add the info to the existing RTP stream */
572                 strinfo->npackets++;
573                 strinfo->stop_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
574                 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
575
576                 /* process RTP Event */
577                 if (rtp_evt_frame_num == pinfo->fd->num) {
578                         strinfo->rtp_event = rtp_evt;
579                         if (rtp_evt_end == TRUE) {
580                                 strinfo->end_stream = TRUE;
581                         }
582                 }
583         }
584
585         the_tapinfo_struct.redraw = TRUE;
586
587         return 1;
588 }
589
590 /****************************************************************************/
591 /* whenever a redraw in the RTP tap listener */
592 static void RTP_packet_draw(void *prs _U_)
593 {
594         voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
595         GList* rtp_streams_list;
596         voip_rtp_stream_info_t *rtp_listinfo;
597         GList* voip_calls_graph_list;
598         guint item;
599         graph_analysis_item_t *gai;
600         graph_analysis_item_t *new_gai;
601         guint16 conv_num;
602         guint32 duration;
603
604         /* add each rtp stream to the graph */
605         rtp_streams_list = g_list_first(rtp_tapinfo->list);
606         while (rtp_streams_list)
607         {
608                 rtp_listinfo = rtp_streams_list->data;
609
610                 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
611                 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
612                 while (voip_calls_graph_list)
613                 {                       
614                         gai = voip_calls_graph_list->data;
615                         conv_num = gai->conv_num;
616                         /* if we get the setup frame number, then get the time position to graph the RTP arrow */
617                         if (rtp_listinfo->setup_frame_number == gai->frame_num){
618                                 /* look again from the begining because there are cases where the Setup frame is after the RTP */
619                                 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
620                                 item = 0;
621                                 while(voip_calls_graph_list){
622                                         gai = voip_calls_graph_list->data;
623                                         /* if RTP was already in the Graph, just update the comment information */
624                                         if (rtp_listinfo->first_frame_num == gai->frame_num){
625                                                 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
626                                                 g_free(gai->comment);
627                                                 gai->comment = g_strdup_printf("%s Num packets:%u  Duration:%u.%03us SSRC:0x%X", 
628                                                                                                                 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets, 
629                                                                                                                 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
630                                                 break;
631                                         }
632
633                                         /* we increment the list here to be able to check if it is the last item in this calls, which means the RTP is after so we have to draw it */
634                                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
635                                         if (!voip_calls_graph_list) item++;
636
637                                         /* add the RTP item to the graph if was not there*/
638                                         if (rtp_listinfo->first_frame_num<gai->frame_num || !voip_calls_graph_list){
639                                                 new_gai = g_malloc(sizeof(graph_analysis_item_t));
640                                                 new_gai->frame_num = rtp_listinfo->first_frame_num;
641                                                 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
642                                                 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
643                                                 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
644                                                 new_gai->port_src = rtp_listinfo->src_port;
645                                                 new_gai->port_dst = rtp_listinfo->dest_port;
646                                                 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
647                                                 new_gai->frame_label = g_strdup_printf("%s (%s) %s", (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->pt_str, (rtp_listinfo->rtp_event == -1)?"":val_to_str(rtp_listinfo->rtp_event, rtp_event_type_values, "Unknown RTP Event")); 
648                                                 new_gai->comment = g_strdup_printf("%s Num packets:%u  Duration:%u.%03us SSRC:0x%X", 
649                                                                                                                         (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets, 
650                                                                                                                         duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
651                                                 new_gai->conv_num = conv_num;
652                                                 new_gai->display=FALSE;
653                                                 new_gai->line_style = 2;  /* the arrow line will be 2 pixels width */
654                                                 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
655                                                 break;
656                                         }
657                                         if (voip_calls_graph_list) item++;
658                                 }
659                                 break;
660                         }
661                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
662                 }
663                 rtp_streams_list = g_list_next(rtp_streams_list);
664         }
665 }
666
667 static gboolean have_RTP_tap_listener=FALSE;
668 /****************************************************************************/
669 void
670 rtp_init_tap(void)
671 {
672         GString *error_string;
673
674         if(have_RTP_tap_listener==FALSE)
675         {
676                 /* don't register tap listener, if we have it already */
677                 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
678                         voip_rtp_reset, 
679                         RTP_packet, 
680                         RTP_packet_draw
681                         );
682                 if (error_string != NULL) {
683                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
684                                       error_string->str);
685                         g_string_free(error_string, TRUE);
686                         exit(1);
687                 }
688                 have_RTP_tap_listener=TRUE;
689         }
690 }
691
692 /****************************************************************************/
693 void
694 remove_tap_listener_rtp(void)
695 {
696         protect_thread_critical_region();
697         remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
698         unprotect_thread_critical_region();
699
700         have_RTP_tap_listener=FALSE;
701 }
702
703 /* XXX just copied from gtk/rpc_stat.c */
704 void protect_thread_critical_region(void);
705 void unprotect_thread_critical_region(void);
706
707 /****************************************************************************/
708 /******************************TAP for T38 **********************************/
709 /****************************************************************************/
710
711 /****************************************************************************/
712 /* whenever a T38 packet is seen by the tap listener */
713 static int 
714 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
715 {
716         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
717
718         voip_calls_info_t *callsinfo = NULL;
719         voip_calls_info_t *tmp_listinfo;
720         GList* voip_calls_graph_list;
721         GList* list;
722         gchar *frame_label = NULL;
723         gchar *comment = NULL;
724         graph_analysis_item_t *tmp_gai, *gai = NULL;
725         guint16 line_style = 2;
726         double duration;
727         int conv_num = -1;
728
729         const t38_packet_info *pi = T38info;
730
731         if  (pi->setup_frame_number != 0) {
732                 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
733                 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
734                 while (voip_calls_graph_list)
735                 {                       
736                         tmp_gai = voip_calls_graph_list->data;
737                         if (pi->setup_frame_number == tmp_gai->frame_num){
738                                 gai = tmp_gai;
739                                 break;
740                         }
741                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
742                 }
743                 if (gai) conv_num = (int) gai->conv_num;
744         }
745
746         /* if setup_frame_number in the t38 packet is 0, it means it was not set using an SDP or H245 sesion, which means we don't 
747          * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
748          * in this case we create a "voip" call that only have t38 media (no signaling)
749          * OR if we have not found the Setup message in the graph. 
750          */
751         if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
752                 /* check whether we already have a call with these parameters in the list */
753                 list = g_list_first(tapinfo->callsinfo_list);
754                 while (list)
755                 {
756                         tmp_listinfo=list->data;
757                         if (tmp_listinfo->protocol == MEDIA_T38){
758                                 callsinfo = (voip_calls_info_t*)(list->data);
759                                 break;
760                         }
761                         list = g_list_next (list);
762                 }
763
764                 /* not in the list? then create a new entry */
765                 if (callsinfo==NULL){
766                         callsinfo = g_malloc0(sizeof(voip_calls_info_t));
767                         callsinfo->call_active_state = VOIP_ACTIVE;
768                         callsinfo->call_state = VOIP_UNKNOWN;
769                         callsinfo->from_identity=g_strdup("T38 Media only");
770                         callsinfo->to_identity=g_strdup("T38 Media only");
771                         COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
772                         callsinfo->first_frame_num=pinfo->fd->num;
773                         callsinfo->selected=FALSE;
774                         callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
775                         callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
776                         callsinfo->protocol=MEDIA_T38;
777                         callsinfo->prot_info=NULL;
778                         callsinfo->free_prot_info = NULL;
779                         callsinfo->npackets = 0;
780                         callsinfo->call_num = tapinfo->ncalls++;
781                         tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
782                 }
783                 ++(callsinfo->npackets);
784                 /* increment the packets counter of all calls */
785                 ++(tapinfo->npackets);
786
787                 conv_num = (int) callsinfo->call_num;
788         }
789
790         /* at this point we should have found the call num for this t38 packets belong */
791         if (conv_num == -1) {
792                 return 0;
793         }
794
795         /* add the item to the graph list */
796         if (pi->type_msg == 0) { /* 0=t30-indicator */
797                 frame_label = g_strdup(val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
798                 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
799                 line_style = 1;
800         } else if (pi->type_msg == 1) { /* 1=data */
801                 switch(pi->Data_Field_field_type_value){
802                         case 0: /* hdlc-data */
803                                 break;
804                         case 2: /* hdlc-fcs-OK */
805                         case 4: /* hdlc-fcs-OK-sig-end */
806                                         frame_label = g_strdup_printf("%s %s", val_to_str(pi->t30_Facsimile_Control & 0x7F, t30_facsimile_control_field_vals_short, "Ukn (0x%02X)"), pi->desc);
807                                         comment = g_strdup_printf("t38:%s:HDLC:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)"), val_to_str(pi->t30_Facsimile_Control & 0x7F, t30_facsimile_control_field_vals, "Ukn (0x%02X)"));
808                                 break;
809                         case 3: /* hdlc-fcs-BAD */
810                         case 5: /* hdlc-fcs-BAD-sig-end */
811                                 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
812                                 comment = g_strdup_printf("WARNING: received t38:%s:HDLC:%s", val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)"), pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
813                                 break;
814                         case 7: /* t4-non-ecm-sig-end */
815                                 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
816                                 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)") );
817                                 comment = g_strdup_printf("t38:t4-non-ecm-data:%s Duration: %.2fs %s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)"), duration, pi->desc_comment );
818                                 insert_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style, pi->time_first_t4_data, pi->frame_num_first_t4_data);
819                                 break;
820                 }
821         }
822
823         if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
824                 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
825         }
826
827         g_free(comment);
828         g_free(frame_label);
829         
830         tapinfo->redraw = TRUE;
831
832         return 1;  /* refresh output */
833 }
834
835 static gboolean have_T38_tap_listener=FALSE;
836 /****************************************************************************/
837 void
838 t38_init_tap(void)
839 {
840         GString *error_string;
841
842         if(have_T38_tap_listener==FALSE)
843         {
844                 /* don't register tap listener, if we have it already */
845                 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
846                         voip_calls_dlg_reset, 
847                         T38_packet, 
848                         voip_calls_dlg_draw
849                         );
850                 if (error_string != NULL) {
851                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
852                                       error_string->str);
853                         g_string_free(error_string, TRUE);
854                         exit(1);
855                 }
856                 have_T38_tap_listener=TRUE;
857         }
858 }
859
860 /****************************************************************************/
861 void
862 remove_tap_listener_t38(void)
863 {
864         protect_thread_critical_region();
865         remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
866         unprotect_thread_critical_region();
867
868         have_T38_tap_listener=FALSE;
869 }
870
871
872 /****************************************************************************/
873 static gchar *sdp_summary = NULL;
874 static guint32 sdp_frame_num = 0;
875
876 /****************************************************************************/
877 /* ***************************TAP for SIP **********************************/
878 /****************************************************************************/
879
880
881 static void free_sip_info(gpointer p) {
882         sip_calls_info_t *si = p;
883         
884         if (si->call_identifier) g_free(si->call_identifier);
885         g_free(si);
886 }
887
888 /****************************************************************************/
889 /* whenever a SIP packet is seen by the tap listener */
890 static int 
891 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
892 {
893         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
894         /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
895            be compared with existing calls */
896
897         voip_calls_info_t *tmp_listinfo;
898         voip_calls_info_t *callsinfo = NULL;
899         sip_calls_info_t *tmp_sipinfo = NULL;
900         GList* list;
901         address tmp_src, tmp_dst;
902         gchar *frame_label = NULL;
903         gchar *comment = NULL;
904
905         const sip_info_value_t *pi = SIPinfo;
906
907         /* do not consider packets without call_id */
908         if (pi->tap_call_id ==NULL){
909                 return 0;
910         }
911
912         /* check whether we already have a call with these parameters in the list */
913         list = g_list_first(tapinfo->callsinfo_list);
914         while (list)
915         {
916                 tmp_listinfo=list->data;
917                 if (tmp_listinfo->protocol == VOIP_SIP){
918                         tmp_sipinfo = tmp_listinfo->prot_info;
919                         if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
920                                 callsinfo = (voip_calls_info_t*)(list->data);
921                                 break;
922                         }
923                 }
924                 list = g_list_next (list);
925         }
926
927         /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
928         if ((callsinfo==NULL) &&(pi->request_method!=NULL)){
929                 if (strcmp(pi->request_method,"INVITE")==0){
930                         callsinfo = g_malloc0(sizeof(voip_calls_info_t));
931                         callsinfo->call_active_state = VOIP_ACTIVE;
932                         callsinfo->call_state = VOIP_CALL_SETUP;
933                         callsinfo->from_identity=g_strdup(pi->tap_from_addr);
934                         callsinfo->to_identity=g_strdup(pi->tap_to_addr);
935                         COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
936                         callsinfo->first_frame_num=pinfo->fd->num;
937                         callsinfo->selected=FALSE;
938                         callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
939                         callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
940                         callsinfo->protocol=VOIP_SIP;
941                         callsinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
942                         callsinfo->free_prot_info = free_sip_info;
943                         tmp_sipinfo = callsinfo->prot_info;
944                         tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
945                         tmp_sipinfo->sip_state = SIP_INVITE_SENT;
946                         tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
947                         callsinfo->npackets = 0;
948                         callsinfo->call_num = tapinfo->ncalls++;
949                         tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
950                 }
951         }
952
953         if (callsinfo!=NULL){
954
955                 /* let's analyze the call state */
956
957                 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
958                 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
959                 
960                 if (pi->request_method == NULL){
961                         frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
962                         comment = g_strdup_printf("SIP Status");
963
964                         if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(callsinfo->initial_speaker)))){
965                                 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
966                                         tmp_sipinfo->sip_state = SIP_200_REC;
967                                 }
968                                 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
969                                         callsinfo->call_state = VOIP_REJECTED;
970                                         tapinfo->rejected_calls++;
971                                 }
972                         }
973
974                 }
975                 else{
976                         frame_label = g_strdup(pi->request_method);
977
978                         if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))){
979                                 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
980                                 callsinfo->call_state = VOIP_CALL_SETUP;
981                                 comment = g_strdup_printf("SIP From: %s To:%s", callsinfo->from_identity, callsinfo->to_identity);
982                         }
983                         else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
984                                 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
985                                 &&(callsinfo->call_state == VOIP_CALL_SETUP)){
986                                 callsinfo->call_state = VOIP_IN_CALL;
987                                 comment = g_strdup_printf("SIP Request");
988                         }
989                         else if (strcmp(pi->request_method,"BYE")==0){
990                                 callsinfo->call_state = VOIP_COMPLETED;
991                                 tapinfo->completed_calls++;
992                                 comment = g_strdup_printf("SIP Request");
993                         }
994                         else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
995                                 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)){
996                                 callsinfo->call_state = VOIP_CANCELLED;
997                                 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
998                                 comment = g_strdup_printf("SIP Request");
999                         } else {
1000                                 comment = g_strdup_printf("SIP Request");
1001                         }
1002                 }
1003
1004                 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1005                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1006                 callsinfo->last_frame_num=pinfo->fd->num;
1007                 ++(callsinfo->npackets);
1008                 /* increment the packets counter of all calls */
1009                 ++(tapinfo->npackets);
1010
1011                 /* add to the graph */
1012                 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);  
1013                 g_free(comment);
1014                 g_free(frame_label);
1015                 g_free((void *)tmp_src.data);
1016                 g_free((void *)tmp_dst.data);
1017
1018                 /* add SDP info if apply */
1019                 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1020                                 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1021                                 g_free(sdp_summary);
1022                                 sdp_summary = NULL;
1023                 }
1024         }
1025
1026         tapinfo->redraw = TRUE;
1027
1028         return 1;  /* refresh output */
1029 }
1030
1031
1032 /****************************************************************************/
1033 voip_calls_tapinfo_t* voip_calls_get_info(void)
1034 {
1035         return &the_tapinfo_struct;
1036 }
1037
1038
1039 /****************************************************************************/
1040 /* TAP INTERFACE */
1041 /****************************************************************************/
1042 static gboolean have_SIP_tap_listener=FALSE;
1043 /****************************************************************************/
1044 void
1045 sip_calls_init_tap(void)
1046 {
1047         GString *error_string;
1048
1049         if(have_SIP_tap_listener==FALSE)
1050         {
1051                 /* don't register tap listener, if we have it already */
1052                 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1053                         voip_calls_dlg_reset, 
1054                         SIPcalls_packet, 
1055                         voip_calls_dlg_draw
1056                         );
1057                 if (error_string != NULL) {
1058                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1059                                       error_string->str);
1060                         g_string_free(error_string, TRUE);
1061                         exit(1);
1062                 }
1063                 have_SIP_tap_listener=TRUE;
1064         }
1065 }
1066
1067 /****************************************************************************/
1068 void
1069 remove_tap_listener_sip_calls(void)
1070 {
1071         protect_thread_critical_region();
1072         remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1073         unprotect_thread_critical_region();
1074
1075         have_SIP_tap_listener=FALSE;
1076 }
1077
1078 /****************************************************************************/
1079 /* ***************************TAP for ISUP **********************************/
1080 /****************************************************************************/
1081
1082 static  guint32         mtp3_opc, mtp3_dpc;
1083 static  guint8          mtp3_ni;
1084 static  guint32         mtp3_frame_num;
1085
1086
1087 /****************************************************************************/
1088 /* whenever a isup_ packet is seen by the tap listener */
1089 static int 
1090 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1091 {
1092         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1093         voip_calls_info_t *tmp_listinfo;
1094         voip_calls_info_t *callsinfo = NULL;
1095         isup_calls_info_t *tmp_isupinfo;
1096         gboolean found = FALSE;
1097         gboolean forward = FALSE;
1098         gboolean right_pair;
1099         GList* list;
1100         gchar *frame_label = NULL;
1101         gchar *comment = NULL;
1102         int i;
1103
1104         /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1105         const isup_tap_rec_t *pi = isup_info;
1106         
1107         /* check if the lower layer is MTP matching the frame number */
1108         if (mtp3_frame_num != pinfo->fd->num) return 0;
1109                 
1110         /* check whether we already have a call with these parameters in the list */
1111         list = g_list_first(tapinfo->callsinfo_list);
1112         while (list)
1113         {
1114                 right_pair = TRUE;
1115                 tmp_listinfo=list->data;
1116                 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1117                         tmp_isupinfo = tmp_listinfo->prot_info;
1118                         if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1119                                 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1120                                          forward = TRUE;
1121                                 } else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1122                                          forward = FALSE;
1123                                 } else{
1124                                         right_pair = FALSE;
1125                                 }
1126                                 
1127                                  if (right_pair){
1128                                         /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1129                                            cic is no longer active */
1130                                         if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1131                                                 found = TRUE;
1132                                         } else if (pi->message_type != 1){
1133                                                 found = TRUE;
1134                                         } else{
1135                                                 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1136                                         }
1137                                 }
1138                                 
1139                                 if (found){
1140                                         callsinfo = (voip_calls_info_t*)(list->data);
1141                                         break;
1142                                 }
1143                         }
1144                 }
1145                 list = g_list_next (list);
1146         }
1147
1148         /* not in the list? then create a new entry if the message is IAM
1149            -i.e. if this session is a call*/
1150
1151
1152         if ((callsinfo==NULL) &&(pi->message_type==1)){
1153                 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1154                 callsinfo->call_active_state = VOIP_ACTIVE;
1155                 callsinfo->call_state = VOIP_UNKNOWN;
1156                 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1157                 callsinfo->selected=FALSE;
1158                 callsinfo->first_frame_num=pinfo->fd->num;
1159                 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1160                 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1161                 callsinfo->protocol=VOIP_ISUP;
1162                 if (pi->calling_number!=NULL){
1163                         callsinfo->from_identity=g_strdup(pi->calling_number);
1164                 }
1165                 if (pi->called_number!=NULL){
1166                         callsinfo->to_identity=g_strdup(pi->called_number);
1167                 }
1168                 callsinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1169                 callsinfo->free_prot_info = g_free;
1170                 tmp_isupinfo=callsinfo->prot_info;
1171                 tmp_isupinfo->opc = mtp3_opc;
1172                 tmp_isupinfo->dpc = mtp3_dpc;
1173                 tmp_isupinfo->ni = mtp3_ni;
1174                 tmp_isupinfo->cic = pinfo->circuit_id;
1175                 callsinfo->npackets = 0;
1176                 callsinfo->call_num = tapinfo->ncalls++;
1177                 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1178         }
1179
1180         
1181         if (callsinfo!=NULL){
1182                 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1183                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1184                 callsinfo->last_frame_num=pinfo->fd->num;
1185                 ++(callsinfo->npackets);
1186
1187                 /* Let's analyze the call state */
1188
1189
1190                 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
1191
1192                 if (isup_message_type_value[i].value==pi->message_type){
1193                         frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
1194                 }
1195                 else{
1196                         frame_label = g_strdup_printf("Unknown");
1197                 }
1198
1199                 if (callsinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1200
1201                         if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1202                                 comment = g_strdup_printf("Call from %s to %s",
1203                                  pi->calling_number, pi->called_number);
1204                          }
1205                 } else if (callsinfo->npackets == 2){ /* in the second packet we show the SPs */
1206                         if (forward){
1207                                 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1208                                  mtp3_ni, mtp3_opc,
1209                                  mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1210                         } else {
1211                                 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1212                                  mtp3_ni, mtp3_dpc,
1213                                  mtp3_ni, mtp3_opc, pinfo->circuit_id);
1214                         }
1215                 }
1216
1217
1218                 switch(pi->message_type){
1219                         case 1: /* IAM */
1220                                 callsinfo->call_state=VOIP_CALL_SETUP;
1221                                 break;
1222                         case 7: /* CONNECT */
1223                         case 9: /* ANSWER */
1224                                 callsinfo->call_state=VOIP_IN_CALL;
1225                                 break;
1226                         case 12: /* RELEASE */
1227                                 if (callsinfo->call_state==VOIP_CALL_SETUP){
1228                                         if (forward){
1229                                                 callsinfo->call_state=VOIP_CANCELLED;
1230                                         }
1231                                         else{
1232                                                 callsinfo->call_state=VOIP_REJECTED;
1233                                                 tapinfo->rejected_calls++;
1234                                         }
1235                                 }
1236                                 else if (callsinfo->call_state == VOIP_IN_CALL){
1237                                         callsinfo->call_state = VOIP_COMPLETED;
1238                                         tapinfo->completed_calls++;
1239                                 }
1240                                 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
1241                                 if (q931_cause_code_vals[i].value==pi->cause_value){
1242                                         comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
1243                                 }
1244                                 else{
1245                                         comment = g_strdup_printf("Cause %i",pi->cause_value);
1246                                 }
1247                                 break;
1248                 }
1249
1250                 /* increment the packets counter of all calls */
1251                 ++(tapinfo->npackets);
1252
1253                 /* add to the graph */
1254                 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);  
1255                 g_free(comment);
1256                 g_free(frame_label);
1257         }
1258
1259         tapinfo->redraw = TRUE;
1260
1261         return 1;  /* refresh output */
1262 }
1263
1264 /****************************************************************************/
1265
1266 static gboolean have_isup_tap_listener=FALSE;
1267
1268 void
1269 isup_calls_init_tap(void)
1270 {
1271         GString *error_string;
1272
1273
1274         if(have_isup_tap_listener==FALSE)
1275         {
1276                 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1277                         NULL,
1278                         voip_calls_dlg_reset, 
1279                         isup_calls_packet, 
1280                         voip_calls_dlg_draw
1281                         );
1282         
1283                 if (error_string != NULL) {
1284                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1285                                       error_string->str);
1286                         g_string_free(error_string, TRUE);
1287                         exit(1);
1288                 }
1289                 have_isup_tap_listener=TRUE;
1290         }
1291 }
1292
1293 /****************************************************************************/
1294
1295 void
1296 remove_tap_listener_isup_calls(void)
1297 {
1298         protect_thread_critical_region();
1299         remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1300         unprotect_thread_critical_region();
1301
1302         have_isup_tap_listener=FALSE;
1303 }
1304
1305
1306 /****************************************************************************/
1307 /* ***************************TAP for MTP3 **********************************/
1308 /****************************************************************************/
1309
1310
1311 /****************************************************************************/
1312 /* whenever a mtp3_ packet is seen by the tap listener */
1313 static int 
1314 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1315 {
1316         const mtp3_tap_rec_t *pi = mtp3_info;
1317
1318         /* keep the data in memory to use when the ISUP information arrives */
1319
1320         mtp3_opc = pi->addr_opc.pc;
1321         mtp3_dpc = pi->addr_dpc.pc;
1322         mtp3_ni = pi->addr_opc.ni;
1323         mtp3_frame_num = pinfo->fd->num;
1324
1325         return 0;
1326 }
1327
1328 /****************************************************************************/
1329
1330 static gboolean have_mtp3_tap_listener=FALSE;
1331 static gboolean have_m3ua_tap_listener=FALSE;
1332
1333 void
1334 mtp3_calls_init_tap(void)
1335 {
1336         GString *error_string;
1337
1338
1339         if(have_mtp3_tap_listener==FALSE)
1340         {
1341                 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1342                         NULL,
1343                         voip_calls_dlg_reset, 
1344                         mtp3_calls_packet, 
1345                         voip_calls_dlg_draw
1346                         );
1347
1348                 if (error_string != NULL) {
1349                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1350                                       error_string->str);
1351                         g_string_free(error_string, TRUE);
1352                         exit(1);
1353                 }
1354                 have_mtp3_tap_listener=TRUE;
1355         }
1356         
1357         if(have_m3ua_tap_listener==FALSE)
1358         {
1359                 error_string = register_tap_listener("m3ua", &(the_tapinfo_struct.mtp3_dummy),
1360                                                                                          NULL,
1361                                                                                          voip_calls_dlg_reset, 
1362                                                                                          mtp3_calls_packet, 
1363                                                                                          voip_calls_dlg_draw
1364                                                                                          );
1365                 
1366                 if (error_string != NULL) {
1367                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1368                                                   error_string->str);
1369                         g_string_free(error_string, TRUE);
1370                         exit(1);
1371                 }
1372                 have_m3ua_tap_listener=TRUE;
1373         }
1374         
1375 }
1376
1377 /****************************************************************************/
1378
1379 void
1380 remove_tap_listener_mtp3_calls(void)
1381 {
1382         protect_thread_critical_region();
1383         remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1384         remove_tap_listener(&(the_tapinfo_struct.m3ua_dummy));
1385         unprotect_thread_critical_region();
1386
1387         have_mtp3_tap_listener=FALSE;
1388         have_m3ua_tap_listener=FALSE;
1389 }
1390
1391 /****************************************************************************/
1392 /* ***************************TAP for Q931 **********************************/
1393 /****************************************************************************/
1394 void h245_add_to_graph(guint32 new_frame_num);
1395 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1396 /* defines specific H323 data */
1397
1398 static gchar *q931_calling_number;
1399 static gchar *q931_called_number;
1400 static guint8 q931_cause_value;
1401 static gint32 q931_crv;
1402 static guint32 q931_frame_num;
1403
1404 static guint32 h225_frame_num = 0;
1405 static guint16 h225_call_num = 0;
1406 static h225_cs_type h225_cstype = H225_OTHER;
1407 static gboolean h225_is_faststart;
1408
1409 static guint32 actrace_frame_num = 0;
1410 static gint32 actrace_trunk = 0;
1411 static gint32 actrace_direction = 0;
1412
1413
1414 /****************************************************************************/
1415 /* whenever a q931_ packet is seen by the tap listener */
1416 static int 
1417 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1418 {
1419         GList *list,*list2;
1420         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; 
1421         h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1422         actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1423         voip_calls_info_t *tmp_listinfo;
1424         voip_calls_info_t *callsinfo = NULL;
1425         h245_address_t *h245_add = NULL;
1426         gchar *comment;
1427
1428         const q931_packet_info *pi = q931_info;
1429
1430         /* free previously allocated q931_calling/ed_number */
1431         g_free(q931_calling_number);
1432         g_free(q931_called_number);
1433         
1434         if (pi->calling_number!=NULL)
1435                 q931_calling_number = g_strdup(pi->calling_number);
1436         else
1437                 q931_calling_number = g_strdup("");
1438
1439         if (pi->called_number!=NULL)
1440                 q931_called_number = g_strdup(pi->called_number);
1441         else
1442                 q931_called_number = g_strdup("");
1443         q931_cause_value = pi->cause_value;
1444         q931_frame_num = pinfo->fd->num;
1445         q931_crv = pi->crv;
1446
1447
1448         /* add staff to H323 calls */
1449         if (h225_frame_num == q931_frame_num) {
1450                 tmp_h323info = NULL;
1451                 list = g_list_first(tapinfo->callsinfo_list);
1452                 while (list)
1453                 {
1454                         tmp_listinfo=list->data;
1455                         if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1456                                 tmp_h323info = tmp_listinfo->prot_info;
1457                                 callsinfo = (voip_calls_info_t*)(list->data);
1458
1459                                 /* Add the CRV to the h323 call */
1460                                 if (tmp_h323info->q931_crv == -1) {
1461                                         tmp_h323info->q931_crv = q931_crv;
1462                                 } else if (tmp_h323info->q931_crv != q931_crv) {
1463                                         tmp_h323info->q931_crv2 = q931_crv;
1464                                 }
1465                                 break;
1466                         }
1467                         list = g_list_next (list);
1468                 }
1469
1470                 if (callsinfo != NULL) {
1471                         comment = NULL;
1472                         if (h225_cstype == H225_SETUP) {
1473                                 /* set te calling and called number from the Q931 packet */
1474                                 if (q931_calling_number != NULL){
1475                                         g_free(callsinfo->from_identity);
1476                                         callsinfo->from_identity=g_strdup(q931_calling_number);
1477                                 }
1478                                 if (q931_called_number != NULL){
1479                                         g_free(callsinfo->to_identity);
1480                                         callsinfo->to_identity=g_strdup(q931_called_number);
1481                                 }
1482
1483                                 /* check if there is an LRQ/LCF that match this Setup */
1484                                 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup 
1485                                         we should also check if the h225 signaling IP and port match the destination 
1486                                         Setup ip and port */
1487                                 list = g_list_first(tapinfo->callsinfo_list);
1488                                 while (list)
1489                                 {
1490                                         tmp_listinfo=list->data;
1491                                         if (tmp_listinfo->protocol == VOIP_H323){
1492                                                 tmp2_h323info = tmp_listinfo->prot_info;
1493                                                 
1494                                                 /* check if the called number match a LRQ/LCF */
1495                                                 if ( (strcmp(callsinfo->to_identity, tmp_listinfo->to_identity)==0)  
1496                                                          && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){ 
1497                                                         /* change the call graph to the LRQ/LCF to belong to this call */
1498                                                         callsinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, callsinfo->call_num);
1499                                                         
1500                                                         /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1501                                                         g_free(tmp_listinfo->from_identity);
1502                                                         g_free(tmp_listinfo->to_identity);
1503                                                         g_free(tmp2_h323info->guid);
1504                                                         
1505                                                         list2 = g_list_first(tmp2_h323info->h245_list);
1506                                                         while (list2)
1507                                                         {
1508                                                                 h245_add=list2->data;
1509                                                                 g_free((void *)h245_add->h245_address.data);
1510                                                                 g_free(list2->data);
1511                                                                 list2 = g_list_next(list2);
1512                                                         }
1513                                                         g_list_free(tmp_h323info->h245_list);
1514                                                         tmp_h323info->h245_list = NULL;
1515                                                         g_free(tmp_listinfo->prot_info);
1516                                                         tapinfo->callsinfo_list = g_list_remove(tapinfo->callsinfo_list, tmp_listinfo);
1517                                                         break;
1518                                                 }
1519                                         }
1520                                 list = g_list_next (list);
1521                                 }
1522
1523                                 comment = g_strdup_printf("H225 From: %s To:%s  TunnH245:%s FS:%s", callsinfo->from_identity, callsinfo->to_identity, (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1524                                                           (h225_is_faststart==TRUE?"on":"off"));
1525                         } else if (h225_cstype == H225_RELEASE_COMPLET) {
1526                                 /* get the Q931 Release cause code */
1527                                 if (q931_cause_value != 0xFF){          
1528                                         comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1529                                 } else { /* Cause not set */
1530                                         comment = g_strdup("H225 No Q931 Rel Cause");
1531                                 }
1532                         }
1533                         /* change the graph comment for this new one */
1534                         if (comment != NULL) {
1535                                 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1536                                 g_free(comment);
1537                         }
1538                 }
1539                 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1540                    as non empty h225 (e.g connect), so we don't have to be here twice */
1541                 h225_frame_num = 0;
1542
1543         /* add staff to H245 */
1544         } else if (h245_labels.frame_num == q931_frame_num) {
1545         /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info, 
1546            so the only way to match those frames is with the Q931 CRV number */ 
1547                 list = g_list_first(tapinfo->callsinfo_list);
1548                 while (list)
1549                 {
1550                         tmp_listinfo=list->data;
1551                         if (tmp_listinfo->protocol == VOIP_H323){
1552                                 tmp_h323info = tmp_listinfo->prot_info;
1553                                 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1554
1555                                         comment = g_strdup("");
1556
1557                                         /* if the frame number exists in graph, append to it*/
1558                                         if (!append_to_frame_graph(tapinfo, q931_frame_num, "", comment)) {
1559                                                 /* if not exist, add to the graph */
1560                                                 add_to_graph(tapinfo, pinfo, "", comment, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1561                                                 ++(tmp_listinfo->npackets);
1562                                                 /* increment the packets counter of all calls */
1563                                                 ++(tapinfo->npackets);
1564                                         }
1565                                         
1566                                         /* Add the H245 info if exists to the Graph */
1567                                         h245_add_to_graph(pinfo->fd->num);
1568                                         g_free(comment);
1569                                         break;
1570                                 }
1571                         }
1572                         list = g_list_next (list);
1573                 }
1574
1575         /* add staff to ACTRACE */
1576         } else if (actrace_frame_num == q931_frame_num) {
1577                 address pstn_add;
1578                 gchar *comment = NULL;
1579
1580                 callsinfo = NULL;
1581                 list = g_list_first(tapinfo->callsinfo_list);
1582                 while (list)
1583                 {
1584                         tmp_listinfo=list->data;
1585                         if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1586                                 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1587                                 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1588                                 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1589                                         callsinfo = (voip_calls_info_t*)(list->data);
1590                                         break;
1591                                 }
1592                         }
1593                         list = g_list_next (list);
1594                 }
1595
1596                 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1597
1598                 /* if it is a new call, add it to the list */
1599                 if (!callsinfo) {
1600                         callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1601                         callsinfo->call_active_state = VOIP_ACTIVE;
1602                         callsinfo->call_state = VOIP_CALL_SETUP;
1603                         callsinfo->from_identity=g_strdup(q931_calling_number);
1604                         callsinfo->to_identity=g_strdup(q931_called_number);
1605                         COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1606                         callsinfo->first_frame_num=pinfo->fd->num;
1607                         callsinfo->selected=FALSE;
1608                         callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1609                         callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1610                         callsinfo->protocol=VOIP_AC_ISDN;
1611                         callsinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1612                         callsinfo->free_prot_info = g_free;
1613                         tmp_actrace_isdn_info=callsinfo->prot_info;
1614                         tmp_actrace_isdn_info->crv=q931_crv;
1615                         tmp_actrace_isdn_info->trunk=actrace_trunk;
1616                         callsinfo->npackets = 0;
1617                         callsinfo->call_num = tapinfo->ncalls++;
1618                         tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1619                 }
1620
1621                 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1622                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1623                 callsinfo->last_frame_num=pinfo->fd->num;
1624                 ++(callsinfo->npackets);
1625                 /* increment the packets counter of all calls */
1626                 ++(tapinfo->npackets);
1627
1628                 switch(pi->message_type){
1629                 case Q931_SETUP:
1630                         comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s  Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1631                         callsinfo->call_state=VOIP_CALL_SETUP;
1632                         break;
1633                 case Q931_CONNECT:
1634                         callsinfo->call_state=VOIP_IN_CALL;
1635                         break;
1636                 case Q931_RELEASE_COMPLETE:
1637                 case Q931_RELEASE:
1638                 case Q931_DISCONNECT:
1639                         if (callsinfo->call_state==VOIP_CALL_SETUP){
1640                                 if (ADDRESSES_EQUAL(&(callsinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){  /* forward direction */
1641                                         callsinfo->call_state=VOIP_CANCELLED;
1642                                 }
1643                                 else{                                                                                           /* reverse */
1644                                         callsinfo->call_state=VOIP_REJECTED;
1645                                         tapinfo->rejected_calls++;
1646                                 }
1647                         } else if ( (callsinfo->call_state!=VOIP_CANCELLED) && (callsinfo->call_state!=VOIP_REJECTED) ){
1648                                         callsinfo->call_state=VOIP_COMPLETED;
1649                                         tapinfo->completed_calls++;
1650                         }
1651                         if (q931_cause_value != 0xFF){          
1652                                 comment = g_strdup_printf("AC_ISDN trunk:%u Q931 Rel Cause (%i):%s", actrace_trunk, q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1653                         } else { /* Cause not set */
1654                                 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1655                         }
1656                         break;
1657                 }
1658
1659                 if (!comment)
1660                         comment = g_strdup_printf("AC_ISDN  trunk:%u", actrace_trunk );
1661
1662                 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, callsinfo->call_num, 
1663                                 actrace_direction?&pstn_add:&(pinfo->src),
1664                                 actrace_direction?&(pinfo->src):&pstn_add,
1665                                 1 );
1666
1667                 g_free(comment);
1668                 g_free((char *)pstn_add.data);
1669         }
1670
1671         tapinfo->redraw = TRUE;
1672
1673         return 1;  /* refresh output */
1674 }
1675
1676 /****************************************************************************/
1677 static gboolean have_q931_tap_listener=FALSE;
1678
1679 void
1680 q931_calls_init_tap(void)
1681 {
1682         GString *error_string;
1683
1684
1685         if(have_q931_tap_listener==FALSE)
1686         {
1687                 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1688                         NULL,
1689                         voip_calls_dlg_reset,
1690                         q931_calls_packet,
1691                         voip_calls_dlg_draw
1692                         );
1693                         
1694                 if (error_string != NULL) {
1695                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1696                                       error_string->str);
1697                         g_string_free(error_string, TRUE);
1698                         exit(1);
1699                 }
1700                 have_q931_tap_listener=TRUE;
1701         }
1702 }
1703
1704 /****************************************************************************/
1705
1706 void
1707 remove_tap_listener_q931_calls(void)
1708 {
1709         protect_thread_critical_region();
1710         remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1711         unprotect_thread_critical_region();
1712
1713         have_q931_tap_listener=FALSE;
1714 }
1715
1716 /****************************************************************************/
1717 /****************************TAP for H323 ***********************************/
1718 /****************************************************************************/
1719
1720 static void add_h245_Address(h323_calls_info_t *h323info,  h245_address_t *h245_address)
1721 {
1722         h323info->h245_list = g_list_append(h323info->h245_list, h245_address);                         
1723 }
1724
1725
1726 static void free_h225_info(gpointer p) {
1727         h323_calls_info_t *tmp_h323info = p;
1728
1729         if (tmp_h323info->guid) g_free(tmp_h323info->guid);
1730
1731         if (tmp_h323info->h245_list) {
1732                 GList* list2 = g_list_first(tmp_h323info->h245_list);
1733                 while (list2)
1734                 {
1735                         h245_address_t *h245_add=list2->data;
1736                         g_free((void *)h245_add->h245_address.data);
1737                         g_free(list2->data);
1738                         list2 = g_list_next(list2);
1739                 }
1740                 
1741                 g_list_free(tmp_h323info->h245_list);
1742                 
1743         }
1744         
1745         g_free(p);
1746 }
1747 /****************************************************************************/
1748 /* whenever a H225 packet is seen by the tap listener */
1749 static int 
1750 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1751 {
1752         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1753         voip_calls_info_t *tmp_listinfo;
1754         voip_calls_info_t *callsinfo = NULL;
1755         h323_calls_info_t *tmp_h323info = NULL;
1756         gchar *frame_label;
1757         gchar *comment;
1758         GList *list;
1759         address tmp_src, tmp_dst;
1760         h245_address_t *h245_add = NULL;
1761         
1762         const h225_packet_info *pi = H225info;
1763         
1764         /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1765         /* OR, if not guid and is H225 return because doesn't belong to a call */
1766         if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1767                 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1768                         return 0;
1769         
1770         /* if it is RAS LCF or LRJ*/
1771         if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) { 
1772                 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1773                 if (!pi->request_available) return 0;
1774                 
1775                 /* check whether we already have a call with this request SeqNum */
1776                 list = g_list_first(tapinfo->callsinfo_list);
1777                 while (list)
1778                 {
1779                         tmp_listinfo=list->data;
1780                         g_assert(tmp_listinfo != NULL);
1781                         if (tmp_listinfo->protocol == VOIP_H323){
1782                                 tmp_h323info = tmp_listinfo->prot_info;
1783                                 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1784                                         callsinfo = (voip_calls_info_t*)(list->data);
1785                                         break;
1786                                 }
1787                         }
1788                         list = g_list_next (list);
1789                 }
1790         } else {
1791                 /* check whether we already have a call with this guid in the list */
1792                 list = g_list_first(tapinfo->callsinfo_list);
1793                 while (list)
1794                 {
1795                         tmp_listinfo=list->data;
1796                         if (tmp_listinfo->protocol == VOIP_H323){
1797                                 tmp_h323info = tmp_listinfo->prot_info;
1798                                 g_assert(tmp_h323info != NULL);
1799                                 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){ 
1800                                         callsinfo = (voip_calls_info_t*)(list->data);
1801                                         break;
1802                                 }
1803                         }
1804                         list = g_list_next (list);
1805                 }
1806         }
1807         
1808         h225_cstype = pi->cs_type;
1809         h225_is_faststart = pi->is_faststart;
1810
1811         /* not in the list? then create a new entry */
1812         if ((callsinfo==NULL)){
1813                 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1814                 callsinfo->call_active_state = VOIP_ACTIVE;
1815                 callsinfo->call_state = VOIP_UNKNOWN;
1816                 callsinfo->from_identity=g_strdup("");
1817                 callsinfo->to_identity=g_strdup("");
1818                 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1819                 callsinfo->selected=FALSE;
1820                 callsinfo->first_frame_num=pinfo->fd->num;
1821                 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1822                 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1823                 callsinfo->protocol=VOIP_H323;
1824                 callsinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1825                 callsinfo->free_prot_info = free_h225_info;
1826                 
1827                 tmp_h323info = callsinfo->prot_info;
1828                 g_assert(tmp_h323info != NULL);
1829                 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1830                 tmp_h323info->h225SetupAddr.type = AT_NONE;
1831                 tmp_h323info->h225SetupAddr.len = 0;
1832                 tmp_h323info->h245_list = NULL;
1833                 tmp_h323info->is_faststart_Setup = FALSE;
1834                 tmp_h323info->is_faststart_Proc = FALSE;
1835                 tmp_h323info->is_h245Tunneling = FALSE;
1836                 tmp_h323info->is_h245 = FALSE;
1837                 tmp_h323info->q931_crv = -1;
1838                 tmp_h323info->q931_crv2 = -1;
1839                 tmp_h323info->requestSeqNum = 0;
1840                 callsinfo->call_num = tapinfo->ncalls++;
1841                 callsinfo->npackets = 0;
1842                 
1843                 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);                            
1844         }
1845
1846         if (callsinfo!=NULL){
1847
1848                 h225_frame_num = pinfo->fd->num;
1849                 h225_call_num = callsinfo->call_num;
1850
1851                 /* let's analyze the call state */
1852
1853                 COPY_ADDRESS(&(tmp_src),&(pinfo->src));
1854                 COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
1855
1856                 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1857                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1858                 callsinfo->last_frame_num=pinfo->fd->num;
1859                 ++(callsinfo->npackets);
1860                 /* increment the packets counter of all calls */
1861                 ++(tapinfo->npackets);
1862
1863
1864                 /* XXX: it is supposed to be initialized isn't it? */
1865                 g_assert(tmp_h323info != NULL);
1866
1867                 /* change the status */
1868                 if (pi->msg_type == H225_CS){
1869
1870                         /* this is still IPv4 only, because the dissector is */
1871                         if (pi->is_h245 == TRUE){
1872                                 h245_add = g_malloc(sizeof (h245_address_t));
1873                                 h245_add->h245_address.type=AT_IPv4;
1874                                 h245_add->h245_address.len=4;
1875                                 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1876                                 memcpy((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1877                                 h245_add->h245_port = pi->h245_port;
1878                                 add_h245_Address(tmp_h323info, h245_add);
1879                         }
1880
1881                         if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1882
1883                         frame_label = g_strdup(pi->frame_label);
1884
1885                         switch(pi->cs_type){
1886                         case H225_SETUP:
1887                                 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1888
1889                                 /* Set the Setup address if it was not set */
1890                                 if (tmp_h323info->h225SetupAddr.type == AT_NONE) 
1891                                   COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1892                                         callsinfo->call_state=VOIP_CALL_SETUP;
1893                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1894                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1895                                 break;
1896                         case H225_CONNECT:
1897                                 callsinfo->call_state=VOIP_IN_CALL;
1898                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1899                                         comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1900                                                                                           (pi->is_faststart==TRUE?"on":"off"));
1901                                 break;
1902                         case H225_RELEASE_COMPLET:
1903                             COPY_ADDRESS(&tmp_src,&(pinfo->src));
1904                                 if (callsinfo->call_state==VOIP_CALL_SETUP){
1905                                         if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){  /* forward direction */
1906                                                 callsinfo->call_state=VOIP_CANCELLED;
1907                                         }
1908                                         else{                                                                                           /* reverse */
1909                                                 callsinfo->call_state=VOIP_REJECTED;
1910                                                 tapinfo->rejected_calls++;
1911                                         }
1912                                 } else {
1913                                                 callsinfo->call_state=VOIP_COMPLETED;
1914                                                 tapinfo->completed_calls++;
1915                                 }
1916                                 comment = g_strdup("H225 No Q931 Rel Cause");
1917                                 break;
1918                         case H225_PROGRESS:
1919                         case H225_ALERTING:
1920                         case H225_CALL_PROCEDING:
1921                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1922                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1923                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1924                                 break;
1925                         default:
1926                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1927                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1928                                 
1929                         } 
1930                 } 
1931                 else if (pi->msg_type == H225_RAS){
1932                 switch(pi->msg_tag){
1933                         case 18:  /* LRQ */
1934                                 if (!pi->is_duplicate){
1935                                         g_free(callsinfo->to_identity);
1936                                         callsinfo->to_identity=g_strdup(pi->dialedDigits);
1937                                         tmp_h323info->requestSeqNum = pi->requestSeqNum;
1938                                 }
1939                         case 19: /* LCF */
1940                                 if (strlen(pi->dialedDigits)) 
1941                                         comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1942                                 else
1943                                         comment = g_strdup("H225 RAS");
1944                                 break;
1945                         default:
1946                                 comment = g_strdup("H225 RAS");
1947                 }
1948                 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
1949         } else {
1950                 frame_label = g_strdup("H225: Unknown");
1951                 comment = g_strdup("");
1952         }
1953
1954         /* add to graph analysis */
1955
1956         /* if the frame number exists in graph, append to it*/
1957         if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1958                 /* if not exist, add to the graph */
1959                 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1960                 g_free((void *)tmp_src.data);
1961                 g_free((void *)tmp_dst.data);
1962         }
1963
1964         /* Add the H245 info if exists to the Graph */
1965         h245_add_to_graph(pinfo->fd->num);
1966
1967         g_free(frame_label);
1968         g_free(comment);
1969         
1970         } 
1971         
1972         tapinfo->redraw = TRUE;
1973
1974         return 1;  /* refresh output */
1975 }
1976
1977
1978 /****************************************************************************/
1979 /* TAP INTERFACE */
1980 /****************************************************************************/
1981 static gboolean have_H225_tap_listener=FALSE;
1982 /****************************************************************************/
1983 void
1984 h225_calls_init_tap(void)
1985 {
1986         GString *error_string;
1987
1988         if(have_H225_tap_listener==FALSE)
1989         {
1990                 /* don't register tap listener, if we have it already */
1991                 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1992                         voip_calls_dlg_reset, 
1993                         H225calls_packet, 
1994                         voip_calls_dlg_draw
1995                         );
1996                         
1997                 if (error_string != NULL) {
1998                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1999                                       error_string->str);
2000                         g_string_free(error_string, TRUE);
2001                         exit(1);
2002                 }
2003                 have_H225_tap_listener=TRUE;
2004         }
2005 }
2006
2007 /****************************************************************************/
2008 void
2009 remove_tap_listener_h225_calls(void)
2010 {
2011         protect_thread_critical_region();
2012         remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
2013         unprotect_thread_critical_region();
2014
2015         have_H225_tap_listener=FALSE;
2016 }
2017
2018 /* Add the h245 label info to the graph */ 
2019 void h245_add_to_graph(guint32 new_frame_num)
2020 {
2021         gint8 n;
2022         
2023         if (new_frame_num != h245_labels.frame_num) return;
2024
2025         for (n=0; n<h245_labels.labels_count; n++) {
2026                 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
2027                 g_free(h245_labels.labels[n].frame_label);
2028                 h245_labels.labels[n].frame_label = NULL;
2029                 g_free(h245_labels.labels[n].comment);
2030                 h245_labels.labels[n].comment = NULL;
2031         }
2032         h245_labels.frame_num = 0;
2033         h245_labels.labels_count = 0;
2034 }
2035
2036 /* free the h245_labels if the frame number is different */ 
2037 static void h245_free_labels(guint32 new_frame_num)
2038 {
2039         gint8 n;
2040         
2041         if (new_frame_num == h245_labels.frame_num) return;
2042
2043         for (n=0; n<h245_labels.labels_count; n++) {
2044                 g_free(h245_labels.labels[n].frame_label);
2045                 h245_labels.labels[n].frame_label = NULL;
2046                 g_free(h245_labels.labels[n].comment);
2047                 h245_labels.labels[n].comment = NULL;
2048         }
2049         h245_labels.frame_num = 0;
2050         h245_labels.labels_count = 0;
2051 }
2052
2053 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */ 
2054 static void h245_add_label(guint32 new_frame_num, const gchar *frame_label, const gchar *comment)
2055 {
2056         h245_free_labels(new_frame_num);
2057
2058         h245_labels.frame_num = new_frame_num;
2059         h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
2060         h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
2061
2062         if (h245_labels.labels_count < (H245_MAX-1))
2063                 h245_labels.labels_count++;
2064
2065 }
2066
2067 /****************************************************************************/
2068 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2069 static int 
2070 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2071 {
2072         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2073         voip_calls_info_t *tmp_listinfo;
2074         voip_calls_info_t *callsinfo = NULL;
2075         h323_calls_info_t *tmp_h323info;
2076         gchar *frame_label;
2077         gchar *comment;
2078         GList* list;
2079         GList* list2;
2080         address tmp_src, tmp_dst;
2081         h245_address_t *h245_add = NULL;
2082
2083         const h245_packet_info *pi = H245info;
2084
2085         /* check if Tunneling is OFF and we have a call with this H245 add */
2086         list = g_list_first(tapinfo->callsinfo_list);
2087         while (list)
2088         {
2089                 tmp_listinfo=list->data;
2090                 if (tmp_listinfo->protocol == VOIP_H323){
2091                         tmp_h323info = tmp_listinfo->prot_info;
2092
2093                         COPY_ADDRESS(&(tmp_src), &(pinfo->src));
2094                         COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
2095                         list2 = g_list_first(tmp_h323info->h245_list);
2096                         while (list2)
2097                         {
2098                                 h245_add=list2->data;
2099                                 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
2100                                         || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
2101                                         callsinfo = (voip_calls_info_t*)(list->data);
2102
2103                                         ++(callsinfo->npackets);
2104                                         /* increment the packets counter of all calls */
2105                                         ++(tapinfo->npackets);
2106
2107                                         break;
2108                                 }                       
2109                         list2 = g_list_next(list2);
2110                         }
2111                         if (callsinfo!=NULL) break;
2112                         g_free((void *)tmp_src.data);
2113                         g_free((void *)tmp_dst.data);
2114                 }
2115                 list = g_list_next(list);
2116         }
2117
2118         /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2119         if (callsinfo!=NULL){
2120                 ++(callsinfo->npackets);
2121                 /* increment the packets counter of all calls */
2122                 ++(tapinfo->npackets);
2123                 frame_label = g_strdup(pi->frame_label);
2124                 comment = g_strdup(pi->comment);
2125                 /* if the frame number exists in graph, append to it*/
2126                 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, frame_label, comment)) {
2127                         /* if not exist, add to the graph */
2128                         add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2129                 }
2130                 g_free(frame_label);
2131                 g_free(comment);
2132         } else { 
2133         /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be 
2134                  tunnel OFF but we did not matched the h245 add, in this case nobady will set this label 
2135                  since the frame_num will not match */ 
2136         
2137                 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2138         }
2139
2140         tapinfo->redraw = TRUE;
2141
2142         return 1;  /* refresh output */
2143 }
2144
2145
2146 /****************************************************************************/
2147 /* TAP INTERFACE */
2148 /****************************************************************************/
2149 static gboolean have_H245dg_tap_listener=FALSE;
2150 /****************************************************************************/
2151 void
2152 h245dg_calls_init_tap(void)
2153 {
2154         GString *error_string;
2155
2156         if(have_H245dg_tap_listener==FALSE)
2157         {
2158                 /* don't register tap listener, if we have it already */
2159                 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2160                         voip_calls_dlg_reset,
2161                         H245dgcalls_packet, 
2162                         voip_calls_dlg_draw
2163                         );
2164                 
2165                 if (error_string != NULL) {
2166                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2167                                       error_string->str);
2168                         g_string_free(error_string, TRUE);
2169                         exit(1);
2170                 }
2171                 have_H245dg_tap_listener=TRUE;
2172         }
2173 }
2174
2175 /****************************************************************************/
2176 void
2177 remove_tap_listener_h245dg_calls(void)
2178 {
2179         protect_thread_critical_region();
2180         remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2181         unprotect_thread_critical_region();
2182
2183         have_H245dg_tap_listener=FALSE;
2184 }
2185
2186 /****************************************************************************/
2187 /****************************TAP for SDP PROTOCOL ***************************/
2188 /****************************************************************************/
2189 /* whenever a SDP packet is seen by the tap listener */
2190 static int 
2191 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2192 {
2193         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2194         const sdp_packet_info *pi = SDPinfo;
2195
2196         /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2197            MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2198            to use it later 
2199         */
2200         g_free(sdp_summary);
2201         sdp_frame_num = pinfo->fd->num;
2202         /* Append to graph the SDP summary if the packet exists */
2203         sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2204         append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2205
2206         tapinfo->redraw = TRUE;
2207
2208         return 1;  /* refresh output */
2209 }
2210
2211
2212 /****************************************************************************/
2213 /* TAP INTERFACE */
2214 /****************************************************************************/
2215 static gboolean have_sdp_tap_listener=FALSE;
2216 /****************************************************************************/
2217 void
2218 sdp_calls_init_tap(void)
2219 {
2220         GString *error_string;
2221
2222         if(have_sdp_tap_listener==FALSE)
2223         {
2224                 /* don't register tap listener, if we have it already */
2225                 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2226                         voip_calls_dlg_reset, 
2227                         SDPcalls_packet, 
2228                         voip_calls_dlg_draw
2229                         );
2230                         
2231                 if (error_string != NULL) {
2232                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2233                                       error_string->str);
2234                         g_string_free(error_string, TRUE);
2235                         exit(1);
2236                 }
2237                 have_sdp_tap_listener=TRUE;
2238         }
2239 }
2240
2241 /****************************************************************************/
2242 void
2243 remove_tap_listener_sdp_calls(void)
2244 {
2245         protect_thread_critical_region();
2246         remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2247         unprotect_thread_critical_region();
2248
2249         have_sdp_tap_listener=FALSE;
2250 }
2251
2252
2253
2254 /****************************************************************************/
2255 /* ***************************TAP for MGCP **********************************/
2256 /****************************************************************************/
2257
2258 /*
2259    This function will look for a signal/event in the SignalReq/ObsEvent string
2260    and return true if it is found 
2261 */
2262 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
2263 {
2264         gint i; 
2265         gchar **resultArray;
2266         
2267         /* if there is no signalStr, just return false */
2268         if (signalStr == NULL) return FALSE;
2269
2270         /* if are both "blank" return true */
2271         if ( (*signal == '\0') &&  (*signalStr == '\0') ) return TRUE;
2272
2273         /* look for signal in signalSre */
2274         resultArray = g_strsplit(signalStr, ",", 10);
2275
2276         for (i = 0; resultArray[i]; i++) {
2277                 g_strstrip(resultArray[i]);
2278                 if (strcmp(resultArray[i], signal) == 0) return TRUE;
2279         }
2280
2281         g_strfreev(resultArray);
2282         
2283         return FALSE;
2284 }
2285
2286 /*
2287    This function will get the Caller ID info and replace the current string
2288    This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2289 */
2290 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2291 {
2292         gchar **arrayStr;
2293         
2294         /* if there is no signalStr, just return false */
2295         if (signalStr == NULL) return;
2296
2297         arrayStr = g_strsplit(signalStr, "\"", 10);
2298
2299         if (arrayStr[0] == NULL) return;
2300
2301         /* look for the ci signal */
2302         if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2303                 /* free the previous "From" field of the call, and assign the new */
2304                 g_free(*callerId);
2305                 *callerId = g_strdup(arrayStr[1]);
2306         }
2307         g_strfreev(arrayStr);
2308
2309         return;
2310 }
2311
2312
2313 /*
2314    This function will get the Dialed Digits and replace the current string
2315    This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2316 */
2317 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2318 {
2319         gchar *tmpStr;
2320         gchar resultStr[50];
2321         gint i,j; 
2322
2323         /* if there is no signalStr, just return false */
2324         if (signalStr == NULL) return;
2325
2326         tmpStr = g_strdup(signalStr);
2327         
2328         for ( i = 0 ; tmpStr[i] ; i++) {
2329                 switch (tmpStr[i]) {
2330                         case '0' : case '1' : case '2' : case '3' : case '4' :
2331                         case '5' : case '6' : case '7' : case '8' : case '9' :
2332                         case '#' : case '*' :
2333                                 break;
2334                         default:
2335                                 tmpStr[i] = '?';
2336                                 break;
2337                 }
2338         }
2339         
2340         for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2341                 if (tmpStr[i] != '?')
2342                         resultStr[j++] = tmpStr[i];
2343         }
2344         resultStr[j] = '\0';
2345
2346         if (*resultStr == '\0') return;
2347         
2348         g_free(*dialedDigits);
2349         *dialedDigits = g_strdup(resultStr);
2350         g_free(tmpStr);
2351
2352         return;
2353 }
2354
2355
2356
2357 /****************************************************************************/
2358 /* whenever a MGCP packet is seen by the tap listener */
2359 static int 
2360 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2361 {
2362         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2363
2364         voip_calls_info_t *tmp_listinfo;
2365         voip_calls_info_t *callsinfo = NULL;
2366         mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2367         GList* list;
2368         GList* listGraph;
2369         gchar *frame_label = NULL;
2370         gchar *comment = NULL;
2371         graph_analysis_item_t *gai;
2372         gboolean new = FALSE;
2373         gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2374         gdouble diff_time;
2375
2376         const mgcp_info_t *pi = MGCPinfo;
2377
2378
2379         if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2380                 /* check whether we already have a call with this Endpoint and it is active*/
2381                 list = g_list_first(tapinfo->callsinfo_list);
2382                 while (list)
2383                 {
2384                         tmp_listinfo=list->data;
2385                         if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2386                                 tmp_mgcpinfo = tmp_listinfo->prot_info;
2387                                 if (pi->endpointId != NULL){
2388                                         if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2389                                                 /*
2390                                                    check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2391                                                    after the call has been released
2392                                                 */
2393                                                 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - tmp_listinfo->stop_sec - (double)tmp_listinfo->stop_usec/1000000;
2394                                                 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2395                                                      (tmp_listinfo->call_state == VOIP_COMPLETED)  ||
2396                                                      (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2397                                                        (diff_time > 2) )
2398                                                 {
2399                                                         tmp_listinfo->call_active_state = VOIP_INACTIVE;
2400                                                 } else {
2401                                                         callsinfo = (voip_calls_info_t*)(list->data);
2402                                                         break;
2403                                                 }
2404                                         }
2405                                 }
2406                         }
2407                         list = g_list_next (list);
2408                 }
2409                 
2410                 /* there is no call with this Endpoint, lets see if this a new call or not */
2411                 if (callsinfo == NULL){
2412                         if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2413                                 /* this is a new call from the Endpoint */      
2414                                 fromEndpoint = TRUE;
2415                                 new = TRUE;
2416                         } else if (strcmp(pi->code, "CRCX") == 0){
2417                                 /* this is a new call from the MGC */
2418                                 fromEndpoint = FALSE;
2419                                 new = TRUE;
2420                         }
2421                         if (!new) return 0;
2422                 } 
2423         } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2424                         ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2425                 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2426                    if there is a request that matches */
2427                 listGraph = g_list_first(tapinfo->graph_analysis->list);
2428                 while (listGraph)
2429                 {
2430                         gai = listGraph->data;
2431                         if (gai->frame_num == pi->req_num){
2432                                 /* there is a request that match, so look the associated call with this call_num */
2433                                 list = g_list_first(tapinfo->callsinfo_list);
2434                                 while (list)
2435                                 {
2436                                         tmp_listinfo=list->data;
2437                                         if (tmp_listinfo->protocol == VOIP_MGCP){
2438                                                 if (tmp_listinfo->call_num == gai->conv_num){
2439                                                         tmp_mgcpinfo = tmp_listinfo->prot_info;
2440                                                         callsinfo = (voip_calls_info_t*)(list->data);
2441                                                         break;
2442                                                 }
2443                                         }
2444                                         list = g_list_next (list);
2445                                 }
2446                                 if (callsinfo != NULL) break;
2447                         }
2448                         listGraph = g_list_next(listGraph);
2449                 }
2450                 /* if there is not a matching request, just return */
2451                 if (callsinfo == NULL) return 0;
2452         } else return 0;
2453
2454         /* not in the list? then create a new entry */
2455         if (callsinfo==NULL){
2456                 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2457                 callsinfo->call_active_state = VOIP_ACTIVE;
2458                 callsinfo->call_state = VOIP_CALL_SETUP;
2459                 if (fromEndpoint) {
2460                         callsinfo->from_identity=g_strdup(pi->endpointId);
2461                         callsinfo->to_identity=g_strdup("");
2462                 } else {
2463                         callsinfo->from_identity=g_strdup("");
2464                         callsinfo->to_identity=g_strdup(pi->endpointId);
2465                 }
2466                 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
2467                 callsinfo->first_frame_num=pinfo->fd->num;
2468                 callsinfo->selected=FALSE;
2469                 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2470                 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2471                 callsinfo->protocol=VOIP_MGCP;
2472                 callsinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2473                 callsinfo->free_prot_info = g_free;
2474                 tmp_mgcpinfo=callsinfo->prot_info;
2475                 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2476                 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2477                 callsinfo->npackets = 0;
2478                 callsinfo->call_num = tapinfo->ncalls++;
2479                 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2480         }
2481
2482         g_assert(tmp_mgcpinfo != NULL);
2483
2484         /* change call state and add to graph */
2485         switch (pi->mgcp_type)
2486         {
2487         case MGCP_REQUEST:
2488                 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2489                         frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2490
2491                         if (tmp_mgcpinfo->fromEndpoint){
2492                                 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2493                                 if (callsinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(callsinfo->to_identity));
2494
2495                         /* from MGC and the user picked up, the call is connected */
2496                         } else if (isSignal("hd", pi->observedEvents))  
2497                                 callsinfo->call_state=VOIP_IN_CALL;
2498
2499                         /* hung up signal */
2500                         if (isSignal("hu", pi->observedEvents)) {
2501                                 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2502                                         callsinfo->call_state = VOIP_CANCELLED;
2503                                 } else {
2504                                         callsinfo->call_state = VOIP_COMPLETED;
2505                                 }
2506                         }       
2507                         
2508                 } else if (strcmp(pi->code, "RQNT") == 0) {
2509                         /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2510                         if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (callsinfo->call_state == VOIP_RINGING) ) { 
2511                                         callsinfo->call_state = VOIP_IN_CALL;
2512                         }
2513
2514                         /* if there is ringback or ring tone, change state to ringing */
2515                         if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) { 
2516                                         callsinfo->call_state = VOIP_RINGING;
2517                         }
2518
2519                         /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2520                         if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state = VOIP_RINGING)) ) { 
2521                                         callsinfo->call_state = VOIP_REJECTED;
2522                         }
2523
2524                         if (pi->signalReq != NULL)
2525                                 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2526                         else
2527                                 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2528                         
2529                         /* use the CallerID info to fill the "From" for the call */
2530                         if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(callsinfo->from_identity));
2531
2532                 } else if (strcmp(pi->code, "DLCX") == 0) {
2533                         /*
2534                           if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2535                           the DLCX as the end of the call
2536                         */
2537                         if (!tmp_mgcpinfo->fromEndpoint){
2538                                 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2539                                         callsinfo->call_state = VOIP_CANCELLED;
2540                                 } 
2541                         } 
2542                 }
2543
2544                 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
2545                 break;
2546         case MGCP_RESPONSE:
2547                 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2548                 break;
2549         case MGCP_OTHERS:
2550                 /* XXX what to do? */
2551                 break;
2552         }
2553
2554
2555         comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2556
2557         callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2558         callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2559         callsinfo->last_frame_num=pinfo->fd->num;
2560         ++(callsinfo->npackets);
2561         /* increment the packets counter of all calls */
2562         ++(tapinfo->npackets);
2563
2564         /* add to the graph */
2565         add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);  
2566         g_free(comment);
2567         g_free(frame_label);
2568
2569         /* add SDP info if apply */
2570         if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2571                         append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2572                         g_free(sdp_summary);
2573                         sdp_summary = NULL;
2574         }
2575
2576         tapinfo->redraw = TRUE;
2577
2578         return 1;  /* refresh output */
2579 }
2580
2581
2582 /****************************************************************************/
2583 /* TAP INTERFACE */
2584 /****************************************************************************/
2585 static gboolean have_MGCP_tap_listener=FALSE;
2586 /****************************************************************************/
2587 void
2588 mgcp_calls_init_tap(void)
2589 {
2590         GString *error_string;
2591
2592         if(have_MGCP_tap_listener==FALSE)
2593         {
2594                 /* don't register tap listener, if we have it already */
2595                 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2596                 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
2597                         voip_calls_dlg_reset, 
2598                         MGCPcalls_packet, 
2599                         voip_calls_dlg_draw
2600                         );
2601                 if (error_string != NULL) {
2602                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2603                                       error_string->str);
2604                         g_string_free(error_string, TRUE);
2605                         exit(1);
2606                 }
2607                 have_MGCP_tap_listener=TRUE;
2608         }
2609 }
2610
2611 /****************************************************************************/
2612 void
2613 remove_tap_listener_mgcp_calls(void)
2614 {
2615         protect_thread_critical_region();
2616         remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2617         unprotect_thread_critical_region();
2618
2619         have_MGCP_tap_listener=FALSE;
2620 }
2621
2622
2623 /****************************************************************************/
2624 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2625 /****************************************************************************/
2626
2627 /* whenever a ACTRACE packet is seen by the tap listener */
2628 static int 
2629 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2630 {
2631         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2632         const actrace_info_t *pi = ACTRACEinfo;
2633         GList *list;
2634         actrace_cas_calls_info_t *tmp_actrace_cas_info;
2635         voip_calls_info_t *tmp_listinfo;
2636         voip_calls_info_t *callsinfo = NULL;
2637
2638
2639         actrace_frame_num = pinfo->fd->num;
2640         actrace_trunk = pi->trunk;
2641         actrace_direction = pi->direction;
2642
2643         if (pi->type == 1){ /* is CAS protocol */
2644                 address pstn_add;
2645                 gchar *comment = NULL;
2646
2647                 callsinfo = NULL;
2648                 list = g_list_first(tapinfo->callsinfo_list);
2649                 while (list)
2650                 {
2651                         tmp_listinfo=list->data;
2652                         if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2653                                 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2654                                 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2655                                 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2656                                         callsinfo = (voip_calls_info_t*)(list->data);
2657                                         break;
2658                                 }
2659                         }
2660                         list = g_list_next (list);
2661                 }
2662
2663                 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
2664
2665                 /* if it is a new call, add it to the list */
2666                 if (!callsinfo) {
2667                         callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2668                         callsinfo->call_active_state = VOIP_ACTIVE;
2669                         callsinfo->call_state = VOIP_CALL_SETUP;
2670                         callsinfo->from_identity=g_strdup("N/A");
2671                         callsinfo->to_identity=g_strdup("N/A");
2672                         COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2673                         callsinfo->first_frame_num=pinfo->fd->num;
2674                         callsinfo->selected=FALSE;
2675                         callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2676                         callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2677                         callsinfo->protocol=VOIP_AC_CAS;
2678                         callsinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2679                         callsinfo->free_prot_info = g_free;
2680                         
2681                         tmp_actrace_cas_info=callsinfo->prot_info;
2682                         tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2683                         tmp_actrace_cas_info->trunk=actrace_trunk;
2684                         callsinfo->npackets = 0;
2685                         callsinfo->call_num = tapinfo->ncalls++;
2686                         tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2687                 }
2688
2689                 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2690                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2691                 callsinfo->last_frame_num=pinfo->fd->num;
2692                 ++(callsinfo->npackets);
2693                 /* increment the packets counter of all calls */
2694                 ++(tapinfo->npackets);
2695
2696                 if (!comment)
2697                         comment = g_strdup_printf("AC_CAS  trunk:%u", actrace_trunk );
2698
2699                 add_to_graph(tapinfo, pinfo, pi->cas_frame_label , comment, callsinfo->call_num, 
2700                                 actrace_direction?&pstn_add:&(pinfo->src),
2701                                 actrace_direction?&(pinfo->src):&pstn_add,
2702                                 1 );
2703
2704                 g_free(comment);
2705                 g_free((char *)pstn_add.data);
2706         }
2707
2708         tapinfo->redraw = TRUE;
2709
2710         return 1;  /* refresh output */
2711 }
2712
2713
2714 /****************************************************************************/
2715 /* TAP INTERFACE */
2716 /****************************************************************************/
2717 static gboolean have_actrace_tap_listener=FALSE;
2718 /****************************************************************************/
2719 void
2720 actrace_calls_init_tap(void)
2721 {
2722         GString *error_string;
2723
2724         if(have_actrace_tap_listener==FALSE)
2725         {
2726                 /* don't register tap listener, if we have it already */
2727                 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2728                         voip_calls_dlg_reset, 
2729                         ACTRACEcalls_packet, 
2730                         voip_calls_dlg_draw
2731                         );
2732                         
2733                 if (error_string != NULL) {
2734                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2735                                       error_string->str);
2736                         g_string_free(error_string, TRUE);
2737                         exit(1);
2738                 }
2739                 have_actrace_tap_listener=TRUE;
2740         }
2741 }
2742
2743 /****************************************************************************/
2744 void
2745 remove_tap_listener_actrace_calls(void)
2746 {
2747         protect_thread_critical_region();
2748         remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2749         unprotect_thread_critical_region();
2750
2751         have_actrace_tap_listener=FALSE;
2752 }
2753
2754
2755
2756
2757
2758 /**************************** TAP for H248/MEGACO **********************************/
2759 static gboolean have_h248_tap_listener = FALSE;
2760 static gboolean have_megaco_tap_listener = FALSE;
2761
2762 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
2763                                                         type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
2764                                                         type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
2765                                                         type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
2766
2767 static int h248_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2768         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2769         const gcp_cmd_t* cmd = prot_info;
2770         GList* list;
2771         voip_calls_info_t *callsinfo = NULL;
2772         address* mgw;
2773         address* mgc;
2774         gchar mgw_addr[128];
2775         
2776         if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
2777                 return 0;
2778         }
2779         
2780         if ( gcp_is_req(cmd->type) ) {
2781                 mgw = &(pinfo->dst);
2782                 mgc = &(pinfo->src);
2783         } else {
2784                 mgc = &(pinfo->dst);
2785                 mgw = &(pinfo->src);
2786         }
2787         
2788         address_to_str_buf(mgw, mgw_addr, 128);
2789         
2790         /* check whether we already have this context in the list */
2791         list = g_list_first(tapinfo->callsinfo_list);
2792         while (list)
2793         {
2794                 voip_calls_info_t* tmp_listinfo = list->data;
2795                 
2796                 if (tmp_listinfo->protocol == TEL_H248){
2797                         if (tmp_listinfo->prot_info == cmd->ctx){
2798                                 callsinfo = (voip_calls_info_t*)(list->data);
2799                                 break;
2800                         }
2801                 }
2802                 list = g_list_next (list);
2803         }
2804         
2805         if (callsinfo==NULL){
2806                         
2807                 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2808                 callsinfo->call_state = VOIP_NO_STATE;
2809                 callsinfo->call_active_state = VOIP_ACTIVE;
2810                 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
2811                 callsinfo->to_identity = g_strdup("");
2812                 callsinfo->prot_info = cmd->ctx;
2813                 callsinfo->free_prot_info = NULL;
2814                                 
2815                 callsinfo->npackets = 1;
2816                 callsinfo->first_frame_num=pinfo->fd->num;
2817                 callsinfo->last_frame_num=pinfo->fd->num;
2818
2819                 COPY_ADDRESS(&(callsinfo->initial_speaker), mgc);
2820         
2821                 callsinfo->protocol = TEL_H248;
2822                 callsinfo->call_num = tapinfo->ncalls++;
2823                 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2824                 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2825                 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2826                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2827
2828                 callsinfo->selected = FALSE;
2829                 
2830                 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2831
2832         } else {
2833                 GString* s = g_string_new("");
2834                 gcp_terms_t *ctx_term;
2835
2836                 g_free(callsinfo->from_identity);
2837                 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)callsinfo->prot_info)->id);
2838
2839                 g_free(callsinfo->to_identity);
2840
2841                 for (ctx_term = ((gcp_ctx_t*)callsinfo->prot_info)->terms.next;
2842                          ctx_term;
2843                          ctx_term = ctx_term->next ) {
2844                         if ( ctx_term->term && ctx_term->term->str) {
2845                                 g_string_sprintfa(s," %s",ctx_term->term->str);
2846                         }
2847                 }
2848                 
2849                 callsinfo->to_identity = s->str;
2850                 g_string_free(s,FALSE);
2851                 
2852                 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2853                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2854                 callsinfo->last_frame_num=pinfo->fd->num;
2855                 ++(callsinfo->npackets);
2856         }
2857         
2858         add_to_graph(tapinfo, pinfo, cmd->str ? cmd->str : "unknown Msg",
2859                                  ep_strdup_printf("TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
2860                                  callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2861         
2862         ++(tapinfo->npackets);
2863
2864         tapinfo->redraw = TRUE;
2865         
2866         return 1;
2867 }
2868
2869 void h248_calls_init_tap(void)
2870 {
2871         GString *error_string;
2872         
2873         
2874         if(have_megaco_tap_listener==FALSE)
2875         {
2876                 error_string = register_tap_listener("megaco", &(the_tapinfo_struct.megaco_dummy),
2877                                                                                          NULL,
2878                                                                                          voip_calls_dlg_reset,
2879                                                                                          h248_calls_packet,
2880                                                                                          voip_calls_dlg_draw);
2881                 
2882                 if (error_string != NULL) {
2883                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2884                                                   error_string->str);
2885                         g_string_free(error_string, TRUE);
2886                         exit(1);
2887                 }
2888                 
2889                 have_megaco_tap_listener=TRUE;
2890         }
2891         
2892         if(have_h248_tap_listener==FALSE)
2893         {
2894                 error_string = register_tap_listener("h248", &(the_tapinfo_struct.h248_dummy),
2895                                                                                          NULL,
2896                                                                                          voip_calls_dlg_reset,
2897                                                                                          h248_calls_packet,
2898                                                                                          voip_calls_dlg_draw);
2899                 
2900                 if (error_string != NULL) {
2901                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2902                                                   error_string->str);
2903                         g_string_free(error_string, TRUE);
2904                         exit(1);
2905                 }
2906                 
2907                 have_h248_tap_listener=TRUE;
2908         }
2909 }
2910
2911 void
2912 remove_tap_listener_h248_calls(void)
2913 {
2914         protect_thread_critical_region();
2915         remove_tap_listener(&(the_tapinfo_struct.h248_dummy));
2916         remove_tap_listener(&(the_tapinfo_struct.megaco_dummy));
2917         unprotect_thread_critical_region();
2918         
2919         have_megaco_tap_listener=FALSE;
2920         have_h248_tap_listener=FALSE;
2921 }
2922
2923
2924 /**************************** TAP for SCCP and SUA **********************************/
2925 /**************************** ( RANAP and BSSAP ) **********************************/
2926 static gboolean have_sccp_tap_listener = FALSE;
2927 static gboolean have_sua_tap_listener = FALSE;
2928
2929 static const voip_protocol sccp_proto_map[] = {
2930         TEL_SCCP,
2931         TEL_BSSMAP,
2932         TEL_RANAP
2933 };
2934 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
2935 const value_string* sccp_payload_values;
2936
2937 static int sccp_calls(packet_info *pinfo, const void *prot_info) {
2938         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2939         const sccp_msg_info_t* msg = prot_info;
2940         sccp_assoc_info_t* assoc = msg->data.co.assoc;
2941         GList* list;
2942         voip_calls_info_t *callsinfo = NULL;
2943         const gchar* label = NULL;
2944         const gchar* comment = NULL;
2945         /* check whether we already have this assoc in the list */
2946
2947         for(list = g_list_first(tapinfo->callsinfo_list) ; list ; list = g_list_next (list) ) {
2948                 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ){
2949                                 callsinfo = (voip_calls_info_t*)(list->data);
2950                                 break;
2951                 }
2952         }
2953         
2954         if (callsinfo==NULL){
2955                 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2956                 callsinfo->call_state = VOIP_CALL_SETUP;
2957                 callsinfo->call_active_state = VOIP_ACTIVE;
2958                 if ( assoc->calling_party ) {
2959                         callsinfo->from_identity =  g_strdup(assoc->calling_party);
2960                 } else {
2961                         callsinfo->from_identity =  g_strdup("Unknown");
2962                 }
2963                 
2964                 if ( assoc->called_party ) {
2965                         callsinfo->to_identity =  g_strdup(assoc->called_party);
2966                 } else {
2967                         callsinfo->to_identity =  g_strdup("Unknown");
2968                 }
2969                 
2970                 callsinfo->prot_info = (void*)assoc;
2971                 callsinfo->free_prot_info = NULL;
2972                 
2973                 callsinfo->npackets = 1;
2974                 callsinfo->first_frame_num=pinfo->fd->num;
2975                 callsinfo->last_frame_num=pinfo->fd->num;
2976                 
2977                 COPY_ADDRESS(&(callsinfo->initial_speaker), &(pinfo->src));
2978                 
2979                 callsinfo->protocol =   SP2VP(assoc->payload);
2980                 callsinfo->start_sec=(gint32) pinfo->fd->rel_ts.secs;
2981                 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2982                 callsinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
2983                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2984                 
2985                 callsinfo->selected = FALSE;
2986                 callsinfo->call_num = tapinfo->ncalls++;
2987                                 
2988                 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2989         } else {
2990                 
2991                 if ( assoc->calling_party ) {
2992                         if (callsinfo->from_identity) g_free(callsinfo->from_identity );
2993                         callsinfo->from_identity =  g_strdup(assoc->calling_party);
2994                 }
2995                 
2996                 if ( assoc->called_party ) {
2997                         if (callsinfo->to_identity) g_free(callsinfo->to_identity );
2998                         callsinfo->to_identity =  g_strdup(assoc->called_party);
2999                 }
3000                 
3001                 callsinfo->protocol =  SP2VP(assoc->payload);
3002                 callsinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
3003                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3004                 callsinfo->last_frame_num=pinfo->fd->num;
3005                 ++(callsinfo->npackets);
3006                 
3007                 switch (msg->type) {
3008                         case SCCP_MSG_TYPE_CC:
3009                                 callsinfo->call_state = VOIP_IN_CALL;
3010                                 break;
3011                         case SCCP_MSG_TYPE_RLC:
3012                                 callsinfo->call_state = VOIP_COMPLETED;
3013                                 callsinfo->call_active_state = VOIP_INACTIVE;
3014                                 break;
3015                         default:
3016                                 break;
3017                 }
3018         }
3019         
3020         if (msg->data.co.label) {
3021                 label = msg->data.co.label;
3022         } else {
3023                 label = val_to_str(msg->type, sccp_payload_values, "Unknown(%d)");
3024         }
3025         
3026         if (msg->data.co.comment) {
3027                 comment = msg->data.co.comment;
3028         } else {
3029                 comment = "";
3030         }
3031         
3032         add_to_graph(tapinfo, pinfo, label,(void*) comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3033         
3034         ++(tapinfo->npackets);
3035
3036         tapinfo->redraw = TRUE;
3037         
3038         return 1;
3039 }
3040
3041 static int sccp_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3042         sccp_payload_values = sccp_message_type_acro_values;
3043         return sccp_calls(pinfo, prot_info);
3044 }
3045
3046
3047 static int sua_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3048         sccp_payload_values = sua_co_class_type_acro_values;
3049         return sccp_calls(pinfo, prot_info);
3050 }
3051
3052
3053 void sccp_calls_init_tap(void)
3054 {
3055         GString *error_string;
3056         
3057         if(have_sccp_tap_listener==FALSE)
3058         {
3059                 error_string = register_tap_listener("sccp", &(the_tapinfo_struct.sccp_dummy),
3060                                                                                          NULL,
3061                                                                                          voip_calls_dlg_reset,
3062                                                                                          sccp_calls_packet,
3063                                                                                          voip_calls_dlg_draw);
3064                 
3065                 if (error_string != NULL) {
3066                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3067                                                   error_string->str);
3068                         g_string_free(error_string, TRUE);
3069                         exit(1);
3070                 }
3071                 
3072                 have_sccp_tap_listener=TRUE;
3073         }
3074
3075         if(have_sua_tap_listener==FALSE)
3076         {
3077                 error_string = register_tap_listener("sua", &(the_tapinfo_struct.sua_dummy),
3078                                                                                          NULL,
3079                                                                                          voip_calls_dlg_reset,
3080                                                                                          sua_calls_packet,
3081                                                                                          voip_calls_dlg_draw);
3082                 
3083                 if (error_string != NULL) {
3084                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3085                                                   error_string->str);
3086                         g_string_free(error_string, TRUE);
3087                         exit(1);
3088                 }
3089                 
3090                 have_sua_tap_listener=TRUE;
3091         }
3092         
3093 }
3094
3095 void
3096 remove_tap_listener_sccp_calls(void)
3097 {
3098         protect_thread_critical_region();
3099         remove_tap_listener(&(the_tapinfo_struct.sccp_dummy));
3100         unprotect_thread_critical_region();
3101         
3102         have_sccp_tap_listener=FALSE;
3103         have_sua_tap_listener=FALSE;
3104 }
3105
3106
3107 /****************************************************************************/
3108 /****************************TAP for UNISTIM ********************************/
3109 /****************************************************************************/
3110
3111 static int 
3112 unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
3113 {
3114         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3115         voip_calls_info_t *tmp_listinfo;
3116         voip_calls_info_t *callsinfo = NULL;
3117         unistim_info_t *tmp_unistim_info = NULL;
3118         GList *list = NULL;
3119         GString *g_tmp = NULL;
3120         gchar *frame_label = NULL;
3121         gchar *comment = NULL;
3122         
3123         /* Fetch specific packet infos */
3124         const unistim_info_t *pi = unistim_info;
3125
3126         /* Init gstring */
3127         g_tmp = g_string_new(NULL);
3128
3129         /* Check to see if this is a dup */
3130         list = g_list_first(tapinfo->callsinfo_list);
3131
3132         while(list)
3133         {
3134                 tmp_listinfo = list->data;
3135
3136                 if(tmp_listinfo->protocol == VOIP_UNISTIM){
3137
3138                         tmp_unistim_info = tmp_listinfo->prot_info;
3139
3140                         /* Search by termid if possible, otherwise use ni/it ip + port.. */
3141                         if(pi->termid != 0){
3142                                 if(tmp_unistim_info->termid == pi->termid){
3143                                         /* If the call has ended, then we can reuse it.. */
3144                                         if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3145                                                 /* Do nothing */
3146                                         } else {
3147                                                 callsinfo = (voip_calls_info_t*)(list->data);
3148                                                 break;
3149                                         }
3150                                 }
3151                         } else {
3152                                 /* If no term id use ips / port to find entry */
3153                                 if(ADDRESSES_EQUAL(&tmp_unistim_info->it_ip, &pinfo->dst) && ADDRESSES_EQUAL(&tmp_unistim_info->ni_ip,&pinfo->src) && (tmp_unistim_info->it_port == pinfo->destport)){
3154                                         if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3155                                                 /* Do nothing previous call */
3156                                         } else {
3157                                                 callsinfo = (voip_calls_info_t*)(list->data);
3158                                                 break;
3159                                         }
3160                                 } 
3161                                 else if(ADDRESSES_EQUAL(&tmp_unistim_info->it_ip, &pinfo->src) && ADDRESSES_EQUAL(&tmp_unistim_info->ni_ip,&pinfo->dst) && (tmp_unistim_info->it_port == pinfo->srcport)) {
3162                                         if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3163                                                 /* Do nothing, it ain't our call.. */
3164                                         } else {
3165                                                 callsinfo = (voip_calls_info_t*)(list->data);
3166                                                 break;
3167                                         }
3168                                 }
3169                         }
3170                 }
3171                 
3172                 /* Otherwise, go to the next one.. */
3173                 list = g_list_next(list);
3174         }
3175
3176         if(pi->payload_type == 2 || pi->payload_type == 1){
3177
3178                 if(pi->key_state == 1 || pi->hook_state == 1){
3179
3180                         /* If the user hits a button, 
3181                            Session will be SETUP */
3182
3183                         /* If new add to list */
3184                         if (callsinfo==NULL){
3185
3186                                 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3187                                 callsinfo->call_active_state = VOIP_ACTIVE;
3188                                 callsinfo->call_state = VOIP_CALL_SETUP;
3189                                 callsinfo->from_identity=g_strdup_printf("%x",pi->termid);
3190                                 callsinfo->to_identity=g_strdup_printf("UNKNOWN");
3191                                 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3192                                 callsinfo->first_frame_num=pinfo->fd->num;
3193                                 callsinfo->selected=FALSE;
3194                                 
3195                                 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3196                                 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3197                                 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3198                                 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3199                                                 
3200                                 callsinfo->protocol=VOIP_UNISTIM;
3201                                 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3202                                 
3203                                 tmp_unistim_info = callsinfo->prot_info;
3204                                 
3205                                 /* Clear tap struct */
3206                                 tmp_unistim_info->rudp_type = 0;
3207                                 tmp_unistim_info->payload_type = 0;
3208                                 tmp_unistim_info->sequence = pi->sequence;
3209                                 tmp_unistim_info->termid = pi->termid;
3210                                 tmp_unistim_info->key_val = -1;
3211                                 tmp_unistim_info->key_state = -1;
3212                                 tmp_unistim_info->hook_state = -1;
3213                                 tmp_unistim_info->stream_connect = -1;
3214                                 tmp_unistim_info->trans_connect = -1;
3215                                 tmp_unistim_info->set_termid = -1;
3216                                 tmp_unistim_info->string_data = NULL;
3217                                 tmp_unistim_info->key_buffer = NULL;
3218                                 
3219                                 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3220                                 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3221                                 tmp_unistim_info->it_port = pi->it_port;
3222
3223                                 callsinfo->free_prot_info = g_free;
3224                                 callsinfo->npackets = 0;
3225                                 callsinfo->call_num = tapinfo->ncalls++;
3226                                 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3227
3228                         } else {
3229
3230                                 /* Set up call wide info struct */
3231                                 tmp_unistim_info = callsinfo->prot_info;
3232                                 tmp_unistim_info->sequence = pi->sequence;
3233                         }
3234
3235                         /* Each packet COULD BE OUR LAST!!!! */
3236                         callsinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3237                         callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3238                         callsinfo->last_frame_num=pinfo->fd->num;
3239
3240                         /* This is a valid packet so increment counter */
3241                         ++(callsinfo->npackets);
3242                         
3243                         /* increment the packets counter of all calls */
3244                         ++(tapinfo->npackets);
3245                 
3246                         /* Key was depressed.. update key buffer.. */
3247                         if(pi->key_val >= 0 && pi->key_val <= 11){
3248
3249                                 if(tmp_unistim_info->key_buffer != NULL){
3250
3251                                         /* assign to temp variable */
3252                                         g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3253
3254                                         /* Manipulate the data */
3255                                         if(pi->key_val == 10) {
3256                                                 tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
3257                                         } else if(pi->key_val == 11) {
3258                                                 tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
3259                                         } else {
3260                                                 tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3261                                         }
3262
3263                                 } else {
3264
3265                                         /* Create new string */
3266                                         if(pi->key_val == 10) {
3267                                                 tmp_unistim_info->key_buffer = g_strdup_printf("*");
3268                                         } else if(pi->key_val == 11) {
3269                                                 tmp_unistim_info->key_buffer = g_strdup_printf("#");
3270                                         } else {
3271                                                 tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
3272                                         }
3273
3274                                 }
3275
3276                                 /* Select for non-digit characters */
3277                                 if(pi->key_val == 10) {
3278                                         comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3279                                 } else if(pi->key_val == 11) {
3280                                         comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3281                                 } else {
3282                                         comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3283                                 }
3284                         } else if(pi->key_val == 12) {
3285                                 /* Set label and comment for graph */
3286                                 comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3287                         } else if(pi->key_val == 13) {
3288                                 /* Set label and comment for graph */
3289                                 comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3290                         } else if(pi->key_val == 14) {
3291                                 /* Set label and comment for graph */
3292                                 comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3293                         } else if(pi->key_val == 15) {
3294                                 if(pi->key_buffer != NULL){
3295                                         /* Get data */
3296                                         g_string_assign(g_tmp,pi->key_buffer);
3297
3298                                         /* Manipulate the data */
3299                                         g_string_truncate(g_tmp,g_tmp->len-1);
3300                                         
3301                                         /* Insert new data */
3302                                         tmp_unistim_info->key_buffer = g_strdup_printf("%s",g_tmp->str);
3303                                 }
3304
3305                                 /* Set label and comment for graph */
3306                                 comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3307                         } else if(pi->key_val == 20) {
3308                                 /* User pressed the soft key 0 probably dial */
3309                                 comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3310                         } else if(pi->key_val == 21) {
3311                                 /* User pressed the soft key 1 */
3312                                 comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3313                         } else if(pi->key_val == 22) {
3314                                 /* User pressed the soft key 2 */
3315                                 /* On cs2k phones, soft key 2 is backspace. */
3316                                 if(pi->key_buffer != NULL) {
3317                                         
3318                                         /* Get data */
3319                                         g_string_assign(g_tmp,pi->key_buffer);
3320
3321                                         /* Manipulate the data */
3322                                         g_string_truncate(g_tmp,g_tmp->len-1);
3323                                         
3324                                         /* Insert new data */
3325                                         tmp_unistim_info->key_buffer = g_strdup_printf("%s",g_tmp->str);
3326                                 }
3327                                 
3328                                 /* add label and comment */
3329                                 comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3330                         } else if(pi->key_val == 28) {
3331                                 /* User pressed something */
3332                                 comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3333                         } else if(pi->key_val == 23) {
3334                                 /* User pressed the soft key 3 */
3335                                 /* Cancel on cs2k so clear buffer */
3336                                 /* On mcs its config which will clear the buffer too */
3337                                 tmp_unistim_info->key_buffer = g_strdup_printf("\n");
3338
3339                                 /* User pressed something, set labels*/
3340                                 comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3341                         } else if(pi->key_val == 27) {
3342                                 /* User pressed something */
3343                                 comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3344                         } else if(pi->key_val == 29) {
3345                                 /* User pressed something */
3346                                 comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3347                         } else if(pi->key_val == 30) {
3348                                 /* User pressed something */
3349                                 comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3350                         } else if(pi->key_val == 31) {
3351                                 /* Handsfree button */
3352                                 comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3353                         } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3354                                 /* Prog. Key X */
3355                                 comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3356                         }
3357
3358                         if(pi->key_val != -1) {
3359
3360                                 frame_label = g_strdup_printf("KEY INPUT");
3361
3362                                 if (comment == NULL)
3363                                         /* Ouch! What do you do!? */
3364                                         /* User pressed something */
3365                                         comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3366
3367                                 /* add to the graph */
3368                                 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3369
3370                         }
3371
3372                         if(pi->hook_state == 1) {
3373
3374                                 /* Phone is off hook */
3375                                 frame_label = g_strdup_printf("OFF HOOK");
3376                                 comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
3377
3378                                 /* add to the graph */
3379                                 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);  
3380                         } else if(pi->hook_state == 0) {
3381
3382                                 /* Phone is on hook */
3383                                 frame_label = g_strdup_printf("ON HOOK");
3384                                 comment = g_strdup_printf("On Hook (%d)", pi->sequence);
3385
3386                                 /* add to the graph */
3387                                 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);  
3388                         }
3389
3390                 }
3391
3392                 /* Open stream was sent from server */
3393                 if(pi->stream_connect == 1 && callsinfo != NULL) {
3394
3395                         /* Open stream */       
3396                         /* Signifies the start of the call so set start_sec & start_usec */
3397                         callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3398                         callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3399                         
3400                         /* Local packets too */
3401                         ++(callsinfo->npackets);
3402
3403                         /* increment the packets counter of all calls */
3404                         ++(tapinfo->npackets);
3405
3406                         /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3407                            Call control protocol, we can only guess at the destination by messing with 
3408                            key buffers. */
3409                         if(tmp_unistim_info->key_buffer != NULL){
3410                                 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3411                         }
3412
3413                         /* change sequence number for ACK detection */
3414                         tmp_unistim_info->sequence = pi->sequence;
3415         
3416                         /* State changes too */
3417                         callsinfo->call_active_state = VOIP_ACTIVE;
3418                         callsinfo->call_state = VOIP_IN_CALL;
3419
3420                         /* Add graph data */
3421                         frame_label = g_strdup_printf("STREAM OPENED");
3422                         comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3423
3424                         /* add to the graph */
3425                         add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);  
3426
3427                         /* Redraw the scree */
3428                         tapinfo->redraw = TRUE;
3429                         return 1;
3430
3431                 } else if(pi->stream_connect == 1 && callsinfo == NULL) {
3432                 
3433                         /* Research indicates some nortel products initiate stream first
3434                          * without keypresses. therefore creating this solely on a keypress is 
3435                          * ineffective.
3436                          * Sometimes calls start immediately with open stream.
3437                          */
3438                         callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3439                         callsinfo->call_active_state = VOIP_ACTIVE;
3440                         callsinfo->call_state = VOIP_CALL_SETUP;
3441                         callsinfo->from_identity=g_strdup_printf("UNKNOWN");
3442                         callsinfo->to_identity=g_strdup_printf("UNKNOWN");
3443                         COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3444                         callsinfo->first_frame_num=pinfo->fd->num;
3445                         callsinfo->selected=FALSE;
3446                                 
3447                         /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3448                         /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3449                         callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3450                         callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3451                                         
3452                         callsinfo->protocol=VOIP_UNISTIM;
3453                         callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3454                         
3455                         tmp_unistim_info = callsinfo->prot_info;
3456                                 
3457                         /* Clear tap struct */
3458                         tmp_unistim_info->rudp_type = 0;
3459                         tmp_unistim_info->payload_type = 0;
3460                         tmp_unistim_info->sequence = pi->sequence;
3461                         tmp_unistim_info->termid = 0;
3462                         tmp_unistim_info->key_val = -1;
3463                         tmp_unistim_info->key_state = -1;
3464                         tmp_unistim_info->hook_state = -1;
3465                         tmp_unistim_info->stream_connect = -1;
3466                         tmp_unistim_info->trans_connect = -1;
3467                         tmp_unistim_info->set_termid = -1;
3468                         tmp_unistim_info->string_data = NULL;
3469                         tmp_unistim_info->key_buffer = NULL;
3470                                 
3471                         COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3472                         COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3473                         tmp_unistim_info->it_port = pi->it_port;
3474
3475                         callsinfo->free_prot_info = g_free;
3476                         callsinfo->npackets = 0;
3477                         callsinfo->call_num = tapinfo->ncalls++;
3478                         tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3479
3480                                 /* Open stream */       
3481                         /* Signifies the start of the call so set start_sec & start_usec */
3482                         callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3483                         callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3484                         
3485                         /* Local packets too */
3486                         ++(callsinfo->npackets);
3487
3488                         /* increment the packets counter of all calls */
3489                         ++(tapinfo->npackets);
3490
3491                         /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3492                            Call control protocol, we can only guess at the destination by messing with 
3493                            key buffers. */
3494                         if(tmp_unistim_info->key_buffer != NULL){
3495                                 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3496                         }
3497
3498                         /* change sequence number for ACK detection */
3499                         tmp_unistim_info->sequence = pi->sequence;
3500         
3501                         /* State changes too */
3502                         callsinfo->call_active_state = VOIP_ACTIVE;
3503                         callsinfo->call_state = VOIP_IN_CALL;
3504
3505                         /* Add graph data */
3506                         frame_label = g_strdup_printf("STREAM OPENED");
3507                         comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3508
3509                         /* add to the graph */
3510                         add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3511
3512                         /* Redraw the scree */
3513                         tapinfo->redraw = TRUE;
3514                         return 1;
3515
3516
3517                 } else if(pi->stream_connect == 0 && callsinfo != NULL) {
3518                         /* Close Stream */
3519                         
3520                         /* Set stop seconds + usec */
3521                         callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3522                         callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3523                         callsinfo->last_frame_num=pinfo->fd->num;
3524                         
3525                         tmp_unistim_info->sequence = pi->sequence;
3526                         
3527                         if(callsinfo->call_state == VOIP_IN_CALL){
3528                                 callsinfo->call_active_state = VOIP_INACTIVE;
3529                                 callsinfo->call_state = VOIP_COMPLETED;
3530                         } else {
3531                                 callsinfo->call_state = VOIP_UNKNOWN;
3532                                 callsinfo->call_active_state = VOIP_INACTIVE;
3533                         }
3534                                 
3535                         frame_label = g_strdup_printf("STREAM CLOSED");
3536                         comment = g_strdup_printf("Stream Closed (%d)",pi->sequence);
3537
3538                         /* add to the graph */
3539                         add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3540
3541                 }
3542
3543         } else if(pi->rudp_type == 1 && callsinfo != NULL) {
3544                 /* ACK */
3545                 /* Only show acks for processed seq #s */
3546                 if(tmp_unistim_info->sequence == pi->sequence) {
3547
3548                         frame_label = g_strdup_printf("ACK");
3549                         comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
3550
3551                         /* add to the graph */
3552                         add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3553
3554                 }
3555
3556         } else if(pi->rudp_type == 0 && callsinfo != NULL) {
3557                 
3558                 /* NAK */
3559                 frame_label = g_strdup_printf("NAK");
3560                 comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
3561
3562                 /* add to the graph */
3563                 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3564
3565         }
3566         
3567         /* free dataz */
3568         g_free(frame_label);
3569         g_free(comment);
3570         
3571         tapinfo->redraw = TRUE;
3572
3573         return 1;
3574 }
3575
3576 /****************************************************************************/
3577 /* TAP INTERFACE */
3578 /****************************************************************************/
3579 static gboolean have_unistim_tap_listener=FALSE;
3580 /****************************************************************************/
3581 void
3582 unistim_calls_init_tap(void){
3583
3584         GString *error_string;
3585
3586         if(have_unistim_tap_listener==FALSE) {
3587
3588                 error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
3589                         NULL,
3590                         voip_calls_dlg_reset,
3591                         unistim_calls_packet, 
3592                         voip_calls_dlg_draw
3593                         );
3594
3595                 if (error_string != NULL) {
3596                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3597                                       error_string->str);
3598                         g_string_free(error_string, TRUE);
3599                         exit(1);
3600                 }
3601
3602                 have_unistim_tap_listener=TRUE;
3603         }
3604 }
3605
3606 /****************************************************************************/
3607 void
3608 remove_tap_listener_unistim_calls(void)
3609 {
3610         protect_thread_critical_region();
3611         remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
3612         unprotect_thread_critical_region();
3613
3614         have_unistim_tap_listener=FALSE;
3615 }
3616
3617 /****************************************************************************/
3618 /* ***************************TAP for OTHER PROTOCOL **********************************/
3619 /****************************************************************************/
3620
3621 static int 
3622 VoIPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *VoIPinfo _U_)
3623 {
3624         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3625         voip_calls_info_t *callsinfo = NULL;
3626         voip_calls_info_t *tmp_listinfo;
3627         GList *list = NULL;
3628         const voip_packet_info_t *pi = VoIPinfo;
3629
3630         if (pi->call_id)
3631                 list = g_list_first(tapinfo->callsinfo_list);
3632         while (list) {
3633                 tmp_listinfo = list->data;
3634                 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
3635                         if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
3636                                 callsinfo = (voip_calls_info_t*)(list->data);
3637                                 break;
3638                         }
3639                 }
3640                 list = g_list_next(list);
3641         }
3642
3643         if (callsinfo == NULL) {
3644                 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3645                 callsinfo->call_active_state = pi->call_active_state;
3646                 callsinfo->call_state = pi->call_state;
3647                 callsinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
3648                 callsinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
3649                 callsinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
3650                 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3651                 callsinfo->selected=FALSE;
3652                 callsinfo->first_frame_num=pinfo->fd->num;
3653                 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3654                 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3655                 callsinfo->protocol=VOIP_COMMON;
3656                 callsinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
3657                 callsinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
3658                 callsinfo->prot_info=NULL;
3659                 callsinfo->free_prot_info = NULL;
3660                 
3661                 callsinfo->call_num = tapinfo->ncalls++;
3662                 callsinfo->npackets = 0;
3663                 
3664                 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);                            
3665         }
3666
3667         if (callsinfo != NULL) {
3668                 callsinfo->call_active_state = pi->call_active_state;
3669                 if ((callsinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
3670                         tapinfo->completed_calls++;
3671         if (pi->call_state != VOIP_NO_STATE)
3672                         callsinfo->call_state = pi->call_state;
3673                 callsinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3674                 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3675                 callsinfo->last_frame_num=pinfo->fd->num;
3676                 ++(callsinfo->npackets);
3677                 ++(tapinfo->npackets);
3678         }
3679
3680         /* add to the graph */
3681         add_to_graph(tapinfo, pinfo, (pi->frame_label)?pi->frame_label:"VoIP msg", (pi->frame_comment)?pi->frame_comment:"", callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3682
3683         tapinfo->redraw = TRUE;
3684
3685         return 1;
3686 }
3687 /****************************************************************************/
3688 static gboolean have_voip_tap_listener=FALSE;
3689
3690 void
3691 VoIPcalls_init_tap(void)
3692 {
3693         GString *error_string;
3694
3695         if(have_voip_tap_listener==FALSE)
3696         {
3697                 error_string = register_tap_listener("voip", &(the_tapinfo_struct.voip_dummy),
3698                         NULL,
3699                         voip_calls_dlg_reset,
3700                         VoIPcalls_packet, 
3701                         voip_calls_dlg_draw
3702                         );
3703
3704                 if (error_string != NULL) {
3705                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3706                                       error_string->str);
3707                         g_string_free(error_string, TRUE);
3708                         exit(1);
3709                 }
3710                 have_voip_tap_listener=TRUE;
3711         }
3712 }
3713 /****************************************************************************/
3714 void
3715 remove_tap_listener_voip_calls(void)
3716 {
3717         protect_thread_critical_region();
3718         remove_tap_listener(&(the_tapinfo_struct.voip_dummy));
3719         unprotect_thread_critical_region();
3720
3721         have_voip_tap_listener=FALSE;
3722 }
3723
3724
3725 /****************************************************************************/
3726 /* ***************************TAP for OTHER PROTOCOL **********************************/
3727 /****************************************************************************/
3728
3729 /****************************************************************************/
3730 /* whenever a prot_ packet is seen by the tap listener */
3731 /*
3732 static int 
3733 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
3734 {
3735         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3736         if (callsinfo!=NULL){
3737                 callsinfo->stop_sec=pinfo->fd->rel_secs;
3738                 callsinfo->stop_usec=pinfo->fd->rel_usecs;
3739                 callsinfo->last_frame_num=pinfo->fd->num;
3740                 ++(callsinfo->npackets);
3741                 ++(tapinfo->npackets);
3742         }
3743
3744         tapinfo->redraw = TRUE;
3745
3746         return 1;
3747 }
3748 */
3749 /****************************************************************************/
3750 /*
3751 static gboolean have_prot__tap_listener=FALSE;
3752
3753 void
3754 prot_calls_init_tap(void)
3755 {
3756         GString *error_string;
3757
3758         if(have_prot__tap_listener==FALSE)
3759         {
3760                 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
3761                         NULL,
3762                         voip_calls_dlg_reset,
3763                         prot__calls_packet, 
3764                         voip_calls_dlg_draw
3765                         );
3766
3767                 if (error_string != NULL) {
3768                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3769                                       error_string->str);
3770                         g_string_free(error_string, TRUE);
3771                         exit(1);
3772                 }
3773                 have_prot__tap_listener=TRUE;
3774         }
3775 }
3776 */
3777 /****************************************************************************/
3778 /*
3779 void
3780 remove_tap_listener_prot__calls(void)
3781 {
3782         protect_thread_critical_region();
3783         remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
3784         unprotect_thread_critical_region();
3785
3786         have_prot__tap_listener=FALSE;
3787 }
3788 */