From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8326
authorEvan Huus <eapache@gmail.com>
Sun, 18 Aug 2013 19:49:08 +0000 (19:49 -0000)
committerEvan Huus <eapache@gmail.com>
Sun, 18 Aug 2013 19:49:08 +0000 (19:49 -0000)
Dissector for the Sippy RTPproxy controlling protocol. RTPproxy is a well-known
(among SIP-engineers) application and it operates using its own simple
text-based protocol. There are several competing products but all of them
implements it (sometimes slightly extending).

svn path=/trunk/; revision=51417

AUTHORS
epan/CMakeLists.txt
epan/dissectors/Makefile.common
epan/dissectors/packet-rtpproxy.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index f1dfb66dba2e6d24f799380688ba234392358a02..fac0672e3fc3623fabe088ec6ade3a102c36103f 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3757,6 +3757,8 @@ Matt Texier               <mtexier[AT]arbor.net>
 Linas Vepstas          <linasvepstas[AT]gmail.com>
 Simon Zhong                    <szhong[AT]juniper.net>
 Bart Van Assche                <bvanassche[AT]acm.org>
+Peter Lemenkov         <lemenkov[AT]gmail.com>
+
 
 Dan Lasley <dlasley[AT]promus.com> gave permission for his
 dumpit() hex-dump routine to be used.
index ee76441f2b9add752a0e5de94364aba569d82dcb..d91efbe8ec44c7e61f9749cd83a9c6ce28b462d8 100644 (file)
@@ -1084,6 +1084,7 @@ set(DISSECTOR_SRC
        dissectors/packet-rtp-events.c
        dissectors/packet-rtp-midi.c
        dissectors/packet-rtp.c
+       dissectors/packet-rtpproxy.c
        dissectors/packet-rtps.c
        dissectors/packet-rtsp.c
        dissectors/packet-rudp.c
index c5132efd8779013138cece4ac71fdceb5b5cf5d0..514a4a49d5dd66222e195a192322c0b96656d9eb 100644 (file)
@@ -1016,6 +1016,7 @@ DISSECTOR_SRC = \
        packet-rtp-events.c     \
        packet-rtp-midi.c       \
        packet-rtp.c            \
+       packet-rtpproxy.c       \
        packet-rtps.c           \
        packet-rtsp.c           \
        packet-rudp.c           \
diff --git a/epan/dissectors/packet-rtpproxy.c b/epan/dissectors/packet-rtpproxy.c
new file mode 100644 (file)
index 0000000..4641e26
--- /dev/null
@@ -0,0 +1,808 @@
+/* packet-rtpproxy.c
+ * RTPproxy command protocol dissector
+ * Copyright 2013, Peter Lemenkov <lemenkov@gmail.com>
+ *
+ * This dissector tries to dissect rtpproxy control protocol. Please visit this
+ * link for brief details on the command format:
+ *
+ * http://www.rtpproxy.org/wiki/RTPproxy/Protocol
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * 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.
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+
+static int proto_rtpproxy = -1;
+
+static int hf_rtpproxy_cookie = -1;
+static int hf_rtpproxy_error = -1;
+static int hf_rtpproxy_status = -1;
+static int hf_rtpproxy_ok = -1;
+static int hf_rtpproxy_ipv4 = -1;
+static int hf_rtpproxy_ipv6 = -1;
+static int hf_rtpproxy_port = -1;
+static int hf_rtpproxy_lf = -1;
+static int hf_rtpproxy_request = -1;
+static int hf_rtpproxy_command = -1;
+static int hf_rtpproxy_command_parameters = -1;
+static int hf_rtpproxy_callid = -1;
+static int hf_rtpproxy_copy_target = -1;
+static int hf_rtpproxy_playback_filename = -1;
+static int hf_rtpproxy_playback_codec = -1;
+static int hf_rtpproxy_notify = -1;
+static int hf_rtpproxy_notify_ipv4 = -1;
+static int hf_rtpproxy_notify_port = -1;
+static int hf_rtpproxy_notify_tag = -1;
+static int hf_rtpproxy_tag = -1;
+static int hf_rtpproxy_mediaid = -1;
+static int hf_rtpproxy_reply = -1;
+static int hf_rtpproxy_version_request = -1;
+static int hf_rtpproxy_version_supported = -1;
+
+static const value_string commandtypenames[] = {
+       { 'V', "Handshake/Ping" },
+       { 'v', "Handshake/Ping" },
+       { 'U', "Offer/Update" },
+       { 'u', "Offer/Update" },
+       { 'L', "Answer/Lookup" },
+       { 'l', "Answer/Lookup" },
+       { 'I', "Information"},
+       { 'i', "Information"},
+       { 'X', "Close all active sessions"},
+       { 'x', "Close all active sessions"},
+       { 'D', "Delete an active session (Bye/Cancel/Error)"},
+       { 'd', "Delete an active session (Bye/Cancel/Error)"},
+       { 'P', "Start playback (music-on-hold)"},
+       { 'p', "Start playback (music-on-hold)"},
+       { 'S', "Stop playback (music-on-hold)"},
+       { 's', "Stop playback (music-on-hold)"},
+       { 'R', "Start recording"},
+       { 'r', "Start recording"},
+       { 'C', "Copy stream"},
+       { 'c', "Copy stream"},
+       { 'Q', "Query info about a session"},
+       { 'q', "Query info about a session"},
+       { 0, NULL }
+};
+
+static const value_string oktypenames[] = {
+       { '0', "Ok"},
+       { '1', "Version Supported"},
+       { 0, NULL }
+};
+
+static const value_string errortypenames[] = {
+       { '1', "Syntax" },      /* E1 */
+       { '7', "Software" },    /* E7 */
+       { '8', "Not Found" },   /* E8 */
+       { 0, NULL }
+};
+
+static const value_string flowcontroltypenames[] = {
+       { '\n', "Yes"},
+       { 0, NULL }
+};
+
+static gint ett_rtpproxy = -1;
+
+static gint ett_rtpproxy_request = -1;
+static gint ett_rtpproxy_command = -1;
+static gint ett_rtpproxy_tag = -1;
+static gint ett_rtpproxy_notify = -1;
+
+static gint ett_rtpproxy_reply = -1;
+
+static guint rtpproxy_tcp_port = 22222;
+static guint rtpproxy_udp_port = 22222;
+
+void proto_reg_handoff_rtpproxy(void);
+
+gint
+rtpptoxy_add_tag(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint realsize)
+{
+       proto_item *ti = NULL;
+       proto_tree *another_tree = NULL;
+       gint new_offset;
+       guint end;
+
+       new_offset = tvb_find_guint8(tvb, begin, -1, ' ');
+       if(new_offset < 0)
+               end = realsize; /* No more parameters */
+       else
+               end = new_offset;
+
+       /* SER/OpenSER/OpenSIPS/Kamailio adds Media-ID right after the Tag
+        * separated by a semicolon
+        */
+       new_offset = tvb_find_guint8(tvb, begin, end, ';');
+       if(new_offset == -1){
+               ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, end - begin, ENC_ASCII | ENC_NA);
+               another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag);
+               ti = proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, 0, ENC_ASCII | ENC_NA);
+               proto_item_set_text(ti, "Media-ID: <skipped>");
+       }
+       else{
+               ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, new_offset - begin, ENC_ASCII | ENC_NA);
+               another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag);
+               proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, end - (new_offset+1), ENC_ASCII | ENC_NA);
+       }
+       return (end == realsize ? -1 : (gint)end);
+}
+
+static void
+dissect_rtpproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       gboolean has_lf = FALSE;
+       guint offset = 0;
+       gint new_offset = 0;
+       guint tmp;
+       guint realsize = 0;
+       guint8* rawstr;
+       proto_item *ti;
+       proto_tree *rtpproxy_tree;
+
+       /* Clear out stuff in the info column - we''l set it later */
+       col_clear(pinfo->cinfo, COL_INFO);
+
+       ti = proto_tree_add_item(tree, proto_rtpproxy, tvb, 0, -1, ENC_NA);
+       rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy);
+
+       /* Extract Cookie */
+       offset = tvb_find_guint8(tvb, offset, -1, ' ');
+       ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_cookie, tvb, 0, offset, ENC_ASCII | ENC_NA);
+
+       /* Skip whitespace */
+       offset = tvb_skip_wsp(tvb, offset+1, -1);
+
+       /* Calculate size to prevent recalculation in the future */
+       realsize = tvb_reported_length(tvb);
+
+       /* Check for LF (required for TCP connection, optional for UDP) */
+       if (tvb_get_guint8(tvb, realsize - 1) == '\n'){
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPproxy");
+               /* Don't count trailing LF */
+               realsize -= 1;
+               has_lf = TRUE;
+       }
+       else
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPproxy (no LF)");
+
+       /* Get payload string */
+       rawstr = tvb_get_ephemeral_string(tvb, offset, realsize - offset);
+
+       /* Extract command */
+       tmp = g_ascii_tolower(tvb_get_guint8(tvb, offset));
+       switch (tmp)
+       {
+               case 's':
+                       /* A specific case - long statistics answer */
+                       /* %COOKIE% sessions created %NUM0% active sessions: %NUM1% */
+                       if ('e' == tvb_get_guint8(tvb, offset+1)){
+                               col_add_fstr(pinfo->cinfo, COL_INFO, "Reply: %s", rawstr);
+                               ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_reply, tvb, offset, -1, ENC_NA);
+
+                               rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_reply);
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_status, tvb, offset, realsize - offset, ENC_NA);
+                               break;
+                       }
+               case 'i':
+               case 'x':
+               case 'u':
+               case 'l':
+               case 'd':
+               case 'p':
+               case 'v':
+               case 'r':
+               case 'c':
+               case 'q':
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "Request: %s", rawstr);
+                       ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_request, tvb, offset, -1, ENC_NA);
+                       rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_request);
+
+                       /* A specific case - version request */
+                       if ((tmp == 'v') && (offset + strlen("VF YYYMMDD") + 1 == realsize)){
+                               /* Skip whitespace */
+                               new_offset = tvb_skip_wsp(tvb, offset + (strlen("VF") + 1), -1);
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_request, tvb, new_offset, strlen("YYYYMMDD"), ENC_ASCII | ENC_NA);
+                               break;
+                       }
+
+                       /* All other commands */
+                       ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command, tvb, offset, 1, ENC_NA);
+
+                       /* A specific case - handshake/ping */
+                       if (tmp == 'v')
+                               break; /* No more parameters */
+
+                       /* A specific case - close all calls */
+                       if (tmp == 'x')
+                               break; /* No more parameters */
+
+                       /* Extract parameters */
+                       /* Parameters should be right after the command and before EOL (in case of Info command) or before whitespace */
+                       new_offset = (tmp == 'i' ? (gint)(realsize - 1 > offset ? offset + strlen("Ib") : offset + strlen("I")) : tvb_find_guint8(tvb, offset, -1, ' '));
+
+                       if (new_offset != (gint)offset + 1){
+                               rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_command);
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameters, tvb, offset+1, new_offset - (offset+1), ENC_ASCII | ENC_NA);
+                               rtpproxy_tree = proto_item_get_parent(ti);
+                       }
+
+                       /* A specific case - query information */
+                       if (tmp == 'i')
+                               break; /* No more parameters */
+
+                       /* Skip whitespace */
+                       offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+
+                       /* Extract Call-ID */
+                       new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_callid, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                       /* Skip whitespace */
+                       offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+
+                       /* Extract IP and Port in case of Offer/Answer */
+                       if ((tmp == 'u') || (tmp == 'l')){
+                               /* Extract IP */
+                               new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+                               if (tvb_find_guint8(tvb, offset, new_offset - offset, ':') == -1)
+                                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                               else
+                                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                               /* Skip whitespace */
+                               offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+
+                               /* Extract Port */
+                               new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                               /* Skip whitespace */
+                               offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+                       }
+
+                       /* Extract Copy target */
+                       if (tmp == 'c'){
+                               new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_copy_target, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                               /* Skip whitespace */
+                               offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+                       }
+
+                       /* Extract Playback file and codecs */
+                       if (tmp == 'p'){
+                               /* Extract filename */
+                               new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_playback_filename, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                               /* Skip whitespace */
+                               offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+
+                               /* Extract codec */
+                               new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_playback_codec, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                               /* Skip whitespace */
+                               offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+                       }
+
+                       /* Extract first tag */
+                       new_offset = rtpptoxy_add_tag(rtpproxy_tree, tvb, offset, realsize);
+                       if(new_offset == -1)
+                               break; /* No more parameters */
+                       /* Skip whitespace */
+                       offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+
+                       /* Extract second tag */
+                       new_offset = rtpptoxy_add_tag(rtpproxy_tree, tvb, offset, realsize);
+                       if(new_offset == -1)
+                               break; /* No more parameters */
+                       /* Skip whitespace */
+                       offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+
+                       /* Extract Notification address */
+                       if (tmp == 'u'){
+                               new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+                               ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify, tvb, offset, realsize - offset, ENC_NA);
+                               proto_item_set_text(ti, "Notify");
+                               rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_notify);
+                               if(new_offset == -1){
+                                       /* FIXME only IPv4 is supported */
+                                       new_offset = tvb_find_guint8(tvb, offset, -1, ':');
+                                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, new_offset+1, realsize - (new_offset+1), ENC_ASCII | ENC_NA);
+                                       break; /* No more parameters */
+                               }
+                               if(new_offset - offset < 6){
+                                       /* Only port is supplied */
+                                       ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, offset, 0, ENC_ASCII | ENC_NA);
+                                       proto_item_set_text(ti, "Notification IPv4: <skipped>");
+                                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                               }
+                               else{
+                                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, new_offset+1, realsize - (new_offset+1), ENC_ASCII | ENC_NA);
+                               }
+                               /* Skip whitespace */
+                               offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_tag, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA);
+                       }
+                       break;
+               case 'a':
+               case 'e':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                       if (tmp == 'e')
+                               col_add_fstr(pinfo->cinfo, COL_INFO, "Error reply: %s", rawstr);
+                       else
+                               col_add_fstr(pinfo->cinfo, COL_INFO, "Reply: %s", rawstr);
+
+                       ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_reply, tvb, offset, -1, ENC_NA);
+                       rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_reply);
+
+                       if (tmp == 'e'){
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_error, tvb, offset+1, 1, ENC_ASCII | ENC_NA);
+                               break;
+                       }
+
+                       if (tmp == 'a'){
+                               /* A specific case - short statistics answer */
+                               /* %COOKIE% active sessions: %NUM1% */
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_status, tvb, offset, realsize - offset, ENC_NA);
+                               break;
+                       }
+                       if ((tmp == '0')&& ((tvb_reported_length(tvb) == offset+1)||(tvb_reported_length(tvb) == offset+2))){
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA);
+                               break;
+                       }
+                       if ((tmp == '1') && ((tvb_reported_length(tvb) == offset+1)||(tvb_reported_length(tvb) == offset+2))){
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA);
+                               break;
+                       }
+                       if (tvb_reported_length(tvb) == offset+9){
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_supported, tvb, offset, 8, ENC_ASCII | ENC_NA);
+                               break;
+                       }
+
+                       /* Extract Port */
+                       new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+                       proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
+                       /* Skip whitespace */
+                       offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+
+                       /* Extract IP */
+                       tmp = tvb_find_line_end(tvb, offset, -1, &new_offset, FALSE);
+                       if (tvb_find_guint8(tvb, offset, -1, ':') == -1)
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, tmp, ENC_ASCII | ENC_NA);
+                       else
+                               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, tmp, ENC_ASCII | ENC_NA);
+                       break;
+               default:
+                       break;
+       }
+       if (has_lf)
+               proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_lf, tvb, realsize, 1, ENC_NA);
+}
+
+void
+proto_register_rtpproxy(void)
+{
+       module_t *rtpproxy_module;
+
+       static hf_register_info hf[] = {
+               {
+                       &hf_rtpproxy_cookie,
+                       {
+                               "Cookie",
+                               "rtpproxy.cookie",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_version_request,
+                       {
+                               "Version Request",
+                               "rtpproxy.version",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_version_supported,
+                       {
+                               "Version Supported",
+                               "rtpproxy.version_supported",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_error,
+                       {
+                               "Error",
+                               "rtpproxy.error",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS(errortypenames),
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_ok,
+                       {
+                               "Ok",
+                               "rtpproxy.ok",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS(oktypenames),
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_status,
+                       {
+                               "Status",
+                               "rtpproxy.status",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_ipv4,
+                       {
+                               "IPv4",
+                               "rtpproxy.ipv4",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_ipv6,
+                       {
+                               "IPv6",
+                               "rtpproxy.ipv6",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_port,
+                       {
+                               "Port",
+                               "rtpproxy.port",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_request,
+                       {
+                               "Request",
+                               "rtpproxy.request",
+                               FT_NONE,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_command,
+                       {
+                               "Command",
+                               "rtpproxy.command",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS(commandtypenames),
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_command_parameters,
+                       {
+                               "Command parameters",
+                               "rtpproxy.command_parameters",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_copy_target,
+                       {
+                               "Copy target",
+                               "rtpproxy.copy_target",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_playback_filename,
+                       {
+                               "Playback filename",
+                               "rtpproxy.playback_filename",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_playback_codec,
+                       {
+                               "Playback codec",
+                               "rtpproxy.playback_codec",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_callid,
+                       {
+                               "Call-ID",
+                               "rtpproxy.callid",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_notify,
+                       {
+                               "Notify",
+                               "rtpproxy.notify",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_tag,
+                       {
+                               "Tag",
+                               "rtpproxy.tag",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_mediaid,
+                       {
+                               "Media-ID",
+                               "rtpproxy.mediaid",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_notify_ipv4,
+                       {
+                               "Notification IPv4",
+                               "rtpproxy.notify_ipv4",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_notify_port,
+                       {
+                               "Notification Port",
+                               "rtpproxy.notify_port",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_notify_tag,
+                       {
+                               "Notification Tag",
+                               "rtpproxy.notify_tag",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_reply,
+                       {
+                               "Reply",
+                               "rtpproxy.reply",
+                               FT_NONE,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+               {
+                       &hf_rtpproxy_lf,
+                       {
+                               "LF",
+                               "rtpproxy.lf",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS(flowcontroltypenames),
+                               0x0,
+                               NULL,
+                               HFILL
+                       }
+               },
+       };
+
+       /* Setup protocol subtree array */
+       static gint *ett[] = {
+               &ett_rtpproxy,
+               &ett_rtpproxy_request,
+               &ett_rtpproxy_command,
+               &ett_rtpproxy_tag,
+               &ett_rtpproxy_notify,
+               &ett_rtpproxy_reply
+       };
+
+       proto_rtpproxy = proto_register_protocol (
+                       "Sippy RTPproxy Protocol", /* name       */
+                       "RTPproxy",      /* short name */
+                       "rtpproxy"       /* abbrev     */
+                       );
+
+       proto_register_field_array(proto_rtpproxy, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
+
+       rtpproxy_module = prefs_register_protocol(proto_rtpproxy, proto_reg_handoff_rtpproxy);
+       prefs_register_uint_preference(rtpproxy_module, "tcp.port",
+                                                                "RTPproxy TCP Port", /* Title */
+                                                                "RTPproxy TCP Port", /* Descr */
+                                                                10,
+                                                                &rtpproxy_tcp_port);
+
+       prefs_register_uint_preference(rtpproxy_module, "udp.port",
+                                                                "RTPproxy UDP Port", /* Title */
+                                                                "RTPproxy UDP Port", /* Descr */
+                                                                10,
+                                                                &rtpproxy_udp_port);
+}
+
+void
+proto_reg_handoff_rtpproxy(void)
+{
+       static guint old_rtpproxy_tcp_port = 0;
+       static guint old_rtpproxy_udp_port = 0;
+
+       static gboolean rtpproxy_initialized = FALSE;
+
+       static dissector_handle_t rtpproxy_tcp_handle, rtpproxy_udp_handle;
+
+       if(!rtpproxy_initialized){
+               rtpproxy_tcp_handle = create_dissector_handle(dissect_rtpproxy, proto_rtpproxy);
+               rtpproxy_udp_handle = create_dissector_handle(dissect_rtpproxy, proto_rtpproxy);
+               rtpproxy_initialized = TRUE;
+       }
+
+       /* Register TCP port for dissection */
+       if(old_rtpproxy_tcp_port != 0 && old_rtpproxy_tcp_port != rtpproxy_tcp_port)
+               dissector_delete_uint("tcp.port", old_rtpproxy_tcp_port, rtpproxy_tcp_handle);
+       if(rtpproxy_tcp_port != 0 && old_rtpproxy_tcp_port != rtpproxy_tcp_port)
+               dissector_add_uint("tcp.port", rtpproxy_tcp_port, rtpproxy_tcp_handle);
+       old_rtpproxy_tcp_port = rtpproxy_tcp_port;
+
+       /* Register UDP port for dissection */
+       if(old_rtpproxy_udp_port != 0 && old_rtpproxy_udp_port != rtpproxy_udp_port)
+               dissector_delete_uint("udp.port", old_rtpproxy_udp_port, rtpproxy_udp_handle);
+       if(rtpproxy_udp_port != 0 && old_rtpproxy_udp_port != rtpproxy_udp_port)
+               dissector_add_uint("udp.port", rtpproxy_udp_port, rtpproxy_udp_handle);
+       old_rtpproxy_udp_port = rtpproxy_udp_port;
+}
+
+/*
+ * 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:
+ */