Ethereal-dev: [Ethereal-dev] mgcp plugin patch

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

From: Ed Warnicke <hagbard@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 3 Mar 2001 18:32:25 -0500 (EST)
Here is a patch for the mgcp plugin that implements piggybacking 
support and fixes a couple of other small issues.  Please check it 
in.

Ed

Index: plugins/mgcp/moduleinfo.h
===================================================================
RCS file: /cvsroot/ethereal/plugins/mgcp/moduleinfo.h,v
retrieving revision 1.3
diff -u -r1.3 moduleinfo.h
--- moduleinfo.h	2001/01/12 04:43:43	1.3
+++ moduleinfo.h	2001/03/03 23:26:39
@@ -13,5 +13,5 @@
 #endif
 
 /* Version number of package */
-#define VERSION "0.0.3"
+#define VERSION "0.0.4"
 
Index: plugins/mgcp/packet-mgcp.c
===================================================================
RCS file: /cvsroot/ethereal/plugins/mgcp/packet-mgcp.c,v
retrieving revision 1.16
diff -u -r1.16 packet-mgcp.c
--- packet-mgcp.c	2001/01/26 06:14:53	1.16
+++ packet-mgcp.c	2001/03/03 23:26:40
@@ -99,6 +99,7 @@
 static int hf_mgcp_param_capabilities = -1;
 static int hf_mgcp_param_extention = -1;
 static int hf_mgcp_param_invalid = -1;
+static int hf_mgcp_messagecount = -1;
 
 /* 
  * Define the trees for mgcp
@@ -131,8 +132,8 @@
 static int global_mgcp_callagent_udp_port = UDP_PORT_MGCP_CALLAGENT;
 static gboolean global_mgcp_raw_text = FALSE;
 static gboolean global_mgcp_dissect_tree = TRUE;
+static gboolean global_mgcp_message_count = FALSE;
 
-
 /*
  * Variables to allow for proper deletion of dissector registration when 
  * the user changes port from the gui. 
@@ -161,6 +162,8 @@
  * subpart of MGCP.  These aren't really proto dissectors but they 
  * are written in the same style.
  */ 
+static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, 
+				 proto_tree *tree);
 static void dissect_mgcp_firstline(tvbuff_t *tvb, 
 				   packet_info* pinfo, 
 				   proto_tree *tree);
@@ -177,6 +180,8 @@
 static gint tvb_skip_wsp(tvbuff_t* tvb, gint offset, gint maxlength);
 static gint tvb_find_null_line(tvbuff_t* tvb, gint offset, gint len,
 			       gint* next_offset); 
+static gint tvb_find_dot_line(tvbuff_t* tvb, gint offset, 
+			      gint len, gint* next_offset);
 static gint tvb_section_length(tvbuff_t* tvb, gint tvb_sectionbegin, 
 			       gint tvb_sectionend);
 static gboolean is_rfc2234_alpha(guint8 c);
@@ -190,19 +195,18 @@
 static void
 dissect_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-  proto_tree *mgcp_tree, *ti;
   gint sectionlen;
+  guint32 num_messages;
   gint tvb_sectionend,tvb_sectionbegin, tvb_len, tvb_current_len;
-  tvbuff_t *next_tvb;
 
   /* Initialize variables */
-  
   tvb_sectionend = 0;
   tvb_sectionbegin = tvb_sectionend;
   sectionlen = 0;
   tvb_len = tvb_length(tvb);
   tvb_current_len  = tvb_len;
-  
+  num_messages = 0;
+
   /*
    * Set the columns now, so that they'll be set correctly if we throw
    * an exception.  We can set them later as well....
@@ -220,6 +224,82 @@
   if(is_mgcp_verb(tvb,0,tvb_len) || is_mgcp_rspcode(tvb,0,tvb_len)){
 
     /* Build the info tree if we've been given a root */
+    if (tree || global_mgcp_message_count == TRUE) {   
+      /* 
+       * Loop through however many mgcp messages may be stuck in 
+       * this packet using piggybacking
+       */
+      do{
+	num_messages++;
+	sectionlen = tvb_find_dot_line(tvb, tvb_sectionbegin, -1,
+				       &tvb_sectionend);
+	if( sectionlen != -1){
+	  dissect_mgcp_message(tvb_new_subset(tvb, tvb_sectionbegin, 
+					      sectionlen, -1),
+			       pinfo, tree);
+	  tvb_sectionbegin = tvb_sectionend;
+	}
+	else {
+	  break;
+	}
+      } while(tvb_sectionend < tvb_len );
+      proto_tree_add_uint_hidden(tree, hf_mgcp_messagecount,NullTVB,0,0,
+				 num_messages); 
+    } 
+
+    /* 
+     * Add our column information we do this after dissecting SDP 
+     * in order to prevent the column info changing to reflect the SDP.
+     */
+    tvb_sectionbegin = 0;
+    if (check_col(pinfo->fd, COL_PROTOCOL)){
+      if( global_mgcp_message_count == TRUE ){
+	if(num_messages > 1){
+	  col_add_fstr(pinfo->fd, COL_PROTOCOL, "MGCP (%i messages)",num_messages);
+	}
+	else {
+	  col_add_fstr(pinfo->fd, COL_PROTOCOL, "MGCP (%i message)",num_messages);
+	}
+      }
+      else {
+	  col_add_str(pinfo->fd, COL_PROTOCOL, "MGCP");
+      }
+    }
+	
+    if (check_col(pinfo->fd, COL_INFO) ){
+      sectionlen = tvb_find_line_end(tvb, tvb_sectionbegin,-1,
+				     &tvb_sectionend);
+      col_add_fstr(pinfo->fd,COL_INFO, "%s", 
+		   tvb_format_text(tvb,tvb_sectionbegin,sectionlen));
+    } 
+  }  
+}
+
+static void 
+dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree){
+
+  /* Declare variables */
+  proto_tree *mgcp_tree, *ti;
+  gint sectionlen;
+  gint tvb_sectionend,tvb_sectionbegin, tvb_len, tvb_current_len;
+  tvbuff_t *next_tvb;
+
+  /* Initialize variables */
+  
+  tvb_sectionend = 0;
+  tvb_sectionbegin = tvb_sectionend;
+  sectionlen = 0;
+  tvb_len = tvb_length(tvb);
+  tvb_current_len  = tvb_len;
+
+  /* 
+   * Check to see whether we're really dealing with MGCP by looking 
+   * for a valid MGCP verb or response code.  This isn't infallible,
+   * but its cheap and its better than nothing.
+   */
+  if(is_mgcp_verb(tvb,0,tvb_len) || is_mgcp_rspcode(tvb,0,tvb_len)){
+    
+    /* Build the info tree if we've been given a root */
     if (tree) {  
       
       /* Create out mgcp subtree */
@@ -258,32 +338,20 @@
 
       /* Do we want to display the raw text of our MGCP packet? */
       if(global_mgcp_raw_text){
-	mgcp_raw_text_add(tvb_new_subset(tvb,0,sectionlen,-1),pinfo, 
+	mgcp_raw_text_add(tvb_new_subset(tvb,0,tvb_len,-1),pinfo, 
 			  mgcp_tree);
       }
 
       /* dissect sdp payload */
-      if( tvb_sectionend < tvb_len ){ 
+      if( tvb_sectionend < tvb_len && global_mgcp_dissect_tree == TRUE){ 
 	next_tvb = tvb_new_subset(tvb, tvb_sectionend, -1, -1);       
 	call_dissector(sdp_handle, next_tvb, pinfo, tree);
       }
     }
-    /* 
-     * Add our column information we do this after dissecting SDP 
-     * in order to prevent the column info changing to reflect the SDP.
-     */
-    tvb_sectionbegin = 0;
-    if (check_col(pinfo->fd, COL_PROTOCOL))
-      col_add_str(pinfo->fd, COL_PROTOCOL, "MGCP");
-    if (check_col(pinfo->fd, COL_INFO) ){
-      sectionlen = tvb_find_line_end(tvb, tvb_sectionbegin,-1,
-				     &tvb_sectionend);
-      col_add_fstr(pinfo->fd,COL_INFO, "%s", 
-		   tvb_format_text(tvb,tvb_sectionbegin,sectionlen));
-    } 
-  }  
+  }
 }
 
+
 /* 
  * Add the raw text of the message to the dissect tree if appropriate 
  * preferences are specified.  The args and returns follow the general 
@@ -298,25 +366,14 @@
   tvb_linebegin = 0;
   tvb_len = tvb_length(tvb);
 
-  linelen = tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend);
-  if(tvb_lineend < tvb_len){
+  do {
+    tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend);    
     linelen = tvb_lineend - tvb_linebegin;
-  }
-  
-  while(tvb_lineend < tvb_len){
     proto_tree_add_text(tree, tvb, tvb_linebegin, linelen, 
 			"%s", tvb_format_text(tvb,tvb_linebegin, 
 					      linelen));
     tvb_linebegin = tvb_lineend;
-    tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend);
-    linelen = tvb_lineend - tvb_linebegin;
-  }
-  if(tvb_linebegin < tvb_len){
-    linelen = tvb_len - tvb_linebegin;
-    proto_tree_add_text(tree, tvb, tvb_linebegin, linelen, 
-			"%s", tvb_format_text(tvb,tvb_linebegin, 
-					      linelen));
-  }
+  } while ( tvb_lineend < tvb_len );
 }
 
 /* Register all the bits needed with the filtering engine */
@@ -427,6 +484,9 @@
     { &hf_mgcp_param_invalid,
       { "Invalid Parameter", "mgcp.param.invalid", FT_STRING, 
 	BASE_DEC, NULL, 0x0, "Invalid Parameter"}},
+    { &hf_mgcp_messagecount, 
+      { "MGCP Message Count", "mgcp.messagecount", FT_UINT32, 
+	BASE_DEC, NULL, 0x0, "Number of MGCP message in a packet"}},
     /* Add more fields here */
   };
   static gint *ett[] = {
@@ -486,6 +546,10 @@
 				 "raw text",
                                  &global_mgcp_dissect_tree);
 
+  prefs_register_bool_preference(mgcp_module, "display_mgcp_message_count", 
+                                 "Display the number of MGCP messages", 
+                                 "found in a packet in the protocol column.",
+                                 &global_mgcp_message_count);
 }
 
 /* The registration hand-off routine */
@@ -832,7 +896,6 @@
       else{
 	tokenlen = tvb_current_offset - tvb_previous_offset;
       }
-
       if(tokennum == 0){
 	if(is_mgcp_verb(tvb,tvb_previous_offset,tvb_current_len)){
 	  mgcp_type = MGCP_REQUEST;
@@ -877,8 +940,8 @@
 				   tvb_previous_offset, tokenlen,
 				   tvb_format_text(tvb, tvb_previous_offset,
 						   tokenlen));
-	  }
-	break;
+	  break;
+	}
       }
       if( (tokennum == 3 && mgcp_type == MGCP_REQUEST) ){
 	if(tvb_current_offset < tvb_len ){
@@ -1082,6 +1145,111 @@
   } 
 
   return (tvb_current_len);
+}
+
+/*
+ * tvb_find_dot_line -  Returns the length from offset to the first line 
+ *                      containing only a dot (.) character.  A line 
+ *                      containing only a dot is used to indicate a 
+ *                      separation between multiple MGCP messages 
+ *                      piggybacked in the same UDP packet.
+ *
+ * Parameters: 
+ * tvb - The tvbuff in which we are looking for a dot line.
+ * offset - The offset in tvb at which we will begin looking for 
+ *          a dot line.
+ * len - The maximum distance from offset in tvb that we will look for 
+ *       a dot line.  If it is -1 we will look to the end of the buffer.
+ *
+ * next_offset - The location to write the offset of first character 
+ *               FOLLOWING the dot line.  
+ *
+ * Returns: The length from offset to the first character BEFORE 
+ *          the dot line or -1 if the character at offset is a . 
+ *          followed by a newline or a carriage return.
+ */
+static gint tvb_find_dot_line(tvbuff_t* tvb, gint offset, 
+			       gint len, gint* next_offset){
+  gint tvb_current_offset, tvb_current_len, maxoffset,tvb_len;
+  guint8 tempchar;
+
+  tvb_current_offset = offset;
+  tvb_current_len = len;
+  tvb_len = tvb_length(tvb);
+
+  if(len == -1){
+    maxoffset = ( tvb_len - 1 );
+  }
+  else { 
+    maxoffset = (len - 1 ) + offset;
+  }
+  tvb_current_offset = offset -1;
+  do {
+    tvb_current_offset = tvb_find_guint8(tvb, tvb_current_offset+1,
+					 tvb_current_len, '.');
+    tvb_current_len = maxoffset - tvb_current_offset + 1;
+    /* 
+     * if we didn't find a . then break out of the loop
+     */
+    if(tvb_current_offset == -1){
+      break;
+    }
+    /* do we have and characters following the . ? */
+    if( tvb_current_offset < maxoffset ) { 
+      tempchar = tvb_get_guint8(tvb,tvb_current_offset+1);
+      /* 
+       * are the characters that follow the dot a newline or carriage return ? 
+       */
+      if(tempchar == '\r' || tempchar == '\n'){
+	/*
+	 * do we have any charaters that proceed the . ?
+	 */
+	if( tvb_current_offset == 0 ){
+	  break;
+	}
+	else {
+	  tempchar = tvb_get_guint8(tvb,tvb_current_offset-1);
+	  /*
+	   * are the characters that follow the dot a newline or a carriage 
+	   * return ?
+	   */
+	  if(tempchar == '\r' || tempchar == '\n'){
+	    break;
+	  }
+	}
+      }
+    }
+    else if ( tvb_current_offset == maxoffset ) {
+      if( tvb_current_offset == 0 ){
+	break;
+      }
+      else {
+	tempchar = tvb_get_guint8(tvb,tvb_current_offset-1);
+	if(tempchar == '\r' || tempchar == '\n'){
+	  break;
+	}
+      }
+    }    
+  } while (tvb_current_offset < maxoffset);
+  /* 
+   * so now we either have the tvb_current_offset of a . in a dot line 
+   * or a tvb_current_offset of -1
+   */
+  if(tvb_current_offset == -1){
+    tvb_current_offset = maxoffset +1;
+    *next_offset = maxoffset + 1;
+  }
+  else {
+    tvb_find_line_end(tvb,tvb_current_offset,tvb_current_len,next_offset);
+  }
+
+  if( tvb_current_offset == offset ){
+    tvb_current_len = -1;
+  }  
+  else {
+    tvb_current_len = tvb_current_offset - offset;
+  }
+  return tvb_current_len;  
 }
 
 static gint tvb_section_length(tvbuff_t* tvb, gint tvb_sectionbegin,