From Alejandro Vaqero:
[obnox/wireshark/wip.git] / gtk / voip_calls.c
index 890d1fe7ea216394c53d44109b4307147629303d..d69443fc1213d36a53467393527e1d333801dcdc 100644 (file)
@@ -10,7 +10,7 @@
  * Copyright 2004, Iskratel, Ltd, Kranj
  * By Miha Jemec <m.jemec@iskratel.si>
  * 
- * H323, RTP and Graph Support
+ * H323, RTP, MGCP and Graph Support
  * By Alejandro Vaquero, alejandro.vaquero@verso.com
  * Copyright 2005, Verso Technologies Inc.
  *
 # include "config.h"
 #endif
 
+#include <string.h>
+
 #include "graph_analysis.h"
 #include "voip_calls.h"
 #include "voip_calls_dlg.h"
-#include "rtp_stream.h"
 
 #include "globals.h"
 
 #include <epan/dissectors/packet-h245.h>
 #include <epan/dissectors/packet-q931.h>
 #include <epan/dissectors/packet-sdp.h>
+#include <plugins/mgcp/packet-mgcp.h>
 #include <epan/dissectors/packet-rtp.h>
 #include "rtp_pt.h"
 
 #include "alert_box.h"
 #include "simple_dialog.h"
 
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#include <string.h>
-
-
-char *voip_call_state_name[6]={
+char *voip_call_state_name[7]={
        "CALL SETUP",
+       "RINGING",
        "IN CALL",
        "CANCELLED",
        "COMPLETED",
@@ -79,10 +71,11 @@ char *voip_call_state_name[6]={
        };
 
 /* defines whether we can consider the call active */
-char *voip_protocol_name[3]={
+char *voip_protocol_name[4]={
        "SIP",
        "ISUP",
-       "H323"
+       "H323",
+       "MGCP"
        };
 
 
@@ -90,7 +83,7 @@ char *voip_protocol_name[3]={
 /****************************************************************************/
 /* the one and only global voip_calls_tapinfo_t structure */
 static voip_calls_tapinfo_t the_tapinfo_struct =
-       {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
+       {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0};
 
 /* the one and only global voip_rtp_tapinfo_t structure */
 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
@@ -103,6 +96,7 @@ void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
        voip_calls_info_t *strinfo;
        sip_calls_info_t *tmp_sipinfo;
        h323_calls_info_t *tmp_h323info;
+       h245_address_t *h245_add;
 
        graph_analysis_item_t *graph_item;
 
@@ -116,6 +110,7 @@ void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
                strinfo = list->data;
                g_free(strinfo->from_identity);
                g_free(strinfo->to_identity);
+               g_free((void *)(strinfo->initial_speaker.data));
                if (strinfo->protocol == VOIP_SIP){
                        tmp_sipinfo = strinfo->prot_info;
                        g_free(tmp_sipinfo->call_identifier);
@@ -127,6 +122,8 @@ void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
                        list2 = g_list_first(tmp_h323info->h245_list);
                        while (list2)
                        {
+                               h245_add=list2->data;
+                               g_free((void *)h245_add->h245_address.data);
                                g_free(list2->data);
                                list2 = g_list_next(list2);
                        }
@@ -182,8 +179,8 @@ int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, gchar *f
        gai = g_malloc(sizeof(graph_analysis_item_t));
        gai->frame_num = pinfo->fd->num;
        gai->time= (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
-       g_memmove(&gai->ip_src, pinfo->src.data, 4);
-       g_memmove(&gai->ip_dst, pinfo->dst.data, 4);
+       COPY_ADDRESS(&(gai->src_addr),&(pinfo->src));
+       COPY_ADDRESS(&(gai->dst_addr),&(pinfo->dst));
        gai->port_src=pinfo->srcport;
        gai->port_dst=pinfo->destport;
        if (frame_label != NULL)
@@ -242,6 +239,28 @@ int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num,
 
 }
 
+/****************************************************************************/
+/* Change all the graph items with call_num to new_call_num */
+guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
+{
+       graph_analysis_item_t *gai;
+       GList* list;
+       guint items_changed;
+
+       items_changed = 0;
+       list = g_list_first(tapinfo->graph_analysis->list);
+       while (list)
+       {
+               gai = list->data;
+               if (gai->conv_num == call_num){
+                       gai->conv_num = new_call_num;
+                       items_changed++;
+               }
+               list = g_list_next (list);
+       }
+       return items_changed;
+}
+
 /****************************************************************************/
 /* ***************************TAP for RTP **********************************/
 /****************************************************************************/
@@ -287,9 +306,16 @@ RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const vo
        while (list)
        {
                tmp_listinfo=list->data;
-               if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) && (tmp_listinfo->ssrc == pi->info_sync_src) ){
+               if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) 
+                       && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
+                       /* if the payload type has changed, we mark the stream as finished to create a new one
+                          this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */           
+                       if ( tmp_listinfo->pt != pi->info_payload_type ) 
+                               tmp_listinfo->end_stream = TRUE;
+                       else {
                                strinfo = (voip_rtp_stream_info_t*)(list->data);
                                break;
+                       }
                }
                list = g_list_next (list);
        }
@@ -302,6 +328,7 @@ RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const vo
                COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
                strinfo->dest_port = pinfo->destport;
                strinfo->ssrc = pi->info_sync_src;
+               strinfo->end_stream = FALSE;
                strinfo->pt = pi->info_payload_type;
                strinfo->npackets = 0;
                strinfo->first_frame_num = pinfo->fd->num;
@@ -362,8 +389,8 @@ void RTP_packet_draw(void *prs _U_)
                                                new_gai = g_malloc(sizeof(graph_analysis_item_t));
                                                new_gai->frame_num = rtp_listinfo->first_frame_num;
                                                new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
-                                               g_memmove(&new_gai->ip_src, rtp_listinfo->src_addr.data, 4);
-                                               g_memmove(&new_gai->ip_dst, rtp_listinfo->dest_addr.data, 4);
+                                               COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
+                                               COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
                                                new_gai->port_src = rtp_listinfo->src_port;
                                                new_gai->port_dst = rtp_listinfo->dest_port;
                                                duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
@@ -445,9 +472,9 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
 
        voip_calls_info_t *tmp_listinfo;
        voip_calls_info_t *strinfo = NULL;
-       sip_calls_info_t *tmp_sipinfo;
+       sip_calls_info_t *tmp_sipinfo = NULL;
        GList* list;
-       guint32 tmp_src, tmp_dst;
+       address tmp_src, tmp_dst;
        gchar *frame_label = NULL;
        gchar *comment = NULL;
 
@@ -481,7 +508,7 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                        strinfo->call_state = VOIP_CALL_SETUP;
                        strinfo->from_identity=g_strdup(pi->tap_from_addr);
                        strinfo->to_identity=g_strdup(pi->tap_to_addr);
-                       g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
+                       COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
                        strinfo->first_frame_num=pinfo->fd->num;
                        strinfo->selected=FALSE;
                        strinfo->start_sec=pinfo->fd->rel_secs;
@@ -506,14 +533,14 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
 
                /* let's analyze the call state */
 
-               g_memmove(&(tmp_src), pinfo->src.data, 4);
-               g_memmove(&(tmp_dst), pinfo->dst.data, 4);
+               COPY_ADDRESS(&(tmp_src), &(pinfo->src));
+               COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
                
                if (pi->request_method == NULL){
                        frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase );
                        comment = g_strdup_printf("SIP Status");
 
-                       if ((pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(tmp_dst==strinfo->initial_speaker)){
+                       if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(strinfo->initial_speaker)))){
                                if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
                                        tmp_sipinfo->sip_state = SIP_200_REC;
                                }
@@ -527,12 +554,14 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                else{
                        frame_label = g_strdup(pi->request_method);
 
-                       if ((strcmp(pi->request_method,"INVITE")==0)&&(tmp_src == strinfo->initial_speaker)){
+                       if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))){
                                tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
+                               strinfo->call_state = VOIP_CALL_SETUP;
                                comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
                        }
                        else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
-                               &&(tmp_src == strinfo->initial_speaker)&&(tmp_sipinfo->sip_state==SIP_200_REC)){
+                               &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
+                               &&(strinfo->call_state == VOIP_CALL_SETUP)){
                                strinfo->call_state = VOIP_IN_CALL;
                                comment = g_strdup_printf("SIP Request");
                        }
@@ -542,7 +571,7 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                                comment = g_strdup_printf("SIP Request");
                        }
                        else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
-                               &&(tmp_src == strinfo->initial_speaker)&&(strinfo->call_state==VOIP_CALL_SETUP)){
+                               &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(strinfo->call_state==VOIP_CALL_SETUP)){
                                strinfo->call_state = VOIP_CANCELLED;
                                tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
                                comment = g_strdup_printf("SIP Request");
@@ -562,6 +591,8 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
                g_free(comment);
                g_free(frame_label);
+               g_free((void *)tmp_src.data);
+               g_free((void *)tmp_dst.data);
        }
        return 1;  /* refresh output */
 }
@@ -627,13 +658,14 @@ static gchar              isup_called_number[255], isup_calling_number[255];
 static guint16         isup_cic;
 static guint8          isup_message_type;
 static guint8          isup_cause_value;
+static guint32         isup_frame_num;
 
 /****************************************************************************/
 /* whenever a isup_ packet is seen by the tap listener */
 static int 
 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
 {
-       voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
+       /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
        const isup_tap_rec_t *pi = isup_info;
 
        if (pi->calling_number!=NULL){
@@ -646,6 +678,8 @@ isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
        isup_cause_value = pi->cause_value;
        isup_cic = pinfo->circuit_id;
 
+       isup_frame_num = pinfo->fd->num;
+       
        return 0;
 }
 
@@ -706,7 +740,7 @@ mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
        voip_calls_info_t *strinfo = NULL;
        isup_calls_info_t *tmp_isupinfo;
        gboolean found = FALSE;
-       gboolean forward;
+       gboolean forward = FALSE;
        gboolean right_pair = TRUE;
        GList* list;
        gchar *frame_label = NULL;
@@ -715,6 +749,9 @@ mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
 
        const mtp3_tap_rec_t *pi = mtp3_info;
 
+       /* check if the upper layer is ISUP matching the frame number */
+       if (isup_frame_num != pinfo->fd->num) return 0;
+       
        /* check wether we already have a call with these parameters in the list */
        list = g_list_first(tapinfo->strinfo_list);
        while (list)
@@ -722,7 +759,7 @@ mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
                tmp_listinfo=list->data;
                if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
                        tmp_isupinfo = tmp_listinfo->prot_info;
-                       if ((tmp_isupinfo->cic == isup_cic)&&(tmp_isupinfo->ni == pi->addr_opc.ni)){
+                       if ((tmp_isupinfo->cic == isup_cic)&&(tmp_isupinfo->ni == pi->addr_opc.ni)) {
                                if ((tmp_isupinfo->opc == pi->addr_opc.pc)&&(tmp_isupinfo->dpc == pi->addr_dpc.pc)){
                                         forward = TRUE;
                                 }
@@ -730,6 +767,7 @@ mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
                                         forward = FALSE;
                                 }
                                 else{
+                                        /* XXX: what about forward is it FALSE as declared or should it be true */
                                         right_pair = FALSE;
                                 }
                                 if (right_pair){
@@ -763,7 +801,7 @@ mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
                strinfo = g_malloc(sizeof(voip_calls_info_t));
                strinfo->call_active_state = VOIP_ACTIVE;
                strinfo->call_state = VOIP_UNKNOWN;
-               g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
+               COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
                strinfo->selected=FALSE;
                strinfo->first_frame_num=pinfo->fd->num;
                strinfo->start_sec=pinfo->fd->rel_secs;
@@ -920,7 +958,7 @@ static guint32 q931_frame_num;
 static int 
 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
 {
-       voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
+       /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; */
        const q931_packet_info *pi = q931_info;
 
        /* free previously allocated q931_calling/ed_number */
@@ -991,15 +1029,10 @@ remove_tap_listener_q931_calls(void)
 static const guint8 guid_allzero[GUID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 /* defines specific H323 data */
 
-void add_h245_Address(h323_calls_info_t *h323info, guint32 h245_address, guint16 h245_port)
-{
-       h245_address_t *h245_add = NULL;
 
-       h245_add = g_malloc(sizeof(h245_address_t));
-               h245_add->h245_address = h245_address;
-               h245_add->h245_port = h245_port;
-
-       h323info->h245_list = g_list_append(h323info->h245_list, h245_add);                             
+void add_h245_Address(h323_calls_info_t *h323info,  h245_address_t *h245_address)
+{
+       h323info->h245_list = g_list_append(h323info->h245_list, h245_address);                         
 }
 
 /****************************************************************************/
@@ -1010,19 +1043,22 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
        voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
        voip_calls_info_t *tmp_listinfo;
        voip_calls_info_t *strinfo = NULL;
-       h323_calls_info_t *tmp_h323info;
+       h323_calls_info_t *tmp_h323info = NULL;
+       h323_calls_info_t *tmp2_h323info;
        gchar *frame_label;
        gchar *comment;
-       GList* list;
-       guint32 tmp_src, tmp_dst;
-
+       GList *list, *list2;
+       address tmp_src, tmp_dst;
+       h245_address_t *h245_add = NULL;
+       guint foo;
+       
        const h225_packet_info *pi = H225info;
-
-       /* if not guid and RAS return because did not belong to a call */
-       if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (pi->msg_type == H225_RAS))
+       
+       /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
+       if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20)))
                return 0;
        
-
+       
        if ( (memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (q931_frame_num == pinfo->fd->num) ){
                /* check wether we already have a call with this Q931 CRV */
                list = g_list_first(tapinfo->strinfo_list);
@@ -1039,6 +1075,24 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                        list = g_list_next (list);
                }
                if (strinfo==NULL)      return 0;               
+       } else if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) { /* RAS LCF or LRJ*/
+               /* if the LCF/LRJ doesn't match to a LRQ, just return */
+               if (!pi->request_available) return 0;
+               
+               /* check wether we already have a call with this request SeqNum */
+               list = g_list_first(tapinfo->strinfo_list);
+               while (list)
+               {
+                       tmp_listinfo=list->data;
+                       if (tmp_listinfo->protocol == VOIP_H323){
+                               tmp_h323info = tmp_listinfo->prot_info;
+                               if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
+                                       strinfo = (voip_calls_info_t*)(list->data);
+                                       break;
+                               }
+                       }
+                       list = g_list_next (list);
+               }
        } else {
                /* check wether we already have a call with this guid in the list */
                list = g_list_first(tapinfo->strinfo_list);
@@ -1047,7 +1101,7 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                        tmp_listinfo=list->data;
                        if (tmp_listinfo->protocol == VOIP_H323){
                                tmp_h323info = tmp_listinfo->prot_info;
-                               if (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0){ 
+                               if ( (memcmp(tmp_h323info->guid, guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0) ){ 
                                        strinfo = (voip_calls_info_t*)(list->data);
                                        break;
                                }
@@ -1055,7 +1109,7 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                        list = g_list_next (list);
                }
        }
-
+       
        /* not in the list? then create a new entry */
        if ((strinfo==NULL)){
                strinfo = g_malloc(sizeof(voip_calls_info_t));
@@ -1063,8 +1117,7 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                strinfo->call_state = VOIP_UNKNOWN;
                strinfo->from_identity=g_strdup("");
                strinfo->to_identity=g_strdup("");
-
-               g_memmove(&(strinfo->initial_speaker), pinfo->src.data,4);
+               COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
                strinfo->selected=FALSE;
                strinfo->first_frame_num=pinfo->fd->num;
                strinfo->start_sec=pinfo->fd->rel_secs;
@@ -1073,7 +1126,8 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
                tmp_h323info = strinfo->prot_info;
                tmp_h323info->guid = (guint8 *) g_memdup(pi->guid,GUID_LEN);
-               tmp_h323info->h225SetupAddr = 0;
+               tmp_h323info->h225SetupAddr.type = AT_NONE;
+               tmp_h323info->h225SetupAddr.len = 0;
                tmp_h323info->h245_list = NULL;
                tmp_h323info->is_faststart_Setup = FALSE;
                tmp_h323info->is_faststart_Proc = FALSE;
@@ -1081,9 +1135,10 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                tmp_h323info->is_h245 = FALSE;
                tmp_h323info->q931_crv = -1;
                tmp_h323info->q931_crv2 = -1;
+               tmp_h323info->requestSeqNum = 0;
                strinfo->call_num = tapinfo->ncalls++;
                strinfo->npackets = 0;
-
+               
                tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);                          
        }
 
@@ -1091,8 +1146,8 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
 
                /* let's analyze the call state */
 
-               g_memmove(&(tmp_src), pinfo->src.data, 4);
-               g_memmove(&(tmp_dst), pinfo->dst.data, 4);
+               COPY_ADDRESS(&(tmp_src),&(pinfo->src));
+               COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
 
                strinfo->stop_sec=pinfo->fd->rel_secs;
                strinfo->stop_usec=pinfo->fd->rel_usecs;
@@ -1101,6 +1156,10 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                /* increment the packets counter of all calls */
                ++(tapinfo->npackets);
 
+
+               /* XXX: it is supposed to be initialized isn't it? */
+               g_assert(tmp_h323info != NULL);
+
                /* change the status */
                if (pi->msg_type == H225_CS){
                        if (tmp_h323info->q931_crv == -1) {
@@ -1109,8 +1168,15 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                                tmp_h323info->q931_crv2 = q931_crv;
                        }
 
+                       /* this is still IPv4 only, because the dissector is */
                        if (pi->is_h245 == TRUE){
-                               add_h245_Address(tmp_h323info, pi->h245_address, pi->h245_port);
+                               h245_add = g_malloc(sizeof (h245_address_t));
+                               h245_add->h245_address.type=AT_IPv4;
+                               h245_add->h245_address.len=4;
+                               h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
+                               g_memmove((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
+                               h245_add->h245_port = pi->h245_port;
+                               add_h245_Address(tmp_h323info, h245_add);
                        }
 
                        if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
@@ -1120,7 +1186,6 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                        switch(pi->cs_type){
                        case H225_SETUP:
                                tmp_h323info->is_faststart_Setup = pi->is_faststart;
-
                                /* set te calling and called number from the Q931 packet */
                                if (q931_frame_num == pinfo->fd->num){
                                        if (q931_calling_number != NULL){
@@ -1132,35 +1197,77 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                                                strinfo->to_identity=g_strdup(q931_called_number);
                                        }
                                }
-                               if (tmp_h323info->h225SetupAddr == 0) g_memmove(&(tmp_h323info->h225SetupAddr), pinfo->src.data,4);
-                               strinfo->call_state=VOIP_CALL_SETUP;
+                                       /* check if there is an LRQ/LCF that match this Setup */
+                                       /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup 
+                                       we should also check if the h225 signaling IP and port match the destination 
+                                       Setup ip and port */
+                                       list = g_list_first(tapinfo->strinfo_list);
+                               foo=    g_list_length(list);
+                               while (list)
+                               {
+                                       tmp_listinfo=list->data;
+                                       if (tmp_listinfo->protocol == VOIP_H323){
+                                               tmp2_h323info = tmp_listinfo->prot_info;
+                                               
+                                               /* check if there called number match a LRQ/LCF */
+                                               if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)  
+                                                        && (memcmp(tmp2_h323info->guid, guid_allzero, GUID_LEN) == 0) ){ 
+                                                       /* change the call graph to the LRQ/LCF to belong to this call */
+                                                       strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
+                                                       
+                                                       /* remove this LRQ/LCF call entry because we have found the Setup that match them */
+                                                       g_free(tmp_listinfo->from_identity);
+                                                       g_free(tmp_listinfo->to_identity);
+                                                       g_free(tmp2_h323info->guid);
+                                                       
+                                                       list2 = g_list_first(tmp2_h323info->h245_list);
+                                                       while (list2)
+                                                       {
+                                                               h245_add=list2->data;
+                                                               g_free((void *)h245_add->h245_address.data);
+                                                               g_free(list2->data);
+                                                               list2 = g_list_next(list2);
+                                                       }
+                                                       g_list_free(tmp_h323info->h245_list);
+                                                       tmp_h323info->h245_list = NULL;
+                                                       g_free(tmp_listinfo->prot_info);
+                                                       tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
+                                                       break;
+                                               }
+                                       }
+                               list = g_list_next (list);
+                               }
+                                       foo = g_list_length(list);
+                               /* Set the Setup address if it was not set */
+                               if (tmp_h323info->h225SetupAddr.type == AT_NONE) 
+                                 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
+                                       strinfo->call_state=VOIP_CALL_SETUP;
                                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"), 
-                                                                                       (pi->is_faststart==TRUE?"on":"off"));
+                                                                                 (pi->is_faststart==TRUE?"on":"off"));
                                break;
                        case H225_CONNECT:
                                strinfo->call_state=VOIP_IN_CALL;
                                if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
-                               comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
-                                                                                       (pi->is_faststart==TRUE?"on":"off"));
+                                       comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
+                                                                                         (pi->is_faststart==TRUE?"on":"off"));
                                break;
                        case H225_RELEASE_COMPLET:
-                               g_memmove(&(tmp_src), pinfo->src.data, 4);
+                           COPY_ADDRESS(&tmp_src,&(pinfo->src));
                                if (strinfo->call_state==VOIP_CALL_SETUP){
-                                       if (tmp_h323info->h225SetupAddr == tmp_src){  /* forward direction */
+                                       if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){  /* forward direction */
                                                strinfo->call_state=VOIP_CANCELLED;
                                        }
                                        else{                                                                                           /* reverse */
                                                strinfo->call_state=VOIP_REJECTED;
                                                tapinfo->rejected_calls++;
                                        }
-                               }
-                               else if (strinfo->call_state == VOIP_IN_CALL){
-                                       strinfo->call_state = VOIP_COMPLETED;
-                                       tapinfo->completed_calls++;
+                               } else {
+                                               strinfo->call_state=VOIP_COMPLETED;
+                                               tapinfo->completed_calls++;
                                }
                                /* get the Q931 Release cause code */
                                if (q931_frame_num == pinfo->fd->num &&
-                                   q931_cause_value != 0xFF){          
+                                       q931_cause_value != 0xFF){              
                                        comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
                                } else {                        /* Cause not set */
                                        comment = g_strdup("H225 No Q931 Rel Cause");
@@ -1171,29 +1278,52 @@ H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
                        case H225_CALL_PROCEDING:
                                if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
                                comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
-                                                                                       (pi->is_faststart==TRUE?"on":"off"));
+                                                                                 (pi->is_faststart==TRUE?"on":"off"));
                                break;
                        default:
                                comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
-                                                                                       (pi->is_faststart==TRUE?"on":"off"));
-
-                       }
-               } else if (pi->msg_type == H225_RAS){
-                       frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
-                       comment = g_strdup("H225 RAS");
-               } else {
-                       frame_label = g_strdup("H225: Unknown");
-                       comment = g_strdup("");
+                                                                                 (pi->is_faststart==TRUE?"on":"off"));
+                               
+                       } /* switch pi->cs_type*/
+               } /* if pi->msg_type == H225_CS */
+               else if (pi->msg_type == H225_RAS){
+               switch(pi->msg_tag){
+                       case 18:  /* LRQ */
+                               if (!pi->is_duplicate){
+                                       g_free(strinfo->to_identity);
+                                       strinfo->to_identity=g_strdup(pi->dialedDigits);
+                                       tmp_h323info->requestSeqNum = pi->requestSeqNum;
+                               }
+                       case 19: /* LCF */
+                               if (strlen(pi->dialedDigits)) 
+                                       comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
+                               else
+                                       comment = g_strdup("H225 RAS");
+                               break;
+                       default:
+                               comment = g_strdup("H225 RAS");
                }
+               frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
+       } else {
+               frame_label = g_strdup("H225: Unknown");
+               comment = g_strdup("");
+       }
 
-               /* add to graph analysis */
-               if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment))          /* if the frame number exists in graph, append to it*/
-                       add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  /* if not exist, add to the graph */
+       /* add to graph analysis */
 
-               g_free(frame_label);
-               g_free(comment);
+       /* if the frame number exists in graph, append to it*/
+       if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
+               /* if not exist, add to the graph */
+               add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
+               g_free((void *)tmp_src.data);
+               g_free((void *)tmp_dst.data);
        }
 
+       g_free(frame_label);
+       g_free(comment);
+       
+       } /* if strinfo!=NULL */
+       
        return 1;  /* refresh output */
 }
 
@@ -1258,7 +1388,7 @@ H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, c
        gchar *comment;
        GList* list;
        GList* list2;
-       guint32 tmp_src, tmp_dst;
+       address tmp_src, tmp_dst;
        h245_address_t *h245_add = NULL;
 
        const h245_packet_info *pi = H245info;
@@ -1276,14 +1406,14 @@ H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, c
                if (tmp_listinfo->protocol == VOIP_H323){
                        tmp_h323info = tmp_listinfo->prot_info;
 
-                       g_memmove(&(tmp_src), pinfo->src.data, 4);
-                       g_memmove(&(tmp_dst), pinfo->dst.data, 4);
+                       COPY_ADDRESS(&(tmp_src), &(pinfo->src));
+                       COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
                        list2 = g_list_first(tmp_h323info->h245_list);
                        while (list2)
                        {
                                h245_add=list2->data;
-                               if ( ((h245_add->h245_address == tmp_src) && (h245_add->h245_port == pinfo->srcport))
-                                       || ((h245_add->h245_address == tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
+                               if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
+                                       || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
                                        strinfo = (voip_calls_info_t*)(list->data);
 
                                        ++(strinfo->npackets);
@@ -1295,6 +1425,8 @@ H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, c
                        list2 = g_list_next(list2);
                        }
                        if (strinfo!=NULL) break;
+                       g_free((void *)tmp_src.data);
+                       g_free((void *)tmp_dst.data);
                }
                list = g_list_next(list);
        }
@@ -1356,6 +1488,8 @@ remove_tap_listener_h245dg_calls(void)
        have_H245dg_tap_listener=FALSE;
 }
 
+static gchar *sdp_summary = NULL;
+static guint32 sdp_frame_num = 0;
 
 /****************************************************************************/
 /****************************TAP for SDP PROTOCOL ***************************/
@@ -1366,11 +1500,16 @@ SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, cons
 {
        voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
        const sdp_packet_info *pi = SDPinfo;
-       char summary_str[50];
-       
+
+       /* There are protocols like MGCP where the SDP is called before the tap for the
+          MGCP packet, in those cases we assign the SPD summary to global lastSDPsummary
+          to use it later 
+       */
+       g_free(sdp_summary);
+       sdp_frame_num = pinfo->fd->num;
        /* Append to graph the SDP summary if the packet exists */
-       g_snprintf(summary_str, 50, "SDP (%s)", pi->summary_str);
-       append_to_frame_graph(tapinfo, pinfo->fd->num, summary_str, NULL);
+       sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
+       append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
 
        return 1;  /* refresh output */
 }
@@ -1423,6 +1562,372 @@ remove_tap_listener_sdp_calls(void)
 
 
 
+/****************************************************************************/
+/* ***************************TAP for MGCP **********************************/
+/****************************************************************************/
+
+/*
+   This function will look for a signal/event in the SignalReq/ObsEvent string
+   and return true if it is found 
+*/
+gboolean isSignal(gchar *signal, gchar *signalStr)
+{
+       gint i; 
+       gchar **resultArray;
+       
+       /* if there is no signalStr, just return false */
+       if (signalStr == NULL) return FALSE;
+
+       /* if are both "blank" return true */
+       if ( (*signal == '\0') &&  (*signalStr == '\0') ) return TRUE;
+
+       /* look for signal in signalSre */
+       resultArray = g_strsplit(signalStr, ",", 10);
+
+       for (i = 0; resultArray[i]; i++) {
+               g_strstrip(resultArray[i]);
+               if (strcmp(resultArray[i], signal) == 0) return TRUE;
+       }
+
+       g_strfreev(resultArray);
+       
+       return FALSE;
+}
+
+/*
+   This function will get the Caller ID info and replace the current string
+   This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
+*/
+void mgcpCallerID(gchar *signalStr, gchar **callerId)
+{
+       gchar **arrayStr;
+       
+       /* if there is no signalStr, just return false */
+       if (signalStr == NULL) return;
+
+       arrayStr = g_strsplit(signalStr, "\"", 10);
+
+       if (arrayStr[0] == NULL) return;
+
+       /* look for the ci signal */
+       if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
+               /* free the previous "From" field of the call, and assign the new */
+               g_free(*callerId);
+               *callerId = g_strdup(arrayStr[1]);
+       }
+       g_strfreev(arrayStr);
+
+       return;
+}
+
+
+/*
+   This function will get the Dialed Digits and replace the current string
+   This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
+*/
+void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
+{
+       gchar *tmpStr;
+       gchar resultStr[50];
+       gint i,j; 
+
+       /* if there is no signalStr, just return false */
+       if (signalStr == NULL) return;
+
+       tmpStr = g_strdup(signalStr);
+       
+       for ( i = 0 ; tmpStr[i] ; i++) {
+               switch (tmpStr[i]) {
+                       case '0' : case '1' : case '2' : case '3' : case '4' :
+                       case '5' : case '6' : case '7' : case '8' : case '9' :
+                       case '#' : case '*' :
+                               break;
+                       default:
+                               tmpStr[i] = '?';
+                               break;
+               }
+       }
+       
+       for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
+               if (tmpStr[i] != '?')
+                       resultStr[j++] = tmpStr[i];
+       }
+       resultStr[j] = '\0';
+
+       if (*resultStr == '\0') return;
+       
+       g_free(*dialedDigits);
+       *dialedDigits = g_strdup(resultStr);
+       g_free(tmpStr);
+
+       return;
+}
+
+
+
+/****************************************************************************/
+/* whenever a MGCP packet is seen by the tap listener */
+static int 
+MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
+{
+       voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
+
+       voip_calls_info_t *tmp_listinfo;
+       voip_calls_info_t *strinfo = NULL;
+       mgcp_calls_info_t *tmp_mgcpinfo = NULL;
+       GList* list;
+       GList* listGraph;
+       gchar *frame_label = NULL;
+       gchar *comment = NULL;
+       graph_analysis_item_t *gai;
+       gboolean new = FALSE;
+       gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
+       gdouble diff_time;
+
+       const mgcp_info_t *pi = MGCPinfo;
+
+
+       if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
+               /* check wether we already have a call with this Endpoint and it is active*/
+               list = g_list_first(tapinfo->strinfo_list);
+               while (list)
+               {
+                       tmp_listinfo=list->data;
+                       if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
+                               tmp_mgcpinfo = tmp_listinfo->prot_info;
+                               if (pi->endpointId != NULL){
+                                       if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
+                                               /*
+                                                  check first if it is an ended call. We consider an ended call after 1sec we don't 
+                                                  get a packet in this Endpoint and the call has been released
+                                               */
+                                               diff_time = (pinfo->fd->rel_secs + (double)pinfo->fd->rel_secs/1000000) - (tmp_listinfo->stop_sec + (double)tmp_listinfo->stop_usec/1000000);
+                                               if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) || (tmp_listinfo->call_state == VOIP_COMPLETED)  || (tmp_listinfo->call_state == VOIP_REJECTED)) && (diff_time > 1) ){
+                                                       tmp_listinfo->call_active_state = VOIP_INACTIVE;
+                                               } else {
+                                                       strinfo = (voip_calls_info_t*)(list->data);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       list = g_list_next (list);
+               }
+               
+               /* there is no call with this Endpoint, lets see if this a new call or not */
+               if (strinfo == NULL){
+                       if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
+                               /* this is a new call from the Endpoint */      
+                               fromEndpoint = TRUE;
+                               new = TRUE;
+                       } else if (strcmp(pi->code, "CRCX") == 0){
+                               /* this is a new call from the MGC */
+                               fromEndpoint = FALSE;
+                               new = TRUE;
+                       }
+                       if (!new) return 0;
+               } 
+       } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
+                       ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
+               /* if it is a response OR if it is a duplicated Request, lets look in the Graph if thre is a request that match */
+               listGraph = g_list_first(tapinfo->graph_analysis->list);
+               while (listGraph)
+               {
+                       gai = listGraph->data;
+                       if (gai->frame_num == pi->req_num){
+                               /* there is a request that match, so look the associated call with this call_num */
+                               list = g_list_first(tapinfo->strinfo_list);
+                               while (list)
+                               {
+                                       tmp_listinfo=list->data;
+                                       if (tmp_listinfo->protocol == VOIP_MGCP){
+                                               if (tmp_listinfo->call_num == gai->conv_num){
+                                                       tmp_mgcpinfo = tmp_listinfo->prot_info;
+                                                       strinfo = (voip_calls_info_t*)(list->data);
+                                                       break;
+                                               }
+                                       }
+                                       list = g_list_next (list);
+                               }
+                               if (strinfo != NULL) break;
+                       }
+                       listGraph = g_list_next(listGraph);
+               }
+               /* if there is not a matching request, just return */
+               if (strinfo == NULL) return 0;
+       } else return 0;
+
+       /* not in the list? then create a new entry */
+       if (strinfo==NULL){
+               strinfo = g_malloc(sizeof(voip_calls_info_t));
+               strinfo->call_active_state = VOIP_ACTIVE;
+               strinfo->call_state = VOIP_CALL_SETUP;
+               if (fromEndpoint) {
+                       strinfo->from_identity=g_strdup(pi->endpointId);
+                       strinfo->to_identity=g_strdup("");
+               } else {
+                       strinfo->from_identity=g_strdup("");
+                       strinfo->to_identity=g_strdup(pi->endpointId);
+               }
+               COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
+               strinfo->first_frame_num=pinfo->fd->num;
+               strinfo->selected=FALSE;
+               strinfo->start_sec=pinfo->fd->rel_secs;
+               strinfo->start_usec=pinfo->fd->rel_usecs;
+               strinfo->protocol=VOIP_MGCP;
+               strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
+               tmp_mgcpinfo=strinfo->prot_info;
+               tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
+               tmp_mgcpinfo->fromEndpoint = fromEndpoint;
+               strinfo->npackets = 0;
+               strinfo->call_num = tapinfo->ncalls++;
+               tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
+       }
+
+       g_assert(tmp_mgcpinfo != NULL);
+
+       /* change call state and add to graph */
+       switch (pi->mgcp_type)
+       {
+       case MGCP_REQUEST:
+               if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
+                       frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
+
+                       if (tmp_mgcpinfo->fromEndpoint){
+                               /* use the Dialed digits to fill the "To" for the call */
+                               mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
+
+                       /* from MGC and the user picked up, the call is connected */
+                       } else if (isSignal("hd", pi->observedEvents))  
+                               strinfo->call_state=VOIP_IN_CALL;
+
+                       /* hung up signal */
+                       if (isSignal("hu", pi->observedEvents)) {
+                               if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
+                                       strinfo->call_state = VOIP_CANCELLED;
+                               } else {
+                                       strinfo->call_state = VOIP_COMPLETED;
+                               }
+                       }       
+                       
+               } else if (strcmp(pi->code, "RQNT") == 0) {
+                       /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
+                       if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) { 
+                                       strinfo->call_state = VOIP_IN_CALL;
+                       }
+
+                       /* if there is ringback or ring tone, change state to ringing */
+                       if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) { 
+                                       strinfo->call_state = VOIP_RINGING;
+                       }
+
+                       /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
+                       if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) { 
+                                       strinfo->call_state = VOIP_REJECTED;
+                       }
+
+                       if (pi->signalReq != NULL)
+                               frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
+                       else
+                               frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
+                       
+                       /* use the CallerID info to fill the "From" for the call */
+                       if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
+
+               } else if (strcmp(pi->code, "DLCX") == 0) {
+                       /*
+                         if there is a DLCX in a call To an Endpoint and the call was not connected, we use
+                         the DLCX as the end of the call
+                       */
+                       if (!tmp_mgcpinfo->fromEndpoint){
+                               if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
+                                       strinfo->call_state = VOIP_CANCELLED;
+                               } 
+                       } 
+               }
+
+               if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
+               break;
+       case MGCP_RESPONSE:
+               frame_label = g_strdup_printf("%d (%s)",pi->rspcode, pi->code);
+               break;
+       case MGCP_OTHERS:
+               /* XXX what to do? */
+               break;
+       }
+
+
+       comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
+
+       strinfo->stop_sec=pinfo->fd->rel_secs;
+       strinfo->stop_usec=pinfo->fd->rel_usecs;
+       strinfo->last_frame_num=pinfo->fd->num;
+       ++(strinfo->npackets);
+       /* increment the packets counter of all calls */
+       ++(tapinfo->npackets);
+
+       /* add to the graph */
+       add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
+       g_free(comment);
+       g_free(frame_label);
+
+       /* add SDP info if apply */
+       if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
+                       append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
+                       g_free(sdp_summary);
+                       sdp_summary = NULL;
+       }
+
+       return 1;  /* refresh output */
+}
+
+
+/****************************************************************************/
+/* TAP INTERFACE */
+/****************************************************************************/
+static gboolean have_MGCP_tap_listener=FALSE;
+/****************************************************************************/
+void
+mgcp_calls_init_tap(void)
+{
+       GString *error_string;
+
+       if(have_MGCP_tap_listener==FALSE)
+       {
+               /* don't register tap listener, if we have it already */
+               /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
+               error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
+                       voip_calls_dlg_reset, 
+                       MGCPcalls_packet, 
+                       voip_calls_dlg_draw
+                       );
+               if (error_string != NULL) {
+                       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                                     error_string->str);
+                       g_string_free(error_string, TRUE);
+                       exit(1);
+               }
+               have_MGCP_tap_listener=TRUE;
+       }
+}
+
+
+
+/* XXX just copied from gtk/rpc_stat.c */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
+/****************************************************************************/
+void
+remove_tap_listener_mgcp_calls(void)
+{
+       protect_thread_critical_region();
+       remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
+       unprotect_thread_critical_region();
+
+       have_MGCP_tap_listener=FALSE;
+}
+
 
 
 /****************************************************************************/