Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Ethereal-dev: [Ethereal-dev] Voip Calls analysis and Graph analysis

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Alejandro Vaquero <alejandrovaquero@xxxxxxxxx>
Date: Fri, 18 Feb 2005 13:00:00 -0700

Hi All,
find attached a patch to add MGCP calls to the "Voip Analysis". The implementation is oriented to MGCP Residential Gateways.

Regards
Alejandro
Index: gtk/voip_calls_dlg.c
===================================================================
--- gtk/voip_calls_dlg.c	(revision 13359)
+++ gtk/voip_calls_dlg.c	(working copy)
@@ -173,6 +173,7 @@
 	remove_tap_listener_q931_calls();
 	remove_tap_listener_sdp_calls();
 	remove_tap_listener_rtp();
+	remove_tap_listener_mgcp_calls();
 }
 
 /****************************************************************************/
@@ -672,6 +673,7 @@
 	q931_calls_init_tap();
 	sdp_calls_init_tap();
 	rtp_init_tap();
+	mgcp_calls_init_tap();
 	
 	/* init the Graph Analysys */
 	graph_analysis_data = graph_analysis_init();
Index: gtk/voip_calls.c
===================================================================
--- gtk/voip_calls.c	(revision 13359)
+++ gtk/voip_calls.c	(working copy)
@@ -52,6 +52,7 @@
 #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"
 
@@ -69,8 +70,9 @@
 #include <string.h>
 
 
-char *voip_call_state_name[6]={
+char *voip_call_state_name[7]={
 	"CALL SETUP",
+	"RINGING",
 	"IN CALL",
 	"CANCELLED",
 	"COMPLETED",
@@ -79,10 +81,11 @@
 	};
 
 /* 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 +93,7 @@
 /****************************************************************************/
 /* 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 =
@@ -1446,6 +1449,8 @@
 	have_H245dg_tap_listener=FALSE;
 }
 
+static gchar *sdp_summary = NULL;
+static guint32 sdp_frame_num = 0;
 
 /****************************************************************************/
 /****************************TAP for SDP PROTOCOL ***************************/
@@ -1456,11 +1461,16 @@
 {
 	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 */
 }
@@ -1513,9 +1523,374 @@
 
 
 
+/****************************************************************************/
+/* ***************************TAP for MGCP **********************************/
+/****************************************************************************/
 
+/*
+   This function will look for a signal/event in the SignalReq/ObsEvent string
+   and return true if it is found 
+*/
+boolean 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)
+{
+	gint i; 
+	gchar **resultArray;
+	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 */
+	resultArray = g_strsplit_set(arrayStr[0], ",(", 10);
+
+	for (i = 0; resultArray[i]; i++) {
+		g_strstrip(resultArray[i]);
+		if (strcmp(resultArray[i], "ci") == 0){
+			if (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);
+			g_strfreev(resultArray);
+			return;
+		}
+	}
+
+	g_strfreev(arrayStr);
+	g_strfreev(resultArray);
+
+	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);
+
+	tmpStr = g_strcanon(tmpStr, "123456790#*", '?');
+
+	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;
+	GList* list;
+	GList* listGraph;
+	gchar *frame_label = NULL;
+	gchar *comment = NULL;
+	graph_analysis_item_t *gai;
+	boolean new = FALSE;
+	boolean 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_ascii_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);
+		}
+		g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
+		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);
+	}
+
+	/* 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;
+	}
+
+
+	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;
+}
+
+
+
+/****************************************************************************/
 /* ***************************TAP for OTHER PROTOCOL **********************************/
 /****************************************************************************/
 
Index: gtk/voip_calls.h
===================================================================
--- gtk/voip_calls.h	(revision 13359)
+++ gtk/voip_calls.h	(working copy)
@@ -44,6 +44,7 @@
 /* defines voip call state */
 typedef enum _voip_call_state {
         VOIP_CALL_SETUP,
+		VOIP_RINGING,
         VOIP_IN_CALL,
         VOIP_CANCELLED,
         VOIP_COMPLETED,
@@ -51,7 +52,7 @@
 		VOIP_UNKNOWN
 } voip_call_state;
 
-extern char *voip_call_state_name[6];
+extern char *voip_call_state_name[7];
 
 typedef enum _voip_call_active_state {
 		VOIP_ACTIVE,
@@ -61,10 +62,11 @@
 typedef enum _voip_protocol {
 		VOIP_SIP,
 		VOIP_ISUP,
-		VOIP_H323
+		VOIP_H323,
+		VOIP_MGCP
 } voip_protocol;
 
-extern char *voip_protocol_name[3];
+extern char *voip_protocol_name[4];
 
 /* defines specific SIP data */
 
@@ -81,13 +83,13 @@
 } sip_calls_info_t;
 
 /* defines specific ISUP data */
-
 typedef struct _isup_calls_info {
 	guint16			cic;
 	guint32			opc, dpc;
 	guint8			ni;
 } isup_calls_info_t;
 
+/* defines specific H245 data */
 typedef struct _h245_address {
 	guint32 h245_address;
 	guint16 h245_port;
@@ -107,6 +109,13 @@
 	guint requestSeqNum;
 } h323_calls_info_t;
 
+/* defines specific MGCP data */
+typedef struct _mgcp_calls_info {
+	gchar *endpointId;
+	gboolean fromEndpoint; /* true if the call was originated from the Endpoint, false for calls from MGC */
+} mgcp_calls_info_t;
+
+
 /* defines a voip call */
 typedef struct _voip_calls_info {
 	voip_call_state call_state;
@@ -149,6 +158,7 @@
 	int mtp3_dummy;
 	int isup_dummy;
 	int q931_dummy;
+	int mgcp_dummy;
 } voip_calls_tapinfo_t;
 
 
@@ -197,6 +207,7 @@
 void q931_calls_init_tap(void);
 void sdp_calls_init_tap(void);
 void rtp_init_tap(void);
+void mgcp_calls_init_tap(void);
 
 
 /*
@@ -211,6 +222,7 @@
 void remove_tap_listener_q931_calls(void);
 void remove_tap_listener_sdp_calls(void);
 void remove_tap_listener_rtp(void);
+void remove_tap_listener_mgcp_calls(void);
 
 /*
 * Retrieves a constant reference to the unique info structure of the voip_calls tap listener.
Index: plugins/mgcp/packet-mgcp.h
===================================================================
--- plugins/mgcp/packet-mgcp.h	(revision 13359)
+++ plugins/mgcp/packet-mgcp.h	(working copy)
@@ -40,6 +40,12 @@
   nstime_t req_time;
   gboolean is_duplicate;
   gboolean request_available;
+  guint32	req_num;	/* frame number request seen */
+  gchar *endpointId;
+  gchar *observedEvents;
+  guint32 rspcode;
+  gchar *signalReq;
+  gboolean *hasDigitMap;
 } mgcp_info_t;
 
 /* Item of request list */
Index: plugins/mgcp/packet-mgcp.c
===================================================================
--- plugins/mgcp/packet-mgcp.c	(revision 13359)
+++ plugins/mgcp/packet-mgcp.c	(working copy)
@@ -226,7 +226,7 @@
 static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo,
 				 proto_tree *tree,proto_tree *mgcp_tree, proto_tree *ti);
 static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo,
-				   proto_tree *tree, mgcp_info_t *mi);
+				   proto_tree *tree);
 static void dissect_mgcp_params(tvbuff_t *tvb,
 				proto_tree *tree);
 static void dissect_mgcp_connectionparams(proto_tree *parent_tree, tvbuff_t *tvb, gint offset, gint param_type_len, gint param_val_len);
@@ -377,6 +377,7 @@
     }
   }
 }
+static mgcp_info_t *mi;
 
 static void
 dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
@@ -386,8 +387,23 @@
   gint sectionlen;
   gint tvb_sectionend,tvb_sectionbegin, tvb_len, tvb_current_len;
   tvbuff_t *next_tvb;
-  static mgcp_info_t mi;
 
+  /* Initialise stat info for passing to tap */
+  mi = g_malloc(sizeof(mgcp_info_t));
+  mi->mgcp_type = MGCP_OTHERS;
+  mi->code[0] = '\0';
+  mi->transid = 0;
+  mi->req_time.secs=0;
+  mi->req_time.nsecs=0;
+  mi->is_duplicate = FALSE;
+  mi->request_available = FALSE;
+  mi->req_num = 0;
+  mi->endpointId = NULL;
+  mi->observedEvents = NULL;
+  mi->rspcode = 0;
+  mi->signalReq = NULL;
+  mi->hasDigitMap = FALSE;
+
   /* Initialize variables */
   tvb_sectionend = 0;
   tvb_sectionbegin = tvb_sectionend;
@@ -409,7 +425,7 @@
     if( sectionlen > 0){
       dissect_mgcp_firstline(tvb_new_subset(tvb, tvb_sectionbegin,
 					    sectionlen,-1), pinfo,
-			     mgcp_tree, &mi);
+			     mgcp_tree);
     }
     tvb_sectionbegin = tvb_sectionend;
 
@@ -882,8 +898,10 @@
 static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf){
   gint returnvalue, tvb_current_offset,counter;
   guint8 tempchar;
+  gchar **buf;
   tvb_current_offset = offset;
-  returnvalue = -1;
+  returnvalue = -1;  
+  buf = NULL;
   *hf = NULL;
   if(len > 0){
     tempchar = tvb_get_guint8(tvb,tvb_current_offset);
@@ -956,12 +974,15 @@
       break;
     case 'S':
       *hf = &hf_mgcp_param_signalreq;
+	  buf = &(mi->signalReq);
       break;
     case 'D':
       *hf = &hf_mgcp_param_digitmap;
+	  mi->hasDigitMap = TRUE;
       break;
     case 'O':
       *hf = &hf_mgcp_param_observedevent;
+	  buf = &(mi->observedEvents);
       break;
     case 'P':
       *hf = &hf_mgcp_param_connectionparam;
@@ -1015,6 +1036,9 @@
       tvb_current_offset = tvb_skip_wsp(tvb,tvb_current_offset,
 					(len - tvb_current_offset + offset));
       returnvalue = tvb_current_offset;
+	  if (buf != NULL) {
+		  *buf = tvb_get_string(tvb, tvb_current_offset, (len - tvb_current_offset + offset));
+	  }
     }
     else {
       *hf = &hf_mgcp_param_invalid;
@@ -1050,11 +1074,12 @@
  
 
 static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo,
-				   proto_tree *tree, mgcp_info_t *mi){
+				   proto_tree *tree){
   gint tvb_current_offset,tvb_previous_offset,tvb_len,tvb_current_len;
   gint tokennum, tokenlen;
   char *transid = NULL;
   char *code = NULL;
+  char *endpointId = NULL;
   mgcp_type_t mgcp_type = MGCP_OTHERS;
   conversation_t* conversation;
   mgcp_call_info_key mgcp_call_key;
@@ -1107,6 +1132,7 @@
 	else if (is_mgcp_rspcode(tvb,tvb_previous_offset,tvb_current_len)){
 	  mgcp_type = MGCP_RESPONSE;
 	  rspcode = atoi(code);
+	  mi->rspcode = rspcode;
 	  proto_tree_add_uint(tree,hf_mgcp_rsp_rspcode, tvb,
 				   tvb_previous_offset, tokenlen,
 				   rspcode);
@@ -1126,10 +1152,11 @@
       }
       if(tokennum == 2){
 	if(mgcp_type == MGCP_REQUEST){
+	  endpointId = tvb_format_text(tvb, tvb_previous_offset,tokenlen);
+	  mi->endpointId = g_strdup(endpointId);
 	  my_proto_tree_add_string(tree,hf_mgcp_req_endpoint, tvb,
 				   tvb_previous_offset, tokenlen,
-				   tvb_format_text(tvb, tvb_previous_offset,
-						   tokenlen));
+				   endpointId);
 	}
 	else if(mgcp_type == MGCP_RESPONSE){
 	  if(tvb_current_offset < tvb_len){
@@ -1214,6 +1241,7 @@
 			if(mgcp_call->req_num){
 				mi->request_available = TRUE;
 				mgcp_call->responded = TRUE;
+				mi->req_num = mgcp_call->req_num;
 				strcpy(mi->code,mgcp_call->code);
 				proto_tree_add_uint_format(tree, hf_mgcp_req_frame,
 				    tvb, 0, 0, mgcp_call->req_num,
@@ -1317,6 +1345,7 @@
 			/* No, so it's a duplicate request.
 			   Mark it as such. */
 			mi->is_duplicate = TRUE;
+			mi->req_num = mgcp_call->req_num;
 			if (check_col(pinfo->cinfo, COL_INFO)) {
 				col_append_fstr(pinfo->cinfo, COL_INFO,
 					", Duplicate Request %u",mi->transid);
@@ -1345,7 +1374,6 @@
 		mgcp_call->req_time.secs=pinfo->fd->abs_secs;
 		mgcp_call->req_time.nsecs=pinfo->fd->abs_usecs*1000;
 		strcpy(mgcp_call->code,mi->code);
-
 		/* store it */
 		g_hash_table_insert(mgcp_calls, new_mgcp_call_key, mgcp_call);
 	}