Blame wireshark-0006-From-Peter-Lemenkov-via-https-bugs.wireshark.org-bug.patch

1444df
From: Evan Huus <eapache@gmail.com>
1444df
Date: Sun, 18 Aug 2013 19:49:08 +0000
61af30
Subject: [PATCH] Dissector for the Sippy RTPproxy controlling protocol
61af30
61af30
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8326
1444df
1444df
Dissector for the Sippy RTPproxy controlling protocol. RTPproxy is a well-known
1444df
(among SIP-engineers) application and it operates using its own simple
1444df
text-based protocol. There are several competing products but all of them
1444df
implements it (sometimes slightly extending).
1444df
1444df
svn path=/trunk/; revision=51417
1444df
1444df
Add a cast to try and fix
1444df
packet-rtpproxy.c:226: warning: implicit conversion shortens 64-bit value into
1444df
a 32-bit value
1444df
1444df
I'm not quite sure what's going on here, all the values in use are either gint
1444df
or guint so they should all be the same size?
1444df
1444df
svn path=/trunk/; revision=51419
1444df
1444df
Take another stab at
1444df
packet-rtpproxy.c:226: warning: implicit conversion shortens 64-bit value into a
1444df
32-bit value
1444df
1444df
svn path=/trunk/; revision=51420
1444df
1444df
One more 64/32-conversion fix for rtpproxy
1444df
1444df
svn path=/trunk/; revision=51421
1444df
1444df
Fix Coverity CID 1063335: Unused pointer value.
1444df
1444df
svn path=/trunk/; revision=51430
173888
173888
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9211 :
173888
Add basic conversation support for rtpproxy dissector
173888
173888
svn path=/trunk/; revision=52331
173888
173888
Let's please fix-encoding-args.pl
173888
173888
svn path=/trunk/; revision=52334
173888
173888
Make RTPProxy a newstyle dissector.
173888
173888
svn path=/trunk/; revision=52476
173888
173888
Try to fix
173888
packet-rtpproxy.c:217: warning: comparison between signed and unsigned
173888
173888
svn path=/trunk/; revision=52477
173888
173888
Fix signed vs. unsigned comparison warnings.
173888
173888
svn path=/trunk/; revision=52483
173888
173888
Add response time to the rtpproxy dissector. Bug 9380 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9380)
173888
173888
From Peter Lemenkov.
173888
173888
svn path=/trunk/; revision=53115
173888
173888
Decode more error replies in RTPproxy dissector.  Bug 9408 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9408)
173888
173888
From Peter Lemenkov
173888
173888
svn path=/trunk/; revision=53245
173888
173888
From Peter Lemenkov
173888
display a text description for the RTPProxy version request
173888
173888
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9416
173888
173888
svn path=/trunk/; revision=53249
173888
173888
replace proto_tree_add_string_format_value() with proto_tree_add_item()
173888
173888
svn path=/trunk/; revision=53261
1444df
65d033
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9429 :
65d033
Fix Notify info parsing in RTPproxy dissector
65d033
65d033
svn path=/trunk/; revision=53385
65d033
65d033
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9430 :
65d033
Fix empty ToTag in RTPproxy's Offer/Update command
65d033
65d033
svn path=/trunk/; revision=53391
65d033
65d033
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9440 :
65d033
RTPproxy: use proto_item_append_text instead of rewriting the entire item's text
65d033
65d033
svn path=/trunk/; revision=53393
65d033
65d033
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9441 :
65d033
Fix Notify IPv6 address parsing in RTPproxy dissector
65d033
65d033
svn path=/trunk/; revision=53394
65d033
65d033
add a cast to fix compiler warning
65d033
65d033
svn path=/trunk/; revision=53401
65d033
65d033
Fix typo errors
65d033
65d033
svn path=/trunk/; revision=53585
65d033
65d033
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9397 :
65d033
Add RTP/RTCP dissector setup based on the replies found in rtpproxy dissector
65d033
65d033
svn path=/trunk/; revision=53603
65d033
65d033
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9444 :
65d033
Add initial parameter parser for commands in RTPproxy dissector
65d033
65d033
svn path=/trunk/; revision=53604
65d033
65d033
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9476 :
65d033
Add DTMF dissector setup based on the information found in RTPproxy requests
65d033
65d033
svn path=/trunk/; revision=53605
65d033
65d033
Squelch a compiler warning.
65d033
65d033
svn path=/trunk/; revision=53606
65d033
65d033
Reinitialize counter between loops to avoid an out of bound access found with fuzz testing.
65d033
65d033
svn path=/trunk/; revision=53612
65d033
61af30
RTPproxy dissector: Add expert info about timeouts.  Bug 9484 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9484)
61af30
61af30
From Peter Lemenkov
61af30
61af30
svn path=/trunk/; revision=53622
61af30
61af30
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9487 :
61af30
Use RTP payload descriptions from RTP dissector in RTPproxy codec param value
61af30
61af30
svn path=/trunk/; revision=53658
61af30
61af30
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9490 :
61af30
Couple packets in RTPproxy dissector not only with CookieID but also with Call-IDs
61af30
61af30
svn path=/trunk/; revision=53673
61af30
61af30
Fix Coverity CID 1134045: Printf format string issue.  (As documented in the printf man page for the ' option, "Note that many versions of gcc(1) cannot parse this option and will issue a warning."  (r47940 reverted a similar change, so this keeps things consistent.)
61af30
61af30
svn path=/trunk/; revision=53705
61af30
61af30
Clean up indentation.
61af30
61af30
svn path=/trunk/; revision=53742
61af30
3a1a1b
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9556
3a1a1b
3a1a1b
Cosmetic change in a LF field representation in the RTPproxy dissector
3a1a1b
3a1a1b
Don't display any value for LF field
3a1a1b
3a1a1b
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
3a1a1b
3a1a1b
svn path=/trunk/; revision=54045
3a1a1b
3a1a1b
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9558
3a1a1b
3a1a1b
Mark generated fields as generated in RTPproxy dissector
3a1a1b
3a1a1b
This patch is cosmetic. It just marks generated fields as generated (to avoid confusion)
3a1a1b
3a1a1b
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
3a1a1b
3a1a1b
svn path=/trunk/; revision=54123
3a1a1b
3a1a1b
From Peter Lemenkov:
3a1a1b
3a1a1b
 "This patch removes misleading dereferencing operator from the
3a1a1b
  array's name. E.g. consider the following declaration:
3a1a1b
3a1a1b
  guint32 ipaddr[4];
3a1a1b
3a1a1b
  ipaddr points to the address of an array of guint32's, while &ipaddr
3a1a1b
  points to the first' guint32 object. E.g. &ipaddr == &ipaddr[0]. The
3a1a1b
  value is the same, but has different type which is necessary
3a1a1b
  sometimes. However inet_pton treats latest argument as void*, and
3a1a1b
  this information is left anyway. So no need to bother with types and
3a1a1b
  let's just pass pointer to the array."
3a1a1b
3a1a1b
  https://bugs.wireshark.org/bugzilla/attachment.cgi?id=12304
3a1a1b
3a1a1b
From me: Remove dereferencing operator from 'ipaddr' in two calls to
3a1a1b
         wmem_memdup().
3a1a1b
3a1a1b
svn path=/trunk/; revision=54156
3a1a1b
ab5f7c
Add numeric types instead of string where possible in the RTPproxy dissector.  Bug 9561 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9561)
ab5f7c
ab5f7c
From Peter Lemenkov
ab5f7c
ab5f7c
svn path=/trunk/; revision=54467
ab5f7c
1444df
diff --git a/AUTHORS b/AUTHORS
173888
index 10782b0..e7b3c18 100644
1444df
--- a/AUTHORS
1444df
+++ b/AUTHORS
173888
@@ -3733,6 +3733,7 @@ Max Baker		<max[AT]warped.org>
1444df
 Mike Garratt		<mg.wireshark[AT]evn.co.nz>
844b61
 Bart Van Assche		<bvanassche[AT]acm.org>
844b61
 Karl Beldan			<karl.beldan[AT]gmail.com>
1444df
+Peter Lemenkov		<lemenkov[AT]gmail.com>
c06811
 Masayuki Takemura	<masayuki.takemura[AT]gmail.com>
1444df
 
c06811
 
1444df
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
88032f
index c5c1193..9c547b3 100644
1444df
--- a/epan/CMakeLists.txt
1444df
+++ b/epan/CMakeLists.txt
1444df
@@ -1083,6 +1083,7 @@ set(DISSECTOR_SRC
1444df
 	dissectors/packet-rtp-events.c
1444df
 	dissectors/packet-rtp-midi.c
1444df
 	dissectors/packet-rtp.c
1444df
+	dissectors/packet-rtpproxy.c
1444df
 	dissectors/packet-rtps.c
1444df
 	dissectors/packet-rtsp.c
1444df
 	dissectors/packet-rudp.c
1444df
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
1444df
index 937f522..73217d7 100644
1444df
--- a/epan/dissectors/Makefile.common
1444df
+++ b/epan/dissectors/Makefile.common
1444df
@@ -1004,6 +1004,7 @@ DISSECTOR_SRC = \
1444df
 	packet-rtp-events.c	\
1444df
 	packet-rtp-midi.c	\
1444df
 	packet-rtp.c		\
1444df
+	packet-rtpproxy.c	\
1444df
 	packet-rtps.c		\
1444df
 	packet-rtsp.c		\
1444df
 	packet-rudp.c		\
1444df
diff --git a/epan/dissectors/packet-rtpproxy.c b/epan/dissectors/packet-rtpproxy.c
1444df
new file mode 100644
ab5f7c
index 0000000..e8c5c95
1444df
--- /dev/null
1444df
+++ b/epan/dissectors/packet-rtpproxy.c
ab5f7c
@@ -0,0 +1,1394 @@
1444df
+/* packet-rtpproxy.c
1444df
+ * RTPproxy command protocol dissector
1444df
+ * Copyright 2013, Peter Lemenkov <lemenkov@gmail.com>
1444df
+ *
1444df
+ * This dissector tries to dissect rtpproxy control protocol. Please visit this
1444df
+ * link for brief details on the command format:
1444df
+ *
1444df
+ * http://www.rtpproxy.org/wiki/RTPproxy/Protocol
1444df
+ *
1444df
+ * $Id$
1444df
+ *
1444df
+ * Wireshark - Network traffic analyzer
1444df
+ * By Gerald Combs <gerald@wireshark.org>
1444df
+ * Copyright 1999 Gerald Combs
1444df
+ *
1444df
+ * This program is free software; you can redistribute it and/or
1444df
+ * modify it under the terms of the GNU General Public License
1444df
+ * as published by the Free Software Foundation; either version 2
1444df
+ * of the License, or (at your option) any later version.
1444df
+ *
1444df
+ * This program is distributed in the hope that it will be useful,
1444df
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1444df
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1444df
+ * GNU General Public License for more details.
1444df
+ *
1444df
+ * You should have received a copy of the GNU General Public License
1444df
+ * along with this program; if not, write to the Free Software
1444df
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1444df
+ */
1444df
+
1444df
+#include "config.h"
1444df
+
173888
+#include <ctype.h>
65d033
+#include <glib.h>
173888
+
65d033
+#include <epan/address.h>
1444df
+#include <epan/packet.h>
1444df
+#include <epan/prefs.h>
173888
+#include <epan/conversation.h>
61af30
+#include <epan/expert.h>
61af30
+#include <epan/rtp_pt.h>
1444df
+
65d033
+#ifdef HAVE_ARPA_INET_H
65d033
+#include <arpa/inet.h>
65d033
+#endif
65d033
+#ifdef HAVE_WINSOCK2_H
65d033
+#include <winsock2.h>       /* needed to define AF_ values on Windows */
65d033
+#endif
65d033
+#ifdef NEED_INET_V6DEFS_H
65d033
+#include "wsutil/inet_v6defs.h"
65d033
+#endif
65d033
+
65d033
+/* For setting up RTP/RTCP dissectors based on the RTPproxy's answers */
65d033
+#include "packet-rtp.h"
65d033
+#include "packet-rtcp.h"
65d033
+
1444df
+static int proto_rtpproxy = -1;
1444df
+
1444df
+static int hf_rtpproxy_cookie = -1;
1444df
+static int hf_rtpproxy_error = -1;
1444df
+static int hf_rtpproxy_status = -1;
1444df
+static int hf_rtpproxy_ok = -1;
1444df
+static int hf_rtpproxy_ipv4 = -1;
1444df
+static int hf_rtpproxy_ipv6 = -1;
1444df
+static int hf_rtpproxy_port = -1;
1444df
+static int hf_rtpproxy_lf = -1;
1444df
+static int hf_rtpproxy_request = -1;
1444df
+static int hf_rtpproxy_command = -1;
1444df
+static int hf_rtpproxy_command_parameters = -1;
65d033
+static int hf_rtpproxy_command_parameter = -1;
65d033
+static int hf_rtpproxy_command_parameter_codec = -1;
65d033
+static int hf_rtpproxy_command_parameter_local = -1;
65d033
+static int hf_rtpproxy_command_parameter_remote = -1;
65d033
+static int hf_rtpproxy_command_parameter_repacketize = -1;
65d033
+static int hf_rtpproxy_command_parameter_dtmf = -1;
65d033
+/* static int hf_rtpproxy_command_parameter_cmap = -1; TODO */
65d033
+static int hf_rtpproxy_command_parameter_proto = -1;
65d033
+static int hf_rtpproxy_command_parameter_transcode = -1;
65d033
+static int hf_rtpproxy_command_parameter_acc = -1;
1444df
+static int hf_rtpproxy_callid = -1;
1444df
+static int hf_rtpproxy_copy_target = -1;
1444df
+static int hf_rtpproxy_playback_filename = -1;
1444df
+static int hf_rtpproxy_playback_codec = -1;
1444df
+static int hf_rtpproxy_notify = -1;
1444df
+static int hf_rtpproxy_notify_ipv4 = -1;
65d033
+static int hf_rtpproxy_notify_ipv6 = -1;
1444df
+static int hf_rtpproxy_notify_port = -1;
1444df
+static int hf_rtpproxy_notify_tag = -1;
1444df
+static int hf_rtpproxy_tag = -1;
1444df
+static int hf_rtpproxy_mediaid = -1;
1444df
+static int hf_rtpproxy_reply = -1;
1444df
+static int hf_rtpproxy_version_request = -1;
1444df
+static int hf_rtpproxy_version_supported = -1;
1444df
+
173888
+/* Request/response tracking */
173888
+static int hf_rtpproxy_request_in = -1;
173888
+static int hf_rtpproxy_response_in = -1;
173888
+static int hf_rtpproxy_response_time = -1;
173888
+
173888
+typedef struct _rtpproxy_info {
173888
+	guint32 req_frame;
173888
+	guint32 resp_frame;
173888
+	nstime_t req_time;
61af30
+	gchar* callid;
173888
+} rtpproxy_info_t;
173888
+
65d033
+static dissector_handle_t rtcp_handle;
65d033
+static dissector_handle_t rtp_events_handle;
65d033
+static dissector_handle_t rtp_handle;
65d033
+
173888
+typedef struct _rtpproxy_conv_info {
173888
+	emem_tree_t *trans;
173888
+} rtpproxy_conv_info_t;
173888
+
173888
+
173888
+static const string_string versiontypenames[] = {
173888
+	{ "20040107", "Basic RTP proxy functionality" },
173888
+	{ "20050322", "Support for multiple RTP streams and MOH" },
173888
+	{ "20060704", "Support for extra parameter in the V command" },
173888
+	{ "20071116", "Support for RTP re-packetization" },
173888
+	{ "20071218", "Support for forking (copying) RTP stream" },
173888
+	{ "20080403", "Support for RTP statistics querying" },
173888
+	{ "20081102", "Support for setting codecs in the update/lookup command" },
173888
+	{ "20081224", "Support for session timeout notifications" },
173888
+	{ "20090810", "Support for automatic bridging" },
173888
+	{ 0, NULL }
173888
+};
173888
+
1444df
+static const value_string commandtypenames[] = {
1444df
+	{ 'V', "Handshake/Ping" },
1444df
+	{ 'v', "Handshake/Ping" },
1444df
+	{ 'U', "Offer/Update" },
1444df
+	{ 'u', "Offer/Update" },
1444df
+	{ 'L', "Answer/Lookup" },
1444df
+	{ 'l', "Answer/Lookup" },
1444df
+	{ 'I', "Information"},
1444df
+	{ 'i', "Information"},
1444df
+	{ 'X', "Close all active sessions"},
1444df
+	{ 'x', "Close all active sessions"},
1444df
+	{ 'D', "Delete an active session (Bye/Cancel/Error)"},
1444df
+	{ 'd', "Delete an active session (Bye/Cancel/Error)"},
1444df
+	{ 'P', "Start playback (music-on-hold)"},
1444df
+	{ 'p', "Start playback (music-on-hold)"},
1444df
+	{ 'S', "Stop playback (music-on-hold)"},
1444df
+	{ 's', "Stop playback (music-on-hold)"},
1444df
+	{ 'R', "Start recording"},
1444df
+	{ 'r', "Start recording"},
1444df
+	{ 'C', "Copy stream"},
1444df
+	{ 'c', "Copy stream"},
1444df
+	{ 'Q', "Query info about a session"},
1444df
+	{ 'q', "Query info about a session"},
1444df
+	{ 0, NULL }
1444df
+};
1444df
+
65d033
+static const value_string paramtypenames[] = {
65d033
+	/* Official command parameters */
65d033
+	{'4', "Remote address is IPv4"},
65d033
+	{'6', "Remote address is IPv6"},
65d033
+	{'a', "Asymmetric RTP"},
65d033
+	{'A', "Asymmetric RTP"},
65d033
+	{'b', "Brief stats"},
65d033
+	{'B', "Brief stats"},
65d033
+	{'c', "Codecs"},
65d033
+	{'C', "Codecs"},
65d033
+	{'e', "External network (non RFC 1918)"},
65d033
+	{'E', "External network (non RFC 1918)"},
65d033
+	{'i', "Internal network (RFC 1918)"},
65d033
+	{'I', "Internal network (RFC 1918)"},
65d033
+	{'l', "Local address"},
65d033
+	{'L', "Local address"},
65d033
+	{'r', "Remote address"},
65d033
+	{'R', "Remote address"},
65d033
+	{'s', "Symmetric RTP (default)"},
65d033
+	{'S', "Symmetric RTP (default)"},
65d033
+	{'w', "Weak connection (allows roaming)"},
65d033
+	{'W', "Weak connection (allows roaming)"},
65d033
+	{'z', "repacketiZe"},
65d033
+	{'Z', "repacketiZe"},
65d033
+	/* Unofficial command parameters / expensions */
65d033
+	{'d', "DTMF payload ID (unofficial extension)"},
65d033
+	{'D', "DTMF payload ID (unofficial extension)"},
65d033
+	{'m', "codec Mapping (unofficial extension)"},
65d033
+	{'M', "codec Mapping (unofficial extension)"},
65d033
+	{'p', "Protocol type (unofficial extension)"},
65d033
+	{'P', "Protocol type (unofficial extension)"},
65d033
+	{'t', "Transcode to (unofficial extension)"},
65d033
+	{'T', "Transcode to (unofficial extension)"},
65d033
+	{'v', "Accounting (unofficial extension)"},
65d033
+	{'V', "Accounting (unofficial extension)"},
65d033
+	{0, NULL}
65d033
+};
65d033
+
65d033
+static const value_string prototypenames[] = {
65d033
+	{ '0', "UDP (default)"},
65d033
+	{ '1', "TCP"},
65d033
+	{ '2', "SCTP"},
65d033
+	{ 0, NULL }
65d033
+};
65d033
+static const value_string acctypenames[] = {
65d033
+	{ '0', "Start"},
65d033
+	{ '1', "Interim update"},
65d033
+	{ '2', "Stop"},
65d033
+	{ 0, NULL }
65d033
+};
65d033
+
1444df
+static const value_string oktypenames[] = {
1444df
+	{ '0', "Ok"},
1444df
+	{ '1', "Version Supported"},
1444df
+	{ 0, NULL }
1444df
+};
1444df
+
173888
+static const string_string errortypenames[] = {
173888
+	{ "E0", "Syntax error" },
173888
+	{ "E1", "Syntax error" },
173888
+	{ "E2", "Syntax error" },
173888
+	{ "E3", "Unknown command" },
173888
+	{ "E4", "Syntax error" },
173888
+	{ "E5", "Out of memory" },
173888
+	{ "E6", "<no description>" },
173888
+	{ "E7", "Software error (can't create listener)" },
173888
+	{ "E8", "Not Found" },
173888
+	{ "E10", "Software error (can't create listener)" },
173888
+	{ "E11", "Out of memory" },
173888
+	{ "E12", "Out of memory" },
173888
+	{ "E13", "Out of memory" },
173888
+	{ "E14", "Out of memory" },
1444df
+	{ 0, NULL }
1444df
+};
1444df
+
1444df
+static gint ett_rtpproxy = -1;
1444df
+
1444df
+static gint ett_rtpproxy_request = -1;
1444df
+static gint ett_rtpproxy_command = -1;
65d033
+static gint ett_rtpproxy_command_parameters = -1;
65d033
+static gint ett_rtpproxy_command_parameters_codecs = -1;
65d033
+static gint ett_rtpproxy_command_parameters_local = -1;
65d033
+static gint ett_rtpproxy_command_parameters_remote = -1;
65d033
+static gint ett_rtpproxy_command_parameters_repacketize = -1;
65d033
+static gint ett_rtpproxy_command_parameters_dtmf = -1;
65d033
+static gint ett_rtpproxy_command_parameters_cmap = -1;
65d033
+static gint ett_rtpproxy_command_parameters_proto = -1;
65d033
+static gint ett_rtpproxy_command_parameters_transcode = -1;
65d033
+static gint ett_rtpproxy_command_parameters_acc = -1;
1444df
+static gint ett_rtpproxy_tag = -1;
1444df
+static gint ett_rtpproxy_notify = -1;
1444df
+
1444df
+static gint ett_rtpproxy_reply = -1;
1444df
+
61af30
+/* Default values */
1444df
+static guint rtpproxy_tcp_port = 22222;
1444df
+static guint rtpproxy_udp_port = 22222;
65d033
+static gboolean rtpproxy_establish_conversation = TRUE;
61af30
+/* See - http://www.opensips.org/html/docs/modules/1.11.x/rtpproxy.html#id250018 */
61af30
+/* See - http://www.kamailio.org/docs/modules/devel/modules/rtpproxy.html#idm448 */
61af30
+static guint rtpproxy_timeout = 1000;
61af30
+static nstime_t rtpproxy_timeout_ns = {1, 0};
1444df
+
1444df
+void proto_reg_handoff_rtpproxy(void);
1444df
+
1444df
+gint
65d033
+rtpproxy_add_tag(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint realsize)
1444df
+{
1444df
+	proto_item *ti = NULL;
1444df
+	proto_tree *another_tree = NULL;
1444df
+	gint new_offset;
1444df
+	guint end;
1444df
+
1444df
+	new_offset = tvb_find_guint8(tvb, begin, -1, ' ');
1444df
+	if(new_offset < 0)
1444df
+		end = realsize; /* No more parameters */
1444df
+	else
1444df
+		end = new_offset;
1444df
+
1444df
+	/* SER/OpenSER/OpenSIPS/Kamailio adds Media-ID right after the Tag
1444df
+	 * separated by a semicolon
1444df
+	 */
1444df
+	new_offset = tvb_find_guint8(tvb, begin, end, ';');
1444df
+	if(new_offset == -1){
1444df
+		ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, end - begin, ENC_ASCII | ENC_NA);
1444df
+		another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag);
1444df
+		ti = proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, 0, ENC_ASCII | ENC_NA);
65d033
+		proto_item_append_text(ti, "<skipped>");
3a1a1b
+		PROTO_ITEM_SET_GENERATED(ti);
1444df
+	}
1444df
+	else{
1444df
+		ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, new_offset - begin, ENC_ASCII | ENC_NA);
3a1a1b
+		if ((guint)new_offset == begin){
65d033
+			proto_item_append_text(ti, "<skipped>"); /* A very first Offer/Update command */
3a1a1b
+			PROTO_ITEM_SET_GENERATED(ti);
3a1a1b
+		}
1444df
+		another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag);
1444df
+		proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, end - (new_offset+1), ENC_ASCII | ENC_NA);
1444df
+	}
1444df
+	return (end == realsize ? -1 : (gint)end);
1444df
+}
1444df
+
173888
+void
65d033
+rtpproxy_add_parameter(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint realsize)
65d033
+{
65d033
+	proto_item *ti;
65d033
+	proto_tree *another_tree = NULL;
65d033
+	guint offset = 0;
65d033
+	guint new_offset = 0;
65d033
+	gint i;
65d033
+	guint pt = 0;
65d033
+	gchar** codecs = NULL;
65d033
+	guint codec_len;
65d033
+	guint8* rawstr = NULL;
65d033
+
65d033
+	/* Extract the entire parameters line. */
65d033
+	/* Something like "t4p1iic8,0,2,4,18,96,97,98,100,101" */
65d033
+	rawstr = tvb_get_ephemeral_string(tvb, begin, realsize);
65d033
+
65d033
+	while(offset < realsize){
65d033
+		ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameter, tvb, begin + offset, 1, ENC_NA);
65d033
+		offset++; /* Skip 1-byte parameter's type */
65d033
+		switch (g_ascii_tolower(tvb_get_guint8(tvb, begin+offset-1)))
65d033
+		{
65d033
+			/* Official long parameters */
65d033
+			case 'c':
65d033
+				new_offset = (gint)strspn(rawstr+offset, "0123456789,");
65d033
+				another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_codecs);
65d033
+				codecs = g_strsplit(tvb_get_ephemeral_string(tvb, begin+offset, new_offset), ",", 0);
65d033
+				i = 0;
65d033
+				while(codecs[i]){
65d033
+					/* We assume strings < 2^32-1 bytes long. :-) */
65d033
+					codec_len = (guint)strlen(codecs[i]);
ab5f7c
+					ti = proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_codec, tvb, begin+offset, codec_len,
ab5f7c
+							(guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin+offset, codec_len), NULL, 10));
61af30
+					proto_item_append_text(ti, " (%s)", val_to_str_ext((guint)strtoul(tvb_format_text(tvb,begin+offset,codec_len),NULL,10), &rtp_payload_type_vals_ext, "Unknown"));
65d033
+					offset += codec_len;
65d033
+					if(codecs[i+1])
65d033
+						offset++; /* skip comma */
65d033
+					i++;
65d033
+				};
65d033
+				g_strfreev(codecs);
65d033
+				break;
65d033
+			case 'l':
65d033
+				new_offset = (gint)strspn(rawstr+offset, "0123456789.");
65d033
+				another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_local);
65d033
+				proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_local, tvb, begin+offset, new_offset, ENC_ASCII | ENC_NA);
65d033
+				offset += new_offset;
65d033
+				break;
65d033
+			case 'r':
65d033
+				new_offset = (gint)strspn(rawstr+offset, "0123456789.");
65d033
+				another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_remote);
65d033
+				proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_remote, tvb, begin+offset, new_offset, ENC_ASCII | ENC_NA);
65d033
+				offset += new_offset;
65d033
+				break;
65d033
+			case 'z':
65d033
+				new_offset = (gint)strspn(rawstr+offset, "0123456789");
65d033
+				another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_repacketize);
ab5f7c
+				proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_repacketize, tvb, begin+offset, new_offset,
ab5f7c
+						(guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin+offset, new_offset), NULL, 10));
65d033
+				offset += new_offset;
65d033
+				break;
65d033
+			/* Unofficial long parameters */
65d033
+			case 'd':
65d033
+				new_offset = (gint)strspn(rawstr+offset, "0123456789");
65d033
+				another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_dtmf);
ab5f7c
+				proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_dtmf, tvb, begin+offset, new_offset,
ab5f7c
+						(guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin+offset, new_offset), NULL, 10));
65d033
+				if(rtpproxy_establish_conversation){
65d033
+					pt = (guint)strtoul(tvb_format_text(tvb,begin+offset,new_offset),NULL,10);
65d033
+					dissector_add_uint("rtp.pt", pt, rtp_events_handle);
65d033
+				}
65d033
+				offset += new_offset;
65d033
+				break;
65d033
+			case 'm':
65d033
+				new_offset = (gint)strspn(rawstr+offset, "0123456789=,");
65d033
+				/* TODO */
65d033
+				offset += new_offset;
65d033
+				break;
65d033
+			case 'p':
65d033
+				another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_proto);
65d033
+				proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_proto, tvb, begin+offset, 1, ENC_NA);
65d033
+				offset++;
65d033
+				break;
65d033
+			case 't':
65d033
+				new_offset = (gint)strspn(rawstr+offset, "0123456789");
65d033
+				another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_transcode);
ab5f7c
+				ti = proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_transcode, tvb, begin+offset, new_offset,
ab5f7c
+						(guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin+offset, new_offset), NULL, 10));
61af30
+				proto_item_append_text(ti, " (%s)", val_to_str_ext((guint)strtoul(tvb_format_text(tvb,begin+offset, new_offset),NULL,10), &rtp_payload_type_vals_ext, "Unknown"));
65d033
+				offset += new_offset;
65d033
+				break;
65d033
+			case 'v':
65d033
+				another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_acc);
65d033
+				proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_acc, tvb, begin+offset, 1, ENC_NA);
65d033
+				offset++;
65d033
+				break;
65d033
+			default:
65d033
+				break;
65d033
+		}
65d033
+	}
65d033
+}
65d033
+
61af30
+rtpproxy_info_t *
173888
+rtpproxy_add_tid(gboolean is_request, tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtpproxy_tree, rtpproxy_conv_info_t *rtpproxy_conv, gchar* cookie)
173888
+{
173888
+	rtpproxy_info_t *rtpproxy_info;
173888
+	proto_item *pi;
173888
+
173888
+	if (!PINFO_FD_VISITED(pinfo)) {
173888
+		if (is_request){
173888
+			rtpproxy_info = se_new(rtpproxy_info_t);
173888
+			rtpproxy_info->req_frame = PINFO_FD_NUM(pinfo);
173888
+			rtpproxy_info->resp_frame = 0;
173888
+			rtpproxy_info->req_time = pinfo->fd->abs_ts;
61af30
+			rtpproxy_info->callid = NULL;
173888
+			se_tree_insert_string(rtpproxy_conv->trans, cookie, rtpproxy_info, 0);
173888
+		} else {
173888
+			rtpproxy_info = (rtpproxy_info_t *)se_tree_lookup_string(rtpproxy_conv->trans, cookie, 0);
173888
+			if (rtpproxy_info) {
173888
+				rtpproxy_info->resp_frame = PINFO_FD_NUM(pinfo);
173888
+			}
173888
+		}
173888
+	} else {
173888
+		rtpproxy_info = (rtpproxy_info_t *)se_tree_lookup_string(rtpproxy_conv->trans, cookie, 0);
173888
+		if (rtpproxy_info && (is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame)) {
173888
+			nstime_t ns;
173888
+
173888
+			pi = proto_tree_add_uint(rtpproxy_tree, is_request ? hf_rtpproxy_response_in : hf_rtpproxy_request_in, tvb, 0, 0, is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame);
173888
+			PROTO_ITEM_SET_GENERATED(pi);
173888
+
173888
+			/* If reply then calculate response time */
173888
+			if (!is_request){
173888
+				nstime_delta(&ns, &pinfo->fd->abs_ts, &rtpproxy_info->req_time);
173888
+				pi = proto_tree_add_time(rtpproxy_tree, hf_rtpproxy_response_time, tvb, 0, 0, &ns);
173888
+				PROTO_ITEM_SET_GENERATED(pi);
61af30
+				if (nstime_cmp(&rtpproxy_timeout_ns, &ns) < 0)
61af30
+					expert_add_info_format(pinfo, rtpproxy_tree, PI_RESPONSE_CODE, PI_WARN, "Response timeout %.3f seconds", nstime_to_sec(&ns);;
173888
+			}
173888
+		}
173888
+	}
61af30
+	/* Could be NULL so we should check it before dereferencing */
61af30
+	return rtpproxy_info;
173888
+}
173888
+
65d033
+void
65d033
+rtpproxy_add_notify_addr(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint end)
65d033
+{
65d033
+	gint offset = 0;
65d033
+	gint tmp = 0;
65d033
+	gboolean ipv6 = FALSE;
65d033
+	proto_item *ti;
65d033
+
65d033
+	/* Check for at least one colon */
65d033
+	offset = tvb_find_guint8(tvb, begin, end, ':');
65d033
+	if(offset != -1){
65d033
+		/* Find if it's the latest colon (not in case of a IPv6) */
65d033
+		while((tmp = tvb_find_guint8(tvb, offset+1, end, ':')) != -1){
65d033
+			ipv6 = TRUE;
65d033
+			offset = tmp;
65d033
+		}
65d033
+		/* We have ip:port */
65d033
+		if(ipv6)
65d033
+			proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv6, tvb, begin, offset - begin, ENC_ASCII | ENC_NA);
65d033
+		else
65d033
+			proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, offset - begin, ENC_ASCII | ENC_NA);
ab5f7c
+		proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, offset+1, end - (offset+1),
ab5f7c
+			(guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, offset+1, end - (offset+1)), NULL, 10));
65d033
+	}
65d033
+	else{
65d033
+		/* Only port is supplied */
65d033
+		ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, 0, ENC_ASCII | ENC_NA);
65d033
+		proto_item_append_text(ti, "<skipped>");
3a1a1b
+		PROTO_ITEM_SET_GENERATED(ti);
ab5f7c
+		proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, begin, end - begin,
ab5f7c
+			(guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin, end - begin), NULL, 10));
65d033
+	}
65d033
+}
65d033
+
173888
+static int
173888
+dissect_rtpproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1444df
+{
1444df
+	gboolean has_lf = FALSE;
173888
+	gint offset = 0;
1444df
+	gint new_offset = 0;
1444df
+	guint tmp;
173888
+	gint realsize = 0;
1444df
+	guint8* rawstr;
173888
+	guint8* tmpstr;
1444df
+	proto_item *ti;
65d033
+	proto_item *ti2;
1444df
+	proto_tree *rtpproxy_tree;
173888
+	conversation_t *conversation;
173888
+	rtpproxy_conv_info_t *rtpproxy_conv;
173888
+	gchar* cookie = NULL;
65d033
+	/* For RT(C)P setup */
65d033
+	address addr;
65d033
+	guint16 port;
65d033
+	guint32 ipaddr[4];
61af30
+	rtpproxy_info_t *rtpproxy_info = NULL;
173888
+
173888
+	/* If it does not start with a printable character it's not RTPProxy */
173888
+	if(!isprint(tvb_get_guint8(tvb, 0)))
173888
+		return 0;
173888
+
173888
+	/* Extract Cookie */
173888
+	offset = tvb_find_guint8(tvb, offset, -1, ' ');
173888
+	if(offset == -1)
173888
+		return 0;
1444df
+
1444df
+	/* Clear out stuff in the info column - we''l set it later */
1444df
+	col_clear(pinfo->cinfo, COL_INFO);
1444df
+
1444df
+	ti = proto_tree_add_item(tree, proto_rtpproxy, tvb, 0, -1, ENC_NA);
1444df
+	rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy);
1444df
+
1444df
+	proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_cookie, tvb, 0, offset, ENC_ASCII | ENC_NA);
173888
+	cookie = tvb_get_ephemeral_string(tvb, 0, offset);
1444df
+
1444df
+	/* Skip whitespace */
1444df
+	offset = tvb_skip_wsp(tvb, offset+1, -1);
1444df
+
1444df
+	/* Calculate size to prevent recalculation in the future */
1444df
+	realsize = tvb_reported_length(tvb);
1444df
+
61af30
+
1444df
+	/* Check for LF (required for TCP connection, optional for UDP) */
1444df
+	if (tvb_get_guint8(tvb, realsize - 1) == '\n'){
1444df
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPproxy");
1444df
+		/* Don't count trailing LF */
1444df
+		realsize -= 1;
1444df
+		has_lf = TRUE;
1444df
+	}
1444df
+	else
1444df
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPproxy (no LF)");
1444df
+
61af30
+
173888
+	/* Try to create conversation */
173888
+	conversation = find_or_create_conversation(pinfo);
173888
+	rtpproxy_conv = (rtpproxy_conv_info_t *)conversation_get_proto_data(conversation, proto_rtpproxy);
173888
+	if (!rtpproxy_conv) {
173888
+		rtpproxy_conv = se_new(rtpproxy_conv_info_t);
173888
+		rtpproxy_conv->trans = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "rtpproxy transactions");;
173888
+		conversation_add_proto_data(conversation, proto_rtpproxy, rtpproxy_conv);
173888
+	}
173888
+
1444df
+	/* Get payload string */
1444df
+	rawstr = tvb_get_ephemeral_string(tvb, offset, realsize - offset);
1444df
+
1444df
+	/* Extract command */
1444df
+	tmp = g_ascii_tolower(tvb_get_guint8(tvb, offset));
1444df
+	switch (tmp)
1444df
+	{
1444df
+		case 's':
1444df
+			/* A specific case - long statistics answer */
1444df
+			/* %COOKIE% sessions created %NUM0% active sessions: %NUM1% */
173888
+			rtpproxy_add_tid(FALSE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie);
1444df
+			if ('e' == tvb_get_guint8(tvb, offset+1)){
1444df
+				col_add_fstr(pinfo->cinfo, COL_INFO, "Reply: %s", rawstr);
1444df
+				ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_reply, tvb, offset, -1, ENC_NA);
1444df
+
1444df
+				rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_reply);
173888
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_status, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA);
1444df
+				break;
1444df
+			}
1444df
+		case 'i':
1444df
+		case 'x':
1444df
+		case 'u':
1444df
+		case 'l':
1444df
+		case 'd':
1444df
+		case 'p':
1444df
+		case 'v':
1444df
+		case 'r':
1444df
+		case 'c':
1444df
+		case 'q':
61af30
+			rtpproxy_info = rtpproxy_add_tid(TRUE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie);
1444df
+			col_add_fstr(pinfo->cinfo, COL_INFO, "Request: %s", rawstr);
1444df
+			ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_request, tvb, offset, -1, ENC_NA);
1444df
+			rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_request);
1444df
+
1444df
+			/* A specific case - version request */
173888
+			if ((tmp == 'v') && (offset + (gint)strlen("VF YYYMMDD") + 1 == realsize)){
1444df
+				/* Skip whitespace */
1444df
+				new_offset = tvb_skip_wsp(tvb, offset + ((guint)strlen("VF") + 1), -1);
173888
+				ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_request, tvb, new_offset, (gint)strlen("YYYYMMDD"), ENC_ASCII | ENC_NA);
173888
+				tmpstr = tvb_get_ephemeral_string(tvb, new_offset, (gint)strlen("YYYYMMDD"));
173888
+				proto_item_append_text(ti, " (%s)", str_to_str(tmpstr, versiontypenames, "Unknown"));
1444df
+				break;
1444df
+			}
1444df
+
1444df
+			/* All other commands */
1444df
+			ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command, tvb, offset, 1, ENC_NA);
1444df
+
1444df
+			/* A specific case - handshake/ping */
1444df
+			if (tmp == 'v')
1444df
+				break; /* No more parameters */
1444df
+
1444df
+			/* A specific case - close all calls */
1444df
+			if (tmp == 'x')
1444df
+				break; /* No more parameters */
1444df
+
1444df
+			/* Extract parameters */
1444df
+			/* Parameters should be right after the command and before EOL (in case of Info command) or before whitespace */
173888
+			new_offset = (tmp == 'i' ? (realsize - 1 > offset ? offset + (gint)strlen("Ib") : offset + (gint)strlen("I")) : tvb_find_guint8(tvb, offset, -1, ' '));
1444df
+
173888
+			if (new_offset != offset + 1){
1444df
+				rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_command);
65d033
+				ti2 = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameters, tvb, offset+1, new_offset - (offset+1), ENC_ASCII | ENC_NA);
65d033
+				rtpproxy_add_parameter(proto_item_add_subtree(ti2, ett_rtpproxy_command_parameters), tvb, offset+1, new_offset - (offset+1));
1444df
+				rtpproxy_tree = proto_item_get_parent(ti);
1444df
+			}
1444df
+
1444df
+			/* A specific case - query information */
1444df
+			if (tmp == 'i')
1444df
+				break; /* No more parameters */
1444df
+
1444df
+			/* Skip whitespace */
1444df
+			offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+
1444df
+			/* Extract Call-ID */
1444df
+			new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1444df
+			proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_callid, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
61af30
+			if(rtpproxy_info && !rtpproxy_info->callid)
16ed22
+				rtpproxy_info->callid = tvb_get_seasonal_string(tvb, offset, new_offset - offset);
1444df
+			/* Skip whitespace */
1444df
+			offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+
1444df
+			/* Extract IP and Port in case of Offer/Answer */
1444df
+			if ((tmp == 'u') || (tmp == 'l')){
1444df
+				/* Extract IP */
1444df
+				new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1444df
+				if (tvb_find_guint8(tvb, offset, new_offset - offset, ':') == -1)
1444df
+					proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
1444df
+				else
1444df
+					proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
1444df
+				/* Skip whitespace */
1444df
+				offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+
1444df
+				/* Extract Port */
1444df
+				new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
ab5f7c
+				proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset,
ab5f7c
+						(guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, offset, new_offset - offset), NULL, 10));
1444df
+				/* Skip whitespace */
1444df
+				offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+			}
1444df
+
1444df
+			/* Extract Copy target */
1444df
+			if (tmp == 'c'){
1444df
+				new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1444df
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_copy_target, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
1444df
+				/* Skip whitespace */
1444df
+				offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+			}
1444df
+
1444df
+			/* Extract Playback file and codecs */
1444df
+			if (tmp == 'p'){
1444df
+				/* Extract filename */
1444df
+				new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1444df
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_playback_filename, tvb, offset, new_offset - offset, ENC_ASCII | ENC_NA);
1444df
+				/* Skip whitespace */
1444df
+				offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+
1444df
+				/* Extract codec */
1444df
+				new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
ab5f7c
+				proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_playback_codec, tvb, offset, new_offset - offset,
ab5f7c
+						(guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, offset, new_offset - offset), NULL, 10));
1444df
+				/* Skip whitespace */
1444df
+				offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+			}
1444df
+
1444df
+			/* Extract first tag */
65d033
+			new_offset = rtpproxy_add_tag(rtpproxy_tree, tvb, offset, realsize);
1444df
+			if(new_offset == -1)
1444df
+				break; /* No more parameters */
1444df
+			/* Skip whitespace */
1444df
+			offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+
1444df
+			/* Extract second tag */
65d033
+			new_offset = rtpproxy_add_tag(rtpproxy_tree, tvb, offset, realsize);
1444df
+			if(new_offset == -1)
1444df
+				break; /* No more parameters */
1444df
+			/* Skip whitespace */
1444df
+			offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+
1444df
+			/* Extract Notification address */
1444df
+			if (tmp == 'u'){
173888
+				ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA);
1444df
+				proto_item_set_text(ti, "Notify");
1444df
+				rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_notify);
65d033
+
65d033
+				/* Check for NotifyTag parameter (separated by space) */
65d033
+				new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1444df
+				if(new_offset == -1){
65d033
+					/* NotifyTag wasn't found (we should re-use Call-ID instead) */
65d033
+					rtpproxy_add_notify_addr(rtpproxy_tree, tvb, offset, realsize);
1444df
+					break; /* No more parameters */
1444df
+				}
65d033
+
65d033
+				/* NotifyTag was found */
65d033
+				rtpproxy_add_notify_addr(rtpproxy_tree, tvb, offset, new_offset);
1444df
+				/* Skip whitespace */
1444df
+				offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+
1444df
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_tag, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA);
1444df
+			}
1444df
+			break;
1444df
+		case 'a':
1444df
+		case 'e':
1444df
+		case '0':
1444df
+		case '1':
1444df
+		case '2':
1444df
+		case '3':
1444df
+		case '4':
1444df
+		case '5':
1444df
+		case '6':
1444df
+		case '7':
1444df
+		case '8':
1444df
+		case '9':
61af30
+			rtpproxy_info = rtpproxy_add_tid(FALSE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie);
1444df
+			if (tmp == 'e')
1444df
+				col_add_fstr(pinfo->cinfo, COL_INFO, "Error reply: %s", rawstr);
1444df
+			else
1444df
+				col_add_fstr(pinfo->cinfo, COL_INFO, "Reply: %s", rawstr);
1444df
+
1444df
+			ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_reply, tvb, offset, -1, ENC_NA);
1444df
+			rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_reply);
1444df
+
61af30
+			if(rtpproxy_info && rtpproxy_info->callid){
61af30
+				ti = proto_tree_add_string(rtpproxy_tree, hf_rtpproxy_callid, tvb, offset, 0, rtpproxy_info->callid);
61af30
+				PROTO_ITEM_SET_GENERATED(ti);
61af30
+			}
61af30
+
1444df
+			if (tmp == 'e'){
173888
+				tmp = tvb_find_line_end(tvb, offset, -1, &new_offset, FALSE);
173888
+				tmpstr = tvb_get_ephemeral_string(tvb, offset, tmp);
173888
+				ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_error, tvb, offset, (gint)strlen(tmpstr), ENC_ASCII | ENC_NA);
173888
+				proto_item_append_text(ti, " (%s)", str_to_str(tmpstr, errortypenames, "Unknown"));
1444df
+				break;
1444df
+			}
1444df
+
1444df
+			if (tmp == 'a'){
1444df
+				/* A specific case - short statistics answer */
1444df
+				/* %COOKIE% active sessions: %NUM1% */
173888
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_status, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA);
1444df
+				break;
1444df
+			}
173888
+			if ((tmp == '0')&& ((tvb_reported_length(tvb) == (guint)(offset+1))||(tvb_reported_length(tvb) == (guint)(offset+2)))){
1444df
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA);
1444df
+				break;
1444df
+			}
173888
+			if ((tmp == '1') && ((tvb_reported_length(tvb) == (guint)(offset+1))||(tvb_reported_length(tvb) == (guint)(offset+2)))){
1444df
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA);
1444df
+				break;
1444df
+			}
173888
+			if (tvb_reported_length(tvb) == (guint)(offset+9)){
1444df
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_supported, tvb, offset, 8, ENC_ASCII | ENC_NA);
1444df
+				break;
1444df
+			}
1444df
+
1444df
+			/* Extract Port */
1444df
+			new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
65d033
+			/* Convert port to unsigned 16-bit number */
65d033
+			port = (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, offset, new_offset - offset), NULL, 10);
ab5f7c
+			proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset, port);
1444df
+			/* Skip whitespace */
1444df
+			offset = tvb_skip_wsp(tvb, new_offset+1, -1);
1444df
+
1444df
+			/* Extract IP */
1444df
+			tmp = tvb_find_line_end(tvb, offset, -1, &new_offset, FALSE);
65d033
+			if (tvb_find_guint8(tvb, offset, -1, ':') == -1){
3a1a1b
+				inet_pton(AF_INET, (char*)tvb_get_ephemeral_string(tvb, offset, tmp), ipaddr);
65d033
+				addr.type = AT_IPv4;
65d033
+				addr.len  = 4;
3a1a1b
+				addr.data = ep_memdup(ipaddr, 4);
1444df
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, tmp, ENC_ASCII | ENC_NA);
65d033
+			}
65d033
+			else{
3a1a1b
+				inet_pton(AF_INET6, (char*)tvb_get_ephemeral_string(tvb, offset, tmp), ipaddr);
65d033
+				addr.type = AT_IPv6;
65d033
+				addr.len  = 16;
3a1a1b
+				addr.data = ep_memdup(ipaddr, 16);
1444df
+				proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, tmp, ENC_ASCII | ENC_NA);
65d033
+			}
65d033
+
65d033
+			if(rtpproxy_establish_conversation){
65d033
+				if (rtp_handle) {
65d033
+					/* FIXME tell if isn't a video stream, and setup codec mapping */
65d033
+					rtp_add_address(pinfo, &addr, port, 0, "RTPproxy", pinfo->fd->num, 0, NULL);
65d033
+				}
65d033
+				if (rtcp_handle) {
65d033
+					rtcp_add_address(pinfo, &addr, port+1, 0, "RTPproxy", pinfo->fd->num);
65d033
+				}
65d033
+			}
1444df
+			break;
1444df
+		default:
1444df
+			break;
1444df
+	}
1444df
+	if (has_lf)
1444df
+		proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_lf, tvb, realsize, 1, ENC_NA);
173888
+
173888
+	return tvb_length(tvb);
1444df
+}
1444df
+
1444df
+void
1444df
+proto_register_rtpproxy(void)
1444df
+{
1444df
+	module_t *rtpproxy_module;
1444df
+
1444df
+	static hf_register_info hf[] = {
1444df
+		{
1444df
+			&hf_rtpproxy_cookie,
1444df
+			{
1444df
+				"Cookie",
1444df
+				"rtpproxy.cookie",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_version_request,
1444df
+			{
1444df
+				"Version Request",
1444df
+				"rtpproxy.version",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_version_supported,
1444df
+			{
1444df
+				"Version Supported",
1444df
+				"rtpproxy.version_supported",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_error,
1444df
+			{
1444df
+				"Error",
1444df
+				"rtpproxy.error",
173888
+				FT_STRING,
173888
+				BASE_NONE,
173888
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_ok,
1444df
+			{
1444df
+				"Ok",
1444df
+				"rtpproxy.ok",
1444df
+				FT_UINT8,
1444df
+				BASE_DEC,
1444df
+				VALS(oktypenames),
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_status,
1444df
+			{
1444df
+				"Status",
1444df
+				"rtpproxy.status",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_ipv4,
1444df
+			{
1444df
+				"IPv4",
1444df
+				"rtpproxy.ipv4",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_ipv6,
1444df
+			{
1444df
+				"IPv6",
1444df
+				"rtpproxy.ipv6",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_port,
1444df
+			{
1444df
+				"Port",
1444df
+				"rtpproxy.port",
ab5f7c
+				FT_UINT16, /* 0 - 65535 */
ab5f7c
+				BASE_DEC,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_request,
1444df
+			{
1444df
+				"Request",
1444df
+				"rtpproxy.request",
1444df
+				FT_NONE,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_command,
1444df
+			{
1444df
+				"Command",
1444df
+				"rtpproxy.command",
1444df
+				FT_UINT8,
1444df
+				BASE_DEC,
1444df
+				VALS(commandtypenames),
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_command_parameters,
1444df
+			{
1444df
+				"Command parameters",
1444df
+				"rtpproxy.command_parameters",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
65d033
+			&hf_rtpproxy_command_parameter,
65d033
+			{
65d033
+				"Parameter",
65d033
+				"rtpproxy.command_parameter",
65d033
+				FT_UINT8,
65d033
+				BASE_DEC,
65d033
+				VALS(paramtypenames),
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
65d033
+			&hf_rtpproxy_command_parameter_codec,
65d033
+			{
65d033
+				"Allowed codec",
65d033
+				"rtpproxy.command_parameter_codec",
ab5f7c
+				FT_UINT8, /* 0 - 127 */
ab5f7c
+				BASE_DEC,
65d033
+				NULL,
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
65d033
+			&hf_rtpproxy_command_parameter_local,
65d033
+			{
65d033
+				"Local IP address",
65d033
+				"rtpproxy.command_parameter_local",
65d033
+				FT_STRING,
65d033
+				BASE_NONE,
65d033
+				NULL,
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
65d033
+			&hf_rtpproxy_command_parameter_remote,
65d033
+			{
65d033
+				"Remote IP address",
65d033
+				"rtpproxy.command_parameter_remote",
65d033
+				FT_STRING,
65d033
+				BASE_NONE,
65d033
+				NULL,
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
65d033
+			&hf_rtpproxy_command_parameter_repacketize,
65d033
+			{
65d033
+				"Repacketize (ms)",
65d033
+				"rtpproxy.command_parameter_repacketize",
ab5f7c
+				FT_UINT16, /* 0 - 1000 milliseconds */
ab5f7c
+				BASE_DEC,
65d033
+				NULL,
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
65d033
+			&hf_rtpproxy_command_parameter_dtmf,
65d033
+			{
65d033
+				"DTMF payload ID",
65d033
+				"rtpproxy.command_parameter_dtmf",
ab5f7c
+				FT_UINT8, /* 0 - 127 */
ab5f7c
+				BASE_DEC,
65d033
+				NULL,
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
65d033
+			&hf_rtpproxy_command_parameter_proto,
65d033
+			{
65d033
+				"RTP tramsission protocol",
65d033
+				"rtpproxy.command_parameter_proto",
65d033
+				FT_UINT8,
65d033
+				BASE_DEC,
65d033
+				VALS(prototypenames),
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
65d033
+			&hf_rtpproxy_command_parameter_transcode,
65d033
+			{
65d033
+				"Transcode to",
65d033
+				"rtpproxy.command_parameter_transcode",
ab5f7c
+				FT_UINT8, /* 0 - 127 */
ab5f7c
+				BASE_DEC,
65d033
+				NULL,
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
65d033
+			&hf_rtpproxy_command_parameter_acc,
65d033
+			{
65d033
+				"Accounting",
65d033
+				"rtpproxy.command_parameter_acc",
65d033
+				FT_UINT8,
65d033
+				BASE_DEC,
65d033
+				VALS(acctypenames),
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
1444df
+			&hf_rtpproxy_copy_target,
1444df
+			{
1444df
+				"Copy target",
1444df
+				"rtpproxy.copy_target",
ab5f7c
+				FT_STRING, /* Filename or UDP address, e.g. /var/tmp/fileXXXX.yyy or IP:Port */
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_playback_filename,
1444df
+			{
1444df
+				"Playback filename",
1444df
+				"rtpproxy.playback_filename",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_playback_codec,
1444df
+			{
1444df
+				"Playback codec",
1444df
+				"rtpproxy.playback_codec",
ab5f7c
+				FT_UINT8, /* 0 - 127 */
ab5f7c
+				BASE_DEC,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_callid,
1444df
+			{
1444df
+				"Call-ID",
1444df
+				"rtpproxy.callid",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_notify,
1444df
+			{
1444df
+				"Notify",
1444df
+				"rtpproxy.notify",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_tag,
1444df
+			{
1444df
+				"Tag",
1444df
+				"rtpproxy.tag",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_mediaid,
1444df
+			{
1444df
+				"Media-ID",
1444df
+				"rtpproxy.mediaid",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_notify_ipv4,
1444df
+			{
1444df
+				"Notification IPv4",
1444df
+				"rtpproxy.notify_ipv4",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
65d033
+			&hf_rtpproxy_notify_ipv6,
65d033
+			{
65d033
+				"Notification IPv6",
65d033
+				"rtpproxy.notify_ipv6",
65d033
+				FT_STRING,
65d033
+				BASE_NONE,
65d033
+				NULL,
65d033
+				0x0,
65d033
+				NULL,
65d033
+				HFILL
65d033
+			}
65d033
+		},
65d033
+		{
1444df
+			&hf_rtpproxy_notify_port,
1444df
+			{
1444df
+				"Notification Port",
1444df
+				"rtpproxy.notify_port",
ab5f7c
+				FT_UINT16,
ab5f7c
+				BASE_DEC,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_notify_tag,
1444df
+			{
1444df
+				"Notification Tag",
1444df
+				"rtpproxy.notify_tag",
1444df
+				FT_STRING,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_reply,
1444df
+			{
1444df
+				"Reply",
1444df
+				"rtpproxy.reply",
1444df
+				FT_NONE,
1444df
+				BASE_NONE,
1444df
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
1444df
+		{
1444df
+			&hf_rtpproxy_lf,
1444df
+			{
1444df
+				"LF",
1444df
+				"rtpproxy.lf",
3a1a1b
+				FT_NONE,
3a1a1b
+				BASE_NONE,
3a1a1b
+				NULL,
1444df
+				0x0,
1444df
+				NULL,
1444df
+				HFILL
1444df
+			}
1444df
+		},
173888
+		{
173888
+			&hf_rtpproxy_request_in,
173888
+			{
173888
+				"Request In",
173888
+				"rtpproxy.request_in",
173888
+				FT_FRAMENUM,
173888
+				BASE_NONE,
173888
+				NULL,
173888
+				0x0,
173888
+				NULL,
173888
+				HFILL
173888
+			}
173888
+
173888
+		},
173888
+		{
173888
+			&hf_rtpproxy_response_in,
173888
+			{
173888
+				"Response In",
173888
+				"rtpproxy.response_in",
173888
+				FT_FRAMENUM,
173888
+				BASE_NONE,
173888
+				NULL,
173888
+				0x0,
173888
+				NULL,
173888
+				HFILL
173888
+			}
173888
+		},
173888
+		{
173888
+			&hf_rtpproxy_response_time,
173888
+			{
173888
+				"Response Time",
173888
+				"rtpproxy.response_time",
173888
+				FT_RELATIVE_TIME,
173888
+				BASE_NONE,
173888
+				NULL,
173888
+				0x0,
173888
+				"The time between the Request and the Reply",
173888
+				HFILL
173888
+			 }
173888
+		}
1444df
+	};
1444df
+
1444df
+	/* Setup protocol subtree array */
1444df
+	static gint *ett[] = {
1444df
+		&ett_rtpproxy,
1444df
+		&ett_rtpproxy_request,
1444df
+		&ett_rtpproxy_command,
65d033
+		&ett_rtpproxy_command_parameters,
65d033
+		&ett_rtpproxy_command_parameters_codecs,
65d033
+		&ett_rtpproxy_command_parameters_local,
65d033
+		&ett_rtpproxy_command_parameters_remote,
65d033
+		&ett_rtpproxy_command_parameters_repacketize,
65d033
+		&ett_rtpproxy_command_parameters_dtmf,
65d033
+		&ett_rtpproxy_command_parameters_cmap,
65d033
+		&ett_rtpproxy_command_parameters_proto,
65d033
+		&ett_rtpproxy_command_parameters_transcode,
65d033
+		&ett_rtpproxy_command_parameters_acc,
1444df
+		&ett_rtpproxy_tag,
1444df
+		&ett_rtpproxy_notify,
1444df
+		&ett_rtpproxy_reply
1444df
+	};
1444df
+
1444df
+	proto_rtpproxy = proto_register_protocol (
1444df
+			"Sippy RTPproxy Protocol", /* name       */
1444df
+			"RTPproxy",      /* short name */
1444df
+			"rtpproxy"       /* abbrev     */
1444df
+			);
1444df
+
1444df
+	proto_register_field_array(proto_rtpproxy, hf, array_length(hf));
1444df
+	proto_register_subtree_array(ett, array_length(ett));
1444df
+
1444df
+	rtpproxy_module = prefs_register_protocol(proto_rtpproxy, proto_reg_handoff_rtpproxy);
61af30
+
1444df
+	prefs_register_uint_preference(rtpproxy_module, "tcp.port",
1444df
+								 "RTPproxy TCP Port", /* Title */
1444df
+								 "RTPproxy TCP Port", /* Descr */
1444df
+								 10,
1444df
+								 &rtpproxy_tcp_port);
1444df
+
1444df
+	prefs_register_uint_preference(rtpproxy_module, "udp.port",
1444df
+								 "RTPproxy UDP Port", /* Title */
1444df
+								 "RTPproxy UDP Port", /* Descr */
1444df
+								 10,
1444df
+								 &rtpproxy_udp_port);
61af30
+
65d033
+	prefs_register_bool_preference(rtpproxy_module, "establish_conversation",
65d033
+                                 "Establish Media Conversation",
65d033
+                                 "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
65d033
+                                 "upon port numbers found in RTPproxy answers",
65d033
+                                 &rtpproxy_establish_conversation);
61af30
+
61af30
+	prefs_register_uint_preference(rtpproxy_module, "reply.timeout",
61af30
+								 "RTPproxy reply timeout", /* Title */
61af30
+								 "Maximum timeout value in waiting for reply from RTPProxy (in milliseconds).", /* Descr */
61af30
+								 10,
61af30
+								 &rtpproxy_timeout);
1444df
+}
1444df
+
1444df
+void
1444df
+proto_reg_handoff_rtpproxy(void)
1444df
+{
1444df
+	static guint old_rtpproxy_tcp_port = 0;
1444df
+	static guint old_rtpproxy_udp_port = 0;
1444df
+
1444df
+	static gboolean rtpproxy_initialized = FALSE;
1444df
+
1444df
+	static dissector_handle_t rtpproxy_tcp_handle, rtpproxy_udp_handle;
1444df
+
1444df
+	if(!rtpproxy_initialized){
173888
+		rtpproxy_tcp_handle = new_create_dissector_handle(dissect_rtpproxy, proto_rtpproxy);
173888
+		rtpproxy_udp_handle = new_create_dissector_handle(dissect_rtpproxy, proto_rtpproxy);
1444df
+		rtpproxy_initialized = TRUE;
1444df
+	}
1444df
+
1444df
+	/* Register TCP port for dissection */
1444df
+	if(old_rtpproxy_tcp_port != 0 && old_rtpproxy_tcp_port != rtpproxy_tcp_port)
1444df
+		dissector_delete_uint("tcp.port", old_rtpproxy_tcp_port, rtpproxy_tcp_handle);
1444df
+	if(rtpproxy_tcp_port != 0 && old_rtpproxy_tcp_port != rtpproxy_tcp_port)
1444df
+		dissector_add_uint("tcp.port", rtpproxy_tcp_port, rtpproxy_tcp_handle);
1444df
+	old_rtpproxy_tcp_port = rtpproxy_tcp_port;
1444df
+
1444df
+	/* Register UDP port for dissection */
1444df
+	if(old_rtpproxy_udp_port != 0 && old_rtpproxy_udp_port != rtpproxy_udp_port)
1444df
+		dissector_delete_uint("udp.port", old_rtpproxy_udp_port, rtpproxy_udp_handle);
1444df
+	if(rtpproxy_udp_port != 0 && old_rtpproxy_udp_port != rtpproxy_udp_port)
1444df
+		dissector_add_uint("udp.port", rtpproxy_udp_port, rtpproxy_udp_handle);
1444df
+	old_rtpproxy_udp_port = rtpproxy_udp_port;
65d033
+
65d033
+	rtcp_handle   = find_dissector("rtcp");
65d033
+	rtp_events_handle    = find_dissector("rtpevent");
65d033
+	rtp_handle    = find_dissector("rtp");
61af30
+
61af30
+	/* Calculate nstime_t struct for the timeout from the rtpproxy_timeout value in milliseconds */
61af30
+	rtpproxy_timeout_ns.secs = (rtpproxy_timeout - rtpproxy_timeout % 1000) / 1000;
61af30
+	rtpproxy_timeout_ns.nsecs = (rtpproxy_timeout % 1000) * 1000;
1444df
+}
1444df
+
1444df
+/*
1444df
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1444df
+ *
1444df
+ * Local variables:
1444df
+ * c-basic-offset: 8
1444df
+ * tab-width: 8
1444df
+ * indent-tabs-mode: t
1444df
+ * End:
1444df
+ *
1444df
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1444df
+ * :indentSize=8:tabSize=8:noTabs=false:
1444df
+ */