wireshark/wireshark-0006-From-Peter-Lemenkov-via-https-bugs.wireshark.org-bug.patch
Peter Lemenkov ab5f7ca144 A couple of bugfixes and enhancements
- Updated RTPproxy dissector (again)
- Fix rare issue with the Sniffer traces (patch no. 23)

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2014-01-13 16:38:45 +04:00

1640 lines
48 KiB
Diff

From: Evan Huus <eapache@gmail.com>
Date: Sun, 18 Aug 2013 19:49:08 +0000
Subject: [PATCH] Dissector for the Sippy RTPproxy controlling protocol
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8326
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
Add a cast to try and fix
packet-rtpproxy.c:226: warning: implicit conversion shortens 64-bit value into
a 32-bit value
I'm not quite sure what's going on here, all the values in use are either gint
or guint so they should all be the same size?
svn path=/trunk/; revision=51419
Take another stab at
packet-rtpproxy.c:226: warning: implicit conversion shortens 64-bit value into a
32-bit value
svn path=/trunk/; revision=51420
One more 64/32-conversion fix for rtpproxy
svn path=/trunk/; revision=51421
Fix Coverity CID 1063335: Unused pointer value.
svn path=/trunk/; revision=51430
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9211 :
Add basic conversation support for rtpproxy dissector
svn path=/trunk/; revision=52331
Let's please fix-encoding-args.pl
svn path=/trunk/; revision=52334
Make RTPProxy a newstyle dissector.
svn path=/trunk/; revision=52476
Try to fix
packet-rtpproxy.c:217: warning: comparison between signed and unsigned
svn path=/trunk/; revision=52477
Fix signed vs. unsigned comparison warnings.
svn path=/trunk/; revision=52483
Add response time to the rtpproxy dissector. Bug 9380 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9380)
From Peter Lemenkov.
svn path=/trunk/; revision=53115
Decode more error replies in RTPproxy dissector. Bug 9408 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9408)
From Peter Lemenkov
svn path=/trunk/; revision=53245
From Peter Lemenkov
display a text description for the RTPProxy version request
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9416
svn path=/trunk/; revision=53249
replace proto_tree_add_string_format_value() with proto_tree_add_item()
svn path=/trunk/; revision=53261
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9429 :
Fix Notify info parsing in RTPproxy dissector
svn path=/trunk/; revision=53385
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9430 :
Fix empty ToTag in RTPproxy's Offer/Update command
svn path=/trunk/; revision=53391
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9440 :
RTPproxy: use proto_item_append_text instead of rewriting the entire item's text
svn path=/trunk/; revision=53393
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9441 :
Fix Notify IPv6 address parsing in RTPproxy dissector
svn path=/trunk/; revision=53394
add a cast to fix compiler warning
svn path=/trunk/; revision=53401
Fix typo errors
svn path=/trunk/; revision=53585
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9397 :
Add RTP/RTCP dissector setup based on the replies found in rtpproxy dissector
svn path=/trunk/; revision=53603
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9444 :
Add initial parameter parser for commands in RTPproxy dissector
svn path=/trunk/; revision=53604
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9476 :
Add DTMF dissector setup based on the information found in RTPproxy requests
svn path=/trunk/; revision=53605
Squelch a compiler warning.
svn path=/trunk/; revision=53606
Reinitialize counter between loops to avoid an out of bound access found with fuzz testing.
svn path=/trunk/; revision=53612
RTPproxy dissector: Add expert info about timeouts. Bug 9484 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9484)
From Peter Lemenkov
svn path=/trunk/; revision=53622
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9487 :
Use RTP payload descriptions from RTP dissector in RTPproxy codec param value
svn path=/trunk/; revision=53658
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9490 :
Couple packets in RTPproxy dissector not only with CookieID but also with Call-IDs
svn path=/trunk/; revision=53673
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.)
svn path=/trunk/; revision=53705
Clean up indentation.
svn path=/trunk/; revision=53742
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9556
Cosmetic change in a LF field representation in the RTPproxy dissector
Don't display any value for LF field
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
svn path=/trunk/; revision=54045
From Peter Lemenkov via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9558
Mark generated fields as generated in RTPproxy dissector
This patch is cosmetic. It just marks generated fields as generated (to avoid confusion)
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
svn path=/trunk/; revision=54123
From Peter Lemenkov:
"This patch removes misleading dereferencing operator from the
array's name. E.g. consider the following declaration:
guint32 ipaddr[4];
ipaddr points to the address of an array of guint32's, while &ipaddr
points to the first' guint32 object. E.g. &ipaddr == &ipaddr[0]. The
value is the same, but has different type which is necessary
sometimes. However inet_pton treats latest argument as void*, and
this information is left anyway. So no need to bother with types and
let's just pass pointer to the array."
https://bugs.wireshark.org/bugzilla/attachment.cgi?id=12304
From me: Remove dereferencing operator from 'ipaddr' in two calls to
wmem_memdup().
svn path=/trunk/; revision=54156
Add numeric types instead of string where possible in the RTPproxy dissector. Bug 9561 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9561)
From Peter Lemenkov
svn path=/trunk/; revision=54467
diff --git a/AUTHORS b/AUTHORS
index 10782b0..e7b3c18 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3733,6 +3733,7 @@ Max Baker <max[AT]warped.org>
Mike Garratt <mg.wireshark[AT]evn.co.nz>
Bart Van Assche <bvanassche[AT]acm.org>
Karl Beldan <karl.beldan[AT]gmail.com>
+Peter Lemenkov <lemenkov[AT]gmail.com>
Masayuki Takemura <masayuki.takemura[AT]gmail.com>
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index 69eb75f..610cea7 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -1083,6 +1083,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
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 937f522..73217d7 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -1004,6 +1004,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
index 0000000..e8c5c95
--- /dev/null
+++ b/epan/dissectors/packet-rtpproxy.c
@@ -0,0 +1,1394 @@
+/* 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 <ctype.h>
+#include <glib.h>
+
+#include <epan/address.h>
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/conversation.h>
+#include <epan/expert.h>
+#include <epan/rtp_pt.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h> /* needed to define AF_ values on Windows */
+#endif
+#ifdef NEED_INET_V6DEFS_H
+#include "wsutil/inet_v6defs.h"
+#endif
+
+/* For setting up RTP/RTCP dissectors based on the RTPproxy's answers */
+#include "packet-rtp.h"
+#include "packet-rtcp.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_command_parameter = -1;
+static int hf_rtpproxy_command_parameter_codec = -1;
+static int hf_rtpproxy_command_parameter_local = -1;
+static int hf_rtpproxy_command_parameter_remote = -1;
+static int hf_rtpproxy_command_parameter_repacketize = -1;
+static int hf_rtpproxy_command_parameter_dtmf = -1;
+/* static int hf_rtpproxy_command_parameter_cmap = -1; TODO */
+static int hf_rtpproxy_command_parameter_proto = -1;
+static int hf_rtpproxy_command_parameter_transcode = -1;
+static int hf_rtpproxy_command_parameter_acc = -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_ipv6 = -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;
+
+/* Request/response tracking */
+static int hf_rtpproxy_request_in = -1;
+static int hf_rtpproxy_response_in = -1;
+static int hf_rtpproxy_response_time = -1;
+
+typedef struct _rtpproxy_info {
+ guint32 req_frame;
+ guint32 resp_frame;
+ nstime_t req_time;
+ gchar* callid;
+} rtpproxy_info_t;
+
+static dissector_handle_t rtcp_handle;
+static dissector_handle_t rtp_events_handle;
+static dissector_handle_t rtp_handle;
+
+typedef struct _rtpproxy_conv_info {
+ emem_tree_t *trans;
+} rtpproxy_conv_info_t;
+
+
+static const string_string versiontypenames[] = {
+ { "20040107", "Basic RTP proxy functionality" },
+ { "20050322", "Support for multiple RTP streams and MOH" },
+ { "20060704", "Support for extra parameter in the V command" },
+ { "20071116", "Support for RTP re-packetization" },
+ { "20071218", "Support for forking (copying) RTP stream" },
+ { "20080403", "Support for RTP statistics querying" },
+ { "20081102", "Support for setting codecs in the update/lookup command" },
+ { "20081224", "Support for session timeout notifications" },
+ { "20090810", "Support for automatic bridging" },
+ { 0, NULL }
+};
+
+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 paramtypenames[] = {
+ /* Official command parameters */
+ {'4', "Remote address is IPv4"},
+ {'6', "Remote address is IPv6"},
+ {'a', "Asymmetric RTP"},
+ {'A', "Asymmetric RTP"},
+ {'b', "Brief stats"},
+ {'B', "Brief stats"},
+ {'c', "Codecs"},
+ {'C', "Codecs"},
+ {'e', "External network (non RFC 1918)"},
+ {'E', "External network (non RFC 1918)"},
+ {'i', "Internal network (RFC 1918)"},
+ {'I', "Internal network (RFC 1918)"},
+ {'l', "Local address"},
+ {'L', "Local address"},
+ {'r', "Remote address"},
+ {'R', "Remote address"},
+ {'s', "Symmetric RTP (default)"},
+ {'S', "Symmetric RTP (default)"},
+ {'w', "Weak connection (allows roaming)"},
+ {'W', "Weak connection (allows roaming)"},
+ {'z', "repacketiZe"},
+ {'Z', "repacketiZe"},
+ /* Unofficial command parameters / expensions */
+ {'d', "DTMF payload ID (unofficial extension)"},
+ {'D', "DTMF payload ID (unofficial extension)"},
+ {'m', "codec Mapping (unofficial extension)"},
+ {'M', "codec Mapping (unofficial extension)"},
+ {'p', "Protocol type (unofficial extension)"},
+ {'P', "Protocol type (unofficial extension)"},
+ {'t', "Transcode to (unofficial extension)"},
+ {'T', "Transcode to (unofficial extension)"},
+ {'v', "Accounting (unofficial extension)"},
+ {'V', "Accounting (unofficial extension)"},
+ {0, NULL}
+};
+
+static const value_string prototypenames[] = {
+ { '0', "UDP (default)"},
+ { '1', "TCP"},
+ { '2', "SCTP"},
+ { 0, NULL }
+};
+static const value_string acctypenames[] = {
+ { '0', "Start"},
+ { '1', "Interim update"},
+ { '2', "Stop"},
+ { 0, NULL }
+};
+
+static const value_string oktypenames[] = {
+ { '0', "Ok"},
+ { '1', "Version Supported"},
+ { 0, NULL }
+};
+
+static const string_string errortypenames[] = {
+ { "E0", "Syntax error" },
+ { "E1", "Syntax error" },
+ { "E2", "Syntax error" },
+ { "E3", "Unknown command" },
+ { "E4", "Syntax error" },
+ { "E5", "Out of memory" },
+ { "E6", "<no description>" },
+ { "E7", "Software error (can't create listener)" },
+ { "E8", "Not Found" },
+ { "E10", "Software error (can't create listener)" },
+ { "E11", "Out of memory" },
+ { "E12", "Out of memory" },
+ { "E13", "Out of memory" },
+ { "E14", "Out of memory" },
+ { 0, NULL }
+};
+
+static gint ett_rtpproxy = -1;
+
+static gint ett_rtpproxy_request = -1;
+static gint ett_rtpproxy_command = -1;
+static gint ett_rtpproxy_command_parameters = -1;
+static gint ett_rtpproxy_command_parameters_codecs = -1;
+static gint ett_rtpproxy_command_parameters_local = -1;
+static gint ett_rtpproxy_command_parameters_remote = -1;
+static gint ett_rtpproxy_command_parameters_repacketize = -1;
+static gint ett_rtpproxy_command_parameters_dtmf = -1;
+static gint ett_rtpproxy_command_parameters_cmap = -1;
+static gint ett_rtpproxy_command_parameters_proto = -1;
+static gint ett_rtpproxy_command_parameters_transcode = -1;
+static gint ett_rtpproxy_command_parameters_acc = -1;
+static gint ett_rtpproxy_tag = -1;
+static gint ett_rtpproxy_notify = -1;
+
+static gint ett_rtpproxy_reply = -1;
+
+/* Default values */
+static guint rtpproxy_tcp_port = 22222;
+static guint rtpproxy_udp_port = 22222;
+static gboolean rtpproxy_establish_conversation = TRUE;
+/* See - http://www.opensips.org/html/docs/modules/1.11.x/rtpproxy.html#id250018 */
+/* See - http://www.kamailio.org/docs/modules/devel/modules/rtpproxy.html#idm448 */
+static guint rtpproxy_timeout = 1000;
+static nstime_t rtpproxy_timeout_ns = {1, 0};
+
+void proto_reg_handoff_rtpproxy(void);
+
+gint
+rtpproxy_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_append_text(ti, "<skipped>");
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ else{
+ ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, new_offset - begin, ENC_ASCII | ENC_NA);
+ if ((guint)new_offset == begin){
+ proto_item_append_text(ti, "<skipped>"); /* A very first Offer/Update command */
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ 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);
+}
+
+void
+rtpproxy_add_parameter(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint realsize)
+{
+ proto_item *ti;
+ proto_tree *another_tree = NULL;
+ guint offset = 0;
+ guint new_offset = 0;
+ gint i;
+ guint pt = 0;
+ gchar** codecs = NULL;
+ guint codec_len;
+ guint8* rawstr = NULL;
+
+ /* Extract the entire parameters line. */
+ /* Something like "t4p1iic8,0,2,4,18,96,97,98,100,101" */
+ rawstr = tvb_get_ephemeral_string(tvb, begin, realsize);
+
+ while(offset < realsize){
+ ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameter, tvb, begin + offset, 1, ENC_NA);
+ offset++; /* Skip 1-byte parameter's type */
+ switch (g_ascii_tolower(tvb_get_guint8(tvb, begin+offset-1)))
+ {
+ /* Official long parameters */
+ case 'c':
+ new_offset = (gint)strspn(rawstr+offset, "0123456789,");
+ another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_codecs);
+ codecs = g_strsplit(tvb_get_ephemeral_string(tvb, begin+offset, new_offset), ",", 0);
+ i = 0;
+ while(codecs[i]){
+ /* We assume strings < 2^32-1 bytes long. :-) */
+ codec_len = (guint)strlen(codecs[i]);
+ ti = proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_codec, tvb, begin+offset, codec_len,
+ (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin+offset, codec_len), NULL, 10));
+ 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"));
+ offset += codec_len;
+ if(codecs[i+1])
+ offset++; /* skip comma */
+ i++;
+ };
+ g_strfreev(codecs);
+ break;
+ case 'l':
+ new_offset = (gint)strspn(rawstr+offset, "0123456789.");
+ another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_local);
+ proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_local, tvb, begin+offset, new_offset, ENC_ASCII | ENC_NA);
+ offset += new_offset;
+ break;
+ case 'r':
+ new_offset = (gint)strspn(rawstr+offset, "0123456789.");
+ another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_remote);
+ proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_remote, tvb, begin+offset, new_offset, ENC_ASCII | ENC_NA);
+ offset += new_offset;
+ break;
+ case 'z':
+ new_offset = (gint)strspn(rawstr+offset, "0123456789");
+ another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_repacketize);
+ proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_repacketize, tvb, begin+offset, new_offset,
+ (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin+offset, new_offset), NULL, 10));
+ offset += new_offset;
+ break;
+ /* Unofficial long parameters */
+ case 'd':
+ new_offset = (gint)strspn(rawstr+offset, "0123456789");
+ another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_dtmf);
+ proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_dtmf, tvb, begin+offset, new_offset,
+ (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin+offset, new_offset), NULL, 10));
+ if(rtpproxy_establish_conversation){
+ pt = (guint)strtoul(tvb_format_text(tvb,begin+offset,new_offset),NULL,10);
+ dissector_add_uint("rtp.pt", pt, rtp_events_handle);
+ }
+ offset += new_offset;
+ break;
+ case 'm':
+ new_offset = (gint)strspn(rawstr+offset, "0123456789=,");
+ /* TODO */
+ offset += new_offset;
+ break;
+ case 'p':
+ another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_proto);
+ proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_proto, tvb, begin+offset, 1, ENC_NA);
+ offset++;
+ break;
+ case 't':
+ new_offset = (gint)strspn(rawstr+offset, "0123456789");
+ another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_transcode);
+ ti = proto_tree_add_uint(another_tree, hf_rtpproxy_command_parameter_transcode, tvb, begin+offset, new_offset,
+ (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin+offset, new_offset), NULL, 10));
+ 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"));
+ offset += new_offset;
+ break;
+ case 'v':
+ another_tree = proto_item_add_subtree(ti, ett_rtpproxy_command_parameters_acc);
+ proto_tree_add_item(another_tree, hf_rtpproxy_command_parameter_acc, tvb, begin+offset, 1, ENC_NA);
+ offset++;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+rtpproxy_info_t *
+rtpproxy_add_tid(gboolean is_request, tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtpproxy_tree, rtpproxy_conv_info_t *rtpproxy_conv, gchar* cookie)
+{
+ rtpproxy_info_t *rtpproxy_info;
+ proto_item *pi;
+
+ if (!PINFO_FD_VISITED(pinfo)) {
+ if (is_request){
+ rtpproxy_info = se_new(rtpproxy_info_t);
+ rtpproxy_info->req_frame = PINFO_FD_NUM(pinfo);
+ rtpproxy_info->resp_frame = 0;
+ rtpproxy_info->req_time = pinfo->fd->abs_ts;
+ rtpproxy_info->callid = NULL;
+ se_tree_insert_string(rtpproxy_conv->trans, cookie, rtpproxy_info, 0);
+ } else {
+ rtpproxy_info = (rtpproxy_info_t *)se_tree_lookup_string(rtpproxy_conv->trans, cookie, 0);
+ if (rtpproxy_info) {
+ rtpproxy_info->resp_frame = PINFO_FD_NUM(pinfo);
+ }
+ }
+ } else {
+ rtpproxy_info = (rtpproxy_info_t *)se_tree_lookup_string(rtpproxy_conv->trans, cookie, 0);
+ if (rtpproxy_info && (is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame)) {
+ nstime_t ns;
+
+ 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);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+ /* If reply then calculate response time */
+ if (!is_request){
+ nstime_delta(&ns, &pinfo->fd->abs_ts, &rtpproxy_info->req_time);
+ pi = proto_tree_add_time(rtpproxy_tree, hf_rtpproxy_response_time, tvb, 0, 0, &ns);
+ PROTO_ITEM_SET_GENERATED(pi);
+ if (nstime_cmp(&rtpproxy_timeout_ns, &ns) < 0)
+ expert_add_info_format(pinfo, rtpproxy_tree, PI_RESPONSE_CODE, PI_WARN, "Response timeout %.3f seconds", nstime_to_sec(&ns));
+ }
+ }
+ }
+ /* Could be NULL so we should check it before dereferencing */
+ return rtpproxy_info;
+}
+
+void
+rtpproxy_add_notify_addr(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint end)
+{
+ gint offset = 0;
+ gint tmp = 0;
+ gboolean ipv6 = FALSE;
+ proto_item *ti;
+
+ /* Check for at least one colon */
+ offset = tvb_find_guint8(tvb, begin, end, ':');
+ if(offset != -1){
+ /* Find if it's the latest colon (not in case of a IPv6) */
+ while((tmp = tvb_find_guint8(tvb, offset+1, end, ':')) != -1){
+ ipv6 = TRUE;
+ offset = tmp;
+ }
+ /* We have ip:port */
+ if(ipv6)
+ proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv6, tvb, begin, offset - begin, ENC_ASCII | ENC_NA);
+ else
+ proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, offset - begin, ENC_ASCII | ENC_NA);
+ proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, offset+1, end - (offset+1),
+ (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, offset+1, end - (offset+1)), NULL, 10));
+ }
+ else{
+ /* Only port is supplied */
+ ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, 0, ENC_ASCII | ENC_NA);
+ proto_item_append_text(ti, "<skipped>");
+ PROTO_ITEM_SET_GENERATED(ti);
+ proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, begin, end - begin,
+ (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, begin, end - begin), NULL, 10));
+ }
+}
+
+static int
+dissect_rtpproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gboolean has_lf = FALSE;
+ gint offset = 0;
+ gint new_offset = 0;
+ guint tmp;
+ gint realsize = 0;
+ guint8* rawstr;
+ guint8* tmpstr;
+ proto_item *ti;
+ proto_item *ti2;
+ proto_tree *rtpproxy_tree;
+ conversation_t *conversation;
+ rtpproxy_conv_info_t *rtpproxy_conv;
+ gchar* cookie = NULL;
+ /* For RT(C)P setup */
+ address addr;
+ guint16 port;
+ guint32 ipaddr[4];
+ rtpproxy_info_t *rtpproxy_info = NULL;
+
+ /* If it does not start with a printable character it's not RTPProxy */
+ if(!isprint(tvb_get_guint8(tvb, 0)))
+ return 0;
+
+ /* Extract Cookie */
+ offset = tvb_find_guint8(tvb, offset, -1, ' ');
+ if(offset == -1)
+ return 0;
+
+ /* 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);
+
+ proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_cookie, tvb, 0, offset, ENC_ASCII | ENC_NA);
+ cookie = tvb_get_ephemeral_string(tvb, 0, offset);
+
+ /* 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)");
+
+
+ /* Try to create conversation */
+ conversation = find_or_create_conversation(pinfo);
+ rtpproxy_conv = (rtpproxy_conv_info_t *)conversation_get_proto_data(conversation, proto_rtpproxy);
+ if (!rtpproxy_conv) {
+ rtpproxy_conv = se_new(rtpproxy_conv_info_t);
+ rtpproxy_conv->trans = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "rtpproxy transactions");;
+ conversation_add_proto_data(conversation, proto_rtpproxy, rtpproxy_conv);
+ }
+
+ /* 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% */
+ rtpproxy_add_tid(FALSE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie);
+ 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_ASCII | ENC_NA);
+ break;
+ }
+ case 'i':
+ case 'x':
+ case 'u':
+ case 'l':
+ case 'd':
+ case 'p':
+ case 'v':
+ case 'r':
+ case 'c':
+ case 'q':
+ rtpproxy_info = rtpproxy_add_tid(TRUE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie);
+ 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 + (gint)strlen("VF YYYMMDD") + 1 == realsize)){
+ /* Skip whitespace */
+ new_offset = tvb_skip_wsp(tvb, offset + ((guint)strlen("VF") + 1), -1);
+ ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_version_request, tvb, new_offset, (gint)strlen("YYYYMMDD"), ENC_ASCII | ENC_NA);
+ tmpstr = tvb_get_ephemeral_string(tvb, new_offset, (gint)strlen("YYYYMMDD"));
+ proto_item_append_text(ti, " (%s)", str_to_str(tmpstr, versiontypenames, "Unknown"));
+ 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' ? (realsize - 1 > offset ? offset + (gint)strlen("Ib") : offset + (gint)strlen("I")) : tvb_find_guint8(tvb, offset, -1, ' '));
+
+ if (new_offset != offset + 1){
+ rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_command);
+ ti2 = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_command_parameters, tvb, offset+1, new_offset - (offset+1), ENC_ASCII | ENC_NA);
+ rtpproxy_add_parameter(proto_item_add_subtree(ti2, ett_rtpproxy_command_parameters), tvb, offset+1, new_offset - (offset+1));
+ 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);
+ if(rtpproxy_info && !rtpproxy_info->callid)
+ rtpproxy_info->callid = tvb_get_seasonal_string(tvb, offset, new_offset - offset);
+ /* 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_uint(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset,
+ (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, offset, new_offset - offset), NULL, 10));
+ /* 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_uint(rtpproxy_tree, hf_rtpproxy_playback_codec, tvb, offset, new_offset - offset,
+ (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, offset, new_offset - offset), NULL, 10));
+ /* Skip whitespace */
+ offset = tvb_skip_wsp(tvb, new_offset+1, -1);
+ }
+
+ /* Extract first tag */
+ new_offset = rtpproxy_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 = rtpproxy_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'){
+ ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify, tvb, offset, realsize - offset, ENC_ASCII | ENC_NA);
+ proto_item_set_text(ti, "Notify");
+ rtpproxy_tree = proto_item_add_subtree(ti, ett_rtpproxy_notify);
+
+ /* Check for NotifyTag parameter (separated by space) */
+ new_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+ if(new_offset == -1){
+ /* NotifyTag wasn't found (we should re-use Call-ID instead) */
+ rtpproxy_add_notify_addr(rtpproxy_tree, tvb, offset, realsize);
+ break; /* No more parameters */
+ }
+
+ /* NotifyTag was found */
+ rtpproxy_add_notify_addr(rtpproxy_tree, tvb, offset, new_offset);
+ /* 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':
+ rtpproxy_info = rtpproxy_add_tid(FALSE, tvb, pinfo, rtpproxy_tree, rtpproxy_conv, cookie);
+ 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(rtpproxy_info && rtpproxy_info->callid){
+ ti = proto_tree_add_string(rtpproxy_tree, hf_rtpproxy_callid, tvb, offset, 0, rtpproxy_info->callid);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+
+ if (tmp == 'e'){
+ tmp = tvb_find_line_end(tvb, offset, -1, &new_offset, FALSE);
+ tmpstr = tvb_get_ephemeral_string(tvb, offset, tmp);
+ ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_error, tvb, offset, (gint)strlen(tmpstr), ENC_ASCII | ENC_NA);
+ proto_item_append_text(ti, " (%s)", str_to_str(tmpstr, errortypenames, "Unknown"));
+ 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_ASCII | ENC_NA);
+ break;
+ }
+ if ((tmp == '0')&& ((tvb_reported_length(tvb) == (guint)(offset+1))||(tvb_reported_length(tvb) == (guint)(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) == (guint)(offset+1))||(tvb_reported_length(tvb) == (guint)(offset+2)))){
+ proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ok, tvb, offset, 1, ENC_ASCII | ENC_NA);
+ break;
+ }
+ if (tvb_reported_length(tvb) == (guint)(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, ' ');
+ /* Convert port to unsigned 16-bit number */
+ port = (guint16) g_ascii_strtoull((gchar*)tvb_get_ephemeral_string(tvb, offset, new_offset - offset), NULL, 10);
+ proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_port, tvb, offset, new_offset - offset, port);
+ /* 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){
+ inet_pton(AF_INET, (char*)tvb_get_ephemeral_string(tvb, offset, tmp), ipaddr);
+ addr.type = AT_IPv4;
+ addr.len = 4;
+ addr.data = ep_memdup(ipaddr, 4);
+ proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv4, tvb, offset, tmp, ENC_ASCII | ENC_NA);
+ }
+ else{
+ inet_pton(AF_INET6, (char*)tvb_get_ephemeral_string(tvb, offset, tmp), ipaddr);
+ addr.type = AT_IPv6;
+ addr.len = 16;
+ addr.data = ep_memdup(ipaddr, 16);
+ proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_ipv6, tvb, offset, tmp, ENC_ASCII | ENC_NA);
+ }
+
+ if(rtpproxy_establish_conversation){
+ if (rtp_handle) {
+ /* FIXME tell if isn't a video stream, and setup codec mapping */
+ rtp_add_address(pinfo, &addr, port, 0, "RTPproxy", pinfo->fd->num, 0, NULL);
+ }
+ if (rtcp_handle) {
+ rtcp_add_address(pinfo, &addr, port+1, 0, "RTPproxy", pinfo->fd->num);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (has_lf)
+ proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_lf, tvb, realsize, 1, ENC_NA);
+
+ return tvb_length(tvb);
+}
+
+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_STRING,
+ BASE_NONE,
+ NULL,
+ 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_UINT16, /* 0 - 65535 */
+ BASE_DEC,
+ 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_command_parameter,
+ {
+ "Parameter",
+ "rtpproxy.command_parameter",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(paramtypenames),
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_command_parameter_codec,
+ {
+ "Allowed codec",
+ "rtpproxy.command_parameter_codec",
+ FT_UINT8, /* 0 - 127 */
+ BASE_DEC,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_command_parameter_local,
+ {
+ "Local IP address",
+ "rtpproxy.command_parameter_local",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_command_parameter_remote,
+ {
+ "Remote IP address",
+ "rtpproxy.command_parameter_remote",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_command_parameter_repacketize,
+ {
+ "Repacketize (ms)",
+ "rtpproxy.command_parameter_repacketize",
+ FT_UINT16, /* 0 - 1000 milliseconds */
+ BASE_DEC,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_command_parameter_dtmf,
+ {
+ "DTMF payload ID",
+ "rtpproxy.command_parameter_dtmf",
+ FT_UINT8, /* 0 - 127 */
+ BASE_DEC,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_command_parameter_proto,
+ {
+ "RTP tramsission protocol",
+ "rtpproxy.command_parameter_proto",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(prototypenames),
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_command_parameter_transcode,
+ {
+ "Transcode to",
+ "rtpproxy.command_parameter_transcode",
+ FT_UINT8, /* 0 - 127 */
+ BASE_DEC,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_command_parameter_acc,
+ {
+ "Accounting",
+ "rtpproxy.command_parameter_acc",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(acctypenames),
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_copy_target,
+ {
+ "Copy target",
+ "rtpproxy.copy_target",
+ FT_STRING, /* Filename or UDP address, e.g. /var/tmp/fileXXXX.yyy or IP:Port */
+ 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_UINT8, /* 0 - 127 */
+ BASE_DEC,
+ 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_ipv6,
+ {
+ "Notification IPv6",
+ "rtpproxy.notify_ipv6",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_notify_port,
+ {
+ "Notification Port",
+ "rtpproxy.notify_port",
+ FT_UINT16,
+ BASE_DEC,
+ 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_NONE,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_request_in,
+ {
+ "Request In",
+ "rtpproxy.request_in",
+ FT_FRAMENUM,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+
+ },
+ {
+ &hf_rtpproxy_response_in,
+ {
+ "Response In",
+ "rtpproxy.response_in",
+ FT_FRAMENUM,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ NULL,
+ HFILL
+ }
+ },
+ {
+ &hf_rtpproxy_response_time,
+ {
+ "Response Time",
+ "rtpproxy.response_time",
+ FT_RELATIVE_TIME,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "The time between the Request and the Reply",
+ HFILL
+ }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_rtpproxy,
+ &ett_rtpproxy_request,
+ &ett_rtpproxy_command,
+ &ett_rtpproxy_command_parameters,
+ &ett_rtpproxy_command_parameters_codecs,
+ &ett_rtpproxy_command_parameters_local,
+ &ett_rtpproxy_command_parameters_remote,
+ &ett_rtpproxy_command_parameters_repacketize,
+ &ett_rtpproxy_command_parameters_dtmf,
+ &ett_rtpproxy_command_parameters_cmap,
+ &ett_rtpproxy_command_parameters_proto,
+ &ett_rtpproxy_command_parameters_transcode,
+ &ett_rtpproxy_command_parameters_acc,
+ &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);
+
+ prefs_register_bool_preference(rtpproxy_module, "establish_conversation",
+ "Establish Media Conversation",
+ "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
+ "upon port numbers found in RTPproxy answers",
+ &rtpproxy_establish_conversation);
+
+ prefs_register_uint_preference(rtpproxy_module, "reply.timeout",
+ "RTPproxy reply timeout", /* Title */
+ "Maximum timeout value in waiting for reply from RTPProxy (in milliseconds).", /* Descr */
+ 10,
+ &rtpproxy_timeout);
+}
+
+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 = new_create_dissector_handle(dissect_rtpproxy, proto_rtpproxy);
+ rtpproxy_udp_handle = new_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;
+
+ rtcp_handle = find_dissector("rtcp");
+ rtp_events_handle = find_dissector("rtpevent");
+ rtp_handle = find_dissector("rtp");
+
+ /* Calculate nstime_t struct for the timeout from the rtpproxy_timeout value in milliseconds */
+ rtpproxy_timeout_ns.secs = (rtpproxy_timeout - rtpproxy_timeout % 1000) / 1000;
+ rtpproxy_timeout_ns.nsecs = (rtpproxy_timeout % 1000) * 1000;
+}
+
+/*
+ * 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:
+ */