From Alejandro Vaquero:
[obnox/wireshark/wip.git] / gtk / voip_calls.c
1 /* voip_calls.c
2  * VoIP calls summary addition for ethereal
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 and Graph Support
14  * By Alejandro Vaquero, alejandro.vaquero@verso.com
15  * Copyright 2005, Verso Technologies Inc.
16  *
17  * Ethereal - Network traffic analyzer
18  * By Gerald Combs <gerald@ethereal.com>
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 "graph_analysis.h"
41 #include "voip_calls.h"
42 #include "voip_calls_dlg.h"
43 #include "rtp_stream.h"
44
45 #include "globals.h"
46
47 #include <epan/tap.h>
48 #include <epan/dissectors/packet-sip.h>
49 #include <epan/dissectors/packet-mtp3.h>
50 #include <epan/dissectors/packet-isup.h>
51 #include <epan/dissectors/packet-h225.h>
52 #include <epan/dissectors/packet-h245.h>
53 #include <epan/dissectors/packet-q931.h>
54 #include <epan/dissectors/packet-sdp.h>
55 #include <epan/dissectors/packet-rtp.h>
56 #include "rtp_pt.h"
57
58 #include "alert_box.h"
59 #include "simple_dialog.h"
60
61 #ifdef HAVE_FCNTL_H
62 #include <fcntl.h>
63 #endif
64
65 #ifdef HAVE_SYS_TYPES_H
66 # include <sys/types.h>
67 #endif
68
69 #include <string.h>
70
71
72 char *voip_call_state_name[6]={
73         "CALL SETUP",
74         "IN CALL",
75         "CANCELLED",
76         "COMPLETED",
77         "REJECTED",
78         "UNKNOWN"
79         };
80
81 /* defines whether we can consider the call active */
82 char *voip_protocol_name[3]={
83         "SIP",
84         "ISUP",
85         "H323"
86         };
87
88
89
90 /****************************************************************************/
91 /* the one and only global voip_calls_tapinfo_t structure */
92 static voip_calls_tapinfo_t the_tapinfo_struct =
93         {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
94
95 /* the one and only global voip_rtp_tapinfo_t structure */
96 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
97         {0, NULL, 0};
98
99 /****************************************************************************/
100 /* when there is a [re]reading of packet's */
101 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
102 {
103         voip_calls_info_t *strinfo;
104         sip_calls_info_t *tmp_sipinfo;
105         h323_calls_info_t *tmp_h323info;
106
107         graph_analysis_item_t *graph_item;
108
109         GList* list;
110         GList* list2;
111
112         /* free the data items first */
113         list = g_list_first(tapinfo->strinfo_list);
114         while (list)
115         {
116                 strinfo = list->data;
117                 g_free(strinfo->from_identity);
118                 g_free(strinfo->to_identity);
119                 if (strinfo->protocol == VOIP_SIP){
120                         tmp_sipinfo = strinfo->prot_info;
121                         g_free(tmp_sipinfo->call_identifier);
122                 }
123                 if (strinfo->protocol == VOIP_H323){
124                         tmp_h323info = strinfo->prot_info;
125                         g_free(tmp_h323info->guid);
126                         /* free the H245 list address */
127                         list2 = g_list_first(tmp_h323info->h245_list);
128                         while (list2)
129                         {
130                                 g_free(list2->data);
131                                 list2 = g_list_next(list2);
132                         }
133                         g_list_free(tmp_h323info->h245_list);
134                         tmp_h323info->h245_list = NULL;
135                 }
136                 g_free(strinfo->prot_info);
137
138                 g_free(list->data);
139                 list = g_list_next(list);
140         }
141         g_list_free(tapinfo->strinfo_list);
142         tapinfo->strinfo_list = NULL;
143         tapinfo->ncalls = 0;
144         tapinfo->npackets = 0;
145         tapinfo->start_packets = 0;
146     tapinfo->completed_calls = 0;
147     tapinfo->rejected_calls = 0;
148
149         /* free the graph data items first */
150         list = g_list_first(tapinfo->graph_analysis->list);
151         while (list)
152         {
153                 graph_item = list->data;
154                 g_free(graph_item->frame_label);
155                 g_free(graph_item->comment);
156                 g_free(list->data);
157                 list = g_list_next(list);
158         }
159         g_list_free(tapinfo->graph_analysis->list);
160         tapinfo->graph_analysis->nconv = 0;
161         tapinfo->graph_analysis->list = NULL;
162
163         ++(tapinfo->launch_count);
164
165         return;
166 }
167
168 /****************************************************************************/
169 void graph_analysis_data_init(void){
170         the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
171         the_tapinfo_struct.graph_analysis->nconv = 0;
172         the_tapinfo_struct.graph_analysis->list = NULL;
173
174 }
175
176 /****************************************************************************/
177 /* Add the RTP streams into the graph data */
178 /** 
179  * TODO: 
180  * - reimplement this function
181  * This function does not work with VoIP taps
182  * which keep the window up to date.
183  * Either make rtp_stream() work without redissection or
184  * add an additional tap listener for rtp to this file.
185  * The second solution is cleaner and probably easier to implement, 
186  * leaving the current rtp analysis feature untouched.
187  */
188 void add_rtp_streams_graph(void)
189 {
190         rtp_stream_info_t *strinfo;
191         GList *strinfo_list;
192         guint nfound;
193         guint item;
194         GList* voip_calls_graph_list;
195         graph_analysis_item_t *gai;
196         graph_analysis_item_t *new_gai;
197         guint16 conv_num;
198         guint32 duration;
199
200         /* Scan for rtpstream */
201         rtpstream_scan();
202
203         /* assigne the RTP streams to calls */
204         nfound = 0;
205         strinfo_list = g_list_first(rtpstream_get_info()->strinfo_list);
206         while (strinfo_list)
207         {
208                 strinfo = (rtp_stream_info_t*)(strinfo_list->data);
209
210                 /* look in the voip calls graph list if there is a match for this RTP stream */
211                 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
212                 item = 0;
213                 while (voip_calls_graph_list)
214                 {                       
215                         gai = voip_calls_graph_list->data;
216                         conv_num = gai->conv_num;
217                         if (strinfo->setup_frame_number == gai->frame_num){
218                                 while(voip_calls_graph_list){
219                                         gai = voip_calls_graph_list->data;
220                                         /* add the RTP item to the graph */
221                                         if (strinfo->first_frame_num<gai->frame_num){
222                                                 new_gai = g_malloc(sizeof(graph_analysis_item_t));
223                                                 new_gai->frame_num = strinfo->first_frame_num;
224                                                 new_gai->time = (double)strinfo->start_rel_sec + (double)strinfo->start_rel_usec/1000000;
225                                                 g_memmove(&new_gai->ip_src, strinfo->src_addr.data, 4);
226                                                 g_memmove(&new_gai->ip_dst, strinfo->dest_addr.data, 4);
227                                                 new_gai->port_src = strinfo->src_port;
228                                                 new_gai->port_dst = strinfo->dest_port;
229                                                 duration = (strinfo->stop_rel_sec*1000000 + strinfo->stop_rel_usec) - (strinfo->start_rel_sec*1000000 + strinfo->start_rel_usec);
230                                                 new_gai->frame_label = g_strdup_printf("RTP (%s)", val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
231                                                 new_gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", strinfo->npackets, duration/1000000,(duration%1000000)/1000, strinfo->ssrc);
232                                                 new_gai->conv_num = conv_num;
233                                                 new_gai->display=FALSE;
234                                                 new_gai->line_style = 2;  /* the arrow line will be 2 pixels width */
235                                                 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
236                                                 
237                                                 break;
238                                         }
239                                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
240                                         item++;
241                                 }
242                                 break;
243                         }
244                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
245                         item++;
246                 }
247                 strinfo_list = g_list_next(strinfo_list);
248         }
249 }
250
251 /****************************************************************************/
252 /* Add a new item into the graph */
253 int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, gchar *frame_label, gchar *comment, guint16 call_num)
254 {
255         graph_analysis_item_t *gai;
256
257         gai = g_malloc(sizeof(graph_analysis_item_t));
258         gai->frame_num = pinfo->fd->num;
259         gai->time= (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
260         g_memmove(&gai->ip_src, pinfo->src.data, 4);
261         g_memmove(&gai->ip_dst, pinfo->dst.data, 4);
262         gai->port_src=pinfo->srcport;
263         gai->port_dst=pinfo->destport;
264         if (frame_label != NULL)
265                 gai->frame_label = g_strdup(frame_label);
266         else
267                 gai->frame_label = g_strdup("");
268
269         if (comment != NULL)
270                 gai->comment = g_strdup(comment);
271         else
272                 gai->comment = g_strdup("");
273         gai->conv_num=call_num;
274         gai->line_style=1;
275         gai->display=FALSE;
276
277         tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
278
279         return 1;
280
281 }
282
283 /****************************************************************************/
284 /* Append str to frame_label and comment in a graph item */
285 /* return 0 if the frame_num is not in the graph list */
286 int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
287 {
288         graph_analysis_item_t *gai;
289         GList* list;
290         gchar *tmp_str = NULL;
291         gchar *tmp_str2 = NULL;
292
293         list = g_list_first(tapinfo->graph_analysis->list);
294         while (list)
295         {
296                 gai = list->data;
297                 if (gai->frame_num == frame_num){
298                         tmp_str = gai->frame_label;
299                         tmp_str2 = gai->comment;
300
301                         if (new_frame_label != NULL){
302                                 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
303                                 g_free(tmp_str);
304                         }
305
306
307                         if (new_comment != NULL){
308                                 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
309                                 g_free(tmp_str2);
310                         }
311                         break;
312                 }
313                 list = g_list_next (list);
314         }
315         if (tmp_str == NULL) return 0;          /* it is not in the list */
316         return 1;
317
318 }
319
320 /****************************************************************************/
321 /* ***************************TAP for RTP **********************************/
322 /****************************************************************************/
323
324 /****************************************************************************/
325 /* when there is a [re]reading of RTP packet's */
326 void voip_rtp_reset(voip_rtp_tapinfo_t *tapinfo)
327 {
328         GList* list;
329         /* free the data items first */
330         list = g_list_first(tapinfo->list);
331         while (list)
332         {
333                 g_free(list->data);
334                 list = g_list_next(list);
335         }
336         g_list_free(tapinfo->list);
337         tapinfo->list = NULL;
338         tapinfo->nstreams = 0;
339         return;
340 }
341
342 /****************************************************************************/
343 /* whenever a RTP packet is seen by the tap listener */
344 static int 
345 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *RTPinfo)
346 {
347         voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
348         voip_rtp_stream_info_t *tmp_listinfo;
349         voip_rtp_stream_info_t *strinfo = NULL;
350         GList* list;
351
352         const struct _rtp_info *pi = RTPinfo;
353
354         /* do not consider RTP packets without a setup frame */
355         if (pi->info_setup_frame_num == 0){
356                 return 0;
357         }
358
359         /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
360         list = g_list_first(tapinfo->list);
361         while (list)
362         {
363                 tmp_listinfo=list->data;
364                 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) && (tmp_listinfo->ssrc == pi->info_sync_src) ){
365                                 strinfo = (voip_rtp_stream_info_t*)(list->data);
366                                 break;
367                 }
368                 list = g_list_next (list);
369         }
370
371         /* not in the list? then create a new entry */
372         if (strinfo==NULL){
373                 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
374                 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
375                 strinfo->src_port = pinfo->srcport;
376                 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
377                 strinfo->dest_port = pinfo->destport;
378                 strinfo->ssrc = pi->info_sync_src;
379                 strinfo->pt = pi->info_payload_type;
380                 strinfo->npackets = 0;
381                 strinfo->first_frame_num = pinfo->fd->num;
382                 strinfo->start_rel_sec = pinfo->fd->rel_secs;
383                 strinfo->start_rel_usec = pinfo->fd->rel_usecs;
384                 strinfo->setup_frame_number = pi->info_setup_frame_num;
385                 tapinfo->list = g_list_append(tapinfo->list, strinfo);
386         }
387
388         if (strinfo!=NULL){
389                 /* Add the info to the existing RTP stream */
390                 strinfo->npackets++;
391                 strinfo->stop_rel_sec = pinfo->fd->rel_secs;
392                 strinfo->stop_rel_usec = pinfo->fd->rel_usecs;
393         }
394         return 1;
395 }
396
397 /****************************************************************************/
398 /* whenever a redraw in the RTP tap listener */
399 void RTP_packet_draw(void *prs _U_)
400 {
401         voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
402         GList* rtp_streams_list;
403         voip_rtp_stream_info_t *rtp_listinfo;
404         GList* voip_calls_graph_list;
405         guint item;
406         graph_analysis_item_t *gai;
407         graph_analysis_item_t *new_gai;
408         guint16 conv_num;
409         guint32 duration;
410
411         /* add each rtp stream to the graph */
412         rtp_streams_list = g_list_first(rtp_tapinfo->list);
413         while (rtp_streams_list)
414         {
415                 rtp_listinfo = rtp_streams_list->data;
416
417                 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
418                 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
419                 item = 0;
420                 while (voip_calls_graph_list)
421                 {                       
422                         gai = voip_calls_graph_list->data;
423                         conv_num = gai->conv_num;
424                         /* if we get the setup frame number, then get the time position to graph the RTP arrow */
425                         if (rtp_listinfo->setup_frame_number == gai->frame_num){
426                                 while(voip_calls_graph_list){
427                                         gai = voip_calls_graph_list->data;
428                                         /* if RTP was already in the Graph, just update the comment information */
429                                         if (rtp_listinfo->first_frame_num == gai->frame_num){
430                                                 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
431                                                 g_free(gai->comment);
432                                                 gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
433                                                 break;
434                                         /* add the RTP item to the graph if was not there*/
435                                         } else if (rtp_listinfo->first_frame_num<gai->frame_num){
436                                                 new_gai = g_malloc(sizeof(graph_analysis_item_t));
437                                                 new_gai->frame_num = rtp_listinfo->first_frame_num;
438                                                 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
439                                                 g_memmove(&new_gai->ip_src, rtp_listinfo->src_addr.data, 4);
440                                                 g_memmove(&new_gai->ip_dst, rtp_listinfo->dest_addr.data, 4);
441                                                 new_gai->port_src = rtp_listinfo->src_port;
442                                                 new_gai->port_dst = rtp_listinfo->dest_port;
443                                                 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
444                                                 new_gai->frame_label = g_strdup_printf("RTP (%s)", val_to_str(rtp_listinfo->pt, rtp_payload_type_short_vals, "%u"));
445                                                 new_gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
446                                                 new_gai->conv_num = conv_num;
447                                                 new_gai->display=FALSE;
448                                                 new_gai->line_style = 2;  /* the arrow line will be 2 pixels width */
449                                                 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
450                                                 break;
451                                         }
452                                         
453                                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
454                                         item++;
455                                 }
456                                 break;
457                         }
458                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
459                         item++;
460                 }
461                 rtp_streams_list = g_list_next(rtp_streams_list);
462         }
463 }
464
465 static gboolean have_RTP_tap_listener=FALSE;
466 /****************************************************************************/
467 void
468 rtp_init_tap(void)
469 {
470         GString *error_string;
471
472         if(have_RTP_tap_listener==FALSE)
473         {
474                 /* don't register tap listener, if we have it already */
475                 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct), NULL,
476                         voip_rtp_reset, 
477                         RTP_packet, 
478                         RTP_packet_draw
479                         );
480                 if (error_string != NULL) {
481                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
482                                       error_string->str);
483                         g_string_free(error_string, TRUE);
484                         exit(1);
485                 }
486                 have_RTP_tap_listener=TRUE;
487         }
488 }
489
490
491
492 /* XXX just copied from gtk/rpc_stat.c */
493 void protect_thread_critical_region(void);
494 void unprotect_thread_critical_region(void);
495
496 /****************************************************************************/
497 void
498 remove_tap_listener_rtp(void)
499 {
500         protect_thread_critical_region();
501         remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
502         unprotect_thread_critical_region();
503
504         have_RTP_tap_listener=FALSE;
505 }
506
507 /****************************************************************************/
508 /* ***************************TAP for SIP **********************************/
509 /****************************************************************************/
510
511 /****************************************************************************/
512 /* whenever a SIP packet is seen by the tap listener */
513 static int 
514 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
515 {
516         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
517         /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
518            be compared with existing calls */
519
520         voip_calls_info_t *tmp_listinfo;
521         voip_calls_info_t *strinfo = NULL;
522         sip_calls_info_t *tmp_sipinfo;
523         GList* list;
524         guint32 tmp_src, tmp_dst;
525         gchar *frame_label = NULL;
526         gchar *comment = NULL;
527
528         const sip_info_value_t *pi = SIPinfo;
529
530         /* do not consider packets without call_id */
531         if (pi->tap_call_id ==NULL){
532                 return 0;
533         }
534
535         /* check wether we already have a call with these parameters in the list */
536         list = g_list_first(tapinfo->strinfo_list);
537         while (list)
538         {
539                 tmp_listinfo=list->data;
540                 if (tmp_listinfo->protocol == VOIP_SIP){
541                         tmp_sipinfo = tmp_listinfo->prot_info;
542                         if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
543                                 strinfo = (voip_calls_info_t*)(list->data);
544                                 break;
545                         }
546                 }
547                 list = g_list_next (list);
548         }
549
550         /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
551         if ((strinfo==NULL) &&(pi->request_method!=NULL)){
552                 if (strcmp(pi->request_method,"INVITE")==0){
553                         strinfo = g_malloc(sizeof(voip_calls_info_t));
554                         strinfo->call_active_state = VOIP_ACTIVE;
555                         strinfo->call_state = VOIP_CALL_SETUP;
556                         strinfo->from_identity=g_strdup(pi->tap_from_addr);
557                         strinfo->to_identity=g_strdup(pi->tap_to_addr);
558                         g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
559                         strinfo->first_frame_num=pinfo->fd->num;
560                         strinfo->selected=FALSE;
561                         strinfo->start_sec=pinfo->fd->rel_secs;
562                         strinfo->start_usec=pinfo->fd->rel_usecs;
563                         strinfo->protocol=VOIP_SIP;
564                         strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
565                         tmp_sipinfo=strinfo->prot_info;
566                         tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
567                         tmp_sipinfo->sip_state=SIP_INVITE_SENT;
568                         tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
569                         strinfo->npackets = 0;
570                         strinfo->call_num = tapinfo->ncalls++;
571                         tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
572                 }
573         }
574
575         g_free(pi->tap_from_addr);
576         g_free(pi->tap_to_addr);
577         g_free(pi->tap_call_id);
578
579         if (strinfo!=NULL){
580
581                 /* let's analyze the call state */
582
583                 g_memmove(&(tmp_src), pinfo->src.data, 4);
584                 g_memmove(&(tmp_dst), pinfo->dst.data, 4);
585                 
586                 if (pi->request_method == NULL){
587                         frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase );
588                         comment = g_strdup_printf("SIP Status");
589
590                         if ((pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(tmp_dst==strinfo->initial_speaker)){
591                                 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
592                                         tmp_sipinfo->sip_state = SIP_200_REC;
593                                 }
594                                 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
595                                         strinfo->call_state = VOIP_REJECTED;
596                                         tapinfo->rejected_calls++;
597                                 }
598                         }
599
600                 }
601                 else{
602                         frame_label = g_strdup(pi->request_method);
603
604                         if ((strcmp(pi->request_method,"INVITE")==0)&&(tmp_src == strinfo->initial_speaker)){
605                                 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
606                                 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
607                         }
608                         else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
609                                 &&(tmp_src == strinfo->initial_speaker)&&(tmp_sipinfo->sip_state==SIP_200_REC)){
610                                 strinfo->call_state = VOIP_IN_CALL;
611                                 comment = g_strdup_printf("SIP Request");
612                         }
613                         else if (strcmp(pi->request_method,"BYE")==0){
614                                 strinfo->call_state = VOIP_COMPLETED;
615                                 tapinfo->completed_calls++;
616                                 comment = g_strdup_printf("SIP Request");
617                         }
618                         else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
619                                 &&(tmp_src == strinfo->initial_speaker)&&(strinfo->call_state==VOIP_CALL_SETUP)){
620                                 strinfo->call_state = VOIP_CANCELLED;
621                                 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
622                                 comment = g_strdup_printf("SIP Request");
623                         } else {
624                                 comment = g_strdup_printf("SIP Request");
625                         }
626                 }
627
628                 strinfo->stop_sec=pinfo->fd->rel_secs;
629                 strinfo->stop_usec=pinfo->fd->rel_usecs;
630                 strinfo->last_frame_num=pinfo->fd->num;
631                 ++(strinfo->npackets);
632                 /* increment the packets counter of all calls */
633                 ++(tapinfo->npackets);
634
635                 /* add to the graph */
636                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
637                 g_free(comment);
638                 g_free(frame_label);
639         }
640         return 1;  /* refresh output */
641 }
642
643
644 /****************************************************************************/
645 const voip_calls_tapinfo_t* voip_calls_get_info(void)
646 {
647         return &the_tapinfo_struct;
648 }
649
650
651 /****************************************************************************/
652 /* TAP INTERFACE */
653 /****************************************************************************/
654 static gboolean have_SIP_tap_listener=FALSE;
655 /****************************************************************************/
656 void
657 sip_calls_init_tap(void)
658 {
659         GString *error_string;
660
661         if(have_SIP_tap_listener==FALSE)
662         {
663                 /* don't register tap listener, if we have it already */
664                 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
665                         voip_calls_dlg_reset, 
666                         SIPcalls_packet, 
667                         voip_calls_dlg_draw
668                         );
669                 if (error_string != NULL) {
670                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
671                                       error_string->str);
672                         g_string_free(error_string, TRUE);
673                         exit(1);
674                 }
675                 have_SIP_tap_listener=TRUE;
676         }
677 }
678
679
680
681 /* XXX just copied from gtk/rpc_stat.c */
682 void protect_thread_critical_region(void);
683 void unprotect_thread_critical_region(void);
684
685 /****************************************************************************/
686 void
687 remove_tap_listener_sip_calls(void)
688 {
689         protect_thread_critical_region();
690         remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
691         unprotect_thread_critical_region();
692
693         have_SIP_tap_listener=FALSE;
694 }
695
696 /****************************************************************************/
697 /* ***************************TAP for ISUP **********************************/
698 /****************************************************************************/
699
700 static gchar            isup_called_number[255], isup_calling_number[255];
701 static guint16          isup_cic;
702 static guint8           isup_message_type;
703 static guint8           isup_cause_value;
704
705 /****************************************************************************/
706 /* whenever a isup_ packet is seen by the tap listener */
707 static int 
708 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
709 {
710         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
711         const isup_tap_rec_t *pi = isup_info;
712
713         if (pi->calling_number!=NULL){
714                 strcpy(isup_calling_number, pi->calling_number);
715         }
716         if (pi->called_number!=NULL){
717                 strcpy(isup_called_number, pi->called_number);
718         }
719         isup_message_type = pi->message_type;
720         isup_cause_value = pi->cause_value;
721         isup_cic = pinfo->circuit_id;
722
723         return 0;
724 }
725
726 /****************************************************************************/
727
728 static gboolean have_isup_tap_listener=FALSE;
729
730 void
731 isup_calls_init_tap(void)
732 {
733         GString *error_string;
734
735
736         if(have_isup_tap_listener==FALSE)
737         {
738                 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
739                         NULL,
740                         voip_calls_dlg_reset, 
741                         isup_calls_packet, 
742                         voip_calls_dlg_draw
743                         );
744         
745                 if (error_string != NULL) {
746                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
747                                       error_string->str);
748                         g_string_free(error_string, TRUE);
749                         exit(1);
750                 }
751                 have_isup_tap_listener=TRUE;
752         }
753 }
754
755 /****************************************************************************/
756
757 void
758 remove_tap_listener_isup_calls(void)
759 {
760         protect_thread_critical_region();
761         remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
762         unprotect_thread_critical_region();
763
764         have_isup_tap_listener=FALSE;
765 }
766
767
768 /****************************************************************************/
769 /* ***************************TAP for MTP3 **********************************/
770 /****************************************************************************/
771
772
773 /****************************************************************************/
774 /* whenever a mtp3_ packet is seen by the tap listener */
775 static int 
776 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
777 {
778         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
779         voip_calls_info_t *tmp_listinfo;
780         voip_calls_info_t *strinfo = NULL;
781         isup_calls_info_t *tmp_isupinfo;
782         gboolean found = FALSE;
783         gboolean forward;
784         gboolean right_pair = TRUE;
785         GList* list;
786         gchar *frame_label = NULL;
787         gchar *comment = NULL;
788         int i;
789
790         const mtp3_tap_rec_t *pi = mtp3_info;
791
792         /* check wether we already have a call with these parameters in the list */
793         list = g_list_first(tapinfo->strinfo_list);
794         while (list)
795         {
796                 tmp_listinfo=list->data;
797                 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
798                         tmp_isupinfo = tmp_listinfo->prot_info;
799                         if ((tmp_isupinfo->cic == isup_cic)&&(tmp_isupinfo->ni == pi->addr_opc.ni)){
800                                 if ((tmp_isupinfo->opc == pi->addr_opc.pc)&&(tmp_isupinfo->dpc == pi->addr_dpc.pc)){
801                                          forward = TRUE;
802                                  }
803                                  else if ((tmp_isupinfo->dpc == pi->addr_opc.pc)&&(tmp_isupinfo->opc == pi->addr_dpc.pc)){
804                                          forward = FALSE;
805                                  }
806                                  else{
807                                          right_pair = FALSE;
808                                  }
809                                  if (right_pair){
810                                         /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
811                                            cic is no longer active */
812                                         if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
813                                                 found = TRUE;
814                                         }
815                                         else if (isup_message_type != 1){
816                                                 found = TRUE;
817                                         }
818                                         else{
819                                                 tmp_listinfo->call_active_state=VOIP_INACTIVE;
820                                         }
821                                 }
822                                 if (found){
823                                         strinfo = (voip_calls_info_t*)(list->data);
824                                         break;
825                                 }
826                         }
827                 }
828                 list = g_list_next (list);
829         }
830
831         /* not in the list? then create a new entry if the message is IAM
832            -i.e. if this session is a call*/
833
834
835         if ((strinfo==NULL) &&(isup_message_type==1)){
836
837                 strinfo = g_malloc(sizeof(voip_calls_info_t));
838                 strinfo->call_active_state = VOIP_ACTIVE;
839                 strinfo->call_state = VOIP_UNKNOWN;
840                 g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
841                 strinfo->selected=FALSE;
842                 strinfo->first_frame_num=pinfo->fd->num;
843                 strinfo->start_sec=pinfo->fd->rel_secs;
844                 strinfo->start_usec=pinfo->fd->rel_usecs;
845                 strinfo->protocol=VOIP_ISUP;
846                 strinfo->from_identity=g_strdup(isup_calling_number);
847                 strinfo->to_identity=g_strdup(isup_called_number);
848                 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
849                 tmp_isupinfo=strinfo->prot_info;
850                 tmp_isupinfo->opc = pi->addr_opc.pc;
851                 tmp_isupinfo->dpc = pi->addr_dpc.pc;
852                 tmp_isupinfo->ni = pi->addr_opc.ni;
853                 tmp_isupinfo->cic = pinfo->circuit_id;
854                 strinfo->npackets = 0;
855                 strinfo->call_num = tapinfo->ncalls++;
856                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
857         }
858
859         if (strinfo!=NULL){
860                 strinfo->stop_sec=pinfo->fd->rel_secs;
861                 strinfo->stop_usec=pinfo->fd->rel_usecs;
862                 strinfo->last_frame_num=pinfo->fd->num;
863                 ++(strinfo->npackets);
864
865                 /* Let's analyze the call state */
866
867
868                 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=isup_message_type);i++);
869
870                 if (isup_message_type_value[i].value==isup_message_type){
871                         frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
872                 }
873                 else{
874                         frame_label = g_strdup_printf("Unknown");
875                 }
876
877                 if (strinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
878                         comment = g_strdup_printf("Call from %s to %s",
879                          isup_calling_number, isup_called_number);
880                 }
881                 else if (strinfo->npackets == 2){ /* in the second packet we show the SPs */
882                         if (forward){
883                                 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
884                                  pi->addr_opc.ni, pi->addr_opc.pc,
885                                  pi->addr_opc.ni, pi->addr_dpc.pc, pinfo->circuit_id);
886
887                         }
888                         else{
889                                 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
890                                  pi->addr_opc.ni, pi->addr_dpc.pc,
891                                  pi->addr_opc.ni, pi->addr_opc.pc, pinfo->circuit_id);
892
893                         }
894                 }
895
896                 switch(isup_message_type){
897                         case 1: /* IAM */
898                                 strinfo->call_state=VOIP_CALL_SETUP;
899                                 break;
900                         case 7: /* CONNECT */
901                         case 9: /* ANSWER */
902                                 strinfo->call_state=VOIP_IN_CALL;
903                                 break;
904                         case 12: /* RELEASE */
905                                 if (strinfo->call_state==VOIP_CALL_SETUP){
906                                         if (forward){
907                                                 strinfo->call_state=VOIP_CANCELLED;
908                                         }
909                                         else{
910                                                 strinfo->call_state=VOIP_REJECTED;
911                                                 tapinfo->rejected_calls++;
912                                         }
913                                 }
914                                 else if (strinfo->call_state == VOIP_IN_CALL){
915                                         strinfo->call_state = VOIP_COMPLETED;
916                                         tapinfo->completed_calls++;
917                                 }
918                                 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=isup_cause_value);i++);
919                                 if (q931_cause_code_vals[i].value==isup_cause_value){
920                                         comment = g_strdup_printf("Cause %i - %s",isup_cause_value, q931_cause_code_vals[i].strptr);
921                                 }
922                                 else{
923                                         comment = g_strdup_printf("Cause %i",isup_cause_value);
924                                 }
925                                 break;
926                 }
927
928                 /* increment the packets counter of all calls */
929                 ++(tapinfo->npackets);
930
931                 /* add to the graph */
932                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
933                 g_free(comment);
934                 g_free(frame_label);
935         }
936
937
938         return 1;
939 }
940
941 /****************************************************************************/
942
943 static gboolean have_mtp3_tap_listener=FALSE;
944
945 void
946 mtp3_calls_init_tap(void)
947 {
948         GString *error_string;
949
950
951         if(have_mtp3_tap_listener==FALSE)
952         {
953                 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
954                         NULL,
955                         voip_calls_dlg_reset, 
956                         mtp3_calls_packet, 
957                         voip_calls_dlg_draw
958                         );
959
960                 if (error_string != NULL) {
961                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
962                                       error_string->str);
963                         g_string_free(error_string, TRUE);
964                         exit(1);
965                 }
966                 have_mtp3_tap_listener=TRUE;
967         }
968 }
969
970 /****************************************************************************/
971
972 void
973 remove_tap_listener_mtp3_calls(void)
974 {
975         protect_thread_critical_region();
976         remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
977         unprotect_thread_critical_region();
978
979         have_mtp3_tap_listener=FALSE;
980 }
981
982 /****************************************************************************/
983 /* ***************************TAP for Q931 **********************************/
984 /****************************************************************************/
985
986 static gchar *q931_calling_number;
987 static gchar *q931_called_number;
988 static guint8 q931_cause_value;
989 static gint32 q931_crv;
990 static guint32 q931_frame_num;
991
992 /****************************************************************************/
993 /* whenever a q931_ packet is seen by the tap listener */
994 static int 
995 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
996 {
997         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
998         const q931_packet_info *pi = q931_info;
999
1000         /* free previously allocated q931_calling/ed_number */
1001         g_free(q931_calling_number);
1002         g_free(q931_called_number);
1003         
1004         if (pi->calling_number!=NULL)
1005                 q931_calling_number = g_strdup(pi->calling_number);
1006         else
1007                 q931_calling_number = g_strdup("");
1008
1009         if (pi->called_number!=NULL)
1010                 q931_called_number = g_strdup(pi->called_number);
1011         else
1012                 q931_called_number = g_strdup("");
1013         q931_cause_value = pi->cause_value;
1014         q931_frame_num = pinfo->fd->num;
1015         q931_crv = pi->crv;
1016
1017         return 0;
1018 }
1019
1020 /****************************************************************************/
1021 static gboolean have_q931_tap_listener=FALSE;
1022
1023 void
1024 q931_calls_init_tap(void)
1025 {
1026         GString *error_string;
1027
1028
1029         if(have_q931_tap_listener==FALSE)
1030         {
1031                 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1032                         NULL,
1033                         voip_calls_dlg_reset,
1034                         q931_calls_packet,
1035                         voip_calls_dlg_draw
1036                         );
1037                         
1038                 if (error_string != NULL) {
1039                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1040                                       error_string->str);
1041                         g_string_free(error_string, TRUE);
1042                         exit(1);
1043                 }
1044                 have_q931_tap_listener=TRUE;
1045         }
1046 }
1047
1048 /****************************************************************************/
1049
1050 void
1051 remove_tap_listener_q931_calls(void)
1052 {
1053         protect_thread_critical_region();
1054         remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1055         unprotect_thread_critical_region();
1056
1057         have_q931_tap_listener=FALSE;
1058 }
1059
1060 /****************************************************************************/
1061 /****************************TAP for H323 ***********************************/
1062 /****************************************************************************/
1063
1064 #define GUID_LEN        16
1065 static const guint8 guid_allzero[GUID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1066 /* defines specific H323 data */
1067
1068 void add_h245_Address(h323_calls_info_t *h323info, guint32 h245_address, guint16 h245_port)
1069 {
1070         h245_address_t *h245_add = NULL;
1071
1072         h245_add = g_malloc(sizeof(h245_address_t));
1073                 h245_add->h245_address = h245_address;
1074                 h245_add->h245_port = h245_port;
1075
1076         h323info->h245_list = g_list_append(h323info->h245_list, h245_add);                             
1077 }
1078
1079 /****************************************************************************/
1080 /* whenever a H225 packet is seen by the tap listener */
1081 static int 
1082 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1083 {
1084         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1085         voip_calls_info_t *tmp_listinfo;
1086         voip_calls_info_t *strinfo = NULL;
1087         h323_calls_info_t *tmp_h323info;
1088         gchar *frame_label;
1089         gchar *comment;
1090         GList* list;
1091         guint32 tmp_src, tmp_dst;
1092
1093         const h225_packet_info *pi = H225info;
1094
1095         /* if not guid and RAS return because did not belong to a call */
1096         if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (pi->msg_type == H225_RAS))
1097                 return 0;
1098         
1099
1100         if ( (memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (q931_frame_num == pinfo->fd->num) ){
1101                 /* check wether we already have a call with this Q931 CRV */
1102                 list = g_list_first(tapinfo->strinfo_list);
1103                 while (list)
1104                 {
1105                         tmp_listinfo=list->data;
1106                         if (tmp_listinfo->protocol == VOIP_H323){
1107                                 tmp_h323info = tmp_listinfo->prot_info;
1108                                 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1109                                         strinfo = (voip_calls_info_t*)(list->data);
1110                                         break;
1111                                 }
1112                         }
1113                         list = g_list_next (list);
1114                 }
1115                 if (strinfo==NULL)      return 0;               
1116         } else {
1117                 /* check wether we already have a call with this guid in the list */
1118                 list = g_list_first(tapinfo->strinfo_list);
1119                 while (list)
1120                 {
1121                         tmp_listinfo=list->data;
1122                         if (tmp_listinfo->protocol == VOIP_H323){
1123                                 tmp_h323info = tmp_listinfo->prot_info;
1124                                 if (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0){ 
1125                                         strinfo = (voip_calls_info_t*)(list->data);
1126                                         break;
1127                                 }
1128                         }
1129                         list = g_list_next (list);
1130                 }
1131         }
1132
1133         /* not in the list? then create a new entry */
1134         if ((strinfo==NULL)){
1135                 strinfo = g_malloc(sizeof(voip_calls_info_t));
1136                 strinfo->call_active_state = VOIP_ACTIVE;
1137                 strinfo->call_state = VOIP_UNKNOWN;
1138                 strinfo->from_identity=g_strdup("");
1139                 strinfo->to_identity=g_strdup("");
1140
1141                 g_memmove(&(strinfo->initial_speaker), pinfo->src.data,4);
1142                 strinfo->selected=FALSE;
1143                 strinfo->first_frame_num=pinfo->fd->num;
1144                 strinfo->start_sec=pinfo->fd->rel_secs;
1145                 strinfo->start_usec=pinfo->fd->rel_usecs;
1146                 strinfo->protocol=VOIP_H323;
1147                 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1148                 tmp_h323info = strinfo->prot_info;
1149                 tmp_h323info->guid = (guint8 *) g_memdup(pi->guid,GUID_LEN);
1150                 tmp_h323info->h225SetupAddr = 0;
1151                 tmp_h323info->h245_list = NULL;
1152                 tmp_h323info->is_faststart_Setup = FALSE;
1153                 tmp_h323info->is_faststart_Proc = FALSE;
1154                 tmp_h323info->is_h245Tunneling = FALSE;
1155                 tmp_h323info->is_h245 = FALSE;
1156                 tmp_h323info->q931_crv = -1;
1157                 tmp_h323info->q931_crv2 = -1;
1158                 strinfo->call_num = tapinfo->ncalls++;
1159                 strinfo->npackets = 0;
1160
1161                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);                          
1162         }
1163
1164         if (strinfo!=NULL){
1165
1166                 /* let's analyze the call state */
1167
1168                 g_memmove(&(tmp_src), pinfo->src.data, 4);
1169                 g_memmove(&(tmp_dst), pinfo->dst.data, 4);
1170
1171                 strinfo->stop_sec=pinfo->fd->rel_secs;
1172                 strinfo->stop_usec=pinfo->fd->rel_usecs;
1173                 strinfo->last_frame_num=pinfo->fd->num;
1174                 ++(strinfo->npackets);
1175                 /* increment the packets counter of all calls */
1176                 ++(tapinfo->npackets);
1177
1178                 /* change the status */
1179                 if (pi->msg_type == H225_CS){
1180                         if (tmp_h323info->q931_crv == -1) {
1181                                 tmp_h323info->q931_crv = q931_crv;
1182                         } else if (tmp_h323info->q931_crv != q931_crv) {
1183                                 tmp_h323info->q931_crv2 = q931_crv;
1184                         }
1185
1186                         if (pi->is_h245 == TRUE){
1187                                 add_h245_Address(tmp_h323info, pi->h245_address, pi->h245_port);
1188                         }
1189
1190                         if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1191
1192                         frame_label = g_strdup(pi->frame_label);
1193
1194                         switch(pi->cs_type){
1195                         case H225_SETUP:
1196                                 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1197
1198                                 /* set te calling and called number from the Q931 packet */
1199                                 if (q931_frame_num == pinfo->fd->num){
1200                                         if (q931_calling_number != NULL){
1201                                                 g_free(strinfo->from_identity);
1202                                                 strinfo->from_identity=g_strdup(q931_calling_number);
1203                                         }
1204                                         if (q931_called_number != NULL){
1205                                                 g_free(strinfo->to_identity);
1206                                                 strinfo->to_identity=g_strdup(q931_called_number);
1207                                         }
1208                                 }
1209                                 if (tmp_h323info->h225SetupAddr == 0) g_memmove(&(tmp_h323info->h225SetupAddr), pinfo->src.data,4);
1210                                 strinfo->call_state=VOIP_CALL_SETUP;
1211                                 comment = g_strdup_printf("H225 From: %s To:%s  TunnH245:%s FS:%s", strinfo->from_identity, strinfo->to_identity, (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1212                                                                                         (pi->is_faststart==TRUE?"on":"off"));
1213                                 break;
1214                         case H225_CONNECT:
1215                                 strinfo->call_state=VOIP_IN_CALL;
1216                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1217                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1218                                                                                         (pi->is_faststart==TRUE?"on":"off"));
1219                                 break;
1220                         case H225_RELEASE_COMPLET:
1221                                 g_memmove(&(tmp_src), pinfo->src.data, 4);
1222                                 if (strinfo->call_state==VOIP_CALL_SETUP){
1223                                         if (tmp_h323info->h225SetupAddr == tmp_src){  /* forward direction */
1224                                                 strinfo->call_state=VOIP_CANCELLED;
1225                                         }
1226                                         else{                                                                                           /* reverse */
1227                                                 strinfo->call_state=VOIP_REJECTED;
1228                                                 tapinfo->rejected_calls++;
1229                                         }
1230                                 }
1231                                 else if (strinfo->call_state == VOIP_IN_CALL){
1232                                         strinfo->call_state = VOIP_COMPLETED;
1233                                         tapinfo->completed_calls++;
1234                                 }
1235                                 /* get the Q931 Release cause code */
1236                                 if (q931_frame_num == pinfo->fd->num &&
1237                                     q931_cause_value != 0xFF){          
1238                                         comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1239                                 } else {                        /* Cause not set */
1240                                         comment = g_strdup("H225 No Q931 Rel Cause");
1241                                 }
1242                                 break;
1243                         case H225_PROGRESS:
1244                         case H225_ALERTING:
1245                         case H225_CALL_PROCEDING:
1246                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1247                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1248                                                                                         (pi->is_faststart==TRUE?"on":"off"));
1249                                 break;
1250                         default:
1251                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1252                                                                                         (pi->is_faststart==TRUE?"on":"off"));
1253
1254                         }
1255                 } else if (pi->msg_type == H225_RAS){
1256                         frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1257                         comment = g_strdup("H225 RAS");
1258                 } else {
1259                         frame_label = g_strdup("H225: Unknown");
1260                         comment = g_strdup("");
1261                 }
1262
1263                 /* add to graph analysis */
1264                 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment))          /* if the frame number exists in graph, append to it*/
1265                         add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  /* if not exist, add to the graph */
1266
1267                 g_free(frame_label);
1268                 g_free(comment);
1269         }
1270
1271         return 1;  /* refresh output */
1272 }
1273
1274
1275 /****************************************************************************/
1276 /* TAP INTERFACE */
1277 /****************************************************************************/
1278 static gboolean have_H225_tap_listener=FALSE;
1279 /****************************************************************************/
1280 void
1281 h225_calls_init_tap(void)
1282 {
1283         GString *error_string;
1284
1285         if(have_H225_tap_listener==FALSE)
1286         {
1287                 /* don't register tap listener, if we have it already */
1288                 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1289                         voip_calls_dlg_reset, 
1290                         H225calls_packet, 
1291                         voip_calls_dlg_draw
1292                         );
1293                         
1294                 if (error_string != NULL) {
1295                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1296                                       error_string->str);
1297                         g_string_free(error_string, TRUE);
1298                         exit(1);
1299                 }
1300                 have_H225_tap_listener=TRUE;
1301         }
1302 }
1303
1304
1305
1306 /* XXX just copied from gtk/rpc_stat.c */
1307 void protect_thread_critical_region(void);
1308 void unprotect_thread_critical_region(void);
1309
1310 /****************************************************************************/
1311 void
1312 remove_tap_listener_h225_calls(void)
1313 {
1314         protect_thread_critical_region();
1315         remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1316         unprotect_thread_critical_region();
1317
1318         have_H225_tap_listener=FALSE;
1319 }
1320
1321
1322 /****************************************************************************/
1323 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1324 static int 
1325 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
1326 {
1327         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1328         voip_calls_info_t *tmp_listinfo;
1329         voip_calls_info_t *strinfo = NULL;
1330         h323_calls_info_t *tmp_h323info;
1331         gchar *frame_label;
1332         gchar *comment;
1333         GList* list;
1334         GList* list2;
1335         guint32 tmp_src, tmp_dst;
1336         h245_address_t *h245_add = NULL;
1337
1338         const h245_packet_info *pi = H245info;
1339
1340         /* if H245 tunneling is on, append to graph */
1341         if (append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) return 1;
1342
1343
1344         /* it is not Tunneling or it is not in the list. So check if there is no tunneling
1345            and there is a call with this H245 address */
1346         list = g_list_first(tapinfo->strinfo_list);
1347         while (list)
1348         {
1349                 tmp_listinfo=list->data;
1350                 if (tmp_listinfo->protocol == VOIP_H323){
1351                         tmp_h323info = tmp_listinfo->prot_info;
1352
1353                         g_memmove(&(tmp_src), pinfo->src.data, 4);
1354                         g_memmove(&(tmp_dst), pinfo->dst.data, 4);
1355                         list2 = g_list_first(tmp_h323info->h245_list);
1356                         while (list2)
1357                         {
1358                                 h245_add=list2->data;
1359                                 if ( ((h245_add->h245_address == tmp_src) && (h245_add->h245_port == pinfo->srcport))
1360                                         || ((h245_add->h245_address == tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
1361                                         strinfo = (voip_calls_info_t*)(list->data);
1362
1363                                         ++(strinfo->npackets);
1364                                         /* increment the packets counter of all calls */
1365                                         ++(tapinfo->npackets);
1366
1367                                         break;
1368                                 }                       
1369                         list2 = g_list_next(list2);
1370                         }
1371                         if (strinfo!=NULL) break;
1372                 }
1373                 list = g_list_next(list);
1374         }
1375
1376         if (strinfo!=NULL){
1377                 frame_label = g_strdup(pi->frame_label);
1378                 comment = g_strdup(pi->comment);
1379                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
1380                 g_free(frame_label);
1381                 g_free(comment);
1382         }
1383
1384         return 1;  /* refresh output */
1385 }
1386
1387
1388 /****************************************************************************/
1389 /* TAP INTERFACE */
1390 /****************************************************************************/
1391 static gboolean have_H245dg_tap_listener=FALSE;
1392 /****************************************************************************/
1393 void
1394 h245dg_calls_init_tap(void)
1395 {
1396         GString *error_string;
1397
1398         if(have_H245dg_tap_listener==FALSE)
1399         {
1400                 /* don't register tap listener, if we have it already */
1401                 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
1402                         voip_calls_dlg_reset,
1403                         H245dgcalls_packet, 
1404                         voip_calls_dlg_draw
1405                         );
1406                 
1407                 if (error_string != NULL) {
1408                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1409                                       error_string->str);
1410                         g_string_free(error_string, TRUE);
1411                         exit(1);
1412                 }
1413                 have_H245dg_tap_listener=TRUE;
1414         }
1415 }
1416
1417
1418 /* XXX just copied from gtk/rpc_stat.c */
1419 void protect_thread_critical_region(void);
1420 void unprotect_thread_critical_region(void);
1421
1422 /****************************************************************************/
1423 void
1424 remove_tap_listener_h245dg_calls(void)
1425 {
1426         protect_thread_critical_region();
1427         remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
1428         unprotect_thread_critical_region();
1429
1430         have_H245dg_tap_listener=FALSE;
1431 }
1432
1433
1434 /****************************************************************************/
1435 /****************************TAP for SDP PROTOCOL ***************************/
1436 /****************************************************************************/
1437 /* whenever a SDP packet is seen by the tap listener */
1438 static int 
1439 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
1440 {
1441         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1442         const sdp_packet_info *pi = SDPinfo;
1443         char summary_str[50];
1444         
1445         /* Append to graph the SDP summary if the packet exists */
1446         g_snprintf(summary_str, 50, "SDP (%s)", pi->summary_str);
1447         append_to_frame_graph(tapinfo, pinfo->fd->num, summary_str, NULL);
1448
1449         return 1;  /* refresh output */
1450 }
1451
1452
1453 /****************************************************************************/
1454 /* TAP INTERFACE */
1455 /****************************************************************************/
1456 static gboolean have_sdp_tap_listener=FALSE;
1457 /****************************************************************************/
1458 void
1459 sdp_calls_init_tap(void)
1460 {
1461         GString *error_string;
1462
1463         if(have_sdp_tap_listener==FALSE)
1464         {
1465                 /* don't register tap listener, if we have it already */
1466                 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
1467                         voip_calls_dlg_reset, 
1468                         SDPcalls_packet, 
1469                         voip_calls_dlg_draw
1470                         );
1471                         
1472                 if (error_string != NULL) {
1473                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1474                                       error_string->str);
1475                         g_string_free(error_string, TRUE);
1476                         exit(1);
1477                 }
1478                 have_sdp_tap_listener=TRUE;
1479         }
1480 }
1481
1482
1483 /* XXX just copied from gtk/rpc_stat.c */
1484 void protect_thread_critical_region(void);
1485 void unprotect_thread_critical_region(void);
1486
1487 /****************************************************************************/
1488 void
1489 remove_tap_listener_sdp_calls(void)
1490 {
1491         protect_thread_critical_region();
1492         remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
1493         unprotect_thread_critical_region();
1494
1495         have_sdp_tap_listener=FALSE;
1496 }
1497
1498
1499
1500
1501
1502 /****************************************************************************/
1503 /* ***************************TAP for OTHER PROTOCOL **********************************/
1504 /****************************************************************************/
1505
1506 /****************************************************************************/
1507 /* whenever a prot_ packet is seen by the tap listener */
1508 /*
1509 static int 
1510 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
1511 {
1512         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1513         if (strinfo!=NULL){
1514                 strinfo->stop_sec=pinfo->fd->rel_secs;
1515                 strinfo->stop_usec=pinfo->fd->rel_usecs;
1516                 strinfo->last_frame_num=pinfo->fd->num;
1517                 ++(strinfo->npackets);
1518                 ++(tapinfo->npackets);
1519         }
1520
1521         return 1;
1522 }
1523 */
1524 /****************************************************************************/
1525 /*
1526 static gboolean have_prot__tap_listener=FALSE;
1527
1528 void
1529 prot_calls_init_tap(void)
1530 {
1531         GString *error_string;
1532
1533         if(have_prot__tap_listener==FALSE)
1534         {
1535                 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
1536                         NULL,
1537                         voip_calls_dlg_reset,
1538                         prot__calls_packet, 
1539                         voip_calls_dlg_draw
1540                         );
1541
1542                 if (error_string != NULL) {
1543                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1544                                       error_string->str);
1545                         g_string_free(error_string, TRUE);
1546                         exit(1);
1547                 }
1548                 have_prot__tap_listener=TRUE;
1549         }
1550 }
1551 */
1552 /****************************************************************************/
1553 /*
1554 void
1555 remove_tap_listener_prot__calls(void)
1556 {
1557         protect_thread_critical_region();
1558         remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
1559         unprotect_thread_critical_region();
1560
1561         have_prot__tap_listener=FALSE;
1562 }
1563 */
1564