2 * VoIP calls summary addition for ethereal
6 * Copyright 2004, Ericsson, Spain
7 * By Francisco Alcoba <francisco.alcoba@ericsson.com>
9 * based on h323_calls.c
10 * Copyright 2004, Iskratel, Ltd, Kranj
11 * By Miha Jemec <m.jemec@iskratel.si>
13 * H323, RTP and Graph Support
14 * By Alejandro Vaquero, alejandro.vaquero@verso.com
15 * Copyright 2005, Verso Technologies Inc.
17 * Ethereal - Network traffic analyzer
18 * By Gerald Combs <gerald@ethereal.com>
19 * Copyright 1998 Gerald Combs
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.
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.
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.
42 #include "graph_analysis.h"
43 #include "voip_calls.h"
44 #include "voip_calls_dlg.h"
49 #include <epan/dissectors/packet-sip.h>
50 #include <epan/dissectors/packet-mtp3.h>
51 #include <epan/dissectors/packet-isup.h>
52 #include <epan/dissectors/packet-h225.h>
53 #include <epan/dissectors/packet-h245.h>
54 #include <epan/dissectors/packet-q931.h>
55 #include <epan/dissectors/packet-sdp.h>
56 #include <plugins/mgcp/packet-mgcp.h>
57 #include <epan/dissectors/packet-rtp.h>
60 #include "alert_box.h"
61 #include "simple_dialog.h"
63 char *voip_call_state_name[7]={
73 /* defines whether we can consider the call active */
74 char *voip_protocol_name[4]={
83 /****************************************************************************/
84 /* the one and only global voip_calls_tapinfo_t structure */
85 static voip_calls_tapinfo_t the_tapinfo_struct =
86 {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0};
88 /* the one and only global voip_rtp_tapinfo_t structure */
89 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
92 /****************************************************************************/
93 /* when there is a [re]reading of packet's */
94 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
96 voip_calls_info_t *strinfo;
97 sip_calls_info_t *tmp_sipinfo;
98 h323_calls_info_t *tmp_h323info;
100 graph_analysis_item_t *graph_item;
105 /* free the data items first */
106 list = g_list_first(tapinfo->strinfo_list);
109 strinfo = list->data;
110 g_free(strinfo->from_identity);
111 g_free(strinfo->to_identity);
112 if (strinfo->protocol == VOIP_SIP){
113 tmp_sipinfo = strinfo->prot_info;
114 g_free(tmp_sipinfo->call_identifier);
116 if (strinfo->protocol == VOIP_H323){
117 tmp_h323info = strinfo->prot_info;
118 g_free(tmp_h323info->guid);
119 /* free the H245 list address */
120 list2 = g_list_first(tmp_h323info->h245_list);
124 list2 = g_list_next(list2);
126 g_list_free(tmp_h323info->h245_list);
127 tmp_h323info->h245_list = NULL;
129 g_free(strinfo->prot_info);
132 list = g_list_next(list);
134 g_list_free(tapinfo->strinfo_list);
135 tapinfo->strinfo_list = NULL;
137 tapinfo->npackets = 0;
138 tapinfo->start_packets = 0;
139 tapinfo->completed_calls = 0;
140 tapinfo->rejected_calls = 0;
142 /* free the graph data items first */
143 list = g_list_first(tapinfo->graph_analysis->list);
146 graph_item = list->data;
147 g_free(graph_item->frame_label);
148 g_free(graph_item->comment);
150 list = g_list_next(list);
152 g_list_free(tapinfo->graph_analysis->list);
153 tapinfo->graph_analysis->nconv = 0;
154 tapinfo->graph_analysis->list = NULL;
156 ++(tapinfo->launch_count);
161 /****************************************************************************/
162 void graph_analysis_data_init(void){
163 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
164 the_tapinfo_struct.graph_analysis->nconv = 0;
165 the_tapinfo_struct.graph_analysis->list = NULL;
169 /****************************************************************************/
170 /* Add a new item into the graph */
171 int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, gchar *frame_label, gchar *comment, guint16 call_num)
173 graph_analysis_item_t *gai;
175 gai = g_malloc(sizeof(graph_analysis_item_t));
176 gai->frame_num = pinfo->fd->num;
177 gai->time= (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
178 g_memmove(&gai->ip_src, pinfo->src.data, 4);
179 g_memmove(&gai->ip_dst, pinfo->dst.data, 4);
180 gai->port_src=pinfo->srcport;
181 gai->port_dst=pinfo->destport;
182 if (frame_label != NULL)
183 gai->frame_label = g_strdup(frame_label);
185 gai->frame_label = g_strdup("");
188 gai->comment = g_strdup(comment);
190 gai->comment = g_strdup("");
191 gai->conv_num=call_num;
195 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
201 /****************************************************************************/
202 /* Append str to frame_label and comment in a graph item */
203 /* return 0 if the frame_num is not in the graph list */
204 int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
206 graph_analysis_item_t *gai;
208 gchar *tmp_str = NULL;
209 gchar *tmp_str2 = NULL;
211 list = g_list_first(tapinfo->graph_analysis->list);
215 if (gai->frame_num == frame_num){
216 tmp_str = gai->frame_label;
217 tmp_str2 = gai->comment;
219 if (new_frame_label != NULL){
220 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
225 if (new_comment != NULL){
226 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
231 list = g_list_next (list);
233 if (tmp_str == NULL) return 0; /* it is not in the list */
238 /****************************************************************************/
239 /* Change all the graph items with call_num to new_call_num */
240 guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
242 graph_analysis_item_t *gai;
247 list = g_list_first(tapinfo->graph_analysis->list);
251 if (gai->conv_num == call_num){
252 gai->conv_num = new_call_num;
255 list = g_list_next (list);
257 return items_changed;
260 /****************************************************************************/
261 /* ***************************TAP for RTP **********************************/
262 /****************************************************************************/
264 /****************************************************************************/
265 /* when there is a [re]reading of RTP packet's */
266 void voip_rtp_reset(void *ptr _U_)
268 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
270 /* free the data items first */
271 list = g_list_first(tapinfo->list);
275 list = g_list_next(list);
277 g_list_free(tapinfo->list);
278 tapinfo->list = NULL;
279 tapinfo->nstreams = 0;
283 /****************************************************************************/
284 /* whenever a RTP packet is seen by the tap listener */
286 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *RTPinfo)
288 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
289 voip_rtp_stream_info_t *tmp_listinfo;
290 voip_rtp_stream_info_t *strinfo = NULL;
293 const struct _rtp_info *pi = RTPinfo;
295 /* do not consider RTP packets without a setup frame */
296 if (pi->info_setup_frame_num == 0){
300 /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
301 list = g_list_first(tapinfo->list);
304 tmp_listinfo=list->data;
305 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) && (tmp_listinfo->ssrc == pi->info_sync_src) ){
306 strinfo = (voip_rtp_stream_info_t*)(list->data);
309 list = g_list_next (list);
312 /* not in the list? then create a new entry */
314 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
315 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
316 strinfo->src_port = pinfo->srcport;
317 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
318 strinfo->dest_port = pinfo->destport;
319 strinfo->ssrc = pi->info_sync_src;
320 strinfo->pt = pi->info_payload_type;
321 strinfo->npackets = 0;
322 strinfo->first_frame_num = pinfo->fd->num;
323 strinfo->start_rel_sec = pinfo->fd->rel_secs;
324 strinfo->start_rel_usec = pinfo->fd->rel_usecs;
325 strinfo->setup_frame_number = pi->info_setup_frame_num;
326 tapinfo->list = g_list_append(tapinfo->list, strinfo);
330 /* Add the info to the existing RTP stream */
332 strinfo->stop_rel_sec = pinfo->fd->rel_secs;
333 strinfo->stop_rel_usec = pinfo->fd->rel_usecs;
338 /****************************************************************************/
339 /* whenever a redraw in the RTP tap listener */
340 void RTP_packet_draw(void *prs _U_)
342 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
343 GList* rtp_streams_list;
344 voip_rtp_stream_info_t *rtp_listinfo;
345 GList* voip_calls_graph_list;
347 graph_analysis_item_t *gai;
348 graph_analysis_item_t *new_gai;
352 /* add each rtp stream to the graph */
353 rtp_streams_list = g_list_first(rtp_tapinfo->list);
354 while (rtp_streams_list)
356 rtp_listinfo = rtp_streams_list->data;
358 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
359 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
361 while (voip_calls_graph_list)
363 gai = voip_calls_graph_list->data;
364 conv_num = gai->conv_num;
365 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
366 if (rtp_listinfo->setup_frame_number == gai->frame_num){
367 while(voip_calls_graph_list){
368 gai = voip_calls_graph_list->data;
369 /* if RTP was already in the Graph, just update the comment information */
370 if (rtp_listinfo->first_frame_num == gai->frame_num){
371 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
372 g_free(gai->comment);
373 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);
375 /* add the RTP item to the graph if was not there*/
376 } else if (rtp_listinfo->first_frame_num<gai->frame_num){
377 new_gai = g_malloc(sizeof(graph_analysis_item_t));
378 new_gai->frame_num = rtp_listinfo->first_frame_num;
379 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
380 g_memmove(&new_gai->ip_src, rtp_listinfo->src_addr.data, 4);
381 g_memmove(&new_gai->ip_dst, rtp_listinfo->dest_addr.data, 4);
382 new_gai->port_src = rtp_listinfo->src_port;
383 new_gai->port_dst = rtp_listinfo->dest_port;
384 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
385 new_gai->frame_label = g_strdup_printf("RTP (%s)", val_to_str(rtp_listinfo->pt, rtp_payload_type_short_vals, "%u"));
386 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);
387 new_gai->conv_num = conv_num;
388 new_gai->display=FALSE;
389 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
390 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
394 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
399 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
402 rtp_streams_list = g_list_next(rtp_streams_list);
406 static gboolean have_RTP_tap_listener=FALSE;
407 /****************************************************************************/
411 GString *error_string;
413 if(have_RTP_tap_listener==FALSE)
415 /* don't register tap listener, if we have it already */
416 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
421 if (error_string != NULL) {
422 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
424 g_string_free(error_string, TRUE);
427 have_RTP_tap_listener=TRUE;
433 /* XXX just copied from gtk/rpc_stat.c */
434 void protect_thread_critical_region(void);
435 void unprotect_thread_critical_region(void);
437 /****************************************************************************/
439 remove_tap_listener_rtp(void)
441 protect_thread_critical_region();
442 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
443 unprotect_thread_critical_region();
445 have_RTP_tap_listener=FALSE;
448 /****************************************************************************/
449 /* ***************************TAP for SIP **********************************/
450 /****************************************************************************/
452 /****************************************************************************/
453 /* whenever a SIP packet is seen by the tap listener */
455 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
457 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
458 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
459 be compared with existing calls */
461 voip_calls_info_t *tmp_listinfo;
462 voip_calls_info_t *strinfo = NULL;
463 sip_calls_info_t *tmp_sipinfo = NULL;
465 guint32 tmp_src, tmp_dst;
466 gchar *frame_label = NULL;
467 gchar *comment = NULL;
469 const sip_info_value_t *pi = SIPinfo;
471 /* do not consider packets without call_id */
472 if (pi->tap_call_id ==NULL){
476 /* check wether we already have a call with these parameters in the list */
477 list = g_list_first(tapinfo->strinfo_list);
480 tmp_listinfo=list->data;
481 if (tmp_listinfo->protocol == VOIP_SIP){
482 tmp_sipinfo = tmp_listinfo->prot_info;
483 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
484 strinfo = (voip_calls_info_t*)(list->data);
488 list = g_list_next (list);
491 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
492 if ((strinfo==NULL) &&(pi->request_method!=NULL)){
493 if (strcmp(pi->request_method,"INVITE")==0){
494 strinfo = g_malloc(sizeof(voip_calls_info_t));
495 strinfo->call_active_state = VOIP_ACTIVE;
496 strinfo->call_state = VOIP_CALL_SETUP;
497 strinfo->from_identity=g_strdup(pi->tap_from_addr);
498 strinfo->to_identity=g_strdup(pi->tap_to_addr);
499 g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
500 strinfo->first_frame_num=pinfo->fd->num;
501 strinfo->selected=FALSE;
502 strinfo->start_sec=pinfo->fd->rel_secs;
503 strinfo->start_usec=pinfo->fd->rel_usecs;
504 strinfo->protocol=VOIP_SIP;
505 strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
506 tmp_sipinfo=strinfo->prot_info;
507 tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
508 tmp_sipinfo->sip_state=SIP_INVITE_SENT;
509 tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
510 strinfo->npackets = 0;
511 strinfo->call_num = tapinfo->ncalls++;
512 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
516 g_free(pi->tap_from_addr);
517 g_free(pi->tap_to_addr);
518 g_free(pi->tap_call_id);
522 /* let's analyze the call state */
524 g_memmove(&(tmp_src), pinfo->src.data, 4);
525 g_memmove(&(tmp_dst), pinfo->dst.data, 4);
527 if (pi->request_method == NULL){
528 frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase );
529 comment = g_strdup_printf("SIP Status");
531 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(tmp_dst==strinfo->initial_speaker)){
532 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
533 tmp_sipinfo->sip_state = SIP_200_REC;
535 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
536 strinfo->call_state = VOIP_REJECTED;
537 tapinfo->rejected_calls++;
543 frame_label = g_strdup(pi->request_method);
545 if ((strcmp(pi->request_method,"INVITE")==0)&&(tmp_src == strinfo->initial_speaker)){
546 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
547 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
549 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
550 &&(tmp_src == strinfo->initial_speaker)&&(tmp_sipinfo->sip_state==SIP_200_REC)){
551 strinfo->call_state = VOIP_IN_CALL;
552 comment = g_strdup_printf("SIP Request");
554 else if (strcmp(pi->request_method,"BYE")==0){
555 strinfo->call_state = VOIP_COMPLETED;
556 tapinfo->completed_calls++;
557 comment = g_strdup_printf("SIP Request");
559 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
560 &&(tmp_src == strinfo->initial_speaker)&&(strinfo->call_state==VOIP_CALL_SETUP)){
561 strinfo->call_state = VOIP_CANCELLED;
562 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
563 comment = g_strdup_printf("SIP Request");
565 comment = g_strdup_printf("SIP Request");
569 strinfo->stop_sec=pinfo->fd->rel_secs;
570 strinfo->stop_usec=pinfo->fd->rel_usecs;
571 strinfo->last_frame_num=pinfo->fd->num;
572 ++(strinfo->npackets);
573 /* increment the packets counter of all calls */
574 ++(tapinfo->npackets);
576 /* add to the graph */
577 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
581 return 1; /* refresh output */
585 /****************************************************************************/
586 const voip_calls_tapinfo_t* voip_calls_get_info(void)
588 return &the_tapinfo_struct;
592 /****************************************************************************/
594 /****************************************************************************/
595 static gboolean have_SIP_tap_listener=FALSE;
596 /****************************************************************************/
598 sip_calls_init_tap(void)
600 GString *error_string;
602 if(have_SIP_tap_listener==FALSE)
604 /* don't register tap listener, if we have it already */
605 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
606 voip_calls_dlg_reset,
610 if (error_string != NULL) {
611 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
613 g_string_free(error_string, TRUE);
616 have_SIP_tap_listener=TRUE;
622 /* XXX just copied from gtk/rpc_stat.c */
623 void protect_thread_critical_region(void);
624 void unprotect_thread_critical_region(void);
626 /****************************************************************************/
628 remove_tap_listener_sip_calls(void)
630 protect_thread_critical_region();
631 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
632 unprotect_thread_critical_region();
634 have_SIP_tap_listener=FALSE;
637 /****************************************************************************/
638 /* ***************************TAP for ISUP **********************************/
639 /****************************************************************************/
641 static gchar isup_called_number[255], isup_calling_number[255];
642 static guint16 isup_cic;
643 static guint8 isup_message_type;
644 static guint8 isup_cause_value;
646 /****************************************************************************/
647 /* whenever a isup_ packet is seen by the tap listener */
649 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
651 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
652 const isup_tap_rec_t *pi = isup_info;
654 if (pi->calling_number!=NULL){
655 strcpy(isup_calling_number, pi->calling_number);
657 if (pi->called_number!=NULL){
658 strcpy(isup_called_number, pi->called_number);
660 isup_message_type = pi->message_type;
661 isup_cause_value = pi->cause_value;
662 isup_cic = pinfo->circuit_id;
667 /****************************************************************************/
669 static gboolean have_isup_tap_listener=FALSE;
672 isup_calls_init_tap(void)
674 GString *error_string;
677 if(have_isup_tap_listener==FALSE)
679 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
681 voip_calls_dlg_reset,
686 if (error_string != NULL) {
687 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
689 g_string_free(error_string, TRUE);
692 have_isup_tap_listener=TRUE;
696 /****************************************************************************/
699 remove_tap_listener_isup_calls(void)
701 protect_thread_critical_region();
702 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
703 unprotect_thread_critical_region();
705 have_isup_tap_listener=FALSE;
709 /****************************************************************************/
710 /* ***************************TAP for MTP3 **********************************/
711 /****************************************************************************/
714 /****************************************************************************/
715 /* whenever a mtp3_ packet is seen by the tap listener */
717 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
719 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
720 voip_calls_info_t *tmp_listinfo;
721 voip_calls_info_t *strinfo = NULL;
722 isup_calls_info_t *tmp_isupinfo;
723 gboolean found = FALSE;
724 gboolean forward = FALSE;
725 gboolean right_pair = TRUE;
727 gchar *frame_label = NULL;
728 gchar *comment = NULL;
731 const mtp3_tap_rec_t *pi = mtp3_info;
733 /* check wether we already have a call with these parameters in the list */
734 list = g_list_first(tapinfo->strinfo_list);
737 tmp_listinfo=list->data;
738 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
739 tmp_isupinfo = tmp_listinfo->prot_info;
740 if ((tmp_isupinfo->cic == isup_cic)&&(tmp_isupinfo->ni == pi->addr_opc.ni)) {
741 if ((tmp_isupinfo->opc == pi->addr_opc.pc)&&(tmp_isupinfo->dpc == pi->addr_dpc.pc)){
744 else if ((tmp_isupinfo->dpc == pi->addr_opc.pc)&&(tmp_isupinfo->opc == pi->addr_dpc.pc)){
748 /* XXX: what about forward is it FALSE as declared or should it be true */
752 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
753 cic is no longer active */
754 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
757 else if (isup_message_type != 1){
761 tmp_listinfo->call_active_state=VOIP_INACTIVE;
765 strinfo = (voip_calls_info_t*)(list->data);
770 list = g_list_next (list);
773 /* not in the list? then create a new entry if the message is IAM
774 -i.e. if this session is a call*/
777 if ((strinfo==NULL) &&(isup_message_type==1)){
779 strinfo = g_malloc(sizeof(voip_calls_info_t));
780 strinfo->call_active_state = VOIP_ACTIVE;
781 strinfo->call_state = VOIP_UNKNOWN;
782 g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
783 strinfo->selected=FALSE;
784 strinfo->first_frame_num=pinfo->fd->num;
785 strinfo->start_sec=pinfo->fd->rel_secs;
786 strinfo->start_usec=pinfo->fd->rel_usecs;
787 strinfo->protocol=VOIP_ISUP;
788 strinfo->from_identity=g_strdup(isup_calling_number);
789 strinfo->to_identity=g_strdup(isup_called_number);
790 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
791 tmp_isupinfo=strinfo->prot_info;
792 tmp_isupinfo->opc = pi->addr_opc.pc;
793 tmp_isupinfo->dpc = pi->addr_dpc.pc;
794 tmp_isupinfo->ni = pi->addr_opc.ni;
795 tmp_isupinfo->cic = pinfo->circuit_id;
796 strinfo->npackets = 0;
797 strinfo->call_num = tapinfo->ncalls++;
798 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
802 strinfo->stop_sec=pinfo->fd->rel_secs;
803 strinfo->stop_usec=pinfo->fd->rel_usecs;
804 strinfo->last_frame_num=pinfo->fd->num;
805 ++(strinfo->npackets);
807 /* Let's analyze the call state */
810 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=isup_message_type);i++);
812 if (isup_message_type_value[i].value==isup_message_type){
813 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
816 frame_label = g_strdup_printf("Unknown");
819 if (strinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
820 comment = g_strdup_printf("Call from %s to %s",
821 isup_calling_number, isup_called_number);
823 else if (strinfo->npackets == 2){ /* in the second packet we show the SPs */
825 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
826 pi->addr_opc.ni, pi->addr_opc.pc,
827 pi->addr_opc.ni, pi->addr_dpc.pc, pinfo->circuit_id);
831 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
832 pi->addr_opc.ni, pi->addr_dpc.pc,
833 pi->addr_opc.ni, pi->addr_opc.pc, pinfo->circuit_id);
838 switch(isup_message_type){
840 strinfo->call_state=VOIP_CALL_SETUP;
842 case 7: /* CONNECT */
844 strinfo->call_state=VOIP_IN_CALL;
846 case 12: /* RELEASE */
847 if (strinfo->call_state==VOIP_CALL_SETUP){
849 strinfo->call_state=VOIP_CANCELLED;
852 strinfo->call_state=VOIP_REJECTED;
853 tapinfo->rejected_calls++;
856 else if (strinfo->call_state == VOIP_IN_CALL){
857 strinfo->call_state = VOIP_COMPLETED;
858 tapinfo->completed_calls++;
860 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=isup_cause_value);i++);
861 if (q931_cause_code_vals[i].value==isup_cause_value){
862 comment = g_strdup_printf("Cause %i - %s",isup_cause_value, q931_cause_code_vals[i].strptr);
865 comment = g_strdup_printf("Cause %i",isup_cause_value);
870 /* increment the packets counter of all calls */
871 ++(tapinfo->npackets);
873 /* add to the graph */
874 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
883 /****************************************************************************/
885 static gboolean have_mtp3_tap_listener=FALSE;
888 mtp3_calls_init_tap(void)
890 GString *error_string;
893 if(have_mtp3_tap_listener==FALSE)
895 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
897 voip_calls_dlg_reset,
902 if (error_string != NULL) {
903 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
905 g_string_free(error_string, TRUE);
908 have_mtp3_tap_listener=TRUE;
912 /****************************************************************************/
915 remove_tap_listener_mtp3_calls(void)
917 protect_thread_critical_region();
918 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
919 unprotect_thread_critical_region();
921 have_mtp3_tap_listener=FALSE;
924 /****************************************************************************/
925 /* ***************************TAP for Q931 **********************************/
926 /****************************************************************************/
928 static gchar *q931_calling_number;
929 static gchar *q931_called_number;
930 static guint8 q931_cause_value;
931 static gint32 q931_crv;
932 static guint32 q931_frame_num;
934 /****************************************************************************/
935 /* whenever a q931_ packet is seen by the tap listener */
937 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
939 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; */
940 const q931_packet_info *pi = q931_info;
942 /* free previously allocated q931_calling/ed_number */
943 g_free(q931_calling_number);
944 g_free(q931_called_number);
946 if (pi->calling_number!=NULL)
947 q931_calling_number = g_strdup(pi->calling_number);
949 q931_calling_number = g_strdup("");
951 if (pi->called_number!=NULL)
952 q931_called_number = g_strdup(pi->called_number);
954 q931_called_number = g_strdup("");
955 q931_cause_value = pi->cause_value;
956 q931_frame_num = pinfo->fd->num;
962 /****************************************************************************/
963 static gboolean have_q931_tap_listener=FALSE;
966 q931_calls_init_tap(void)
968 GString *error_string;
971 if(have_q931_tap_listener==FALSE)
973 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
975 voip_calls_dlg_reset,
980 if (error_string != NULL) {
981 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
983 g_string_free(error_string, TRUE);
986 have_q931_tap_listener=TRUE;
990 /****************************************************************************/
993 remove_tap_listener_q931_calls(void)
995 protect_thread_critical_region();
996 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
997 unprotect_thread_critical_region();
999 have_q931_tap_listener=FALSE;
1002 /****************************************************************************/
1003 /****************************TAP for H323 ***********************************/
1004 /****************************************************************************/
1007 static const guint8 guid_allzero[GUID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1008 /* defines specific H323 data */
1010 void add_h245_Address(h323_calls_info_t *h323info, guint32 h245_address, guint16 h245_port)
1012 h245_address_t *h245_add = NULL;
1014 h245_add = g_malloc(sizeof(h245_address_t));
1015 h245_add->h245_address = h245_address;
1016 h245_add->h245_port = h245_port;
1018 h323info->h245_list = g_list_append(h323info->h245_list, h245_add);
1021 /****************************************************************************/
1022 /* whenever a H225 packet is seen by the tap listener */
1024 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1026 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1027 voip_calls_info_t *tmp_listinfo;
1028 voip_calls_info_t *strinfo = NULL;
1029 h323_calls_info_t *tmp_h323info = NULL;
1030 h323_calls_info_t *tmp2_h323info;
1034 guint32 tmp_src, tmp_dst;
1037 const h225_packet_info *pi = H225info;
1039 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1040 if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20)))
1044 if ( (memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (q931_frame_num == pinfo->fd->num) ){
1045 /* check wether we already have a call with this Q931 CRV */
1046 list = g_list_first(tapinfo->strinfo_list);
1049 tmp_listinfo=list->data;
1050 if (tmp_listinfo->protocol == VOIP_H323){
1051 tmp_h323info = tmp_listinfo->prot_info;
1052 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1053 strinfo = (voip_calls_info_t*)(list->data);
1057 list = g_list_next (list);
1059 if (strinfo==NULL) return 0;
1060 } else if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) { /* RAS LCF or LRJ*/
1061 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1062 if (!pi->request_available) return 0;
1064 /* check wether we already have a call with this request SeqNum */
1065 list = g_list_first(tapinfo->strinfo_list);
1068 tmp_listinfo=list->data;
1069 if (tmp_listinfo->protocol == VOIP_H323){
1070 tmp_h323info = tmp_listinfo->prot_info;
1071 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1072 strinfo = (voip_calls_info_t*)(list->data);
1076 list = g_list_next (list);
1079 /* check wether we already have a call with this guid in the list */
1080 list = g_list_first(tapinfo->strinfo_list);
1083 tmp_listinfo=list->data;
1084 if (tmp_listinfo->protocol == VOIP_H323){
1085 tmp_h323info = tmp_listinfo->prot_info;
1086 if ( (memcmp(tmp_h323info->guid, guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0) ){
1087 strinfo = (voip_calls_info_t*)(list->data);
1091 list = g_list_next (list);
1095 /* not in the list? then create a new entry */
1096 if ((strinfo==NULL)){
1097 strinfo = g_malloc(sizeof(voip_calls_info_t));
1098 strinfo->call_active_state = VOIP_ACTIVE;
1099 strinfo->call_state = VOIP_UNKNOWN;
1100 strinfo->from_identity=g_strdup("");
1101 strinfo->to_identity=g_strdup("");
1103 g_memmove(&(strinfo->initial_speaker), pinfo->src.data,4);
1104 strinfo->selected=FALSE;
1105 strinfo->first_frame_num=pinfo->fd->num;
1106 strinfo->start_sec=pinfo->fd->rel_secs;
1107 strinfo->start_usec=pinfo->fd->rel_usecs;
1108 strinfo->protocol=VOIP_H323;
1109 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1110 tmp_h323info = strinfo->prot_info;
1111 tmp_h323info->guid = (guint8 *) g_memdup(pi->guid,GUID_LEN);
1112 tmp_h323info->h225SetupAddr = 0;
1113 tmp_h323info->h245_list = NULL;
1114 tmp_h323info->is_faststart_Setup = FALSE;
1115 tmp_h323info->is_faststart_Proc = FALSE;
1116 tmp_h323info->is_h245Tunneling = FALSE;
1117 tmp_h323info->is_h245 = FALSE;
1118 tmp_h323info->q931_crv = -1;
1119 tmp_h323info->q931_crv2 = -1;
1120 tmp_h323info->requestSeqNum = 0;
1121 strinfo->call_num = tapinfo->ncalls++;
1122 strinfo->npackets = 0;
1124 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1127 /* let's analyze the call state */
1129 g_memmove(&(tmp_src), pinfo->src.data, 4);
1130 g_memmove(&(tmp_dst), pinfo->dst.data, 4);
1132 strinfo->stop_sec=pinfo->fd->rel_secs;
1133 strinfo->stop_usec=pinfo->fd->rel_usecs;
1134 strinfo->last_frame_num=pinfo->fd->num;
1135 ++(strinfo->npackets);
1136 /* increment the packets counter of all calls */
1137 ++(tapinfo->npackets);
1139 /* XXX: it is supposed to be initialized isn't it? */
1140 g_assert(tmp_h323info != NULL);
1142 /* change the status */
1143 if (pi->msg_type == H225_CS) {
1144 if (tmp_h323info->q931_crv == -1) {
1145 tmp_h323info->q931_crv = q931_crv;
1146 } else if (tmp_h323info->q931_crv != q931_crv) {
1147 tmp_h323info->q931_crv2 = q931_crv;
1150 if (pi->is_h245 == TRUE){
1151 add_h245_Address(tmp_h323info, pi->h245_address, pi->h245_port);
1154 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1156 frame_label = g_strdup(pi->frame_label);
1158 switch(pi->cs_type){
1160 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1161 /* set te calling and called number from the Q931 packet */
1162 if (q931_frame_num == pinfo->fd->num){
1163 if (q931_calling_number != NULL){
1164 g_free(strinfo->from_identity);
1165 strinfo->from_identity=g_strdup(q931_calling_number);
1167 if (q931_called_number != NULL){
1168 g_free(strinfo->to_identity);
1169 strinfo->to_identity=g_strdup(q931_called_number);
1172 /* check if there is an LRQ/LCF that match this Setup */
1173 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1174 we should also check if the h225 signaling IP and port match the destination
1175 Setup ip and port */
1176 list = g_list_first(tapinfo->strinfo_list);
1177 foo= g_list_length(list);
1180 tmp_listinfo=list->data;
1181 if (tmp_listinfo->protocol == VOIP_H323){
1182 tmp2_h323info = tmp_listinfo->prot_info;
1184 /* check if there called number match a LRQ/LCF */
1185 if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)
1186 && (memcmp(tmp2_h323info->guid, guid_allzero, GUID_LEN) == 0) ){
1187 /* change the call graph to the LRQ/LCF to belong to this call */
1188 strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
1190 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1191 g_free(tmp_listinfo->from_identity);
1192 g_free(tmp_listinfo->to_identity);
1193 g_free(tmp2_h323info->guid);
1194 g_list_free(tmp2_h323info->h245_list);
1195 tmp2_h323info->h245_list = NULL;
1196 g_free(tmp_listinfo->prot_info);
1197 tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
1201 list = g_list_next (list);
1203 foo = g_list_length(list);
1204 /* Set the Setup address if it was not set */
1205 if (tmp_h323info->h225SetupAddr == 0) g_memmove(&(tmp_h323info->h225SetupAddr), pinfo->src.data,4);
1206 strinfo->call_state=VOIP_CALL_SETUP;
1207 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"),
1208 (pi->is_faststart==TRUE?"on":"off"));
1211 strinfo->call_state=VOIP_IN_CALL;
1212 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1213 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1214 (pi->is_faststart==TRUE?"on":"off"));
1216 case H225_RELEASE_COMPLET:
1217 g_memmove(&(tmp_src), pinfo->src.data, 4);
1218 if (strinfo->call_state==VOIP_CALL_SETUP){
1219 if (tmp_h323info->h225SetupAddr == tmp_src){ /* forward direction */
1220 strinfo->call_state=VOIP_CANCELLED;
1223 strinfo->call_state=VOIP_REJECTED;
1224 tapinfo->rejected_calls++;
1228 strinfo->call_state=VOIP_REJECTED;
1229 tapinfo->rejected_calls++;
1231 /* get the Q931 Release cause code */
1232 if (q931_frame_num == pinfo->fd->num &&
1233 q931_cause_value != 0xFF){
1234 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1235 } else { /* Cause not set */
1236 comment = g_strdup("H225 No Q931 Rel Cause");
1241 case H225_CALL_PROCEDING:
1242 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1243 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1244 (pi->is_faststart==TRUE?"on":"off"));
1247 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1248 (pi->is_faststart==TRUE?"on":"off"));
1251 } else if (pi->msg_type == H225_RAS){
1252 switch(pi->msg_tag){
1254 if (!pi->is_duplicate){
1255 g_free(strinfo->to_identity);
1256 strinfo->to_identity=g_strdup(pi->dialedDigits);
1257 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1260 if (strlen(pi->dialedDigits))
1261 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1263 comment = g_strdup("H225 RAS");
1266 comment = g_strdup("H225 RAS");
1268 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1270 frame_label = g_strdup("H225: Unknown");
1271 comment = g_strdup("");
1274 /* add to graph analysis */
1276 /* if the frame number exists in graph, append to it*/
1277 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1278 /* if not exist, add to the graph */
1279 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
1282 g_free(frame_label);
1285 return 1; /* refresh output */
1289 /****************************************************************************/
1291 /****************************************************************************/
1292 static gboolean have_H225_tap_listener=FALSE;
1293 /****************************************************************************/
1295 h225_calls_init_tap(void)
1297 GString *error_string;
1299 if(have_H225_tap_listener==FALSE)
1301 /* don't register tap listener, if we have it already */
1302 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1303 voip_calls_dlg_reset,
1308 if (error_string != NULL) {
1309 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1311 g_string_free(error_string, TRUE);
1314 have_H225_tap_listener=TRUE;
1320 /* XXX just copied from gtk/rpc_stat.c */
1321 void protect_thread_critical_region(void);
1322 void unprotect_thread_critical_region(void);
1324 /****************************************************************************/
1326 remove_tap_listener_h225_calls(void)
1328 protect_thread_critical_region();
1329 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1330 unprotect_thread_critical_region();
1332 have_H225_tap_listener=FALSE;
1336 /****************************************************************************/
1337 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1339 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
1341 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1342 voip_calls_info_t *tmp_listinfo;
1343 voip_calls_info_t *strinfo = NULL;
1344 h323_calls_info_t *tmp_h323info;
1349 guint32 tmp_src, tmp_dst;
1350 h245_address_t *h245_add = NULL;
1352 const h245_packet_info *pi = H245info;
1354 /* if H245 tunneling is on, append to graph */
1355 if (append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) return 1;
1358 /* it is not Tunneling or it is not in the list. So check if there is no tunneling
1359 and there is a call with this H245 address */
1360 list = g_list_first(tapinfo->strinfo_list);
1363 tmp_listinfo=list->data;
1364 if (tmp_listinfo->protocol == VOIP_H323){
1365 tmp_h323info = tmp_listinfo->prot_info;
1367 g_memmove(&(tmp_src), pinfo->src.data, 4);
1368 g_memmove(&(tmp_dst), pinfo->dst.data, 4);
1369 list2 = g_list_first(tmp_h323info->h245_list);
1372 h245_add=list2->data;
1373 if ( ((h245_add->h245_address == tmp_src) && (h245_add->h245_port == pinfo->srcport))
1374 || ((h245_add->h245_address == tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
1375 strinfo = (voip_calls_info_t*)(list->data);
1377 ++(strinfo->npackets);
1378 /* increment the packets counter of all calls */
1379 ++(tapinfo->npackets);
1383 list2 = g_list_next(list2);
1385 if (strinfo!=NULL) break;
1387 list = g_list_next(list);
1391 frame_label = g_strdup(pi->frame_label);
1392 comment = g_strdup(pi->comment);
1393 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
1394 g_free(frame_label);
1398 return 1; /* refresh output */
1402 /****************************************************************************/
1404 /****************************************************************************/
1405 static gboolean have_H245dg_tap_listener=FALSE;
1406 /****************************************************************************/
1408 h245dg_calls_init_tap(void)
1410 GString *error_string;
1412 if(have_H245dg_tap_listener==FALSE)
1414 /* don't register tap listener, if we have it already */
1415 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
1416 voip_calls_dlg_reset,
1421 if (error_string != NULL) {
1422 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1424 g_string_free(error_string, TRUE);
1427 have_H245dg_tap_listener=TRUE;
1432 /* XXX just copied from gtk/rpc_stat.c */
1433 void protect_thread_critical_region(void);
1434 void unprotect_thread_critical_region(void);
1436 /****************************************************************************/
1438 remove_tap_listener_h245dg_calls(void)
1440 protect_thread_critical_region();
1441 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
1442 unprotect_thread_critical_region();
1444 have_H245dg_tap_listener=FALSE;
1447 static gchar *sdp_summary = NULL;
1448 static guint32 sdp_frame_num = 0;
1450 /****************************************************************************/
1451 /****************************TAP for SDP PROTOCOL ***************************/
1452 /****************************************************************************/
1453 /* whenever a SDP packet is seen by the tap listener */
1455 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
1457 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1458 const sdp_packet_info *pi = SDPinfo;
1460 /* There are protocols like MGCP where the SDP is called before the tap for the
1461 MGCP packet, in those cases we assign the SPD summary to global lastSDPsummary
1464 g_free(sdp_summary);
1465 sdp_frame_num = pinfo->fd->num;
1466 /* Append to graph the SDP summary if the packet exists */
1467 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
1468 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1470 return 1; /* refresh output */
1474 /****************************************************************************/
1476 /****************************************************************************/
1477 static gboolean have_sdp_tap_listener=FALSE;
1478 /****************************************************************************/
1480 sdp_calls_init_tap(void)
1482 GString *error_string;
1484 if(have_sdp_tap_listener==FALSE)
1486 /* don't register tap listener, if we have it already */
1487 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
1488 voip_calls_dlg_reset,
1493 if (error_string != NULL) {
1494 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1496 g_string_free(error_string, TRUE);
1499 have_sdp_tap_listener=TRUE;
1504 /* XXX just copied from gtk/rpc_stat.c */
1505 void protect_thread_critical_region(void);
1506 void unprotect_thread_critical_region(void);
1508 /****************************************************************************/
1510 remove_tap_listener_sdp_calls(void)
1512 protect_thread_critical_region();
1513 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
1514 unprotect_thread_critical_region();
1516 have_sdp_tap_listener=FALSE;
1521 /****************************************************************************/
1522 /* ***************************TAP for MGCP **********************************/
1523 /****************************************************************************/
1526 This function will look for a signal/event in the SignalReq/ObsEvent string
1527 and return true if it is found
1529 gboolean isSignal(gchar *signal, gchar *signalStr)
1532 gchar **resultArray;
1534 /* if there is no signalStr, just return false */
1535 if (signalStr == NULL) return FALSE;
1537 /* if are both "blank" return true */
1538 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
1540 /* look for signal in signalSre */
1541 resultArray = g_strsplit(signalStr, ",", 10);
1543 for (i = 0; resultArray[i]; i++) {
1544 g_strstrip(resultArray[i]);
1545 if (strcmp(resultArray[i], signal) == 0) return TRUE;
1548 g_strfreev(resultArray);
1554 This function will get the Caller ID info and replace the current string
1555 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
1557 void mgcpCallerID(gchar *signalStr, gchar **callerId)
1560 gchar **resultArray;
1563 /* if there is no signalStr, just return false */
1564 if (signalStr == NULL) return;
1566 arrayStr = g_strsplit(signalStr, "\"", 10);
1568 if (arrayStr[0] == NULL) return;
1570 /* look for the ci signal */
1571 resultArray = g_strsplit(arrayStr[0], ",(", 10);
1573 for (i = 0; resultArray[i]; i++) {
1574 g_strstrip(resultArray[i]);
1575 if (strcmp(resultArray[i], "ci") == 0){
1576 if (arrayStr[1] != NULL){
1577 /* free the previous "From" field of the call, and assign the new */
1579 *callerId = g_strdup(arrayStr[1]);
1581 g_strfreev(arrayStr);
1582 g_strfreev(resultArray);
1587 g_strfreev(arrayStr);
1588 g_strfreev(resultArray);
1595 This function will get the Dialed Digits and replace the current string
1596 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
1598 void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
1601 gchar resultStr[50];
1604 /* if there is no signalStr, just return false */
1605 if (signalStr == NULL) return;
1607 tmpStr = g_strdup(signalStr);
1609 for ( i = 0 ; tmpStr[i] ; i++) {
1610 switch (tmpStr[i]) {
1611 case '0' : case '1' : case '2' : case '3' : case '4' :
1612 case '5' : case '6' : case '7' : case '8' : case '9' :
1613 case '#' : case '*' :
1621 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
1622 if (tmpStr[i] != '?')
1623 resultStr[j++] = tmpStr[i];
1625 resultStr[j] = '\0';
1627 if (*resultStr == '\0') return;
1629 g_free(*dialedDigits);
1630 *dialedDigits = g_strdup(resultStr);
1638 /****************************************************************************/
1639 /* whenever a MGCP packet is seen by the tap listener */
1641 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
1643 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1645 voip_calls_info_t *tmp_listinfo;
1646 voip_calls_info_t *strinfo = NULL;
1647 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
1650 gchar *frame_label = NULL;
1651 gchar *comment = NULL;
1652 graph_analysis_item_t *gai;
1653 gboolean new = FALSE;
1654 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
1657 const mgcp_info_t *pi = MGCPinfo;
1660 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
1661 /* check wether we already have a call with this Endpoint and it is active*/
1662 list = g_list_first(tapinfo->strinfo_list);
1665 tmp_listinfo=list->data;
1666 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
1667 tmp_mgcpinfo = tmp_listinfo->prot_info;
1668 if (pi->endpointId != NULL){
1669 if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
1671 check first if it is an ended call. We consider an ended call after 1sec we don't
1672 get a packet in this Endpoint and the call has been released
1674 diff_time = (pinfo->fd->rel_secs + (double)pinfo->fd->rel_secs/1000000) - (tmp_listinfo->stop_sec + (double)tmp_listinfo->stop_usec/1000000);
1675 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) || (tmp_listinfo->call_state == VOIP_COMPLETED) || (tmp_listinfo->call_state == VOIP_REJECTED)) && (diff_time > 1) ){
1676 tmp_listinfo->call_active_state = VOIP_INACTIVE;
1678 strinfo = (voip_calls_info_t*)(list->data);
1684 list = g_list_next (list);
1687 /* there is no call with this Endpoint, lets see if this a new call or not */
1688 if (strinfo == NULL){
1689 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
1690 /* this is a new call from the Endpoint */
1691 fromEndpoint = TRUE;
1693 } else if (strcmp(pi->code, "CRCX") == 0){
1694 /* this is a new call from the MGC */
1695 fromEndpoint = FALSE;
1700 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
1701 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
1702 /* if it is a response OR if it is a duplicated Request, lets look in the Graph if thre is a request that match */
1703 listGraph = g_list_first(tapinfo->graph_analysis->list);
1706 gai = listGraph->data;
1707 if (gai->frame_num == pi->req_num){
1708 /* there is a request that match, so look the associated call with this call_num */
1709 list = g_list_first(tapinfo->strinfo_list);
1712 tmp_listinfo=list->data;
1713 if (tmp_listinfo->protocol == VOIP_MGCP){
1714 if (tmp_listinfo->call_num == gai->conv_num){
1715 tmp_mgcpinfo = tmp_listinfo->prot_info;
1716 strinfo = (voip_calls_info_t*)(list->data);
1720 list = g_list_next (list);
1722 if (strinfo != NULL) break;
1724 listGraph = g_list_next(listGraph);
1726 /* if there is not a matching request, just return */
1727 if (strinfo == NULL) return 0;
1730 /* not in the list? then create a new entry */
1732 strinfo = g_malloc(sizeof(voip_calls_info_t));
1733 strinfo->call_active_state = VOIP_ACTIVE;
1734 strinfo->call_state = VOIP_CALL_SETUP;
1736 strinfo->from_identity=g_strdup(pi->endpointId);
1737 strinfo->to_identity=g_strdup("");
1739 strinfo->from_identity=g_strdup("");
1740 strinfo->to_identity=g_strdup(pi->endpointId);
1742 g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
1743 strinfo->first_frame_num=pinfo->fd->num;
1744 strinfo->selected=FALSE;
1745 strinfo->start_sec=pinfo->fd->rel_secs;
1746 strinfo->start_usec=pinfo->fd->rel_usecs;
1747 strinfo->protocol=VOIP_MGCP;
1748 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
1749 tmp_mgcpinfo=strinfo->prot_info;
1750 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
1751 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
1752 strinfo->npackets = 0;
1753 strinfo->call_num = tapinfo->ncalls++;
1754 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1757 g_assert(tmp_mgcpinfo != NULL);
1759 /* change call state and add to graph */
1760 switch (pi->mgcp_type)
1763 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
1764 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
1766 if (tmp_mgcpinfo->fromEndpoint){
1767 /* use the Dialed digits to fill the "To" for the call */
1768 mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
1770 /* from MGC and the user picked up, the call is connected */
1771 } else if (isSignal("hd", pi->observedEvents))
1772 strinfo->call_state=VOIP_IN_CALL;
1774 /* hung up signal */
1775 if (isSignal("hu", pi->observedEvents)) {
1776 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
1777 strinfo->call_state = VOIP_CANCELLED;
1779 strinfo->call_state = VOIP_COMPLETED;
1783 } else if (strcmp(pi->code, "RQNT") == 0) {
1784 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
1785 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) {
1786 strinfo->call_state = VOIP_IN_CALL;
1789 /* if there is ringback or ring tone, change state to ringing */
1790 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
1791 strinfo->call_state = VOIP_RINGING;
1794 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
1795 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) {
1796 strinfo->call_state = VOIP_REJECTED;
1799 if (pi->signalReq != NULL)
1800 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
1802 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
1804 /* use the CallerID info to fill the "From" for the call */
1805 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
1807 } else if (strcmp(pi->code, "DLCX") == 0) {
1809 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
1810 the DLCX as the end of the call
1812 if (!tmp_mgcpinfo->fromEndpoint){
1813 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
1814 strinfo->call_state = VOIP_CANCELLED;
1819 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
1822 frame_label = g_strdup_printf("%d (%s)",pi->rspcode, pi->code);
1825 /* XXX what to do? */
1830 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
1832 strinfo->stop_sec=pinfo->fd->rel_secs;
1833 strinfo->stop_usec=pinfo->fd->rel_usecs;
1834 strinfo->last_frame_num=pinfo->fd->num;
1835 ++(strinfo->npackets);
1836 /* increment the packets counter of all calls */
1837 ++(tapinfo->npackets);
1839 /* add to the graph */
1840 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
1842 g_free(frame_label);
1844 /* add SDP info if apply */
1845 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1846 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1847 g_free(sdp_summary);
1851 return 1; /* refresh output */
1855 /****************************************************************************/
1857 /****************************************************************************/
1858 static gboolean have_MGCP_tap_listener=FALSE;
1859 /****************************************************************************/
1861 mgcp_calls_init_tap(void)
1863 GString *error_string;
1865 if(have_MGCP_tap_listener==FALSE)
1867 /* don't register tap listener, if we have it already */
1868 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
1869 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
1870 voip_calls_dlg_reset,
1874 if (error_string != NULL) {
1875 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1877 g_string_free(error_string, TRUE);
1880 have_MGCP_tap_listener=TRUE;
1886 /* XXX just copied from gtk/rpc_stat.c */
1887 void protect_thread_critical_region(void);
1888 void unprotect_thread_critical_region(void);
1890 /****************************************************************************/
1892 remove_tap_listener_mgcp_calls(void)
1894 protect_thread_critical_region();
1895 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
1896 unprotect_thread_critical_region();
1898 have_MGCP_tap_listener=FALSE;
1903 /****************************************************************************/
1904 /* ***************************TAP for OTHER PROTOCOL **********************************/
1905 /****************************************************************************/
1907 /****************************************************************************/
1908 /* whenever a prot_ packet is seen by the tap listener */
1911 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
1913 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1915 strinfo->stop_sec=pinfo->fd->rel_secs;
1916 strinfo->stop_usec=pinfo->fd->rel_usecs;
1917 strinfo->last_frame_num=pinfo->fd->num;
1918 ++(strinfo->npackets);
1919 ++(tapinfo->npackets);
1925 /****************************************************************************/
1927 static gboolean have_prot__tap_listener=FALSE;
1930 prot_calls_init_tap(void)
1932 GString *error_string;
1934 if(have_prot__tap_listener==FALSE)
1936 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
1938 voip_calls_dlg_reset,
1943 if (error_string != NULL) {
1944 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1946 g_string_free(error_string, TRUE);
1949 have_prot__tap_listener=TRUE;
1953 /****************************************************************************/
1956 remove_tap_listener_prot__calls(void)
1958 protect_thread_critical_region();
1959 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
1960 unprotect_thread_critical_region();
1962 have_prot__tap_listener=FALSE;