GSM A DTAP: add UMTS EVS to supported codecs list IE
[metze/wireshark/wip.git] / epan / dissectors / packet-mgcp.c
index 33756c2d2004c1960787611afade6c37505cb9b2..2d7b601120fe331373bd6f5c73efd4343fa3d895 100644 (file)
@@ -7,10 +7,10 @@
  * NCS 1.0: PacketCable Network-Based Call Signaling Protocol Specification,
  *          PKT-SP-EC-MGCP-I09-040113, January 13, 2004, Cable Television
  *          Laboratories, Inc., http://www.PacketCable.com/
+ * NCS 1.5: PKT-SP-NCS1.5-I04-120412, April 12, 2012 Cable Television
+ *          Laboratories, Inc., http://www.PacketCable.com/
  * www.iana.org/assignments/mgcp-localconnectionoptions
  *
- * $Id$
- *
  * Copyright (c) 2000 by Ed Warnicke <hagbard@physics.rutgers.edu>
  * Copyright (c) 2004 by Thomas Anders <thomas.anders [AT] blue-cable.de>
  *
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1999 Gerald Combs
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 #include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
 
 #include <epan/packet.h>
-#include <epan/emem.h>
+#include <epan/exceptions.h>
 #include <epan/prefs.h>
 #include <epan/conversation.h>
 #include <epan/tap.h>
-#include <epan/strutil.h>
+#include <epan/rtd_table.h>
+#include <epan/expert.h>
 #include "packet-mgcp.h"
 
+#include <wsutil/strtoi.h>
 
 #define TCP_PORT_MGCP_GATEWAY 2427
 #define UDP_PORT_MGCP_GATEWAY 2427
@@ -103,6 +89,33 @@ static int hf_mgcp_param_localconnoptions_t = -1;
 static int hf_mgcp_param_localconnoptions_rcnf = -1;
 static int hf_mgcp_param_localconnoptions_rdir = -1;
 static int hf_mgcp_param_localconnoptions_rsh = -1;
+static int hf_mgcp_param_localconnoptions_mp = -1;
+static int hf_mgcp_param_localconnoptions_fxr = -1;
+static int hf_mgcp_param_localvoicemetrics = -1;
+static int hf_mgcp_param_remotevoicemetrics = -1;
+static int hf_mgcp_param_voicemetrics_nlr = -1;
+static int hf_mgcp_param_voicemetrics_jdr = -1;
+static int hf_mgcp_param_voicemetrics_bld = -1;
+static int hf_mgcp_param_voicemetrics_gld = -1;
+static int hf_mgcp_param_voicemetrics_bd = -1;
+static int hf_mgcp_param_voicemetrics_gd = -1;
+static int hf_mgcp_param_voicemetrics_rtd = -1;
+static int hf_mgcp_param_voicemetrics_esd = -1;
+static int hf_mgcp_param_voicemetrics_sl = -1;
+static int hf_mgcp_param_voicemetrics_nl = -1;
+static int hf_mgcp_param_voicemetrics_rerl = -1;
+static int hf_mgcp_param_voicemetrics_gmn = -1;
+static int hf_mgcp_param_voicemetrics_nsr = -1;
+static int hf_mgcp_param_voicemetrics_xsr = -1;
+static int hf_mgcp_param_voicemetrics_mlq = -1;
+static int hf_mgcp_param_voicemetrics_mcq = -1;
+static int hf_mgcp_param_voicemetrics_plc = -1;
+static int hf_mgcp_param_voicemetrics_jba = -1;
+static int hf_mgcp_param_voicemetrics_jbr = -1;
+static int hf_mgcp_param_voicemetrics_jbn = -1;
+static int hf_mgcp_param_voicemetrics_jbm = -1;
+static int hf_mgcp_param_voicemetrics_jbs = -1;
+static int hf_mgcp_param_voicemetrics_iaj = -1;
 static int hf_mgcp_param_connectionmode = -1;
 static int hf_mgcp_param_reqevents = -1;
 static int hf_mgcp_param_restartmethod = -1;
@@ -135,6 +148,7 @@ static int hf_mgcp_param_maxmgcpdatagram = -1;
 static int hf_mgcp_param_packagelist = -1;
 static int hf_mgcp_param_extension = -1;
 static int hf_mgcp_param_extension_critical = -1;
+static int hf_mgcp_param_resourceid = -1;
 static int hf_mgcp_param_invalid = -1;
 static int hf_mgcp_messagecount = -1;
 static int hf_mgcp_dup = -1;
@@ -142,6 +156,10 @@ static int hf_mgcp_req_dup = -1;
 static int hf_mgcp_req_dup_frame = -1;
 static int hf_mgcp_rsp_dup = -1;
 static int hf_mgcp_rsp_dup_frame = -1;
+static int hf_mgcp_unknown_parameter = -1;
+static int hf_mgcp_malformed_parameter = -1;
+
+static expert_field ei_mgcp_rsp_rspcode_invalid = EI_INIT;
 
 static const value_string mgcp_return_code_vals[] = {
        {000, "Response Acknowledgement"},
@@ -203,6 +221,7 @@ static const value_string mgcp_return_code_vals[] = {
        {541, "Invalid or unsupported LocalConnectionOptions"},
        {0,   NULL }
 };
+static value_string_ext mgcp_return_code_vals_ext = VALUE_STRING_EXT_INIT(mgcp_return_code_vals);
 
 /* TODO: add/use when tested/have capture to test with */
 /*
@@ -228,6 +247,8 @@ static int ett_mgcp = -1;
 static int ett_mgcp_param = -1;
 static int ett_mgcp_param_connectionparam = -1;
 static int ett_mgcp_param_localconnectionoptions = -1;
+static int ett_mgcp_param_localvoicemetrics = -1;
+static int ett_mgcp_param_remotevoicemetrics = -1;
 
 /*
  * Define the tap for mgcp
@@ -248,17 +269,17 @@ static int mgcp_tap = -1;
  * the raw text of the mgcp message, much like the HTTP dissector does.
  *
  */
-static guint global_mgcp_gateway_tcp_port = TCP_PORT_MGCP_GATEWAY;
-static guint global_mgcp_gateway_udp_port = UDP_PORT_MGCP_GATEWAY;
+static guint global_mgcp_gateway_tcp_port   = TCP_PORT_MGCP_GATEWAY;
+static guint global_mgcp_gateway_udp_port   = UDP_PORT_MGCP_GATEWAY;
 static guint global_mgcp_callagent_tcp_port = TCP_PORT_MGCP_CALLAGENT;
 static guint global_mgcp_callagent_udp_port = UDP_PORT_MGCP_CALLAGENT;
-static gboolean global_mgcp_raw_text = FALSE;
+static gboolean global_mgcp_raw_text      = FALSE;
 static gboolean global_mgcp_message_count = FALSE;
 
 /* Some basic utility functions that are specific to this dissector */
 static gboolean is_mgcp_verb(tvbuff_t *tvb, gint offset, gint maxlength, const gchar **verb_name);
 static gboolean is_mgcp_rspcode(tvbuff_t *tvb, gint offset, gint maxlength);
-static gint tvb_parse_param(tvbuff_t *tvb, gint offset, gint maxlength, int** hf);
+static gint tvb_parse_param(tvbuff_t *tvb, gint offset, gint maxlength, int** hf, mgcp_info_t* mi);
 
 /*
  * The various functions that either dissect some
@@ -266,19 +287,120 @@ static gint tvb_parse_param(tvbuff_t *tvb, gint offset, gint maxlength, int** hf
  * are written in the same style.
  */
 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);
-static void dissect_mgcp_params(tvbuff_t *tvb, 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);
+static void dissect_mgcp_params(tvbuff_t *tvb, proto_tree *tree, mgcp_info_t* mi);
 static void dissect_mgcp_connectionparams(proto_tree *parent_tree, tvbuff_t *tvb,
-                                          gint offset, gint param_type_len,
-                                          gint param_val_len);
+                                         gint offset, gint param_type_len,
+                                         gint param_val_len);
 static void dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, tvbuff_t *tvb,
-                                                gint offset, gint param_type_len,
-                                                gint param_val_len);
-
+                                               gint offset, gint param_type_len,
+                                               gint param_val_len);
+static void dissect_mgcp_localvoicemetrics(proto_tree *parent_tree, tvbuff_t *tvb,
+                                               gint offset, gint param_type_len,
+                                               gint param_val_len);
+static void dissect_mgcp_remotevoicemetrics(proto_tree *parent_tree, tvbuff_t *tvb,
+                                               gint offset, gint param_type_len,
+                                               gint param_val_len);
 
 static void mgcp_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
 
+#define NUM_TIMESTATS 11
+
+static const value_string mgcp_mesage_type[] = {
+       {  0, "Overall"},
+       {  1, "EPCF   "},
+       {  2, "CRCX   "},
+       {  3, "MDCX   "},
+       {  4, "DLCX   "},
+       {  5, "RQNT   "},
+       {  6, "NTFY   "},
+       {  7, "AUEP   "},
+       {  8, "AUCX   "},
+       {  9, "RSIP   "},
+       {  0, NULL}
+};
+
+static int
+mgcpstat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pmi)
+{
+       rtd_data_t* rtd_data = (rtd_data_t*)pms;
+       rtd_stat_table* ms = &rtd_data->stat_table;
+       const mgcp_info_t *mi = (const mgcp_info_t *)pmi;
+       nstime_t delta;
+       int ret = 0;
+
+       switch (mi->mgcp_type) {
+
+       case MGCP_REQUEST:
+               if (mi->is_duplicate) {
+                       /* Duplicate is ignored */
+                       ms->time_stats[0].req_dup_num++;
+               }
+               else {
+                       ms->time_stats[0].open_req_num++;
+               }
+               break;
+
+       case MGCP_RESPONSE:
+               if (mi->is_duplicate) {
+                       /* Duplicate is ignored */
+                       ms->time_stats[0].rsp_dup_num++;
+               }
+               else if (!mi->request_available) {
+                       /* no request was seen */
+                       ms->time_stats[0].disc_rsp_num++;
+               }
+               else {
+                       ms->time_stats[0].open_req_num--;
+                       /* calculate time delta between request and response */
+                       nstime_delta(&delta, &pinfo->abs_ts, &mi->req_time);
+
+                       time_stat_update(&(ms->time_stats[0].rtd[0]), &delta, pinfo);
+
+                       if (g_ascii_strncasecmp(mi->code, "EPCF", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[1]), &delta, pinfo);
+                       }
+                       else if (g_ascii_strncasecmp(mi->code, "CRCX", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[2]), &delta, pinfo);
+                       }
+                       else if (g_ascii_strncasecmp(mi->code, "MDCX", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[3]), &delta, pinfo);
+                       }
+                       else if (g_ascii_strncasecmp(mi->code, "DLCX", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[4]), &delta, pinfo);
+                       }
+                       else if (g_ascii_strncasecmp(mi->code, "RQNT", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[5]), &delta, pinfo);
+                       }
+                       else if (g_ascii_strncasecmp(mi->code, "NTFY", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[6]), &delta, pinfo);
+                       }
+                       else if (g_ascii_strncasecmp(mi->code, "AUEP", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[7]), &delta, pinfo);
+                       }
+                       else if (g_ascii_strncasecmp(mi->code, "AUCX", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[8]), &delta, pinfo);
+                       }
+                       else if (g_ascii_strncasecmp(mi->code, "RSIP", 4) == 0 ) {
+                               time_stat_update(&(ms->time_stats[0].rtd[9]), &delta, pinfo);
+                       }
+                       else {
+                               time_stat_update(&(ms->time_stats[0].rtd[10]), &delta, pinfo);
+                       }
+
+                       ret = 1;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+
 /*
  * Some functions which should be moved to a library
  * as I think that people may find them of general usefulness.
@@ -291,7 +413,7 @@ static dissector_handle_t sdp_handle;
 static dissector_handle_t mgcp_handle;
 extern void
 dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-     dissector_handle_t subdissector_handle);
+                 dissector_handle_t subdissector_handle);
 extern guint16 is_asciitpkt(tvbuff_t *tvb);
 
 /*
@@ -304,7 +426,7 @@ typedef struct _mgcp_call_info_key
        conversation_t *conversation;
 } mgcp_call_info_key;
 
-static GHashTable *mgcp_calls;
+static wmem_map_t *mgcp_calls;
 
 /* Compare 2 keys */
 static gint mgcp_call_equal(gconstpointer k1, gconstpointer k2)
@@ -321,111 +443,103 @@ static guint mgcp_call_hash(gconstpointer k)
 {
        const mgcp_call_info_key* key = (const mgcp_call_info_key*) k;
 
-       return key->transid  + key->conversation->index;
+       return key->transid  + key->conversation->conv_index;
 }
 
 
 /************************************************************************
  * dissect_mgcp - The dissector for the Media Gateway Control Protocol
  ************************************************************************/
-static int dissect_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int dissect_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
 {
        gint sectionlen;
        guint32 num_messages;
-       gint tvb_sectionend,tvb_sectionbegin, tvb_len;
-       proto_tree *mgcp_tree, *ti;
+       gint tvb_sectionend, tvb_sectionbegin, tvb_len;
+       proto_tree *mgcp_tree = NULL;
+       proto_item *ti = NULL, *tii;
        const gchar *verb_name = "";
 
        /* Initialize variables */
        tvb_sectionend = 0;
        tvb_sectionbegin = tvb_sectionend;
-       sectionlen = 0;
-       tvb_len = tvb_length(tvb);
+       tvb_len = tvb_reported_length(tvb);
        num_messages = 0;
-       mgcp_tree = NULL;
-       ti = NULL;
 
        /*
         * 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.
+        * but it's cheap and it's better than nothing.
         */
-       if (is_mgcp_verb(tvb,0,tvb_len, &verb_name) || is_mgcp_rspcode(tvb,0,tvb_len))
-       {
-               /*
-                * Set the columns now, so that they'll be set correctly if we throw
-                * an exception.  We can set them later as well....
-                */
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "MGCP");
-               col_clear(pinfo->cinfo, COL_INFO);
+       if (!is_mgcp_verb(tvb, 0, tvb_len, &verb_name) && !is_mgcp_rspcode(tvb, 0, tvb_len))
+               return 0;
 
-               /*
-                * Loop through however many mgcp messages may be stuck in
-                * this packet using piggybacking
-                */
-               do
-               {
-                       num_messages++;
-                       if (tree)
-                       {
-                               /* Create our mgcp subtree */
-                               ti = proto_tree_add_item(tree,proto_mgcp,tvb,0,0, ENC_NA);
-                               mgcp_tree = proto_item_add_subtree(ti, ett_mgcp);
-                       }
+       /*
+        * Set the columns now, so that they'll be set correctly if we throw
+        * an exception.  We can set them later as well....
+        */
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "MGCP");
+       col_clear(pinfo->cinfo, COL_INFO);
 
-                       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, mgcp_tree,ti);
-                               tvb_sectionbegin = tvb_sectionend;
-                       }
-                       else
-                       {
-                               break;
-                       }
-               } while (tvb_sectionend < tvb_len);
+       /*
+        * Loop through however many mgcp messages may be stuck in
+        * this packet using piggybacking
+        */
+       do
+       {
+               num_messages++;
 
-               if (mgcp_tree)
+               /* Create our mgcp subtree */
+               ti = proto_tree_add_item(tree, proto_mgcp, tvb, 0, 0, ENC_NA);
+               mgcp_tree = proto_item_add_subtree(ti, ett_mgcp);
+
+               sectionlen = tvb_find_dot_line(tvb, tvb_sectionbegin, -1, &tvb_sectionend);
+               if (sectionlen != -1)
                {
-                       proto_item *tii = proto_tree_add_uint(mgcp_tree, hf_mgcp_messagecount, tvb,
-                                                            0 ,0 , num_messages);
-                       PROTO_ITEM_SET_HIDDEN(tii);
+                       dissect_mgcp_message(tvb_new_subset_length_caplen(tvb, tvb_sectionbegin,
+                                               sectionlen, sectionlen),
+                                       pinfo, tree, mgcp_tree, ti);
+                       tvb_sectionbegin = tvb_sectionend;
                }
-
-               /*
-                * Add our column information after dissecting SDP
-                * in order to prevent the column info changing to reflect the SDP
-                * (when showing message count)
-                */
-               tvb_sectionbegin = 0;
-               if (global_mgcp_message_count == TRUE )
+               else
                {
-                       if (num_messages > 1)
-                       {
-                               col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MGCP (%i messages)",num_messages);
-                       }
-                       else
-                       {
-                               col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MGCP (%i message)",num_messages);
-                       }
+                       break;
                }
+       } while (tvb_sectionend < tvb_len);
 
-               sectionlen = tvb_find_line_end(tvb, tvb_sectionbegin,-1,
-                                              &tvb_sectionend,FALSE);
-               col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s",
-                                tvb_format_text(tvb, tvb_sectionbegin, sectionlen));
+       tii = proto_tree_add_uint(mgcp_tree, hf_mgcp_messagecount, tvb,
+                       0 , 0 , num_messages);
+       PROTO_ITEM_SET_HIDDEN(tii);
 
-               return tvb_len;
+       /*
+        * Add our column information after dissecting SDP
+        * in order to prevent the column info changing to reflect the SDP
+        * (when showing message count)
+        */
+       tvb_sectionbegin = 0;
+       if (global_mgcp_message_count == TRUE )
+       {
+               if (num_messages > 1)
+               {
+                       col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MGCP (%i messages)", num_messages);
+               }
+               else
+               {
+                       col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MGCP (%i message)", num_messages);
+               }
        }
 
-       return 0;
+       sectionlen = tvb_find_line_end(tvb, tvb_sectionbegin, -1,
+                       &tvb_sectionend, FALSE);
+       col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s",
+                       tvb_format_text(tvb, tvb_sectionbegin, sectionlen));
+
+       return tvb_len;
 }
+
 /************************************************************************
  * dissect_tpkt_mgcp - The dissector for the ASCII TPKT Media Gateway Control Protocol
  ************************************************************************/
-static int dissect_tpkt_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int dissect_tpkt_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
 {
        guint16 ascii_tpkt;
        int     offset = 0;
@@ -441,7 +555,7 @@ static int dissect_tpkt_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
                 * It's not a ASCII TPKT packet
                 * in MGCP
                 */
-               offset = dissect_mgcp(tvb, pinfo, tree);
+               offset = dissect_mgcp(tvb, pinfo, tree, NULL);
        }
        else
        {
@@ -449,73 +563,44 @@ static int dissect_tpkt_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
                 * Dissect ASCII TPKT header
                 */
                dissect_asciitpkt(tvb, pinfo, tree, mgcp_handle);
-               offset = tvb_length(tvb);
+               offset = tvb_reported_length(tvb);
        }
 
        return offset;
 }
 
-#define MAX_MGCP_MESSAGES_IN_PACKET 5
-static mgcp_info_t pi_arr[MAX_MGCP_MESSAGES_IN_PACKET];
-static int pi_current = 0;
-static mgcp_info_t *mi;
-
 /* Dissect an individual MGCP message */
 static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                                 proto_tree *mgcp_tree, proto_tree *ti)
+                                proto_tree *mgcp_tree, proto_tree *ti)
 {
        /* Declare variables */
        gint sectionlen;
-       gint tvb_sectionend,tvb_sectionbegin, tvb_len;
+       gint tvb_sectionend, tvb_sectionbegin, tvb_len;
        tvbuff_t *next_tvb;
        const gchar *verb_name = "";
-
-       /* Initialise stat info for passing to tap */
-       pi_current++;
-       if (pi_current == MAX_MGCP_MESSAGES_IN_PACKET)
-       {
-               /* Overwrite info in first struct if run out of space... */
-               pi_current = 0;
-       }
-       mi = &pi_arr[pi_current];
-
+    mgcp_info_t* mi = wmem_new0(pinfo->pool, 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;
-       sectionlen = 0;
-       tvb_len = tvb_length(tvb);
+       tvb_len = tvb_reported_length(tvb);
 
        /*
         * 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.
+        * but it's cheap and it's better than nothing.
         */
-       if (is_mgcp_verb(tvb,0,tvb_len,&verb_name) || is_mgcp_rspcode(tvb,0,tvb_len))
+       if (is_mgcp_verb(tvb, 0, tvb_len, &verb_name) || is_mgcp_rspcode(tvb, 0, tvb_len))
        {
                /* dissect first line */
                tvb_sectionbegin = 0;
                tvb_sectionend = tvb_sectionbegin;
-               sectionlen = tvb_find_line_end(tvb,0,-1,&tvb_sectionend,FALSE);
+               sectionlen = tvb_find_line_end(tvb, 0, -1, &tvb_sectionend, FALSE);
                if (sectionlen > 0)
                {
-                       dissect_mgcp_firstline(tvb_new_subset(tvb, tvb_sectionbegin,
-                                              sectionlen,-1), pinfo,
-                                              mgcp_tree);
+                       dissect_mgcp_firstline(tvb_new_subset_length_caplen(tvb, tvb_sectionbegin,
+                                              sectionlen, sectionlen), pinfo,
+                                              mgcp_tree, mi);
                }
                tvb_sectionbegin = tvb_sectionend;
 
@@ -526,24 +611,22 @@ static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
                                                        &tvb_sectionend);
                        if (sectionlen > 0)
                        {
-                               dissect_mgcp_params(tvb_new_subset(tvb, tvb_sectionbegin, sectionlen, -1),
-                                                                  mgcp_tree);
-                               tvb_sectionbegin = tvb_sectionend;
+                               dissect_mgcp_params(tvb_new_subset_length_caplen(tvb, tvb_sectionbegin, sectionlen, sectionlen),
+                                                                  mgcp_tree, mi);
                        }
                }
 
                /* Set the mgcp payload length correctly so we don't include any
                   encapsulated SDP */
                sectionlen = tvb_sectionend;
-               proto_item_set_len(ti,sectionlen);
+               proto_item_set_len(ti, sectionlen);
 
                /* Display the raw text of the mgcp message if desired */
 
                /* Do we want to display the raw text of our MGCP packet? */
                if (global_mgcp_raw_text)
                {
-                       if (tree)
-                               mgcp_raw_text_add(tvb, mgcp_tree);
+                       mgcp_raw_text_add(tvb, mgcp_tree);
                }
 
                /* Dissect sdp payload */
@@ -562,392 +645,17 @@ static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
  */
 static void mgcp_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
 {
-       gint tvb_linebegin,tvb_lineend,tvb_len,linelen;
+       gint tvb_linebegin, tvb_lineend, linelen;
 
        tvb_linebegin = 0;
-       tvb_len = tvb_length(tvb);
 
        do
        {
-               tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend,FALSE);
+               tvb_find_line_end(tvb, tvb_linebegin, -1, &tvb_lineend, FALSE);
                linelen = tvb_lineend - tvb_linebegin;
-               proto_tree_add_text(tree, tvb, tvb_linebegin, linelen, "%s",
-                                   tvb_format_text(tvb, tvb_linebegin, linelen));
+               proto_tree_add_format_text(tree, tvb, tvb_linebegin, linelen);
                tvb_linebegin = tvb_lineend;
-       } while (tvb_lineend < tvb_len);
-}
-
-/* Discard and init any state we've saved */
-static void mgcp_init_protocol(void)
-{
-       if (mgcp_calls != NULL)
-       {
-               g_hash_table_destroy(mgcp_calls);
-               mgcp_calls = NULL;
-       }
-
-       mgcp_calls = g_hash_table_new(mgcp_call_hash, mgcp_call_equal);
-}
-
-/* Register all the bits needed with the filtering engine */
-void proto_register_mgcp(void)
-{
-    static hf_register_info hf[] =
-    {
-        { &hf_mgcp_req,
-          { "Request", "mgcp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
-            "True if MGCP request", HFILL }},
-        { &hf_mgcp_rsp,
-          { "Response", "mgcp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
-            "TRUE if MGCP response", HFILL }},
-        { &hf_mgcp_req_frame,
-          { "Request Frame", "mgcp.reqframe", FT_FRAMENUM, BASE_NONE, NULL, 0,
-            NULL, HFILL }},
-        { &hf_mgcp_rsp_frame,
-          { "Response Frame", "mgcp.rspframe", FT_FRAMENUM, BASE_NONE, NULL, 0,
-            NULL, HFILL }},
-        { &hf_mgcp_time,
-          { "Time from request", "mgcp.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
-            "Timedelta between Request and Response", HFILL }},
-        { &hf_mgcp_req_verb,
-          { "Verb", "mgcp.req.verb", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Name of the verb", HFILL }},
-        { &hf_mgcp_req_endpoint,
-          { "Endpoint", "mgcp.req.endpoint", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Endpoint referenced by the message", HFILL }},
-        { &hf_mgcp_transid,
-          { "Transaction ID", "mgcp.transid", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Transaction ID of this message", HFILL }},
-        { &hf_mgcp_version,
-          { "Version", "mgcp.version", FT_STRING, BASE_NONE, NULL, 0x0,
-            "MGCP Version", HFILL }},
-        { &hf_mgcp_rsp_rspcode,
-          { "Response Code", "mgcp.rsp.rspcode", FT_UINT32, BASE_DEC, VALS(mgcp_return_code_vals), 0x0,
-            NULL, HFILL }},
-        { &hf_mgcp_rsp_rspstring,
-          { "Response String", "mgcp.rsp.rspstring", FT_STRING, BASE_NONE, NULL, 0x0,
-            NULL, HFILL }},
-        { &hf_mgcp_params,
-          { "Parameters", "mgcp.params", FT_NONE, BASE_NONE, NULL, 0x0,
-            "MGCP parameters", HFILL }},
-        { &hf_mgcp_param_rspack,
-          { "ResponseAck (K)", "mgcp.param.rspack", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Response Ack", HFILL }},
-        { &hf_mgcp_param_bearerinfo,
-          { "BearerInformation (B)", "mgcp.param.bearerinfo", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Bearer Information", HFILL }},
-        { &hf_mgcp_param_callid,
-          { "CallId (C)", "mgcp.param.callid", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Call Id", HFILL }},
-        { &hf_mgcp_param_connectionid,
-          {"ConnectionIdentifier (I)", "mgcp.param.connectionid", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Connection Identifier", HFILL }},
-        { &hf_mgcp_param_secondconnectionid,
-          { "SecondConnectionID (I2)", "mgcp.param.secondconnectionid", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Second Connection Identifier", HFILL }},
-        { &hf_mgcp_param_notifiedentity,
-          { "NotifiedEntity (N)", "mgcp.param.notifiedentity", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Notified Entity", HFILL }},
-        { &hf_mgcp_param_requestid,
-          { "RequestIdentifier (X)", "mgcp.param.requestid", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Request Identifier", HFILL }},
-        { &hf_mgcp_param_localconnoptions,
-          { "LocalConnectionOptions (L)", "mgcp.param.localconnectionoptions", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Local Connection Options", HFILL }},
-        { &hf_mgcp_param_localconnoptions_p,
-          { "Packetization period (p)", "mgcp.param.localconnectionoptions.p", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Packetization period", HFILL }},
-        { &hf_mgcp_param_localconnoptions_a,
-          { "Codecs (a)", "mgcp.param.localconnectionoptions.a", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Codecs", HFILL }},
-        { &hf_mgcp_param_localconnoptions_s,
-          { "Silence Suppression (s)", "mgcp.param.localconnectionoptions.s", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Silence Suppression", HFILL }},
-        { &hf_mgcp_param_localconnoptions_e,
-          { "Echo Cancellation (e)", "mgcp.param.localconnectionoptions.e", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Echo Cancellation", HFILL }},
-        { &hf_mgcp_param_localconnoptions_scrtp,
-          { "RTP ciphersuite (sc-rtp)", "mgcp.param.localconnectionoptions.scrtp", FT_STRING, BASE_NONE, NULL, 0x0,
-            "RTP ciphersuite", HFILL }},
-        { &hf_mgcp_param_localconnoptions_scrtcp,
-          { "RTCP ciphersuite (sc-rtcp)", "mgcp.param.localconnectionoptions.scrtcp", FT_STRING, BASE_NONE, NULL, 0x0,
-            "RTCP ciphersuite", HFILL }},
-        { &hf_mgcp_param_localconnoptions_b,
-          { "Bandwidth (b)", "mgcp.param.localconnectionoptions.b", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Bandwidth", HFILL }},
-        { &hf_mgcp_param_localconnoptions_esccd,
-          { "Content Destination (es-ccd)", "mgcp.param.localconnectionoptions.esccd", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Content Destination", HFILL }},
-        { &hf_mgcp_param_localconnoptions_escci,
-          { "Content Identifier (es-cci)", "mgcp.param.localconnectionoptions.escci", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Content Identifier", HFILL }},
-        { &hf_mgcp_param_localconnoptions_dqgi,
-          { "D-QoS GateID (dq-gi)", "mgcp.param.localconnectionoptions.dqgi", FT_STRING, BASE_NONE, NULL, 0x0,
-            "D-QoS GateID", HFILL }},
-        { &hf_mgcp_param_localconnoptions_dqrd,
-          { "D-QoS Reserve Destination (dq-rd)", "mgcp.param.localconnectionoptions.dqrd", FT_STRING, BASE_NONE, NULL, 0x0,
-            "D-QoS Reserve Destination", HFILL }},
-        { &hf_mgcp_param_localconnoptions_dqri,
-          { "D-QoS Resource ID (dq-ri)", "mgcp.param.localconnectionoptions.dqri", FT_STRING, BASE_NONE, NULL, 0x0,
-            "D-QoS Resource ID", HFILL }},
-        { &hf_mgcp_param_localconnoptions_dqrr,
-          { "D-QoS Resource Reservation (dq-rr)", "mgcp.param.localconnectionoptions.dqrr", FT_STRING, BASE_NONE, NULL, 0x0,
-            "D-QoS Resource Reservation", HFILL }},
-        { &hf_mgcp_param_localconnoptions_k,
-          { "Encryption Key (k)", "mgcp.param.localconnectionoptions.k", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Encryption Key", HFILL }},
-        { &hf_mgcp_param_localconnoptions_gc,
-          { "Gain Control (gc)", "mgcp.param.localconnectionoptions.gc", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Gain Control", HFILL }},
-        { &hf_mgcp_param_localconnoptions_fmtp,
-          { "Media Format (fmtp)", "mgcp.param.localconnectionoptions.fmtp", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Media Format", HFILL }},
-        { &hf_mgcp_param_localconnoptions_nt,
-          { "Network Type (nt)", "mgcp.param.localconnectionoptions.nt", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Network Type", HFILL }},
-        { &hf_mgcp_param_localconnoptions_ofmtp,
-          { "Optional Media Format (o-fmtp)", "mgcp.param.localconnectionoptions.ofmtp", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Optional Media Format", HFILL }},
-        { &hf_mgcp_param_localconnoptions_r,
-          { "Resource Reservation (r)", "mgcp.param.localconnectionoptions.r", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Resource Reservation", HFILL }},
-        { &hf_mgcp_param_localconnoptions_t,
-          { "Type of Service (r)", "mgcp.param.localconnectionoptions.t", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Type of Service", HFILL }},
-        { &hf_mgcp_param_localconnoptions_rcnf,
-          { "Reservation Confirmation (r-cnf)", "mgcp.param.localconnectionoptions.rcnf", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Reservation Confirmation", HFILL }},
-        { &hf_mgcp_param_localconnoptions_rdir,
-          { "Reservation Direction (r-dir)", "mgcp.param.localconnectionoptions.rdir", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Reservation Direction", HFILL }},
-        { &hf_mgcp_param_localconnoptions_rsh,
-          { "Resource Sharing (r-sh)", "mgcp.param.localconnectionoptions.rsh", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Resource Sharing", HFILL }},
-        { &hf_mgcp_param_connectionmode,
-          { "ConnectionMode (M)", "mgcp.param.connectionmode", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Connection Mode", HFILL }},
-        { &hf_mgcp_param_reqevents,
-          { "RequestedEvents (R)", "mgcp.param.reqevents", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Requested Events", HFILL }},
-        { &hf_mgcp_param_signalreq,
-          { "SignalRequests (S)", "mgcp.param.signalreq", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Signal Request", HFILL }},
-        { &hf_mgcp_param_restartmethod,
-          { "RestartMethod (RM)", "mgcp.param.restartmethod", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Restart Method", HFILL }},
-        { &hf_mgcp_param_restartdelay,
-          { "RestartDelay (RD)", "mgcp.param.restartdelay", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Restart Delay", HFILL }},
-        { &hf_mgcp_param_digitmap,
-          { "DigitMap (D)", "mgcp.param.digitmap", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Digit Map", HFILL }},
-        { &hf_mgcp_param_observedevent,
-          { "ObservedEvents (O)", "mgcp.param.observedevents", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Observed Events", HFILL }},
-        { &hf_mgcp_param_connectionparam,
-          { "ConnectionParameters (P)", "mgcp.param.connectionparam", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Connection Parameters", HFILL }},
-        { &hf_mgcp_param_connectionparam_ps,
-          { "Packets sent (PS)", "mgcp.param.connectionparam.ps", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Packets sent (P:PS)", HFILL }},
-        { &hf_mgcp_param_connectionparam_os,
-          { "Octets sent (OS)", "mgcp.param.connectionparam.os", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Octets sent (P:OS)", HFILL }},
-        { &hf_mgcp_param_connectionparam_pr,
-          { "Packets received (PR)", "mgcp.param.connectionparam.pr", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Packets received (P:PR)", HFILL }},
-        { &hf_mgcp_param_connectionparam_or,
-          { "Octets received (OR)", "mgcp.param.connectionparam.or", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Octets received (P:OR)", HFILL }},
-        { &hf_mgcp_param_connectionparam_pl,
-          { "Packets lost (PL)", "mgcp.param.connectionparam.pl", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Packets lost (P:PL)", HFILL }},
-        { &hf_mgcp_param_connectionparam_ji,
-          { "Jitter (JI)", "mgcp.param.connectionparam.ji", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Average inter-packet arrival jitter in milliseconds (P:JI)", HFILL }},
-        { &hf_mgcp_param_connectionparam_la,
-          { "Latency (LA)", "mgcp.param.connectionparam.la", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Average latency in milliseconds (P:LA)", HFILL }},
-        { &hf_mgcp_param_connectionparam_pcrps,
-          { "Remote Packets sent (PC/RPS)", "mgcp.param.connectionparam.pcrps", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Remote Packets sent (P:PC/RPS)", HFILL }},
-        { &hf_mgcp_param_connectionparam_pcros,
-          { "Remote Octets sent (PC/ROS)", "mgcp.param.connectionparam.pcros", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Remote Octets sent (P:PC/ROS)", HFILL }},
-        { &hf_mgcp_param_connectionparam_pcrpl,
-          { "Remote Packets lost (PC/RPL)", "mgcp.param.connectionparam.pcrpl", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Remote Packets lost (P:PC/RPL)", HFILL }},
-        { &hf_mgcp_param_connectionparam_pcrji,
-          { "Remote Jitter (PC/RJI)", "mgcp.param.connectionparam.pcrji", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Remote Jitter (P:PC/RJI)", HFILL }},
-        { &hf_mgcp_param_connectionparam_x,
-          { "Vendor Extension", "mgcp.param.connectionparam.x", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Vendor Extension (P:X-*)", HFILL }},
-        { &hf_mgcp_param_reasoncode,
-          { "ReasonCode (E)", "mgcp.param.reasoncode", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Reason Code", HFILL }},
-        { &hf_mgcp_param_eventstates,
-          { "EventStates (ES)", "mgcp.param.eventstates", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Event States", HFILL }},
-        { &hf_mgcp_param_specificendpoint,
-          { "SpecificEndpointID (Z)", "mgcp.param.specificendpointid", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Specific Endpoint ID", HFILL }},
-        { &hf_mgcp_param_secondendpointid,
-          { "SecondEndpointID (Z2)", "mgcp.param.secondendpointid", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Second Endpoint ID", HFILL }},
-        { &hf_mgcp_param_reqinfo,
-          { "RequestedInfo (F)", "mgcp.param.reqinfo", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Requested Info", HFILL }},
-        { &hf_mgcp_param_quarantinehandling,
-          { "QuarantineHandling (Q)", "mgcp.param.quarantinehandling", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Quarantine Handling", HFILL }},
-        { &hf_mgcp_param_detectedevents,
-          { "DetectedEvents (T)", "mgcp.param.detectedevents", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Detected Events", HFILL }},
-        { &hf_mgcp_param_capabilities,
-          { "Capabilities (A)", "mgcp.param.capabilities", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Capabilities", HFILL }},
-        { &hf_mgcp_param_maxmgcpdatagram,
-          {"MaxMGCPDatagram (MD)", "mgcp.param.maxmgcpdatagram", FT_STRING, BASE_NONE, NULL, 0x0,
-           "Maximum MGCP Datagram size", HFILL }},
-        { &hf_mgcp_param_packagelist,
-          {"PackageList (PL)", "mgcp.param.packagelist", FT_STRING, BASE_NONE, NULL, 0x0,
-           "Package List", HFILL }},
-        { &hf_mgcp_param_extension,
-          { "Extension Parameter (non-critical)", "mgcp.param.extension", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Extension Parameter", HFILL }},
-        { &hf_mgcp_param_extension_critical,
-          { "Extension Parameter (critical)", "mgcp.param.extensioncritical", FT_STRING, BASE_NONE, NULL, 0x0,
-            "Critical Extension Parameter", HFILL }},
-        { &hf_mgcp_param_invalid,
-          { "Invalid Parameter", "mgcp.param.invalid", FT_STRING, BASE_NONE, NULL, 0x0,
-            NULL, HFILL }},
-        { &hf_mgcp_messagecount,
-          { "MGCP Message Count", "mgcp.messagecount", FT_UINT32, BASE_DEC, NULL, 0x0,
-            "Number of MGCP message in a packet", HFILL }},
-        { &hf_mgcp_dup,
-          { "Duplicate Message", "mgcp.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
-            NULL, HFILL }},
-        { &hf_mgcp_req_dup,
-          { "Duplicate Request", "mgcp.req.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
-            NULL, HFILL }},
-        { &hf_mgcp_req_dup_frame,
-          { "Original Request Frame", "mgcp.req.dup.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
-            "Frame containing original request", HFILL }},
-        { &hf_mgcp_rsp_dup,
-          { "Duplicate Response", "mgcp.rsp.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
-            NULL, HFILL }},
-        { &hf_mgcp_rsp_dup_frame,
-          { "Original Response Frame", "mgcp.rsp.dup.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
-            "Frame containing original response", HFILL }},
-    };
-
-    static gint *ett[] =
-    {
-        &ett_mgcp,
-        &ett_mgcp_param,
-        &ett_mgcp_param_connectionparam,
-        &ett_mgcp_param_localconnectionoptions
-    };
-
-    module_t *mgcp_module;
-
-    /* Register protocol */
-    proto_mgcp = proto_register_protocol("Media Gateway Control Protocol", "MGCP", "mgcp");
-    proto_register_field_array(proto_mgcp, hf, array_length(hf));
-    proto_register_subtree_array(ett, array_length(ett));
-    register_init_routine(&mgcp_init_protocol);
-
-    new_register_dissector("mgcp", dissect_mgcp, proto_mgcp);
-
-    /* Register our configuration options */
-    mgcp_module = prefs_register_protocol(proto_mgcp, proto_reg_handoff_mgcp);
-
-    prefs_register_uint_preference(mgcp_module, "tcp.gateway_port",
-                                   "MGCP Gateway TCP Port",
-                                   "Set the UDP port for gateway messages "
-                                   "(if other than the default of 2427)",
-                                   10, &global_mgcp_gateway_tcp_port);
-
-    prefs_register_uint_preference(mgcp_module, "udp.gateway_port",
-                                   "MGCP Gateway UDP Port",
-                                   "Set the TCP port for gateway messages "
-                                   "(if other than the default of 2427)",
-                                   10, &global_mgcp_gateway_udp_port);
-
-    prefs_register_uint_preference(mgcp_module, "tcp.callagent_port",
-                                   "MGCP Callagent TCP Port",
-                                   "Set the TCP port for callagent messages "
-                                   "(if other than the default of 2727)",
-                                   10, &global_mgcp_callagent_tcp_port);
-
-    prefs_register_uint_preference(mgcp_module, "udp.callagent_port",
-                                   "MGCP Callagent UDP Port",
-                                   "Set the UDP port for callagent messages "
-                                   "(if other than the default of 2727)",
-                                   10, &global_mgcp_callagent_udp_port);
-
-
-    prefs_register_bool_preference(mgcp_module, "display_raw_text",
-                                  "Display raw text for MGCP message",
-                                  "Specifies that the raw text of the "
-                                  "MGCP message should be displayed "
-                                  "instead of (or in addition to) the "
-                                  "dissection tree",
-                                  &global_mgcp_raw_text);
-
-    prefs_register_obsolete_preference(mgcp_module, "display_dissect_tree");
-
-    prefs_register_bool_preference(mgcp_module, "display_mgcp_message_count",
-                                   "Display the number of MGCP messages",
-                                   "Display the number of MGCP messages "
-                                   "found in a packet in the protocol column.",
-                                   &global_mgcp_message_count);
-
-    mgcp_tap = register_tap("mgcp");
-}
-
-/* The registration hand-off routine */
-void proto_reg_handoff_mgcp(void)
-{
-       static gboolean mgcp_prefs_initialized = FALSE;
-       static dissector_handle_t mgcp_tpkt_handle;
-       /*
-        * Variables to allow for proper deletion of dissector registration when
-        * the user changes port from the gui.
-        */
-       static guint gateway_tcp_port;
-       static guint gateway_udp_port;
-       static guint callagent_tcp_port;
-       static guint callagent_udp_port;
-
-       if (!mgcp_prefs_initialized)
-       {
-               /* Get a handle for the SDP dissector. */
-               sdp_handle = find_dissector("sdp");
-               mgcp_handle = new_create_dissector_handle(dissect_mgcp, proto_mgcp);
-               mgcp_tpkt_handle = new_create_dissector_handle(dissect_tpkt_mgcp, proto_mgcp);
-               mgcp_prefs_initialized = TRUE;
-       }
-       else
-       {
-               dissector_delete_uint("tcp.port", gateway_tcp_port, mgcp_tpkt_handle);
-               dissector_delete_uint("udp.port", gateway_udp_port, mgcp_handle);
-               dissector_delete_uint("tcp.port", callagent_tcp_port, mgcp_tpkt_handle);
-               dissector_delete_uint("udp.port", callagent_udp_port, mgcp_handle);
-       }
-
-       /* Set our port number for future use */
-       gateway_tcp_port = global_mgcp_gateway_tcp_port;
-       gateway_udp_port = global_mgcp_gateway_udp_port;
-
-       callagent_tcp_port = global_mgcp_callagent_tcp_port;
-       callagent_udp_port = global_mgcp_callagent_udp_port;
-
-       dissector_add_uint("tcp.port", global_mgcp_gateway_tcp_port, mgcp_tpkt_handle);
-       dissector_add_uint("udp.port", global_mgcp_gateway_udp_port, mgcp_handle);
-       dissector_add_uint("tcp.port", global_mgcp_callagent_tcp_port, mgcp_tpkt_handle);
-       dissector_add_uint("udp.port", global_mgcp_callagent_udp_port, mgcp_handle);
+       } while (tvb_offset_exists(tvb, tvb_lineend));
 }
 
 /*
@@ -965,9 +673,17 @@ void proto_reg_handoff_mgcp(void)
  */
 static gboolean is_mgcp_verb(tvbuff_t *tvb, gint offset, gint maxlength, const gchar **verb_name)
 {
-       int returnvalue = FALSE;
+       gboolean returnvalue = FALSE;
        gchar word[5];
 
+       /* This function is used for checking if a packet is actually an
+          mgcp packet. Make sure that we do not throw an exception
+          during such a check. If we did throw an exeption, we could
+          not refuse the packet and give other dissectors the chance to
+          look at it. */
+       if (tvb_captured_length_remaining(tvb, offset) < (gint)sizeof(word))
+               return FALSE;
+
        /* Read the string into 'word' and see if it looks like the start of a verb */
        if ((maxlength >= 4) && tvb_get_nstringz0(tvb, offset, sizeof(word), word))
        {
@@ -991,7 +707,7 @@ static gboolean is_mgcp_verb(tvbuff_t *tvb, gint offset, gint maxlength, const g
        /* May be whitespace after verb code - anything else is an error.. */
        if (returnvalue && maxlength >= 5)
        {
-               char next = tvb_get_guint8(tvb,4);
+               char next = tvb_get_guint8(tvb, 4);
                if ((next != ' ') && (next != '\t'))
                {
                        returnvalue = FALSE;
@@ -1017,14 +733,18 @@ static gboolean is_mgcp_verb(tvbuff_t *tvb, gint offset, gint maxlength, const g
  */
 static gboolean is_mgcp_rspcode(tvbuff_t *tvb, gint offset, gint maxlength)
 {
-       int returnvalue = FALSE;
+       gboolean returnvalue = FALSE;
        guint8 word[4];
 
+       /* see the comment in is_mgcp_verb() */
+       if (tvb_captured_length_remaining(tvb, offset) < (gint)sizeof(word))
+               return FALSE;
+
        /* Do 1st 3 characters look like digits? */
        if (maxlength >= 3)
        {
                tvb_get_nstringz0(tvb, offset, sizeof(word), word);
-               if (isdigit(word[0]) && isdigit(word[1]) && isdigit(word[2]))
+               if (g_ascii_isdigit(word[0]) && g_ascii_isdigit(word[1]) && g_ascii_isdigit(word[2]))
                {
                        returnvalue = TRUE;
                }
@@ -1076,24 +796,24 @@ static gboolean is_rfc2234_alpha(guint8 c)
  * Returns: The offset in tvb where the value of the MGCP parameter
  *          begins.
  */
-static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
+static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf, mgcp_info_t* mi)
 {
-       gint returnvalue = -1, tvb_current_offset,counter;
+       gint returnvalue = -1, tvb_current_offset, counter;
        guint8 tempchar, plus_minus;
        gchar **buf;
 
        tvb_current_offset = offset;
        *hf = NULL;
-       buf=NULL;
+       buf = NULL;
 
        if (len > 0)
        {
-               tempchar = tvb_get_guint8(tvb,tvb_current_offset);
+               tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset));
 
                switch (tempchar)
                {
                        case 'K':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1101,7 +821,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                *hf = &hf_mgcp_param_rspack;
                                break;
                        case 'B':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1109,7 +829,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                *hf = &hf_mgcp_param_bearerinfo;
                                break;
                        case 'C':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1119,7 +839,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                        case 'I':
                                tvb_current_offset++;
                                if (len > (tvb_current_offset - offset) &&
-                                  (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':')
+                                  (tempchar = tvb_get_guint8(tvb, tvb_current_offset)) == ':')
                                {
                                        *hf = &hf_mgcp_param_connectionid;
                                        tvb_current_offset--;
@@ -1131,7 +851,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                }
                                break;
                        case 'N':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1144,16 +864,36 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
 
                                /* X: is RequestIdentifier */
                                if (len > (tvb_current_offset - offset) &&
-                                  (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':')
+                                  (tempchar = tvb_get_guint8(tvb, tvb_current_offset)) == ':')
                                {
                                        *hf = &hf_mgcp_param_requestid;
                                        tvb_current_offset--;
                                }
+                               /* XRM/MCR */
+                               else
+                               if (len > (tvb_current_offset - offset) &&
+                                  (tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb,tvb_current_offset))) == 'R')
+                               {
+                                       /* Move past 'R' */
+                                       tvb_current_offset += 3;
+                                       if (len > (tvb_current_offset - offset) &&
+                                               (tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb,tvb_current_offset))) == 'R')
+                                       {
+                                               *hf = &hf_mgcp_param_remotevoicemetrics;
+                                       }
+                                       else
+                                       if (len > (tvb_current_offset - offset) &&
+                                          (tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb,tvb_current_offset))) == 'L')
+                                       {
+                                               *hf = &hf_mgcp_param_localvoicemetrics;
+                                       }
+                                       tvb_current_offset -= 4;
+                               }
 
                                /* X+...: or X-....: are vendor extension parameters */
                                else
                                if (len > (tvb_current_offset - offset) &&
-                                   ((plus_minus = tvb_get_guint8(tvb,tvb_current_offset)) == '-' ||
+                                   ((plus_minus = tvb_get_guint8(tvb, tvb_current_offset)) == '-' ||
                                     (plus_minus == '+')))
                                {
                                        /* Move past + or - */
@@ -1163,7 +903,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                        for (counter = 1;
                                            ((len > (counter + tvb_current_offset-offset)) &&
                                            (is_rfc2234_alpha(tempchar = tvb_get_guint8(tvb, tvb_current_offset+counter)) ||
-                                            isdigit(tempchar))) ;
+                                            g_ascii_isdigit(tempchar))) ;
                                             counter++);
 
                                        if (tempchar == ':')
@@ -1183,7 +923,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                }
                                break;
                        case 'L':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1193,7 +933,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                        case 'M':
                                tvb_current_offset++;
                                if (len > (tvb_current_offset - offset) &&
-                                  (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':')
+                                  (tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset))) == ':')
                                {
                                        *hf = &hf_mgcp_param_connectionmode;
                                        tvb_current_offset--;
@@ -1207,7 +947,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                        case 'R':
                                tvb_current_offset++;
                                if (len > (tvb_current_offset - offset) &&
-                                   (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':')
+                                   (tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset))) == ':')
                                {
                                        *hf = &hf_mgcp_param_reqevents;
                                        tvb_current_offset--;
@@ -1224,7 +964,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                }
                                break;
                        case 'S':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1233,8 +973,20 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                buf = &(mi->signalReq);
                                break;
                        case 'D':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
+                                       if (len > (tvb_current_offset + 5 - offset) &&
+                                               (g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset + 1) == 'Q')) &&
+                                               (                tvb_get_guint8(tvb, tvb_current_offset + 2) == '-' ) &&
+                                               (g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset + 3) == 'R')) &&
+                                               (g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset + 4) == 'I')) &&
+                                               (                tvb_get_guint8(tvb, tvb_current_offset + 5) == ':' )
+                                       ) {
+                                               tvb_current_offset+=4;
+                                               *hf = &hf_mgcp_param_resourceid;
+                                               break;
+                                       }
+
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
                                }
@@ -1242,7 +994,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                mi->hasDigitMap = TRUE;
                                break;
                        case 'O':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1253,7 +1005,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                        case 'P':
                                tvb_current_offset++;
                                if (len > (tvb_current_offset - offset) &&
-                                   (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':')
+                                   (tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset))) == ':')
                                {
                                        *hf = &hf_mgcp_param_connectionparam;
                                        tvb_current_offset--;
@@ -1267,7 +1019,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                        case 'E':
                                tvb_current_offset++;
                                if (len > (tvb_current_offset - offset) &&
-                                   (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':')
+                                   (tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset))) == ':')
                                {
                                        *hf = &hf_mgcp_param_reasoncode;
                                        tvb_current_offset--;
@@ -1281,7 +1033,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                        case 'Z':
                                tvb_current_offset++;
                                if (len > (tvb_current_offset - offset) &&
-                                   (tempchar = tvb_get_guint8(tvb,tvb_current_offset)) == ':')
+                                   (tempchar = (guint8)g_ascii_toupper(tvb_get_guint8(tvb, tvb_current_offset))) == ':')
                                {
                                        *hf = &hf_mgcp_param_specificendpoint;
                                        tvb_current_offset--;
@@ -1293,7 +1045,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                }
                                break;
                        case 'F':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1301,7 +1053,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                *hf = &hf_mgcp_param_reqinfo;
                                break;
                        case 'Q':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1309,7 +1061,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                *hf = &hf_mgcp_param_quarantinehandling;
                                break;
                        case 'T':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1317,7 +1069,7 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
                                *hf = &hf_mgcp_param_detectedevents;
                                break;
                        case 'A':
-                               if (tvb_get_guint8(tvb,tvb_current_offset+1) != ':')
+                               if (tvb_get_guint8(tvb, tvb_current_offset+1) != ':')
                                {
                                        *hf = &hf_mgcp_param_invalid;
                                        break;
@@ -1335,16 +1087,16 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
 
                /* Add a recognised parameter type if we have one */
                if (*hf != NULL && len > (tvb_current_offset - offset) &&
-                   tvb_get_guint8(tvb,tvb_current_offset) == ':')
+                   tvb_get_guint8(tvb, tvb_current_offset) == ':')
                {
                        tvb_current_offset++;
-                       tvb_current_offset = tvb_skip_wsp(tvb,tvb_current_offset, (len - tvb_current_offset + offset));
+                       tvb_current_offset = tvb_skip_wsp(tvb, tvb_current_offset, (len - tvb_current_offset + offset));
                        returnvalue = tvb_current_offset;
 
-                       /* set the observedEvents or signalReq used in Voip Calls analysis */
-                       if (buf != NULL) {
-                               *buf = tvb_get_ephemeral_string(tvb, tvb_current_offset, (len - tvb_current_offset + offset));
-                       }
+                       /* set the observedEvents or signalReq used in Voip Calls analysis */
+                       if (buf != NULL) {
+                               *buf = tvb_get_string_enc(wmem_packet_scope(), tvb, tvb_current_offset, (len - tvb_current_offset + offset), ENC_ASCII);
+                       }
                }
        }
        else
@@ -1355,7 +1107,8 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
 
        /* For these types, show the whole line */
        if ((*hf == &hf_mgcp_param_invalid) ||
-           (*hf == &hf_mgcp_param_extension) || (*hf == &hf_mgcp_param_extension_critical))
+           (*hf == &hf_mgcp_param_extension) || (*hf == &hf_mgcp_param_extension_critical) ||
+           (*hf == &hf_mgcp_param_localvoicemetrics) || (*hf == &hf_mgcp_param_remotevoicemetrics))
        {
                returnvalue = offset;
        }
@@ -1380,9 +1133,9 @@ static gint tvb_parse_param(tvbuff_t* tvb, gint offset, gint len, int** hf)
  * tree - The tree from which to hang the structured information parsed
  *        from the first line of the MGCP message.
  */
-static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mgcp_info_t* mi)
 {
-       gint tvb_current_offset,tvb_previous_offset,tvb_len,tvb_current_len;
+       gint tvb_current_offset, tvb_previous_offset, tvb_len, tvb_current_len;
        gint tokennum, tokenlen;
        proto_item* hidden_item;
        char *transid = NULL;
@@ -1394,25 +1147,24 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
        mgcp_call_info_key *new_mgcp_call_key = NULL;
        mgcp_call_t *mgcp_call = NULL;
        nstime_t delta;
-       gint rspcode = 0;
        const gchar *verb_description = "";
        char code_with_verb[64] = "";  /* To fit "<4-letter-code> (<longest-verb>)" */
+       proto_item* pi;
 
-       static address null_address = { AT_NONE, 0, NULL };
+       static address null_address = ADDRESS_INIT_NONE;
        tvb_previous_offset = 0;
-       tvb_len = tvb_length(tvb);
-       tvb_current_len = tvb_len;
+       tvb_len = tvb_reported_length(tvb);
        tvb_current_offset = tvb_previous_offset;
        mi->is_duplicate = FALSE;
        mi->request_available = FALSE;
 
-       if (tree)
+       /* if (tree) */
        {
                tokennum = 0;
 
                do
                {
-                       tvb_current_len = tvb_length_remaining(tvb,tvb_previous_offset);
+                       tvb_current_len = tvb_reported_length_remaining(tvb, tvb_previous_offset);
                        tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_current_len, ' ');
                        if (tvb_current_offset == -1)
                        {
@@ -1426,10 +1178,14 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                        if (tokennum == 0)
                        {
                                if (tokenlen > 4)
-                                       THROW(ReportedBoundsError);
-                               code = tvb_format_text(tvb,tvb_previous_offset,tokenlen);
-                               g_strlcpy(mi->code,code,5);
-                               if (is_mgcp_verb(tvb,tvb_previous_offset,tvb_current_len,&verb_description))
+                               {
+                                       /* XXX - exception */
+                                       return;
+                               }
+
+                               code = tvb_format_text(tvb, tvb_previous_offset, tokenlen);
+                               g_strlcpy(mi->code, code, 5);
+                               if (is_mgcp_verb(tvb, tvb_previous_offset, tvb_current_len, &verb_description))
                                {
                                        mgcp_type = MGCP_REQUEST;
                                        if (verb_description != NULL)
@@ -1444,13 +1200,15 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                                                     strlen(code_with_verb) ? code_with_verb : code);
                                }
                                else
-                               if (is_mgcp_rspcode(tvb,tvb_previous_offset,tvb_current_len))
+                               if (is_mgcp_rspcode(tvb, tvb_previous_offset, tvb_current_len))
                                {
+                                       gboolean rspcode_valid;
                                        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);
+                                       rspcode_valid = ws_strtou32(code, NULL, &mi->rspcode);
+                                       pi = proto_tree_add_uint(tree, hf_mgcp_rsp_rspcode, tvb,
+                                                           tvb_previous_offset, tokenlen, mi->rspcode);
+                                       if (!rspcode_valid)
+                                               expert_add_info(pinfo, pi, &ei_mgcp_rsp_rspcode_invalid);
                                }
                                else
                                {
@@ -1459,9 +1217,9 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                        }
                        if (tokennum == 1)
                        {
-                               transid = tvb_format_text(tvb,tvb_previous_offset,tokenlen);
+                               transid = tvb_format_text(tvb, tvb_previous_offset, tokenlen);
                                /* XXX - what if this isn't a valid text string? */
-                               mi->transid = atol(transid);
+                               mi->transid = (guint32)strtoul(transid, NULL, 10);
                                proto_tree_add_string(tree, hf_mgcp_transid, tvb,
                                                      tvb_previous_offset, tokenlen, transid);
                        }
@@ -1469,9 +1227,9 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                        {
                                if (mgcp_type == MGCP_REQUEST)
                                {
-                                       endpointId = tvb_format_text(tvb, tvb_previous_offset,tokenlen);
-                                       mi->endpointId = ep_strdup(endpointId);
-                                       proto_tree_add_string(tree,hf_mgcp_req_endpoint, tvb,
+                                       endpointId = tvb_format_text(tvb, tvb_previous_offset, tokenlen);
+                                       mi->endpointId = wmem_strdup(wmem_packet_scope(), endpointId);
+                                       proto_tree_add_string(tree, hf_mgcp_req_endpoint, tvb,
                                                              tvb_previous_offset, tokenlen, endpointId);
                                }
                                else
@@ -1499,15 +1257,15 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                if (tvb_current_offset < tvb_len )
                                {
                                        tokenlen = tvb_find_line_end(tvb, tvb_previous_offset,
-                                                                    -1, &tvb_current_offset,FALSE);
+                                                                    -1, &tvb_current_offset, FALSE);
                                }
                                else
                                {
                                        tokenlen = tvb_current_len;
                                }
-                               proto_tree_add_string(tree,hf_mgcp_version, tvb,
+                               proto_tree_add_string(tree, hf_mgcp_version, tvb,
                                                      tvb_previous_offset, tokenlen,
-                                                     tvb_format_text(tvb,tvb_previous_offset,
+                                                     tvb_format_text(tvb, tvb_previous_offset,
                                                      tokenlen));
                                break;
                        }
@@ -1517,7 +1275,7 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                                                   tvb_current_len);
                        }
                        tokennum++;
-               } while (tvb_current_offset < tvb_len && tvb_previous_offset < tvb_len && tokennum <= 3);
+               } while (tvb_current_offset < tvb_len && tvb_offset_exists(tvb, tvb_current_offset) && tvb_previous_offset < tvb_len && tokennum <= 3);
 
                switch (mgcp_type)
                {
@@ -1543,9 +1301,7 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                   to which the call was sent. */
                                if (pinfo->ptype == PT_TCP)
                                {
-                                       conversation = find_conversation(pinfo->fd->num, &pinfo->src,
-                                                                        &pinfo->dst, pinfo->ptype, pinfo->srcport,
-                                                                        pinfo->destport, 0);
+                                       conversation = find_conversation_pinfo(pinfo, 0);
                                }
                                else
                                {
@@ -1554,8 +1310,8 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                         * pointer for the second address argument even
                                         * if you do that.
                                         */
-                                       conversation = find_conversation(pinfo->fd->num, &null_address,
-                                                                        &pinfo->dst, pinfo->ptype, pinfo->srcport,
+                                       conversation = find_conversation(pinfo->num, &null_address,
+                                                                        &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype), pinfo->srcport,
                                                                         pinfo->destport, 0);
                                }
                                if (conversation != NULL)
@@ -1564,7 +1320,7 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                           matching conversation is available. */
                                        mgcp_call_key.transid = mi->transid;
                                        mgcp_call_key.conversation = conversation;
-                                       mgcp_call = g_hash_table_lookup(mgcp_calls, &mgcp_call_key);
+                                       mgcp_call = (mgcp_call_t *)wmem_map_lookup(mgcp_calls, &mgcp_call_key);
                                        if (mgcp_call)
                                        {
                                                /* Indicate the frame to which this is a reply. */
@@ -1574,13 +1330,13 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                                        mi->request_available = TRUE;
                                                        mgcp_call->responded = TRUE;
                                                        mi->req_num = mgcp_call->req_num;
-                                                       g_strlcpy(mi->code,mgcp_call->code,5);
+                                                       g_strlcpy(mi->code, mgcp_call->code, 5);
                                                        item = proto_tree_add_uint_format(tree, hf_mgcp_req_frame,
                                                                                          tvb, 0, 0, mgcp_call->req_num,
                                                                                          "This is a response to a request in frame %u",
                                                                                          mgcp_call->req_num);
                                                        PROTO_ITEM_SET_GENERATED(item);
-                                                       nstime_delta(&delta, &pinfo->fd->abs_ts, &mgcp_call->req_time);
+                                                       nstime_delta(&delta, &pinfo->abs_ts, &mgcp_call->req_time);
                                                        item = proto_tree_add_time(tree, hf_mgcp_time, tvb, 0, 0, &delta);
                                                        PROTO_ITEM_SET_GENERATED(item);
                                                }
@@ -1590,33 +1346,32 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                                        /* We have not yet seen a response to that call, so
                                                           this must be the first response; remember its
                                                           frame number. */
-                                                       mgcp_call->rsp_num = pinfo->fd->num;
+                                                       mgcp_call->rsp_num = pinfo->num;
                                                }
                                                else
                                                {
                                                        /* We have seen a response to this call - but was it
                                                           *this* response? (disregard provisional responses) */
-                                                       if ((mgcp_call->rsp_num != pinfo->fd->num) &&
+                                                       if ((mgcp_call->rsp_num != pinfo->num) &&
                                                            (mi->rspcode >= 200) &&
                                                            (mi->rspcode == mgcp_call->rspcode))
                                                        {
+                                                               proto_item* item;
+
                                                                /* No, so it's a duplicate response. Mark it as such. */
                                                                mi->is_duplicate = TRUE;
                                                                col_append_fstr(pinfo->cinfo, COL_INFO,
-                                                                               ", Duplicate Response %u",
-                                                                               mi->transid);
-                                                               if (tree)
-                                                               {
-                                                                       proto_item* item;
-                                                                       item = proto_tree_add_uint(tree, hf_mgcp_dup, tvb, 0,0, mi->transid);
-                                                                       PROTO_ITEM_SET_HIDDEN(item);
-                                                                       item = proto_tree_add_uint(tree, hf_mgcp_rsp_dup,
-                                                                                                  tvb, 0, 0, mi->transid);
-                                                                       PROTO_ITEM_SET_GENERATED(item);
-                                                                       item = proto_tree_add_uint(tree, hf_mgcp_rsp_dup_frame,
-                                                                                                  tvb, 0, 0, mgcp_call->rsp_num);
-                                                                       PROTO_ITEM_SET_GENERATED(item);
-                                                               }
+                                                                               ", Duplicate Response %u",
+                                                                               mi->transid);
+
+                                                               item = proto_tree_add_uint(tree, hf_mgcp_dup, tvb, 0, 0, mi->transid);
+                                                               PROTO_ITEM_SET_HIDDEN(item);
+                                                               item = proto_tree_add_uint(tree, hf_mgcp_rsp_dup,
+                                                                               tvb, 0, 0, mi->transid);
+                                                               PROTO_ITEM_SET_GENERATED(item);
+                                                               item = proto_tree_add_uint(tree, hf_mgcp_rsp_dup_frame,
+                                                                               tvb, 0, 0, mgcp_call->rsp_num);
+                                                               PROTO_ITEM_SET_GENERATED(item);
                                                        }
                                                }
                                                /* Now store the response code (after comparison above) */
@@ -1646,9 +1401,7 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                 */
                                if (pinfo->ptype == PT_TCP)
                                {
-                                       conversation = find_conversation(pinfo->fd->num, &pinfo->src,
-                                                                        &pinfo->dst, pinfo->ptype, pinfo->srcport,
-                                                                        pinfo->destport, 0);
+                                       conversation = find_conversation_pinfo(pinfo, 0);
                                }
                                else
                                {
@@ -1658,8 +1411,8 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                         * pointer for the second address argument even
                                         * if you do that.
                                         */
-                                       conversation = find_conversation(pinfo->fd->num, &pinfo->src,
-                                                                        &null_address, pinfo->ptype, pinfo->srcport,
+                                       conversation = find_conversation(pinfo->num, &pinfo->src,
+                                                                        &null_address, conversation_pt_to_endpoint_type(pinfo->ptype), pinfo->srcport,
                                                                         pinfo->destport, 0);
                                }
                                if (conversation == NULL)
@@ -1667,14 +1420,14 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                        /* It's not part of any conversation - create a new one. */
                                        if (pinfo->ptype == PT_TCP)
                                        {
-                                               conversation = conversation_new(pinfo->fd->num, &pinfo->src,
-                                                                               &pinfo->dst, pinfo->ptype, pinfo->srcport,
+                                               conversation = conversation_new(pinfo->num, &pinfo->src,
+                                                                               &pinfo->dst, ENDPOINT_TCP, pinfo->srcport,
                                                                                pinfo->destport, 0);
                                        }
                                        else
                                        {
-                                               conversation = conversation_new(pinfo->fd->num, &pinfo->src,
-                                                                               &null_address, pinfo->ptype, pinfo->srcport,
+                                               conversation = conversation_new(pinfo->num, &pinfo->src,
+                                                                               &null_address, conversation_pt_to_endpoint_type(pinfo->ptype), pinfo->srcport,
                                                                                pinfo->destport, 0);
                                        }
                                }
@@ -1684,13 +1437,13 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                mgcp_call_key.conversation = conversation;
 
                                /* Look up the request */
-                               mgcp_call = g_hash_table_lookup(mgcp_calls, &mgcp_call_key);
+                               mgcp_call = (mgcp_call_t *)wmem_map_lookup(mgcp_calls, &mgcp_call_key);
                                if (mgcp_call != NULL)
                                {
                                        /* We've seen a request with this TRANSID, with the same
                                           source and destination, before - but was it
                                           *this* request? */
-                                       if (pinfo->fd->num != mgcp_call->req_num)
+                                       if (pinfo->num != mgcp_call->req_num)
                                        {
                                                /* No, so it's a duplicate request. Mark it as such. */
                                                mi->is_duplicate = TRUE;
@@ -1701,11 +1454,11 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                                if (tree)
                                                {
                                                        proto_item* item;
-                                                       item = proto_tree_add_uint(tree, hf_mgcp_dup, tvb, 0,0, mi->transid);
+                                                       item = proto_tree_add_uint(tree, hf_mgcp_dup, tvb, 0, 0, mi->transid);
                                                        PROTO_ITEM_SET_HIDDEN(item);
-                                                       item = proto_tree_add_uint(tree, hf_mgcp_req_dup, tvb, 0,0, mi->transid);
+                                                       item = proto_tree_add_uint(tree, hf_mgcp_req_dup, tvb, 0, 0, mi->transid);
                                                        PROTO_ITEM_SET_GENERATED(item);
-                                                       item = proto_tree_add_uint(tree, hf_mgcp_req_dup_frame, tvb, 0,0, mi->req_num);
+                                                       item = proto_tree_add_uint(tree, hf_mgcp_req_dup_frame, tvb, 0, 0, mi->req_num);
                                                        PROTO_ITEM_SET_GENERATED(item);
                                                }
                                        }
@@ -1717,18 +1470,18 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                                           frame numbers are 1-origin, so we use 0
                                           to mean "we don't yet know in which frame
                                           the reply for this call appears". */
-                                       new_mgcp_call_key = se_alloc(sizeof(*new_mgcp_call_key));
-                                       *new_mgcp_call_key = mgcp_call_key;
-                                       mgcp_call = se_alloc(sizeof(*mgcp_call));
-                                       mgcp_call->req_num = pinfo->fd->num;
-                                       mgcp_call->rsp_num = 0;
-                                       mgcp_call->transid = mi->transid;
+                                       new_mgcp_call_key    = (mgcp_call_info_key *)wmem_alloc(wmem_file_scope(), sizeof(*new_mgcp_call_key));
+                                       *new_mgcp_call_key   = mgcp_call_key;
+                                       mgcp_call            = (mgcp_call_t *)wmem_alloc(wmem_file_scope(), sizeof(*mgcp_call));
+                                       mgcp_call->req_num   = pinfo->num;
+                                       mgcp_call->rsp_num   = 0;
+                                       mgcp_call->transid   = mi->transid;
                                        mgcp_call->responded = FALSE;
-                                       mgcp_call->req_time=pinfo->fd->abs_ts;
-                                       g_strlcpy(mgcp_call->code,mi->code,5);
+                                       mgcp_call->req_time=pinfo->abs_ts;
+                                       g_strlcpy(mgcp_call->code, mi->code, 5);
 
                                        /* Store it */
-                                       g_hash_table_insert(mgcp_calls, new_mgcp_call_key, mgcp_call);
+                                       wmem_map_insert(mgcp_calls, new_mgcp_call_key, mgcp_call);
                                }
                                if (mgcp_call->rsp_num)
                                {
@@ -1767,61 +1520,73 @@ static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree
  * tree - The tree from which to hang the structured information parsed
  *        from the parameters of the MGCP message.
  */
-static void dissect_mgcp_params(tvbuff_t *tvb, proto_tree *tree)
+static void dissect_mgcp_params(tvbuff_t *tvb, proto_tree *tree, mgcp_info_t* mi)
 {
        int linelen, tokenlen, *my_param;
        gint tvb_lineend, tvb_linebegin, tvb_len, old_lineend;
        gint tvb_tokenbegin;
        proto_tree *mgcp_param_ti, *mgcp_param_tree;
 
-       tvb_len = tvb_length(tvb);
+       tvb_len = tvb_reported_length(tvb);
        tvb_linebegin = 0;
        tvb_lineend = tvb_linebegin;
 
-       if (tree)
+       mgcp_param_ti = proto_tree_add_item(tree, hf_mgcp_params, tvb,
+                       tvb_linebegin, tvb_len, ENC_NA);
+       proto_item_set_text(mgcp_param_ti, "Parameters");
+       mgcp_param_tree = proto_item_add_subtree(mgcp_param_ti, ett_mgcp_param);
+
+       /* Parse the parameters */
+       while (tvb_offset_exists(tvb, tvb_lineend))
        {
-               mgcp_param_ti = proto_tree_add_item(tree, hf_mgcp_params, tvb,
-                                                   tvb_linebegin, tvb_len, ENC_NA);
-               proto_item_set_text(mgcp_param_ti, "Parameters");
-               mgcp_param_tree = proto_item_add_subtree(mgcp_param_ti, ett_mgcp_param);
+               old_lineend = tvb_lineend;
+               linelen = tvb_find_line_end(tvb, tvb_linebegin, -1, &tvb_lineend, FALSE);
+               tvb_tokenbegin = tvb_parse_param(tvb, tvb_linebegin, linelen, &my_param, mi);
 
-               /* Parse the parameters */
-               while (tvb_lineend < tvb_len)
+               if (my_param)
                {
-                       old_lineend = tvb_lineend;
-                       linelen = tvb_find_line_end(tvb, tvb_linebegin, -1,&tvb_lineend,FALSE);
-                       tvb_tokenbegin = tvb_parse_param(tvb, tvb_linebegin, linelen, &my_param);
-
-                       if (my_param)
+                       if (*my_param == hf_mgcp_param_connectionparam)
                        {
-                               if (*my_param == hf_mgcp_param_connectionparam)
+                               tokenlen = tvb_find_line_end(tvb, tvb_tokenbegin, -1, &tvb_lineend, FALSE);
+                               dissect_mgcp_connectionparams(mgcp_param_tree, tvb, tvb_linebegin,
+                                               tvb_tokenbegin - tvb_linebegin, tokenlen);
+                       }
+                       else
+                               if (*my_param == hf_mgcp_param_localconnoptions)
                                {
-                                       tokenlen = tvb_find_line_end(tvb,tvb_tokenbegin,-1,&tvb_lineend,FALSE);
-                                       dissect_mgcp_connectionparams(mgcp_param_tree, tvb, tvb_linebegin,
-                                                                     tvb_tokenbegin - tvb_linebegin, tokenlen);
+                                       tokenlen = tvb_find_line_end(tvb, tvb_tokenbegin, -1, &tvb_lineend, FALSE);
+                                       dissect_mgcp_localconnectionoptions(mgcp_param_tree, tvb, tvb_linebegin,
+                                                       tvb_tokenbegin - tvb_linebegin, tokenlen);
                                }
                                else
-                               if (*my_param == hf_mgcp_param_localconnoptions)
+                               if (*my_param == hf_mgcp_param_localvoicemetrics)
                                {
                                        tokenlen = tvb_find_line_end(tvb,tvb_tokenbegin,-1,&tvb_lineend,FALSE);
-                                       dissect_mgcp_localconnectionoptions(mgcp_param_tree, tvb, tvb_linebegin,
-                                                                           tvb_tokenbegin - tvb_linebegin, tokenlen);
+                                       dissect_mgcp_localvoicemetrics(mgcp_param_tree, tvb, tvb_linebegin,
+                                                                tvb_tokenbegin - tvb_linebegin, tokenlen);
                                }
                                else
+                               if (*my_param == hf_mgcp_param_remotevoicemetrics)
                                {
                                        tokenlen = tvb_find_line_end(tvb,tvb_tokenbegin,-1,&tvb_lineend,FALSE);
-                                       proto_tree_add_string(mgcp_param_tree,*my_param, tvb,
-                                                             tvb_linebegin, linelen,
-                                                             tvb_format_text(tvb,tvb_tokenbegin, tokenlen));
+                                       dissect_mgcp_remotevoicemetrics(mgcp_param_tree, tvb, tvb_linebegin,
+                                                                tvb_tokenbegin - tvb_linebegin, tokenlen);
                                }
-                       }
+                               else
+                               {
+                                       tokenlen = tvb_find_line_end(tvb, tvb_tokenbegin, -1, &tvb_lineend, FALSE);
+                                       proto_tree_add_string(mgcp_param_tree, *my_param, tvb,
+                                                       tvb_linebegin, linelen,
+                                                       tvb_format_text(tvb, tvb_tokenbegin, tokenlen));
+                               }
+               }
 
-                       tvb_linebegin = tvb_lineend;
-                       /* Its a infinite loop if we didn't advance (or went backwards) */
-                       if (old_lineend >= tvb_lineend)
-                       {
-                               THROW(ReportedBoundsError);
-                       }
+               tvb_linebegin = tvb_lineend;
+               /* Its a infinite loop if we didn't advance (or went backwards) */
+               if (old_lineend >= tvb_lineend)
+               {
+                       /* XXX - exception */
+                       break;
                }
        }
 }
@@ -1830,34 +1595,32 @@ 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)
 {
-       proto_tree *tree = parent_tree;
-       proto_item *item = NULL;
+       proto_tree *tree;
+       proto_item *item;
 
-       gchar *tokenline = NULL;
-       gchar **tokens = NULL;
-       gchar **typval = NULL;
-       guint i = 0;
-       guint tokenlen = 0;
-       int hf_uint = -1;
-       int hf_string = -1;
+       gchar *tokenline;
+       gchar **tokens;
+       guint i;
 
-       if (parent_tree)
-       {
-               item = proto_tree_add_item(parent_tree, hf_mgcp_param_connectionparam, tvb, offset, param_type_len+param_val_len, ENC_ASCII|ENC_NA);
-               tree = proto_item_add_subtree(item, ett_mgcp_param_connectionparam);
-       }
+       item = proto_tree_add_item(parent_tree, hf_mgcp_param_connectionparam, tvb, offset, param_type_len+param_val_len, ENC_ASCII|ENC_NA);
+       tree = proto_item_add_subtree(item, ett_mgcp_param_connectionparam);
 
        /* The P: line */
        offset += param_type_len; /* skip the P: */
-       tokenline = tvb_get_ephemeral_string(tvb, offset, param_val_len);
+       tokenline = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, param_val_len, ENC_ASCII);
 
        /* Split into type=value pairs separated by comma */
-       tokens = ep_strsplit(tokenline, ",", -1);
+       tokens = wmem_strsplit(wmem_packet_scope(), tokenline, ",", -1);
 
        for (i = 0; tokens[i] != NULL; i++)
        {
+               gchar **typval;
+               guint tokenlen;
+               int hf_uint = -1;
+               int hf_string = -1;
+
                tokenlen = (int)strlen(tokens[i]);
-               typval = ep_strsplit(tokens[i], "=", 2);
+               typval = wmem_strsplit(wmem_packet_scope(), tokens[i], "=", 2);
                if ((typval[0] != NULL) && (typval[1] != NULL))
                {
                        if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PS"))
@@ -1913,25 +1676,22 @@ dissect_mgcp_connectionparams(proto_tree *parent_tree, tvbuff_t *tvb, gint offse
                                hf_string = -1;
                        }
 
-                       if (tree)
+                       if (hf_uint != -1)
                        {
-                               if (hf_uint != -1)
-                               {
-                                       proto_tree_add_uint(tree, hf_uint, tvb, offset, tokenlen, atol(typval[1]));
-                               }
-                               else if (hf_string != -1)
-                               {
-                                       proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
-                               }
-                               else
-                               {
-                                       proto_tree_add_text(tree, tvb, offset, tokenlen, "Unknown parameter: %s", tokens[i]);
-                               }
+                               proto_tree_add_uint(tree, hf_uint, tvb, offset, tokenlen, (guint32)strtoul(typval[1], NULL, 10));
+                       }
+                       else if (hf_string != -1)
+                       {
+                               proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
+                       }
+                       else
+                       {
+                               proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
                        }
                }
-               else if (tree)
+               else
                {
-                       proto_tree_add_text(tree, tvb, offset, tokenlen, "Malformed parameter: %s", tokens[i]);
+                       proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
                }
                offset += tokenlen + 1; /* 1 extra for the delimiter */
        }
@@ -1942,36 +1702,34 @@ dissect_mgcp_connectionparams(proto_tree *parent_tree, tvbuff_t *tvb, gint offse
 static void
 dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, tvbuff_t *tvb, gint offset, gint param_type_len, gint param_val_len)
 {
-       proto_tree *tree = parent_tree;
-       proto_item *item = NULL;
+       proto_tree *tree;
+       proto_item *item;
 
-       gchar *tokenline = NULL;
-       gchar **tokens = NULL;
-       gchar **typval = NULL;
-       guint i = 0;
-       guint tokenlen = 0;
-       int hf_uint = -1;
-       int hf_string = -1;
+       gchar *tokenline;
+       gchar **tokens;
+       guint i;
 
-       if (parent_tree)
-       {
-               item = proto_tree_add_item(parent_tree, hf_mgcp_param_localconnoptions, tvb, offset, param_type_len+param_val_len, ENC_ASCII|ENC_NA);
-               tree = proto_item_add_subtree(item, ett_mgcp_param_localconnectionoptions);
-       }
+       item = proto_tree_add_item(parent_tree, hf_mgcp_param_localconnoptions, tvb, offset, param_type_len+param_val_len, ENC_ASCII|ENC_NA);
+       tree = proto_item_add_subtree(item, ett_mgcp_param_localconnectionoptions);
 
        /* The L: line */
        offset += param_type_len; /* skip the L: */
-       tokenline = tvb_get_ephemeral_string(tvb, offset, param_val_len);
+       tokenline = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, param_val_len, ENC_ASCII);
 
        /* Split into type=value pairs separated by comma */
-       tokens = ep_strsplit(tokenline, ",", -1);
+       tokens = wmem_strsplit(wmem_packet_scope(), tokenline, ",", -1);
        for (i = 0; tokens[i] != NULL; i++)
        {
+               gchar **typval;
+               guint tokenlen;
+               int hf_uint;
+               int hf_string;
+
                hf_uint = -1;
                hf_string = -1;
 
                tokenlen = (int)strlen(tokens[i]);
-               typval = ep_strsplit(tokens[i], ":", 2);
+               typval = wmem_strsplit(wmem_packet_scope(), tokens[i], ":", 2);
                if ((typval[0] != NULL) && (typval[1] != NULL))
                {
                        if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "p"))
@@ -2066,38 +1824,337 @@ dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, tvbuff_t *tvb, gint
                        {
                                hf_string = hf_mgcp_param_localconnoptions_rsh;
                        }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "mp"))
+                       {
+                               hf_string = hf_mgcp_param_localconnoptions_mp;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "fxr/fx"))
+                       {
+                               hf_string = hf_mgcp_param_localconnoptions_fxr;
+                       }
                        else
                        {
                                hf_uint = -1;
                                hf_string = -1;
                        }
 
+                       /* Add item */
+                       if (hf_uint != -1)
+                       {
+                               proto_tree_add_uint(tree, hf_uint, tvb, offset, tokenlen, (guint32)strtoul(typval[1], NULL, 10));
+                       }
+                       else if (hf_string != -1)
+                       {
+                               proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
+                       }
+                       else
+                       {
+                               proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
+                       }
+               }
+       }
+}
+
+/* Dissect the Local Voice Metrics option */
+static void
+dissect_mgcp_localvoicemetrics(proto_tree *parent_tree, tvbuff_t *tvb, gint offset, gint param_type_len, gint param_val_len)
+{
+       proto_tree *tree = parent_tree;
+       proto_item *item = NULL;
+
+       gchar *tokenline = NULL;
+       gchar **tokens = NULL;
+       gchar **typval = NULL;
+       guint i = 0;
+       guint tokenlen = 0;
+       int hf_string = -1;
+
+       if (parent_tree)
+       {
+       item = proto_tree_add_item(parent_tree, hf_mgcp_param_localvoicemetrics, tvb, offset, param_type_len+param_val_len, ENC_ASCII|ENC_NA);
+               tree = proto_item_add_subtree(item, ett_mgcp_param_localvoicemetrics);
+       }
+
+       /* The XRM/LVM: line */
+       offset += 9; /* skip the XRM/LVM: */
+       tokenline = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, param_val_len - 9, ENC_ASCII);
+
+       /* Split into type=value pairs separated by comma and WSP */
+       tokens = wmem_strsplit(wmem_packet_scope(), tokenline, ",", -1);
+       for (i = 0; tokens[i] != NULL; i++)
+       {
+
+               tokenlen = (int)strlen(tokens[i]);
+               typval = wmem_strsplit(wmem_packet_scope(), tokens[i], "=", 2);
+               if ((typval[0] != NULL) && (typval[1] != NULL))
+               {
+                       if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NLR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_nlr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JDR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jdr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BLD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_bld;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GLD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_gld;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_bd;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_gd;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RTD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_rtd;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "ESD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_esd;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "SL"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_sl;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NL"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_nl;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RERL"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_rerl;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GMN"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_gmn;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NSR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_nsr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "XSR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_xsr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MLQ"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_mlq;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MCQ"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_mcq;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PLC"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_plc;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBA"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jba;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jbr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBN"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jbn;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBM"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jbm;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBS"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jbs;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "IAJ"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_iaj;
+                       }
+                       else
+                       {
+                               hf_string = -1;
+                       }
+
                        /* Add item */
                        if (tree)
                        {
-                               if (hf_uint != -1)
-                               {
-                                       proto_tree_add_uint(tree, hf_uint, tvb, offset, tokenlen, atol(typval[1]));
-                               }
-                               else if (hf_string != -1)
+                               if (hf_string != -1)
                                {
                                        proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
                                }
                                else
                                {
-                                       proto_tree_add_text(tree, tvb, offset, tokenlen, "Unknown parameter: %s", tokens[i]);
+                                       proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
                                }
                        }
                }
                else if (tree)
                {
-                       proto_tree_add_text(tree, tvb, offset, tokenlen, "Malformed parameter: %s", tokens[i]);
+                       proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
                }
                offset += tokenlen + 1; /* 1 extra for the delimiter */
        }
 }
 
+/* Dissect the Remote Voice Metrics option */
+static void
+dissect_mgcp_remotevoicemetrics(proto_tree *parent_tree, tvbuff_t *tvb, gint offset, gint param_type_len, gint param_val_len)
+{
+       proto_tree *tree = parent_tree;
+       proto_item *item = NULL;
+
+       gchar *tokenline = NULL;
+       gchar **tokens = NULL;
+       gchar **typval = NULL;
+       guint i = 0;
+       guint tokenlen = 0;
+       int hf_string = -1;
+
+       if (parent_tree)
+       {
+       item = proto_tree_add_item(parent_tree, hf_mgcp_param_remotevoicemetrics, tvb, offset, param_type_len+param_val_len, ENC_ASCII|ENC_NA);
+               tree = proto_item_add_subtree(item, ett_mgcp_param_remotevoicemetrics);
+       }
+
+       /* The XRM/RVM: line */
+       offset += 9; /* skip the XRM/RVM: */
+       tokenline = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, param_val_len - 9, ENC_ASCII);
+
+       /* Split into type=value pairs separated by comma and WSP */
+       tokens = wmem_strsplit(wmem_packet_scope(), tokenline, ",", -1);
+       for (i = 0; tokens[i] != NULL; i++)
+       {
+               tokenlen = (int)strlen(tokens[i]);
+               typval = wmem_strsplit(wmem_packet_scope(), tokens[i], "=", 2);
+               if ((typval[0] != NULL) && (typval[1] != NULL))
+               {
+                       if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NLR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_nlr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JDR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jdr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BLD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_bld;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GLD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_gld;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_bd;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_gd;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RTD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_rtd;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "ESD"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_esd;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "SL"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_sl;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NL"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_nl;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RERL"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_rerl;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GMN"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_gmn;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NSR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_nsr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "XSR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_xsr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MLQ"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_mlq;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MCQ"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_mcq;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PLC"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_plc;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBA"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jba;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBR"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jbr;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBN"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jbn;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBM"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jbm;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBS"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_jbs;
+                       }
+                       else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "IAJ"))
+                       {
+                               hf_string = hf_mgcp_param_voicemetrics_iaj;
+                       }
+                       else
+                       {
+                               hf_string = -1;
+                       }
 
+                       /* Add item */
+                       if (tree)
+                       {
+                               if (hf_string != -1)
+                               {
+                                       proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
+                               }
+                               else
+                               {
+                                       proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
+                               }
+                       }
+               }
+               else if (tree)
+               {
+                       proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
+               }
+               offset += tokenlen + 1; /* 1 extra for the delimiter */
+       }
+}
 
 /*
  * tvb_find_null_line - Returns the length from offset to the first null
@@ -2121,7 +2178,7 @@ dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, tvbuff_t *tvb, gint
  */
 static gint tvb_find_null_line(tvbuff_t* tvb, gint offset, gint len, gint* next_offset)
 {
-       gint tvb_lineend,tvb_current_len,tvb_linebegin,maxoffset;
+       gint tvb_lineend, tvb_current_len, tvb_linebegin, maxoffset;
        guint tempchar;
 
        tvb_linebegin = offset;
@@ -2134,20 +2191,20 @@ static gint tvb_find_null_line(tvbuff_t* tvb, gint offset, gint len, gint* next_
        }
        else
        {
-               tvb_current_len = tvb_length_remaining(tvb,offset);
+               tvb_current_len = tvb_reported_length_remaining(tvb, offset);
        }
 
        maxoffset = (tvb_current_len - 1) + offset;
 
-       /* Loop around until we either find a line begining with a carriage return
+       /* Loop around until we either find a line beginning with a carriage return
           or newline character or until we hit the end of the tvbuff. */
        do
        {
                tvb_linebegin = tvb_lineend;
-               tvb_current_len = tvb_length_remaining(tvb,tvb_linebegin);
-               tvb_find_line_end(tvb, tvb_linebegin, tvb_current_len, &tvb_lineend,FALSE);
-               tempchar = tvb_get_guint8(tvb,tvb_linebegin);
-       } while (tempchar != '\r' && tempchar != '\n' && tvb_lineend <= maxoffset);
+               tvb_current_len = tvb_reported_length_remaining(tvb, tvb_linebegin);
+               tvb_find_line_end(tvb, tvb_linebegin, tvb_current_len, &tvb_lineend, FALSE);
+               tempchar = tvb_get_guint8(tvb, tvb_linebegin);
+       } while (tempchar != '\r' && tempchar != '\n' && tvb_lineend <= maxoffset && tvb_offset_exists(tvb, tvb_lineend));
 
 
        *next_offset = tvb_lineend;
@@ -2158,7 +2215,7 @@ static gint tvb_find_null_line(tvbuff_t* tvb, gint offset, gint len, gint* next_
        }
        else
        {
-               tvb_current_len = tvb_length_remaining(tvb,offset);
+               tvb_current_len = tvb_reported_length_remaining(tvb, offset);
        }
 
        return tvb_current_len;
@@ -2187,11 +2244,10 @@ static gint tvb_find_null_line(tvbuff_t* tvb, gint offset, gint len, gint* next_
  */
 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;
+       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);
+       tvb_len = tvb_reported_length(tvb);
 
        if (len == -1)
        {
@@ -2218,7 +2274,7 @@ static gint tvb_find_dot_line(tvbuff_t* tvb, gint offset, gint len, gint* next_o
                /* Do we have and characters following the . ? */
                if (tvb_current_offset < maxoffset)
                {
-                       tempchar = tvb_get_guint8(tvb,tvb_current_offset+1);
+                       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')
                        {
@@ -2229,7 +2285,7 @@ static gint tvb_find_dot_line(tvbuff_t* tvb, gint offset, gint len, gint* next_o
                                }
                                else
                                {
-                                       tempchar = tvb_get_guint8(tvb,tvb_current_offset-1);
+                                       tempchar = tvb_get_guint8(tvb, tvb_current_offset-1);
 
                                        /* Are the characters that follow the dot a newline or a
                                           carriage return ? */
@@ -2249,7 +2305,7 @@ static gint tvb_find_dot_line(tvbuff_t* tvb, gint offset, gint len, gint* next_o
                        }
                        else
                        {
-                               tempchar = tvb_get_guint8(tvb,tvb_current_offset-1);
+                               tempchar = tvb_get_guint8(tvb, tvb_current_offset-1);
                                if (tempchar == '\r' || tempchar == '\n')
                                {
                                        break;
@@ -2270,7 +2326,7 @@ static gint tvb_find_dot_line(tvbuff_t* tvb, gint offset, gint len, gint* next_o
        }
        else
        {
-               tvb_find_line_end(tvb,tvb_current_offset,tvb_current_len,next_offset,FALSE);
+               tvb_find_line_end(tvb, tvb_current_offset, tvb_current_len, next_offset, FALSE);
        }
 
        if (tvb_current_offset == offset)
@@ -2285,3 +2341,486 @@ static gint tvb_find_dot_line(tvbuff_t* tvb, gint offset, gint len, gint* next_o
        return tvb_current_len;
 }
 
+/* Register all the bits needed with the filtering engine */
+
+void proto_register_mgcp(void);
+void proto_reg_handoff_mgcp(void);
+
+void proto_register_mgcp(void)
+{
+       expert_module_t* expert_mgcp;
+
+       static hf_register_info hf[] =
+               {
+                       { &hf_mgcp_req,
+                         { "Request", "mgcp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+                           "True if MGCP request", HFILL }},
+                       { &hf_mgcp_rsp,
+                         { "Response", "mgcp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+                           "TRUE if MGCP response", HFILL }},
+                       { &hf_mgcp_req_frame,
+                         { "Request Frame", "mgcp.reqframe", FT_FRAMENUM, BASE_NONE, NULL, 0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_rsp_frame,
+                         { "Response Frame", "mgcp.rspframe", FT_FRAMENUM, BASE_NONE, NULL, 0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_time,
+                         { "Time from request", "mgcp.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
+                           "Timedelta between Request and Response", HFILL }},
+                       { &hf_mgcp_req_verb,
+                         { "Verb", "mgcp.req.verb", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Name of the verb", HFILL }},
+                       { &hf_mgcp_req_endpoint,
+                         { "Endpoint", "mgcp.req.endpoint", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Endpoint referenced by the message", HFILL }},
+                       { &hf_mgcp_transid,
+                         { "Transaction ID", "mgcp.transid", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Transaction ID of this message", HFILL }},
+                       { &hf_mgcp_version,
+                         { "Version", "mgcp.version", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "MGCP Version", HFILL }},
+                       { &hf_mgcp_rsp_rspcode,
+                         { "Response Code", "mgcp.rsp.rspcode", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &mgcp_return_code_vals_ext, 0x0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_rsp_rspstring,
+                         { "Response String", "mgcp.rsp.rspstring", FT_STRING, BASE_NONE, NULL, 0x0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_params,
+                         { "Parameters", "mgcp.params", FT_NONE, BASE_NONE, NULL, 0x0,
+                           "MGCP parameters", HFILL }},
+                       { &hf_mgcp_param_rspack,
+                         { "ResponseAck (K)", "mgcp.param.rspack", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Response Ack", HFILL }},
+                       { &hf_mgcp_param_bearerinfo,
+                         { "BearerInformation (B)", "mgcp.param.bearerinfo", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Bearer Information", HFILL }},
+                       { &hf_mgcp_param_callid,
+                         { "CallId (C)", "mgcp.param.callid", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Call Id", HFILL }},
+                       { &hf_mgcp_param_connectionid,
+                         {"ConnectionIdentifier (I)", "mgcp.param.connectionid", FT_STRING, BASE_NONE, NULL, 0x0,
+                          "Connection Identifier", HFILL }},
+                       { &hf_mgcp_param_secondconnectionid,
+                         { "SecondConnectionID (I2)", "mgcp.param.secondconnectionid", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Second Connection Identifier", HFILL }},
+                       { &hf_mgcp_param_notifiedentity,
+                         { "NotifiedEntity (N)", "mgcp.param.notifiedentity", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Notified Entity", HFILL }},
+                       { &hf_mgcp_param_requestid,
+                         { "RequestIdentifier (X)", "mgcp.param.requestid", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Request Identifier", HFILL }},
+                       { &hf_mgcp_param_localconnoptions,
+                         { "LocalConnectionOptions (L)", "mgcp.param.localconnectionoptions", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Local Connection Options", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_p,
+                         { "Packetization period (p)", "mgcp.param.localconnectionoptions.p", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Packetization period", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_a,
+                         { "Codecs (a)", "mgcp.param.localconnectionoptions.a", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Codecs", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_s,
+                         { "Silence Suppression (s)", "mgcp.param.localconnectionoptions.s", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Silence Suppression", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_e,
+                         { "Echo Cancellation (e)", "mgcp.param.localconnectionoptions.e", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Echo Cancellation", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_scrtp,
+                         { "RTP ciphersuite (sc-rtp)", "mgcp.param.localconnectionoptions.scrtp", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "RTP ciphersuite", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_scrtcp,
+                         { "RTCP ciphersuite (sc-rtcp)", "mgcp.param.localconnectionoptions.scrtcp", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "RTCP ciphersuite", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_b,
+                         { "Bandwidth (b)", "mgcp.param.localconnectionoptions.b", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Bandwidth", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_esccd,
+                         { "Content Destination (es-ccd)", "mgcp.param.localconnectionoptions.esccd", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Content Destination", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_escci,
+                         { "Content Identifier (es-cci)", "mgcp.param.localconnectionoptions.escci", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Content Identifier", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_dqgi,
+                         { "D-QoS GateID (dq-gi)", "mgcp.param.localconnectionoptions.dqgi", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "D-QoS GateID", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_dqrd,
+                         { "D-QoS Reserve Destination (dq-rd)", "mgcp.param.localconnectionoptions.dqrd", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "D-QoS Reserve Destination", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_dqri,
+                         { "D-QoS Resource ID (dq-ri)", "mgcp.param.localconnectionoptions.dqri", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "D-QoS Resource ID", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_dqrr,
+                         { "D-QoS Resource Reservation (dq-rr)", "mgcp.param.localconnectionoptions.dqrr", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "D-QoS Resource Reservation", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_k,
+                         { "Encryption Key (k)", "mgcp.param.localconnectionoptions.k", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Encryption Key", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_gc,
+                         { "Gain Control (gc)", "mgcp.param.localconnectionoptions.gc", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Gain Control", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_fmtp,
+                         { "Media Format (fmtp)", "mgcp.param.localconnectionoptions.fmtp", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Media Format", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_nt,
+                         { "Network Type (nt)", "mgcp.param.localconnectionoptions.nt", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Network Type", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_ofmtp,
+                         { "Optional Media Format (o-fmtp)", "mgcp.param.localconnectionoptions.ofmtp", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Optional Media Format", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_r,
+                         { "Resource Reservation (r)", "mgcp.param.localconnectionoptions.r", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Resource Reservation", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_t,
+                         { "Type of Service (r)", "mgcp.param.localconnectionoptions.t", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Type of Service", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_rcnf,
+                         { "Reservation Confirmation (r-cnf)", "mgcp.param.localconnectionoptions.rcnf", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Reservation Confirmation", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_rdir,
+                         { "Reservation Direction (r-dir)", "mgcp.param.localconnectionoptions.rdir", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Reservation Direction", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_rsh,
+                         { "Resource Sharing (r-sh)", "mgcp.param.localconnectionoptions.rsh", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Resource Sharing", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_mp,
+                         { "Multiple Packetization period (mp)", "mgcp.param.localconnectionoptions.mp", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Multiple Packetization period", HFILL }},
+                       { &hf_mgcp_param_localconnoptions_fxr,
+                         { "FXR (fxr/fx)", "mgcp.param.localconnectionoptions.fxr", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "FXR", HFILL }},
+                       { &hf_mgcp_param_localvoicemetrics,
+                         { "LocalVoiceMetrics (XRM/LVM)", "mgcp.param.localvoicemetrics", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Local Voice Metrics", HFILL }},
+                       { &hf_mgcp_param_remotevoicemetrics,
+                         { "RemoteVoiceMetrics (XRM/RVM)", "mgcp.param.remotevoicemetrics", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Remote Voice Metrics", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_nlr,
+                         { "Network packet loss rate(NLR)", "mgcp.param.voicemetrics.nlr", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics NLR", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_jdr,
+                         { "Jitter buffer discard rate(JDR)", "mgcp.param.voicemetrics.jdr", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics JDR", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_bld,
+                         { "Burst loss density(BLD)", "mgcp.param.voicemetrics.bld", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics BLD", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_gld,
+                         { "Gap loss density(GLD)", "mgcp.param.voicemetrics.gld", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics GLD", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_bd,
+                         { "Burst duration(BD)", "mgcp.param.voicemetrics.bd", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics BD", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_gd,
+                         { "Gap duration(GD)", "mgcp.param.voicemetrics.gd", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics GD", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_rtd,
+                         { "Round trip network delay(RTD)", "mgcp.param.voicemetrics.rtd", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics RTD", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_esd,
+                         { "End system delay(ESD)", "mgcp.param.voicemetrics.esd", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics ESD", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_sl,
+                         { "Signal level(SL)", "mgcp.param.voicemetrics.sl", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics SL", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_nl,
+                         { "Noise level(NL)", "mgcp.param.voicemetrics.nl", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metricsx NL", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_rerl,
+                         { "Residual echo return loss(RERL)", "mgcp.param.voicemetrics.rerl", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics ERL", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_gmn,
+                         { "Minimum gap threshold(GMN)", "mgcp.param.voicemetrics.gmn", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics GMN", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_nsr,
+                         { "R factor(NSR)", "mgcp.param.voicemetrics.nsr", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics NSR", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_xsr,
+                         { "External R factor(XSR)", "mgcp.param.voicemetrics.xsr", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics XSR", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_mlq,
+                         { "Estimated MOS-LQ(MLQ)", "mgcp.param.voicemetrics.mlq", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics MLQ", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_mcq,
+                         { "Estimated MOS-CQ(MCQ)", "mgcp.param.voicemetrics.mcq", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics MCQ", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_plc,
+                         { "Packet loss concealment type(PLC)", "mgcp.param.voicemetrics.plc", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics PLC", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_jba,
+                         { "Jitter Buffer Adaptive(JBA)", "mgcp.param.voicemetrics.jba", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics JBA", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_jbr,
+                         { "Jitter Buffer Rate(JBR)", "mgcp.param.voicemetrics.jbr", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics JBR", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_jbn,
+                         { "Nominal jitter buffer delay(JBN)", "mgcp.param.voicemetrics.jbn", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics JBN", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_jbm,
+                         { "Maximum jitter buffer delay(JBM)", "mgcp.param.voicemetrics.jbm", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics JBM", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_jbs,
+                         { "Absolute maximum jitter buffer delay(JBS)", "mgcp.param.voicemetrics.jbs", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics JBS", HFILL }},
+                       { &hf_mgcp_param_voicemetrics_iaj,
+                         { "Inter-arrival Jitter(IAJ)", "mgcp.param.voicemetrics.iaj", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Voice Metrics IAJ", HFILL }},
+                       { &hf_mgcp_param_connectionmode,
+                         { "ConnectionMode (M)", "mgcp.param.connectionmode", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Connection Mode", HFILL }},
+                       { &hf_mgcp_param_reqevents,
+                         { "RequestedEvents (R)", "mgcp.param.reqevents", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Requested Events", HFILL }},
+                       { &hf_mgcp_param_signalreq,
+                         { "SignalRequests (S)", "mgcp.param.signalreq", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Signal Request", HFILL }},
+                       { &hf_mgcp_param_restartmethod,
+                         { "RestartMethod (RM)", "mgcp.param.restartmethod", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Restart Method", HFILL }},
+                       { &hf_mgcp_param_restartdelay,
+                         { "RestartDelay (RD)", "mgcp.param.restartdelay", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Restart Delay", HFILL }},
+                       { &hf_mgcp_param_digitmap,
+                         { "DigitMap (D)", "mgcp.param.digitmap", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Digit Map", HFILL }},
+                       { &hf_mgcp_param_observedevent,
+                         { "ObservedEvents (O)", "mgcp.param.observedevents", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Observed Events", HFILL }},
+                       { &hf_mgcp_param_connectionparam,
+                         { "ConnectionParameters (P)", "mgcp.param.connectionparam", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Connection Parameters", HFILL }},
+                       { &hf_mgcp_param_connectionparam_ps,
+                         { "Packets sent (PS)", "mgcp.param.connectionparam.ps", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Packets sent (P:PS)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_os,
+                         { "Octets sent (OS)", "mgcp.param.connectionparam.os", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Octets sent (P:OS)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_pr,
+                         { "Packets received (PR)", "mgcp.param.connectionparam.pr", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Packets received (P:PR)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_or,
+                         { "Octets received (OR)", "mgcp.param.connectionparam.or", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Octets received (P:OR)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_pl,
+                         { "Packets lost (PL)", "mgcp.param.connectionparam.pl", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Packets lost (P:PL)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_ji,
+                         { "Jitter (JI)", "mgcp.param.connectionparam.ji", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Average inter-packet arrival jitter in milliseconds (P:JI)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_la,
+                         { "Latency (LA)", "mgcp.param.connectionparam.la", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Average latency in milliseconds (P:LA)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_pcrps,
+                         { "Remote Packets sent (PC/RPS)", "mgcp.param.connectionparam.pcrps", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Remote Packets sent (P:PC/RPS)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_pcros,
+                         { "Remote Octets sent (PC/ROS)", "mgcp.param.connectionparam.pcros", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Remote Octets sent (P:PC/ROS)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_pcrpl,
+                         { "Remote Packets lost (PC/RPL)", "mgcp.param.connectionparam.pcrpl", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Remote Packets lost (P:PC/RPL)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_pcrji,
+                         { "Remote Jitter (PC/RJI)", "mgcp.param.connectionparam.pcrji", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Remote Jitter (P:PC/RJI)", HFILL }},
+                       { &hf_mgcp_param_connectionparam_x,
+                         { "Vendor Extension", "mgcp.param.connectionparam.x", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Vendor Extension (P:X-*)", HFILL }},
+                       { &hf_mgcp_param_reasoncode,
+                         { "ReasonCode (E)", "mgcp.param.reasoncode", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Reason Code", HFILL }},
+                       { &hf_mgcp_param_eventstates,
+                         { "EventStates (ES)", "mgcp.param.eventstates", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Event States", HFILL }},
+                       { &hf_mgcp_param_specificendpoint,
+                         { "SpecificEndpointID (Z)", "mgcp.param.specificendpointid", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Specific Endpoint ID", HFILL }},
+                       { &hf_mgcp_param_secondendpointid,
+                         { "SecondEndpointID (Z2)", "mgcp.param.secondendpointid", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Second Endpoint ID", HFILL }},
+                       { &hf_mgcp_param_reqinfo,
+                         { "RequestedInfo (F)", "mgcp.param.reqinfo", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Requested Info", HFILL }},
+                       { &hf_mgcp_param_quarantinehandling,
+                         { "QuarantineHandling (Q)", "mgcp.param.quarantinehandling", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Quarantine Handling", HFILL }},
+                       { &hf_mgcp_param_detectedevents,
+                         { "DetectedEvents (T)", "mgcp.param.detectedevents", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Detected Events", HFILL }},
+                       { &hf_mgcp_param_capabilities,
+                         { "Capabilities (A)", "mgcp.param.capabilities", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Capabilities", HFILL }},
+                       { &hf_mgcp_param_maxmgcpdatagram,
+                         {"MaxMGCPDatagram (MD)", "mgcp.param.maxmgcpdatagram", FT_STRING, BASE_NONE, NULL, 0x0,
+                          "Maximum MGCP Datagram size", HFILL }},
+                       { &hf_mgcp_param_packagelist,
+                         {"PackageList (PL)", "mgcp.param.packagelist", FT_STRING, BASE_NONE, NULL, 0x0,
+                          "Package List", HFILL }},
+                       { &hf_mgcp_param_extension,
+                         { "Extension Parameter (non-critical)", "mgcp.param.extension", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Extension Parameter", HFILL }},
+                       { &hf_mgcp_param_extension_critical,
+                         { "Extension Parameter (critical)", "mgcp.param.extensioncritical", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Critical Extension Parameter", HFILL }},
+                       { &hf_mgcp_param_resourceid,
+                         { "ResourceIdentifier (DQ-RI)", "mgcp.param.resourceid", FT_STRING, BASE_NONE, NULL, 0x0,
+                           "Resource Identifier", HFILL }},
+                       { &hf_mgcp_param_invalid,
+                         { "Invalid Parameter", "mgcp.param.invalid", FT_STRING, BASE_NONE, NULL, 0x0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_messagecount,
+                         { "MGCP Message Count", "mgcp.messagecount", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           "Number of MGCP message in a packet", HFILL }},
+                       { &hf_mgcp_dup,
+                         { "Duplicate Message", "mgcp.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_req_dup,
+                         { "Duplicate Request", "mgcp.req.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_req_dup_frame,
+                         { "Original Request Frame", "mgcp.req.dup.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+                           "Frame containing original request", HFILL }},
+                       { &hf_mgcp_rsp_dup,
+                         { "Duplicate Response", "mgcp.rsp.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_rsp_dup_frame,
+                         { "Original Response Frame", "mgcp.rsp.dup.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+                           "Frame containing original response", HFILL }},
+                       { &hf_mgcp_unknown_parameter,
+                         { "Unknown parameter", "mgcp.unknown_parameter", FT_STRING, BASE_NONE, NULL, 0x0,
+                           NULL, HFILL }},
+                       { &hf_mgcp_malformed_parameter,
+                         { "Malformed parameter", "mgcp.rsp.malformed_parameter", FT_STRING, BASE_NONE, NULL, 0x0,
+                           NULL, HFILL }},
+               };
+
+       static gint *ett[] =
+               {
+                       &ett_mgcp,
+                       &ett_mgcp_param,
+                       &ett_mgcp_param_connectionparam,
+                       &ett_mgcp_param_localconnectionoptions,
+                       &ett_mgcp_param_localvoicemetrics,
+                       &ett_mgcp_param_remotevoicemetrics
+               };
+
+       static ei_register_info ei[] = {
+               { &ei_mgcp_rsp_rspcode_invalid, { "mgcp.rsp.rspcode.invalid", PI_MALFORMED, PI_ERROR,
+               "RSP code must be a string containing an integer", EXPFILL }}
+       };
+
+       module_t *mgcp_module;
+
+       /* Register protocol */
+       proto_mgcp = proto_register_protocol("Media Gateway Control Protocol", "MGCP", "mgcp");
+       proto_register_field_array(proto_mgcp, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
+
+       mgcp_calls = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), mgcp_call_hash, mgcp_call_equal);
+
+       mgcp_handle = register_dissector("mgcp", dissect_mgcp, proto_mgcp);
+
+       /* Register our configuration options */
+       mgcp_module = prefs_register_protocol(proto_mgcp, proto_reg_handoff_mgcp);
+
+       prefs_register_uint_preference(mgcp_module, "tcp.gateway_port",
+                                      "MGCP Gateway TCP Port",
+                                      "Set the UDP port for gateway messages "
+                                      "(if other than the default of 2427)",
+                                      10, &global_mgcp_gateway_tcp_port);
+
+       prefs_register_uint_preference(mgcp_module, "udp.gateway_port",
+                                      "MGCP Gateway UDP Port",
+                                      "Set the TCP port for gateway messages "
+                                      "(if other than the default of 2427)",
+                                      10, &global_mgcp_gateway_udp_port);
+
+       prefs_register_uint_preference(mgcp_module, "tcp.callagent_port",
+                                      "MGCP Callagent TCP Port",
+                                      "Set the TCP port for callagent messages "
+                                      "(if other than the default of 2727)",
+                                      10, &global_mgcp_callagent_tcp_port);
+
+       prefs_register_uint_preference(mgcp_module, "udp.callagent_port",
+                                      "MGCP Callagent UDP Port",
+                                      "Set the UDP port for callagent messages "
+                                      "(if other than the default of 2727)",
+                                      10, &global_mgcp_callagent_udp_port);
+
+
+       prefs_register_bool_preference(mgcp_module, "display_raw_text",
+                                      "Display raw text for MGCP message",
+                                      "Specifies that the raw text of the "
+                                      "MGCP message should be displayed "
+                                      "instead of (or in addition to) the "
+                                      "dissection tree",
+                                      &global_mgcp_raw_text);
+
+       prefs_register_obsolete_preference(mgcp_module, "display_dissect_tree");
+
+       prefs_register_bool_preference(mgcp_module, "display_mgcp_message_count",
+                                      "Display the number of MGCP messages",
+                                      "Display the number of MGCP messages "
+                                      "found in a packet in the protocol column.",
+                                      &global_mgcp_message_count);
+
+       mgcp_tap = register_tap("mgcp");
+
+       register_rtd_table(proto_mgcp, NULL, 1, NUM_TIMESTATS, mgcp_mesage_type, mgcpstat_packet, NULL);
+
+       expert_mgcp = expert_register_protocol(proto_mgcp);
+       expert_register_field_array(expert_mgcp, ei, array_length(ei));
+
+}
+
+/* The registration hand-off routine */
+void proto_reg_handoff_mgcp(void)
+{
+       static gboolean mgcp_prefs_initialized = FALSE;
+       static dissector_handle_t mgcp_tpkt_handle;
+       /*
+        * Variables to allow for proper deletion of dissector registration when
+        * the user changes port from the gui.
+        */
+       static guint gateway_tcp_port;
+       static guint gateway_udp_port;
+       static guint callagent_tcp_port;
+       static guint callagent_udp_port;
+
+       if (!mgcp_prefs_initialized)
+       {
+               /* Get a handle for the SDP dissector. */
+               sdp_handle = find_dissector_add_dependency("sdp", proto_mgcp);
+               mgcp_tpkt_handle = create_dissector_handle(dissect_tpkt_mgcp, proto_mgcp);
+               mgcp_prefs_initialized = TRUE;
+       }
+       else
+       {
+               dissector_delete_uint("tcp.port", gateway_tcp_port,   mgcp_tpkt_handle);
+               dissector_delete_uint("udp.port", gateway_udp_port,   mgcp_handle);
+               dissector_delete_uint("tcp.port", callagent_tcp_port, mgcp_tpkt_handle);
+               dissector_delete_uint("udp.port", callagent_udp_port, mgcp_handle);
+       }
+
+       /* Set our port number for future use */
+       gateway_tcp_port = global_mgcp_gateway_tcp_port;
+       gateway_udp_port = global_mgcp_gateway_udp_port;
+
+       callagent_tcp_port = global_mgcp_callagent_tcp_port;
+       callagent_udp_port = global_mgcp_callagent_udp_port;
+
+       /* Names of port preferences too specific to add "auto" preference here */
+       dissector_add_uint("tcp.port", global_mgcp_gateway_tcp_port,   mgcp_tpkt_handle);
+       dissector_add_uint("udp.port", global_mgcp_gateway_udp_port,   mgcp_handle);
+       dissector_add_uint("tcp.port", global_mgcp_callagent_tcp_port, mgcp_tpkt_handle);
+       dissector_add_uint("udp.port", global_mgcp_callagent_udp_port, mgcp_handle);
+}
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */