aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2000-10-19 06:45:11 +0000
committerGuy Harris <guy@alum.mit.edu>2000-10-19 06:45:11 +0000
commit3f8b7cd0fc93040f23b1d1b0e061dc1097321f4e (patch)
treeb9eea74fb6b18aeb12b57161706786110421caa1
parent9de17c39f5e6828c6631af911d114f935b0feb4d (diff)
Andreas Sikkema's new H.261 and TPKT dissectors, replacement RTCP and
RTP dissectors, and changes to the Q.931 dissector for use with H.323. svn path=/trunk/; revision=2511
-rw-r--r--AUTHORS11
-rw-r--r--Makefile.am6
-rw-r--r--Makefile.nmake4
-rw-r--r--packet-h261.c262
-rw-r--r--packet-h261.h30
-rw-r--r--packet-q931.c369
-rw-r--r--packet-rtcp.c1427
-rw-r--r--packet-rtcp.h19
-rw-r--r--packet-rtp.c708
-rw-r--r--packet-rtp.h19
-rw-r--r--packet-rtsp.c6
-rw-r--r--packet-tpkt.c187
-rw-r--r--packet-tpkt.h30
13 files changed, 2490 insertions, 588 deletions
diff --git a/AUTHORS b/AUTHORS
index 9c5a06465b..d74cb0f777 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -124,7 +124,7 @@ Aaron Hillegass <aaron@classmax.com> {
}
Jason Lango <jal@netapp.com> {
- RTSP, SDP, RTCP, RTP
+ RTSP, SDP
}
Johan Feyaerts <Johan.Feyaerts@siemens.atea.be> {
@@ -203,7 +203,7 @@ Heikki Vatiainen <hessu@cs.tut.fi> {
VRRP (Virtual Router Redundancy)
HSRP (Hot Standby Router Protocol)
option to control whether to interpret the IPv4 TOS field as
- such or as the DiffServ field
+ such or as the DiffServ field
COPS
}
@@ -295,6 +295,7 @@ Doug Nazar <nazard@dragoninc.on.ca> {
Andreas Sikkema <andreas.sikkema@philips.com> {
Fixes to SMB dissector
Fixes to capture file handling on Win32
+ RTCP, RTP, TPKT (RFC 1006), H.261
}
Mark Muhlestein <mmm@netapp.com> {
@@ -307,10 +308,10 @@ Graham Bloice <graham.bloice@trihedral.com> {
Support for sorting columns in the summary by clicking on them
Win32 Makefile improvements
Support for "Update list of packets in real time" during capture
- on Win32
+ on Win32
Support for inverse video rather than boldface highlighting of
- the bytes, in the hex dump window, corresponding to a selected
- field
+ the bytes, in the hex dump window, corresponding to a selected
+ field
}
Ralf Schneider <ralf.schneider@alcatel.se> {
diff --git a/Makefile.am b/Makefile.am
index 871f2dbef7..b7a3afe7de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal
#
-# $Id: Makefile.am,v 1.235 2000/10/14 05:11:11 gram Exp $
+# $Id: Makefile.am,v 1.236 2000/10/19 06:45:10 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@zing.org>
@@ -63,6 +63,7 @@ DISSECTOR_SOURCES = \
packet-giop.c \
packet-gre.c \
packet-h1.c \
+ packet-h261.c \
packet-hsrp.c \
packet-http.c \
packet-icmpv6.c\
@@ -151,6 +152,7 @@ DISSECTOR_SOURCES = \
packet-tftp.c \
packet-time.c \
packet-tns.c \
+ packet-tpkt.c \
packet-tr.c \
packet-trmac.c \
packet-udp.c \
@@ -190,6 +192,7 @@ noinst_HEADERS = \
packet-eth.h \
packet-fddi.h \
packet-frame.h \
+ packet-h261.h \
packet-http.h \
packet-ip.h \
packet-ipp.h \
@@ -239,6 +242,7 @@ noinst_HEADERS = \
packet-tcp.h \
packet-tftp.h \
packet-tns.h \
+ packet-tpkt.h \
packet-tr.h \
packet-trmac.h \
packet-udp.h \
diff --git a/Makefile.nmake b/Makefile.nmake
index a8dbda8b54..5824652d74 100644
--- a/Makefile.nmake
+++ b/Makefile.nmake
@@ -1,7 +1,7 @@
## Makefile for building ethereal.exe with Microsoft C and nmake
## Use: nmake -f makefile.nmake
#
-# $Id: Makefile.nmake,v 1.58 2000/10/14 04:31:24 gram Exp $
+# $Id: Makefile.nmake,v 1.59 2000/10/19 06:45:10 guy Exp $
include config.nmake
@@ -51,6 +51,7 @@ DISSECTOR_SOURCES = \
packet-giop.c \
packet-gre.c \
packet-h1.c \
+ packet-h261.c \
packet-hsrp.c \
packet-http.c \
packet-icmpv6.c\
@@ -139,6 +140,7 @@ DISSECTOR_SOURCES = \
packet-tftp.c \
packet-time.c \
packet-tns.c \
+ packet-tpkt.c \
packet-tr.c \
packet-trmac.c \
packet-udp.c \
diff --git a/packet-h261.c b/packet-h261.c
new file mode 100644
index 0000000000..8bcbde1291
--- /dev/null
+++ b/packet-h261.c
@@ -0,0 +1,262 @@
+/* packet-h261.c
+ *
+ * Routines for ITU-T Recommendation H.261 dissection
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Andreas Sikkema <andreas.sikkema@philips.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the H261 protocol according to Annex C
+ * of ITU-T Recommendation H.225.0 (02/98)
+ *
+ * This dissector is called by the RTP dissector
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include "packet.h"
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-h261.h"
+
+/* H261 header fields */
+static int proto_h261 = -1;
+static int hf_h261_sbit = -1;
+static int hf_h261_ebit = -1;
+static int hf_h261_ibit = -1;
+static int hf_h261_vbit = -1;
+static int hf_h261_gobn = -1;
+static int hf_h261_mbap = -1;
+static int hf_h261_quant = -1;
+static int hf_h261_hmvd = -1; /* Mislabeled in a figure in section C.3.1 as HMDV */
+static int hf_h261_vmvd = -1;
+static int hf_h261_data = -1;
+
+/* H261 fields defining a sub tree */
+static gint ett_h261 = -1;
+
+void
+dissect_h261( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *h261_tree = NULL;
+ unsigned int offset = 0;
+
+ if ( check_col( pinfo->fd, COL_PROTOCOL ) ) {
+ col_add_str( pinfo->fd, COL_PROTOCOL, "H261" );
+ }
+
+ if ( check_col( pinfo->fd, COL_INFO) ) {
+ col_add_str( pinfo->fd, COL_INFO, "H.261 message");
+ }
+
+ if ( tree ) {
+ /* Using fd->pkt_len here instead of END_OF_FRAME. This variable is changed in dissect_rtp()! */
+ ti = proto_tree_add_item( tree, proto_h261, tvb, offset, tvb_length( tvb ), FALSE );
+ h261_tree = proto_item_add_subtree( ti, ett_h261 );
+ /* SBIT 1st octet, 3 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_sbit, tvb, offset, 1, tvb_get_guint8( tvb, offset ) >> 5 );
+ /* EBIT 1st octet, 3 bits */
+ proto_tree_add_item( h261_tree, hf_h261_ebit, tvb, offset, 1, ( tvb_get_guint8( tvb, offset ) << 3 ) >> 5 );
+ /* I flag, 1 bit */
+ proto_tree_add_boolean( h261_tree, hf_h261_ibit, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 2 );
+ /* V flag, 1 bit */
+ proto_tree_add_boolean( h261_tree, hf_h261_vbit, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 1 );
+ offset++;
+
+ /* GOBN 2nd octet, 4 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_gobn, tvb, offset, 1, tvb_get_guint8( tvb, offset ) >> 4 );
+ /* MBAP 2nd octet, 4 bits, 3rd octet 1 bit */
+ proto_tree_add_uint( h261_tree, hf_h261_mbap, tvb, offset, 1,
+ ( tvb_get_guint8( tvb, offset ) & 15 )
+ + ( tvb_get_guint8( tvb, offset + 1 ) >> 7 ) );
+ offset++;
+
+ /* QUANT 3rd octet, 5 bits (starting at bit 2!) */
+ proto_tree_add_uint( h261_tree, hf_h261_mbap, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 124 );
+ /* HMDV 3rd octet 2 bits, 4th octet 3 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_mbap, tvb, offset, 1,
+ ( ( tvb_get_guint8( tvb, offset ) << 4) >> 4 )
+ + ( tvb_get_guint8( tvb, offset ) >> 5 ) );
+ offset++;
+
+ /* VMVD 4th octet, last 5 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_mbap, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 31 );
+ offset++;
+
+ /* The rest of the packet is the H.261 stream */
+ proto_tree_add_bytes( h261_tree, hf_h261_data, tvb, offset, tvb_length_remaining( tvb, offset ), tvb_get_ptr( tvb, offset, tvb_length_remaining( tvb, offset ) ) );
+ }
+}
+
+void
+proto_register_h261(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_h261_sbit,
+ {
+ "Start bit position",
+ "h261.sbit",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_ebit,
+ {
+ "End bit position",
+ "h261.ebit",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_ibit,
+ {
+ "Intra frame encoded data flag",
+ "h261.i",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_vbit,
+ {
+ "Motion vector flag",
+ "h261.v",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_gobn,
+ {
+ "GOB Number",
+ "h261.gobn",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_mbap,
+ {
+ "Macroblock address predictor",
+ "h261.mbap",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_quant,
+ {
+ "Quantizer",
+ "h261.quant",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_hmvd,
+ {
+ "Horizontal motion vctor data",
+ "h261.hmvd",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_vmvd,
+ {
+ "Vertical motion vector data",
+ "h261.vmvd",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_h261_data,
+ {
+ "H.261 stream",
+ "h261.stream",
+ FT_BYTES,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+};
+
+ static gint *ett[] =
+ {
+ &ett_h261,
+ };
+
+
+ proto_h261 = proto_register_protocol("ITU-T Recommendation H.261", "h261");
+ proto_register_field_array(proto_h261, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/packet-h261.h b/packet-h261.h
new file mode 100644
index 0000000000..ad29d8ee32
--- /dev/null
+++ b/packet-h261.h
@@ -0,0 +1,30 @@
+/* packet-h261.h
+ *
+ * Routines for ITU-T Recommendation H.261 dissection
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Andreas Sikkema <andreas.sikkema@philips.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+void dissect_h261( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree );
+void proto_register_h261( void );
diff --git a/packet-q931.c b/packet-q931.c
index 1317b85d03..76bf16d54e 100644
--- a/packet-q931.c
+++ b/packet-q931.c
@@ -2,7 +2,9 @@
* Routines for Q.931 frame disassembly
* Guy Harris <guy@alum.mit.edu>
*
- * $Id: packet-q931.c,v 1.17 2000/08/13 14:08:38 deniel Exp $
+ * $Id: packet-q931.c,v 1.18 2000/10/19 06:45:10 guy Exp $
+ *
+ * Modified by Andreas Sikkema for possible use with H.323
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -39,6 +41,11 @@
#include "nlpid.h"
#include "packet-q931.h"
+#ifdef H323
+#include "packet-tpkt.h"
+#include "packet-h225.h"
+#endif
+
/* Q.931 references:
*
* http://www.acacia-net.com/Clarinet/Protocol/q9313svn.htm
@@ -63,6 +70,7 @@ static gint ett_q931_ie = -1;
/*
* Q.931 message types.
*/
+#define Q931_ESCAPE 0x00
#define Q931_ALERTING 0x01
#define Q931_CALL_PROCEEDING 0x02
#define Q931_CONNECT 0x07
@@ -98,6 +106,7 @@ static gint ett_q931_ie = -1;
#define Q931_STATUS_ENQUIRY 0x75
static const value_string q931_message_type_vals[] = {
+ { Q931_ESCAPE, "ESCAPE" },
{ Q931_ALERTING, "ALERTING" },
{ Q931_CALL_PROCEEDING, "CALL PROCEEDING" },
{ Q931_CONNECT, "CONNECT" },
@@ -506,6 +515,46 @@ static const value_string q931_uil3_vals[] = {
{ 0, NULL }
};
+/*
+ * XXX - should this (or, rather, a routine to return a string containing
+ * the stuff we put after "Protocol discriminator:") be in "packet-osi.c"?
+ *
+ * I.e., is the convention that 16-63 and 80-254 are for network-layer
+ * or layer-3 protocols, and 64-79 are for national use, specific to
+ * Q.931 (and maybe Q.2931), or is it a more general ISO standard?
+ */
+static void
+dissect_q931_protocol_discriminator(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ unsigned int discriminator = tvb_get_guint8(tvb, offset);
+ char *nlpid_string;
+
+ nlpid_string = match_strval(discriminator, nlpid_vals);
+ if (nlpid_string != NULL) {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: %s", nlpid_string);
+ } else {
+ if ((discriminator >= 16 && discriminator < 63)
+ || ((discriminator >= 80) && (discriminator < 254))) {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Network layer or layer 3 protocol (0x%02X)",
+ discriminator);
+ } else if (discriminator >= 64 && discriminator <= 79) {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: National use (0x%02X)",
+ discriminator);
+ } else {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Reserved (0x%02X)",
+ discriminator);
+ }
+ }
+}
+
void
dissect_q931_bearer_capability_ie(tvbuff_t *tvb, int offset, int len,
proto_tree *tree)
@@ -699,7 +748,7 @@ dissect_q931_bearer_capability_ie(tvbuff_t *tvb, int offset, int len,
proto_tree_add_text(tree, tvb, offset, 1,
"Modem type: %s",
val_to_str(modem_type, q931_l1_modem_type_vals,
- NULL));
+ "Unknown (0x%02X)"));
}
offset += 1;
len -= 1;
@@ -1004,7 +1053,7 @@ dissect_q931_cause_ie(tvbuff_t *tvb, int offset, int len,
proto_tree_add_text(tree, tvb, offset, 1,
"Recommendation: %s",
val_to_str(octet & 0x7F, q931_cause_recommendation_vals,
- "Unknown (0x%X)"));
+ "Unknown (0x%02X)"));
offset += 1;
len -= 1;
}
@@ -1015,7 +1064,7 @@ dissect_q931_cause_ie(tvbuff_t *tvb, int offset, int len,
proto_tree_add_text(tree, tvb, offset, 1,
"Cause value: %s",
val_to_str(octet & 0x7F, q931_cause_code_vals,
- "Unknown (0x%X)"));
+ "Unknown (0x%02X)"));
offset += 1;
len -= 1;
@@ -1148,7 +1197,7 @@ dissect_q931_channel_identification_ie(tvbuff_t *tvb, int offset, int len,
proto_tree_add_text(tree, tvb, offset, 1,
"Channel selection: %s",
val_to_str(octet & 0x03, q931_not_basic_channel_selection_vals,
- NULL));
+ "Unknown (0x%X)"));
} else {
proto_tree_add_text(tree, tvb, offset, 1,
"Channel selection: %s",
@@ -1210,7 +1259,7 @@ dissect_q931_channel_identification_ie(tvbuff_t *tvb, int offset, int len,
"%s type: %s",
(octet & Q931_IS_SLOT_MAP) ? "Map element" : "Channel",
val_to_str(octet & 0x0F, q931_element_type_vals,
- "Unknown (0x%02X)"));
+ "Unknown (0x%02X)"));
/*
* XXX - dump the channel number or slot map.
@@ -1327,9 +1376,8 @@ dissect_q931_ns_facilities_ie(tvbuff_t *tvb, int offset, int len,
netid_len = len;
if (netid_len != 0) {
proto_tree_add_text(tree, tvb, offset, netid_len,
- "Network identification: %.*s",
- netid_len,
- tvb_get_ptr(tvb, offset, netid_len));
+ "Network identification: %s",
+ tvb_format_text(tvb, offset, netid_len));
offset += netid_len;
len -= netid_len;
}
@@ -1431,7 +1479,8 @@ dissect_q931_signal_ie(tvbuff_t *tvb, int offset, int len,
}
proto_tree_add_text(tree, tvb, offset, 1,
"Signal: %s",
- val_to_str(tvb_get_guint8(tvb, offset), q931_signal_vals, "Unknown (0x%02X)"));
+ val_to_str(tvb_get_guint8(tvb, offset), q931_signal_vals,
+ "Unknown (0x%02X)"));
}
/*
@@ -1463,20 +1512,20 @@ dissect_q931_information_rate_ie(tvbuff_t *tvb, int offset, int len,
}
proto_tree_add_text(tree, tvb, offset + 0, 1,
"Incoming information rate: %s",
- val_to_str(tvb_get_guint8(tvb, offset + 0) & 0x1F, q931_throughput_class_vals,
- "Unknown (0x%02X)"));
+ val_to_str(tvb_get_guint8(tvb, offset + 0) & 0x1F,
+ q931_throughput_class_vals, "Unknown (0x%02X)"));
proto_tree_add_text(tree, tvb, offset + 1, 1,
"Outgoing information rate: %s",
- val_to_str(tvb_get_guint8(tvb, offset + 1) & 0x1F, q931_throughput_class_vals,
- "Unknown (0x%02X)"));
+ val_to_str(tvb_get_guint8(tvb, offset + 1) & 0x1F,
+ q931_throughput_class_vals, "Unknown (0x%02X)"));
proto_tree_add_text(tree, tvb, offset + 2, 1,
"Minimum incoming information rate: %s",
- val_to_str(tvb_get_guint8(tvb, offset + 2) & 0x1F, q931_throughput_class_vals,
- "Unknown (0x%02X)"));
+ val_to_str(tvb_get_guint8(tvb, offset + 2) & 0x1F,
+ q931_throughput_class_vals, "Unknown (0x%02X)"));
proto_tree_add_text(tree, tvb, offset + 3, 1,
"Minimum outgoing information rate: %s",
- val_to_str(tvb_get_guint8(tvb, offset + 3) & 0x1F, q931_throughput_class_vals,
- "Unknown (0x%02X)"));
+ val_to_str(tvb_get_guint8(tvb, offset + 3) & 0x1F,
+ q931_throughput_class_vals, "Unknown (0x%02X)"));
}
static int
@@ -1620,8 +1669,7 @@ dissect_q931_pl_binary_parameters_ie(tvbuff_t *tvb, int offset, int len,
octet = tvb_get_guint8(tvb, offset);
proto_tree_add_text(tree, tvb, offset, 1,
"Fast select: %s",
- val_to_str(octet & 0x18, q931_fast_selected_vals,
- NULL));
+ val_to_str(octet & 0x18, q931_fast_selected_vals, NULL));
proto_tree_add_text(tree, tvb, offset, 1,
"%s",
(octet & 0x04) ? "No request/request denied" :
@@ -1690,15 +1738,15 @@ dissect_q931_cug_ie(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
return;
proto_tree_add_text(tree, tvb, offset, 1,
"CUG indication: %s",
- val_to_str(tvb_get_guint8(tvb, offset) & 0x07, q931_cug_indication_vals,
- "Unknown (0x%02X)"));
+ val_to_str(tvb_get_guint8(tvb, offset) & 0x07,
+ q931_cug_indication_vals, "Unknown (0x%02X)"));
offset += 1;
len -= 1;
if (len == 0)
return;
- proto_tree_add_text(tree, tvb, offset, len, "CUG index code: %.*s", len,
- tvb_get_ptr(tvb, offset, len));
+ proto_tree_add_text(tree, tvb, offset, len, "CUG index code: %s",
+ tvb_format_text(tvb, offset, len));
}
/*
@@ -1717,8 +1765,8 @@ dissect_q931_reverse_charge_ind_ie(tvbuff_t *tvb, int offset, int len,
return;
proto_tree_add_text(tree, tvb, offset, 1,
"Reverse charging indication: %s",
- val_to_str(tvb_get_guint8(tvb, offset) & 0x07, q931_reverse_charging_indication_vals,
- "Unknown (0x%02X)"));
+ val_to_str(tvb_get_guint8(tvb, offset) & 0x07,
+ q931_reverse_charging_indication_vals, "Unknown (0x%02X)"));
}
/*
@@ -1823,8 +1871,8 @@ dissect_q931_number_ie(tvbuff_t *tvb, int offset, int len,
if (len == 0)
return;
- proto_tree_add_text(tree, tvb, offset, len, "Number: %.*s",
- len, tvb_get_ptr(tvb, offset, len));
+ proto_tree_add_text(tree, tvb, offset, len, "Number: %s",
+ tvb_format_text(tvb, offset, len));
}
/*
@@ -1889,8 +1937,8 @@ dissect_q931_restart_indicator_ie(tvbuff_t *tvb, int offset, int len,
}
proto_tree_add_text(tree, tvb, offset, 1,
"Restart indicator: %s",
- val_to_str(tvb_get_guint8(tvb, offset) & 0x07, q931_restart_indicator_class_vals,
- "Unknown (0x%02X)"));
+ val_to_str(tvb_get_guint8(tvb, offset) & 0x07,
+ q931_restart_indicator_class_vals, "Unknown (0x%02X)"));
}
/*
@@ -1958,7 +2006,7 @@ dissect_q931_high_layer_compat_ie(tvbuff_t *tvb, int offset, int len,
proto_tree_add_text(tree, tvb, offset, 1,
"High layer characteristics identification: %s",
val_to_str(characteristics, q931_high_layer_characteristics_vals,
- NULL));
+ "Unknown (0x%02X)"));
offset += 1;
len -= 1;
@@ -1969,13 +2017,15 @@ dissect_q931_high_layer_compat_ie(tvbuff_t *tvb, int offset, int len,
if (characteristics == Q931_AUDIOVISUAL) {
proto_tree_add_text(tree, tvb, offset, 1,
"Extended audiovisual characteristics identification: %s",
- val_to_str(octet & 0x7F, q931_audiovisual_characteristics_vals,
- NULL));
+ val_to_str(octet & 0x7F,
+ q931_audiovisual_characteristics_vals,
+ "Unknown (0x%02X)"));
} else {
proto_tree_add_text(tree, tvb, offset, 1,
"Extended high layer characteristics identification: %s",
- val_to_str(octet & 0x7F, q931_high_layer_characteristics_vals,
- NULL));
+ val_to_str(octet & 0x7F,
+ q931_high_layer_characteristics_vals,
+ "Unknown (0x%02X)"));
}
}
}
@@ -2018,8 +2068,8 @@ dissect_q931_user_user_ie(tvbuff_t *tvb, int offset, int len,
switch (octet) {
case Q931_PROTOCOL_DISCRIMINATOR_IA5:
- proto_tree_add_text(tree, tvb, offset, len, "User information: %.*s",
- len, tvb_get_ptr(tvb, offset, len));
+ proto_tree_add_text(tree, tvb, offset, len, "User information: %s",
+ tvb_format_text(tvb, offset, len));
break;
default:
@@ -2037,8 +2087,8 @@ dissect_q931_ia5_ie(tvbuff_t *tvb, int offset, int len, proto_tree *tree,
char *label)
{
if (len != 0) {
- proto_tree_add_text(tree, tvb, offset, len, "%s: %.*s", label, len,
- tvb_get_ptr(tvb, offset, len));
+ proto_tree_add_text(tree, tvb, offset, len, "%s: %s", label,
+ tvb_format_text(tvb, offset, len));
}
}
@@ -2051,8 +2101,9 @@ static const value_string q931_codeset_vals[] = {
{ 0x00, NULL },
};
-void
-dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static gboolean
+q931_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean started_heuristic)
{
int offset = 0;
guint reported_length;
@@ -2063,13 +2114,107 @@ dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
guint8 call_ref[15];
guint8 message_type;
guint8 info_element;
- guint8 info_element_len;
- int codeset;
+ guint16 info_element_len;
+ int codeset;
gboolean non_locking_shift;
+ guint8 protocol_discriminator;
- CHECK_DISPLAY_AS_DATA(proto_q931, tvb, pinfo, tree);
+#ifdef H323
+ tvbuff_t *h225_tvb;
+ gboolean is_h323_h225 = FALSE;
+ /*
+ * It is very much possible to find a TPKT header here
+ * TPKT is defined in RFC 1009 as a wrapper around ISO
+ * defined protocols. There could even be several TPKT
+ * wrapped messages in one TCP data field...
+ * XXXXXXXX THIS IS NOT IMPLEMENTED YET!!! XXXXXXXXXXX
+ *
+ * For Q.931 related messages this is easy. If a
+ * protocol discriminator is found with a value of 3
+ * and it's the first discriminator in the Q.931
+ * message one can safely assume it to be a TPKT
+ * header. See also Q.931 Table 4-1/Q.931
+ */
+#endif
- pinfo->current_proto = "Q.931";
+ protocol_discriminator = tvb_get_guint8( tvb, offset );
+ /* Keep the protocol discriminator for later use */
+
+#ifdef H323
+ if ( started_heuristic ) {
+ /*
+ * The heuristic Q.931 message should conform to this
+ */
+ if ( protocol_discriminator != NLPID_Q_931 )
+ return FALSE;
+
+ if ( ! is_tpkt( tvb, &offset ) )
+ return FALSE;
+
+ if ( tvb_length_remaining( tvb, offset ) <= 3 )
+ return FALSE;
+ }
+
+ /*
+ * The first byte should be < 8 (3 is TPKT, rest is Q.931)
+ */
+ if ( protocol_discriminator < 8 ) {
+ /*
+ * The minimum length of a Q.931 message is 3:
+ * 1 byte for the protocol discriminator,
+ * 1 for the call_reference length,
+ * and one for the message type.
+ */
+ if ( tvb_length_remaining( tvb, offset ) <= 3 )
+ return FALSE;
+
+ /*
+ * OK, there are a couple of bytes available, but is there
+ * also a protocol discriminator?
+ */
+ if ( tvb_length_remaining( tvb, offset ) > 3 ) {
+ /* Reread the protocol discriminator */
+ protocol_discriminator =
+ tvb_get_guint8( tvb, offset + 4);
+ } else {
+ /* No discriminator available */
+ protocol_discriminator = 0;
+ }
+
+ /*
+ * If it's not H.323 related Q.931 no heuristic action needed
+ * Dangerous, there might be other uses for this code.....
+ */
+ if ( ( started_heuristic ) && (protocol_discriminator != 8 ) )
+ return FALSE;
+
+ /*
+ * Always check if it's a real TPKT message
+ */
+ if ( ! is_tpkt( tvb, &offset ) )
+ return FALSE;
+
+ dissect_tpkt( tvb, &offset, pinfo, tree );
+
+ /*
+ * Reset the current_proto variable because dissect_tpkt
+ * messed with it
+ */
+ if ( started_heuristic )
+ pinfo->current_proto = "Q.931 HEUR";
+ else
+ pinfo->current_proto = "Q.931";
+ }
+#endif
+
+ /*
+ * The minimum length of a Q.931 message is
+ * 3, 1 byte for the protocol discr. 1 for the call_reference length,
+ * and one for the message type.
+ */
+ if ( tvb_length_remaining( tvb, offset ) <= 3 ) {
+ return FALSE;
+ }
if (check_col(pinfo->fd, COL_PROTOCOL))
col_add_str(pinfo->fd, COL_PROTOCOL, "Q.931");
@@ -2079,7 +2224,7 @@ dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tvb_length(tvb), FALSE);
q931_tree = proto_item_add_subtree(ti, ett_q931);
- proto_tree_add_uint(q931_tree, hf_q931_discriminator, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ dissect_q931_protocol_discriminator( tvb, offset, q931_tree );
}
offset += 1;
call_ref_len = tvb_get_guint8(tvb, offset) & 0xF; /* XXX - do as a bit field? */
@@ -2195,20 +2340,72 @@ dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/*
* Variable-length IE.
*/
+#ifndef H323
info_element_len = tvb_get_guint8(tvb, offset + 1);
- if (q931_tree != NULL) {
- ti = proto_tree_add_text(q931_tree, tvb, offset,
- 1+1+info_element_len, "%s",
- val_to_str(info_element, q931_info_element_vals,
- "Unknown information element (0x%02X)"));
- ie_tree = proto_item_add_subtree(ti, ett_q931_ie);
- proto_tree_add_text(ie_tree, tvb, offset, 1,
- "Information element: %s",
- val_to_str(info_element, q931_info_element_vals,
- "Unknown (0x%02X)"));
- proto_tree_add_text(ie_tree, tvb, offset + 1, 1,
- "Length: %u", info_element_len);
+#else
+ /*
+ * According to page 18 from Recommendation H.225.0 :
+ * " Length of user-user contents contents
+ * - Shall be 2 octets instead of 1 (as in Figure 4-36/Q.931)"
+ *
+ * This will be true for all messages going to / from TCP port
+ * 1720 and with the first and fourth octet of the user-user
+ * IE having the values 0x7E and 0x05 resp.
+ * See http://www.mbuf.org/~moto/h323/h323decoder.html
+ *
+ */
+ if ( ( tvb_get_guint8( tvb, offset ) == 0x7E ) &&
+ ( tvb_get_guint8( tvb, offset + 3 ) == 0x05 ) &&
+ /* ( ( pi.srcport == 1720 ) || ( pi.destport == 1720 ) ) && */
+ ( protocol_discriminator == NLPID_Q_931 ) ) {
+ info_element_len = tvb_get_ntohs( tvb, offset + 1 );
+ is_h323_h225 = TRUE;
+ if ( tree == NULL ) {
+ h225_tvb = tvb_new_subset( tvb, offset + 4, info_element_len - 1, info_element_len - 1 );
+ dissect_h225_cs( h225_tvb, pinfo, tree );
+ /*
+ * Skip the 4 bytes of the element header and then the element itself
+ */
+ offset += 4;
+ offset += info_element_len - 1;
+ }
+ } else {
+ info_element_len = tvb_get_guint8( tvb, offset + 1 );
+ }
+#endif
+ if (q931_tree != NULL) {
+#ifdef H323
+ if (is_h323_h225) {
+ ti = proto_tree_add_text(q931_tree, tvb, offset,
+ 1+1+1, "%s",
+ val_to_str(info_element,
+ q931_info_element_vals,
+ "Unknown information element (0x%02X)"));
+ ie_tree = proto_item_add_subtree(ti,
+ ett_q931_ie);
+ proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "Information element: %s",
+ val_to_str(info_element,
+ q931_info_element_vals, "Unknown (0x%02X)"));
+ proto_tree_add_text(ie_tree, tvb, offset + 1,
+ 2, "Length: %u", info_element_len);
+ } else {
+#endif
+ ti = proto_tree_add_text(q931_tree, tvb, offset,
+ 1+1+info_element_len, "%s",
+ val_to_str(info_element, q931_info_element_vals,
+ "Unknown information element (0x%02X)"));
+ ie_tree = proto_item_add_subtree(ti, ett_q931_ie);
+ proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "Information element: %s",
+ val_to_str(info_element, q931_info_element_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(ie_tree, tvb, offset + 1, 1,
+ "Length: %u", info_element_len);
+#ifdef H323
+ }
+#endif
switch (info_element) {
case Q931_IE_SEGMENTED_MESSAGE:
@@ -2339,8 +2536,28 @@ dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
break;
case Q931_IE_USER_USER:
- dissect_q931_user_user_ie(tvb,
- offset + 2, info_element_len, ie_tree);
+#ifdef H323
+ if (is_h323_h225) {
+ h225_tvb = tvb_new_subset(tvb,
+ offset + 4, info_element_len - 1,
+ info_element_len - 1);
+ dissect_h225_cs(h225_tvb, pinfo, tree);
+ offset += 3;
+ proto_tree_add_text(ie_tree, tvb,
+ offset, 1,
+ "Protocol discriminator: %s",
+ val_to_str(tvb_get_guint8(tvb, offset),
+ q931_protocol_discriminator_vals,
+ "Unknown (0x%02x)"));
+ offset += info_element_len;
+ } else {
+#endif
+ dissect_q931_user_user_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+#ifdef H323
+ }
+#endif
break;
default:
@@ -2356,6 +2573,29 @@ dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (non_locking_shift)
codeset = 0;
}
+
+ /*
+ * Heuristic should return TRUE if it get's here.
+ */
+
+ return TRUE;
+
+}
+
+#ifdef H323
+gboolean
+dissect_q931_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ pinfo->current_proto = "Q.931 HEUR";
+ return q931_dissector(tvb, pinfo, tree, TRUE);
+}
+#endif
+
+void
+dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ pinfo->current_proto = "Q.931";
+ q931_dissector(tvb, pinfo, tree, FALSE);
}
void
@@ -2387,4 +2627,13 @@ proto_register_q931(void)
proto_q931 = proto_register_protocol ("Q.931", "q931");
proto_register_field_array (proto_q931, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_q931(void)
+{
+#ifdef H323
+ heur_dissector_add("tcp", dissect_q931_heur);
+#endif
}
diff --git a/packet-rtcp.c b/packet-rtcp.c
index 604f15bac6..d1d9788213 100644
--- a/packet-rtcp.c
+++ b/packet-rtcp.c
@@ -1,9 +1,10 @@
/* packet-rtcp.c
- * Routines for RTCP packet disassembly
*
- * Jason Lango <jal@netapp.com>
- *
- * $Id: packet-rtcp.c,v 1.5 2000/09/11 16:16:02 gram Exp $
+ * Routines for RTCP dissection
+ * RTCP = Real-time Transport Control Protocol
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Written by Andreas Sikkema <andreas.sikkema@philips.com>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -23,436 +24,1172 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the RTCP protocol according to Annex A
+ * of ITU-T Recommendation H.225.0 (02/98) and RFC 1889
+ * H.225.0 literally copies RFC 1889, but omitting a few sections.
*
+ * RTCP traffic is handled by an uneven UDP portnumber. This can be any
+ * port number, but there is a registered port available, port 5005
+ * See Annex B of ITU-T Recommendation H.225.0, section B.7
*
*/
-#include "config.h"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include "packet.h"
#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+# include <sys/types.h>
#endif
#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
+# include <netinet/in.h>
#endif
+#include <stdio.h>
#include <string.h>
-#include <ctype.h>
-#include <glib.h>
-#include "packet.h"
#include "packet-rtcp.h"
-#include "strutil.h"
-
-static int proto_rtcp = -1;
-
-static gint ett_rtcp = -1;
-
-#define _RTCP_FLAG_BITS(hdr, s, n) \
- ((u_int)(((hdr)->rtcp_flag_bits >> (8 - (s) - (n))) & ((1 << (n)) - 1)))
-#define RTCP_VERSION(hdr) _RTCP_FLAG_BITS(hdr, 0, 2)
-#define RTCP_PADDING(hdr) _RTCP_FLAG_BITS(hdr, 2, 1)
-#define RTCP_COUNT(hdr) _RTCP_FLAG_BITS(hdr, 3, 5)
-
-#define RTCP_TYPE_SR 200 /* Sender Report */
-#define RTCP_TYPE_RR 201 /* Receiver Report */
-#define RTCP_TYPE_SDES 202 /* Source Description */
-#define RTCP_TYPE_BYE 203 /* Goodbye */
-#define RTCP_TYPE_APP 204 /* Application-defined */
-
-typedef struct rtcp_hdr {
- guint8 rtcp_flag_bits;
- guint8 rtcp_type; /* packet type */
- guint16 rtcp_length; /* length in 32 bit words minus 1 */
-} rtcp_hdr_t;
-
-typedef struct rtcp_report {
- guint32 rtcp_rr_ssrc; /* SSRC of source */
- guint8 rtcp_rr_flt; /* fraction lost */
- guint8 rtcp_rr_cplthi; /* hi-byte of cplt */
- guint16 rtcp_rr_cplt; /* cumulative packets lost */
- guint32 rtcp_rr_xhiseq; /* extended highest seq num rcvd */
- guint32 rtcp_rr_jitter; /* interarrival jitter */
- guint32 rtcp_rr_lsr; /* middle bits of last SR timestamp */
- guint32 rtcp_rr_dlsr; /* delay since last SR */
-} rtcp_report_t;
+/* #include "packet-ntp.h" */
+#include "conversation.h"
-static int
-dissect_rtcp_report(rtcp_hdr_t *hdr, int sn, const u_char *pd, int offset,
- int start_packet, int end_packet, proto_tree *rtcp_tree)
+/* Version is the first 2 bits of the first octet*/
+#define RTCP_VERSION(octet) ((octet) >> 6)
+
+/* Padding is the third bit; no need to shift, because true is any value
+ other than 0! */
+#define RTCP_PADDING(octet) ((octet) & 0x20)
+
+/* Receiver/ Sender count is the 5 last bits */
+#define RTCP_COUNT(octet) ((octet) & 0x1F)
+
+static const value_string rtcp_version_vals[] =
+{
+ { 0, "Old VAT Version" },
+ { 1, "First Draft Version" },
+ { 2, "RFC 1889 Version" },
+ { 0, NULL },
+};
+
+/* RTCP packet types according to Section A.11.1 */
+#define RTCP_SR 200
+#define RTCP_RR 201
+#define RTCP_SDES 202
+#define RTCP_BYE 203
+#define RTCP_APP 204
+/* Supplemental H.261 specific RTCP packet types according to Section C.3.5 */
+#define RTCP_FIR 192
+#define RTCP_NACK 193
+
+static const value_string rtcp_packet_type_vals[] =
+{
+ { RTCP_SR, "Sender Report" },
+ { RTCP_RR, "Receiver Report" },
+ { RTCP_SDES, "Source description" },
+ { RTCP_BYE, "Goodbye" },
+ { RTCP_APP, "Application specific" },
+ { RTCP_FIR, "Full Intra-frame Request (H.261)" },
+ { RTCP_NACK, "Negative Acknowledgement (H.261)" },
+ { 0, NULL },
+};
+
+/* RTCP SDES types (Section A.11.2) */
+#define RTCP_SDES_END 0
+#define RTCP_SDES_CNAME 1
+#define RTCP_SDES_NAME 2
+#define RTCP_SDES_EMAIL 3
+#define RTCP_SDES_PHONE 4
+#define RTCP_SDES_LOC 5
+#define RTCP_SDES_TOOL 6
+#define RTCP_SDES_NOTE 7
+#define RTCP_SDES_PRIV 8
+
+static const value_string rtcp_sdes_type_vals[] =
{
- int end_offset = offset + END_OF_FRAME;
- rtcp_report_t rep;
-
- if (offset >= end_offset)
- return -1;
-
- memcpy(&rep, &pd[offset], sizeof(rtcp_report_t) <= END_OF_FRAME ?
- sizeof(rtcp_report_t) : END_OF_FRAME);
-
- rep.rtcp_rr_ssrc = ntohl(rep.rtcp_rr_ssrc);
- rep.rtcp_rr_cplt = ntohs(rep.rtcp_rr_cplt);
- rep.rtcp_rr_xhiseq = ntohl(rep.rtcp_rr_xhiseq);
- rep.rtcp_rr_jitter = ntohl(rep.rtcp_rr_jitter);
- rep.rtcp_rr_lsr = ntohl(rep.rtcp_rr_lsr);
- rep.rtcp_rr_dlsr = ntohl(rep.rtcp_rr_dlsr);
-
- if ((offset + sizeof(rtcp_report_t)) > end_offset) {
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 0,
- "Warning: Bad packet length -- "
- "data might be incorrect");
+ { RTCP_SDES_END, "END" },
+ { RTCP_SDES_CNAME, "CNAME (user and domain)" },
+ { RTCP_SDES_NAME, "NAME (common name)" },
+ { RTCP_SDES_EMAIL, "EMAIL (e-mail address)" },
+ { RTCP_SDES_PHONE, "PHONE (phone number)" },
+ { RTCP_SDES_LOC, "LOC (geographic location)" },
+ { RTCP_SDES_TOOL, "TOOL (name/version of source app)" },
+ { RTCP_SDES_NOTE, "NOTE (note about source)" },
+ { RTCP_SDES_PRIV, "PRIV (private extensions)" },
+ { 0, NULL },
+};
+
+/* RTCP header fields */
+static int proto_rtcp = -1;
+static int hf_rtcp_version = -1;
+static int hf_rtcp_padding = -1;
+static int hf_rtcp_rc = -1;
+static int hf_rtcp_sc = -1;
+static int hf_rtcp_pt = -1;
+static int hf_rtcp_length = -1;
+static int hf_rtcp_ssrc_sender = -1;
+static int hf_rtcp_ntp = -1;
+static int hf_rtcp_rtp_timestamp = -1;
+static int hf_rtcp_sender_pkt_cnt = -1;
+static int hf_rtcp_sender_oct_cnt = -1;
+static int hf_rtcp_ssrc_source = -1;
+static int hf_rtcp_ssrc_fraction = -1;
+static int hf_rtcp_ssrc_cum_nr = -1;
+/* First the 32 bit number, then the split
+ * up 16 bit values */
+/* These two are added to a subtree */
+static int hf_rtcp_ssrc_ext_high_seq = -1;
+static int hf_rtcp_ssrc_high_seq = -1;
+static int hf_rtcp_ssrc_high_cycles = -1;
+static int hf_rtcp_ssrc_jitter = -1;
+static int hf_rtcp_ssrc_lsr = -1;
+static int hf_rtcp_ssrc_dlsr = -1;
+static int hf_rtcp_ssrc_csrc = -1;
+static int hf_rtcp_ssrc_type = -1;
+static int hf_rtcp_ssrc_length = -1;
+static int hf_rtcp_ssrc_text = -1;
+static int hf_rtcp_ssrc_prefix_len = -1;
+static int hf_rtcp_ssrc_prefix_string= -1;
+static int hf_rtcp_subtype = -1;
+static int hf_rtcp_name_ascii = -1;
+static int hf_rtcp_app_data = -1;
+static int hf_rtcp_fsn = -1;
+static int hf_rtcp_blp = -1;
+static int hf_rtcp_padding_count = -1;
+static int hf_rtcp_padding_data = -1;
+
+/* RTCP fields defining a sub tree */
+static gint ett_rtcp = -1;
+static gint ett_ssrc = -1;
+static gint ett_ssrc_item = -1;
+static gint ett_ssrc_ext_high = -1;
+static gint ett_sdes = -1;
+static gint ett_sdes_item = -1;
+
+static address fake_addr;
+static int heur_init = FALSE;
+
+static char rtcp_proto[] = "RTCP";
+
+void rtcp_add_address( const unsigned char* ip_addr, int prt )
+{
+ address src_addr;
+ conversation_t* pconv = ( conversation_t* ) NULL;
+
+ src_addr.type = AT_IPv4;
+ src_addr.len = 4;
+ src_addr.data = ip_addr;
+
+ /*
+ * The first time the function is called let the udp dissector
+ * know that we're interested in traffic
+ */
+ if ( ! heur_init ) {
+ heur_dissector_add( "udp", dissect_rtcp_heur );
+ heur_init = TRUE;
}
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4,
- "Source %d SSRC: %u", sn + 1, rep.rtcp_rr_ssrc);
- offset += 4;
+ /*
+ * Check if the ip address and port combination is not
+ * already registered
+ */
+ pconv = find_conversation( &src_addr, &fake_addr, PT_UDP, prt, 0 );
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 1,
- "Fraction lost: %u / 256", (unsigned) rep.rtcp_rr_flt);
- offset += 1;
+ /*
+ * If not, add
+ */
+ if ( ! pconv ) {
+ conversation_new( &src_addr, &fake_addr, PT_UDP, (guint32) prt, (guint32) 0, (void*) rtcp_proto );
+ }
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 3,
- "Cumulative Packets Lost: %lu",
- (((unsigned long) rep.rtcp_rr_cplthi) << 16) +
- (unsigned long) rep.rtcp_rr_cplt);
- offset += 3;
+}
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4,
- "Extended Highest Seq #: %lu",
- (unsigned long) rep.rtcp_rr_xhiseq);
- offset += 4;
+#if 0
+static void rtcp_init( void )
+{
+ unsigned char* tmp_data;
+ int i;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4,
- "Jitter: %lu", (unsigned long) rep.rtcp_rr_jitter);
- offset += 4;
+ /* Create a fake adddress... */
+ fake_addr.type = AT_IPv4;
+ fake_addr.len = 4;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4,
- "Last SR timestamp (middle): %lu",
- (unsigned long) rep.rtcp_rr_lsr);
- offset += 4;
+ tmp_data = malloc( fake_addr.len );
+ for ( i = 0; i < fake_addr.len; i++) {
+ tmp_data[i] = 0;
+ }
+ fake_addr.data = tmp_data;
+}
+#endif
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4,
- "Delay Since Last SR: %lu",
- (unsigned long) rep.rtcp_rr_dlsr);
- offset += 4;
+gboolean
+dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ /* This is a heuristic dissector, which means we get all the UDP
+ * traffic not sent to a known dissector and not claimed by
+ * a heuristic dissector called before us!
+ * So we first check if the frame is really meant for us.
+ */
+ conversation_t* pconv;
+ if ( ( pconv = find_conversation( &pi.src, &fake_addr, pi.ptype, pi.srcport, 0 ) ) == NULL ) {
+ /*
+ * The source ip:port combination was not what we were looking for, check the destination
+ */
+ if ( ( pconv = find_conversation( &pi.dst, &fake_addr, pi.ptype, pi.destport, 0 ) ) == NULL ) {
+ return FALSE;
+ }
+ }
- return offset;
+
+ /*
+ * An RTCP conversation always contains data
+ */
+ if ( pconv->data == NULL )
+ return FALSE;
+
+ /*
+ * An RTCP conversation data always contains "RTCP"
+ */
+ if ( strcmp( pconv->data, rtcp_proto ) != 0 )
+ return FALSE;
+
+ /*
+ * The message is a valid RTCP message!
+ */
+ dissect_rtcp( tvb, pinfo, tree );
+
+ return TRUE;
}
-typedef struct rtcp_rr {
- guint32 rtcp_rr_ssrc;
-} rtcp_rr_t;
static int
-dissect_rtcp_rr(rtcp_hdr_t *hdr, const u_char *pd, int offset,
- int start_packet, int end_packet, proto_tree *rtcp_tree)
+dissect_rtcp_nack( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
{
- int end_offset = offset + END_OF_FRAME;
- rtcp_rr_t rr;
- int sn;
-
- memcpy(&rr, &pd[offset], sizeof(rtcp_rr_t) < END_OF_FRAME ?
- sizeof(rtcp_rr_t) : END_OF_FRAME);
- rr.rtcp_rr_ssrc = ntohl(rr.rtcp_rr_ssrc);
-
- if ((offset + sizeof(rtcp_rr_t)) >= end_offset)
- return -1;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4, "Sender SSRC: %u",
- rr.rtcp_rr_ssrc);
+ /* Packet type = FIR (H261) */
+ proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 31 );
+ offset++;
+ /* Packet type, 8 bits = APP */
+ proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+
+ /* Packet length in 32 bit words minus one */
+ proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ /* SSRC */
+ proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
offset += 4;
+
+ /* FSN, 16 bits */
+ proto_tree_add_uint( tree, hf_rtcp_fsn, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
- for (sn = 0; sn < RTCP_COUNT(hdr); sn++) {
- offset = dissect_rtcp_report(hdr, sn, pd, offset, start_packet,
- end_packet, rtcp_tree);
- }
+ /* BLP, 16 bits */
+ proto_tree_add_uint( tree, hf_rtcp_blp, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
return offset;
}
-typedef struct rtcp_sr {
- guint32 rtcp_sr_ssrc;
- guint32 rtcp_sr_ntp_hi; /* MSW of NTP timestamp */
- guint32 rtcp_sr_ntp_lo; /* LSW of NTP timestamp */
- guint32 rtcp_sr_rtp_time; /* RTP timestamp */
- guint32 rtcp_sr_npackets; /* sender's packet count */
- guint32 rtcp_sr_nbytes; /* sender's octet count */
-} rtcp_sr_t;
-
static int
-dissect_rtcp_sr(rtcp_hdr_t *hdr, const u_char *pd, int offset,
- int start_packet, int end_packet, proto_tree *rtcp_tree)
+dissect_rtcp_fir( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
{
- int end_offset = offset + END_OF_FRAME;
- rtcp_sr_t sr;
- int sn;
-
- memcpy(&sr, &pd[offset], sizeof(rtcp_sr_t) < END_OF_FRAME ?
- sizeof(rtcp_sr_t) : END_OF_FRAME);
- sr.rtcp_sr_ssrc = ntohl(sr.rtcp_sr_ssrc);
- sr.rtcp_sr_ntp_hi = ntohl(sr.rtcp_sr_ntp_hi);
- sr.rtcp_sr_ntp_lo = ntohl(sr.rtcp_sr_ntp_lo);
- sr.rtcp_sr_rtp_time = ntohl(sr.rtcp_sr_rtp_time);
- sr.rtcp_sr_npackets = ntohl(sr.rtcp_sr_npackets);
- sr.rtcp_sr_nbytes = ntohl(sr.rtcp_sr_nbytes);
-
- if ((offset + sizeof(rtcp_sr_t)) > end_offset) {
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 0,
- "Warning: Bad packet length -- "
- "data might be incorrect");
- }
+ /* Packet type = FIR (H261) */
+ proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 31 );
+ offset++;
+ /* Packet type, 8 bits = APP */
+ proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4, "Sender's SSRC: %u",
- sr.rtcp_sr_ssrc);
- offset += 4;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4, "NTP timestamp, MSW: %u",
- sr.rtcp_sr_ntp_hi);
- offset += 4;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4, "NTP timestamp, LSW: %u",
- sr.rtcp_sr_ntp_lo);
- offset += 4;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4, "RTP timestamp: %u",
- sr.rtcp_sr_rtp_time);
+ /* Packet length in 32 bit words minus one */
+ proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ /* SSRC */
+ proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
offset += 4;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4, "Sender's packet count: %u",
- sr.rtcp_sr_npackets);
+
+ return offset;
+}
+
+static int
+dissect_rtcp_app( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
+ unsigned int padding, unsigned int packet_len )
+{
+ unsigned int counter = 0;
+ char ascii_name[5];
+
+ /* SSRC / CSRC */
+ proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
offset += 4;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4, "Sender's octet count: %u",
- sr.rtcp_sr_nbytes);
+ packet_len -= 4;
+
+ /* Name (ASCII) */
+ for( counter = 0; counter < 4; counter++ )
+ ascii_name[ counter ] = tvb_get_guint8( tvb, offset + counter );
+ /* strncpy( ascii_name, pd + offset, 4 ); */
+ ascii_name[4] = '\0';
+ proto_tree_add_string( tree, hf_rtcp_name_ascii, tvb, offset, 4,
+ ascii_name );
offset += 4;
-
- for (sn = 0; sn < RTCP_COUNT(hdr); sn++) {
- offset = dissect_rtcp_report(hdr, sn, pd, offset, start_packet,
- end_packet, rtcp_tree);
+ packet_len -= 4;
+
+ /* Applications specific data */
+ if ( padding ) {
+ /* If there's padding present, we have to remove that from the data part
+ * The last octet of the packet contains the length of the padding
+ */
+ packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
}
+ proto_tree_add_item( tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
+ offset += packet_len;
return offset;
}
-static struct rtcp_chunk_type {
- int type;
- const char *name;
-} rtcp_chunk_types[] = {
- { 1, "CNAME (user and domain)" },
- { 2, "NAME (common name)" },
- { 3, "EMAIL (e-mail address)" },
- { 4, "PHONE (phone number)" },
- { 5, "LOC (geographic location)" },
- { 6, "TOOL (name/version of source app)" },
- { 7, "NOTE (note about source)" },
- { 8, "PRIV (private extensions)" },
- { 0, 0 }
-};
-
-static struct rtcp_chunk_type *
-rtcp_find_chunk_type(int type)
+static int
+dissect_rtcp_bye( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
+ int count )
{
- struct rtcp_chunk_type *tt = rtcp_chunk_types;
- static struct rtcp_chunk_type unk = { 0, "UNKNOWN" };
- for (; tt->type; tt++) {
- if (type == tt->type)
- return tt;
+ unsigned int chunk = 1;
+ unsigned int reason_length = 0;
+ unsigned int counter = 0;
+ char* reason_text = NULL;
+
+ while ( chunk <= count ) {
+ /* source identifier, 32 bits */
+ proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
}
- return &unk;
+
+ /* Bye reason consists of an 8 bit length l and a string with length l */
+ reason_length = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
+ offset++;
+
+ reason_text = ( char* ) malloc( reason_length + 1 );
+ for ( counter = 0; counter < reason_length; counter++ ) reason_text[ counter ] = tvb_get_guint8( tvb, offset + counter );
+ /* strncpy( reason_text, pd + offset, reason_length ); */
+ reason_text[ reason_length ] = '\0';
+ proto_tree_add_string( tree, hf_rtcp_ssrc_text, tvb, offset, reason_length, reason_text );
+ free( reason_text );
+ offset += reason_length;
+
+ return offset;
+
}
static int
-dissect_rtcp_sdes_chunk(rtcp_hdr_t *hdr, int cn, const u_char *pd, int offset,
- int start_packet, int end_packet, proto_tree *rtcp_tree)
+dissect_rtcp_sdes( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
+ int count )
{
- unsigned type;
- unsigned len;
- struct rtcp_chunk_type *ctype;
-
- if ((offset + 4) > end_packet)
- return -1;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 4, "Chunk %d SSRC: %u",
- cn + 1, pntohl(&pd[offset]));
- offset += 4;
-
- for (;;) {
- if ((offset + 1) > end_packet)
- return -1;
+ unsigned int chunk = 1;
+ proto_item *sdes_item;
+ proto_tree *sdes_tree;
+ proto_tree *sdes_item_tree;
+ proto_item *ti;
+ int start_offset;
+ int items_start_offset;
+ guint32 ssrc;
+ unsigned int item_len = 0;
+ unsigned int sdes_type = 0;
+ unsigned int counter = 0;
+ unsigned int prefix_len = 0;
+ char *prefix_string = NULL;
+
+ while ( chunk <= count ) {
+ /* Create a subtree for this chunk; we don't yet know
+ the length. */
+ start_offset = offset;
+
+ ssrc = tvb_get_ntohl( tvb, offset );
+ sdes_item = proto_tree_add_text(tree, tvb, offset, 0,
+ "Chunk %u, SSRC/CSRC %u", chunk, ssrc);
+ sdes_tree = proto_item_add_subtree( sdes_item, ett_sdes );
+
+ /* SSRC_n source identifier, 32 bits */
+ proto_tree_add_uint( sdes_tree, hf_rtcp_ssrc_source, tvb, offset, 4, ssrc );
+ offset += 4;
+
+ /* Create a subtree for the SDES items; we don't yet know
+ the length */
+ items_start_offset = offset;
+ ti = proto_tree_add_text(sdes_tree, tvb, offset, 0,
+ "SDES items" );
+ sdes_item_tree = proto_item_add_subtree( ti, ett_sdes_item );
+
+ /*
+ * Not every message is ended with "null" bytes, so check for
+ * end of frame instead.
+ */
+ while ( ( tvb_get_guint8( tvb, offset ) != RTCP_SDES_END )
+ && ( tvb_length_remaining( tvb, offset) >= 2 ) ) {
+ /* while ( ( pd[ offset ] != RTCP_SDES_END ) && ( BYTES_ARE_IN_FRAME( offset, 2 ) ) ) { */
+ /* ID, 8 bits */
+ sdes_type = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
+ offset++;
- type = pd[offset];
- if (type == 0) {
- int pad_start = offset;
+ /* Item length, 8 bits */
+ item_len = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
offset++;
- /* NULL terminator -- align to next 32 bit boundary */
- if ((offset - start_packet) & 3) {
- offset += 4 - ((offset - start_packet) & 3);
- }
- proto_tree_add_text(rtcp_tree, NullTVB, pad_start,
- offset - pad_start,
- "(end of chunk and alignment padding)");
- break;
+
+ if ( sdes_type == RTCP_SDES_PRIV ) {
+ /* PRIV adds two items between the SDES length
+ * and value - an 8 bit length giving the
+ * length of a "prefix string", and the string.
+ */
+ prefix_len = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_prefix_len, tvb, offset, 1, FALSE );
+ offset++;
+
+ prefix_string = ( char * ) malloc( prefix_len + 1 );
+ for ( counter = 0; counter < prefix_len; counter++ )
+ prefix_string[ counter ] =
+ tvb_get_guint8( tvb, offset + counter );
+ /* strncpy( prefix_string, pd + offset, prefix_len ); */
+ prefix_string[ prefix_len ] = '\0';
+ proto_tree_add_string( sdes_item_tree, hf_rtcp_ssrc_prefix_string, tvb, offset, prefix_len, prefix_string );
+ free( prefix_string );
+ offset += prefix_len;
+ }
+ prefix_string = ( char * ) malloc( item_len + 1 );
+ for ( counter = 0; counter < item_len; counter++ )
+ prefix_string[ counter ] =
+ tvb_get_guint8( tvb, offset + counter );
+ /* strncpy( prefix_string, pd + offset, item_len ); */
+ prefix_string[ item_len] = 0;
+ proto_tree_add_string( sdes_item_tree, hf_rtcp_ssrc_text, tvb, offset, item_len, prefix_string );
+ free( prefix_string );
+ offset += item_len;
}
- ctype = rtcp_find_chunk_type(type);
+ /* Set the length of the items subtree. */
+ proto_item_set_len(ti, offset - items_start_offset);
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 1, "Chunk type: %s",
- ctype->name);
- offset++;
+ /* 32 bits = 4 bytes, so.....
+ * If offset % 4 != 0, we divide offset by 4, add one and then
+ * multiply by 4 again to reach the boundary
+ */
+ if ( offset % 4 != 0 )
+ offset = ((offset / 4) + 1 ) * 4;
- if ((offset + 1) > end_packet)
- return -1;
+ /* Set the length of this chunk. */
+ proto_item_set_len(sdes_item, offset - start_offset);
- len = pd[offset];
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 1, "Chunk length: %u",
- (unsigned) len);
- offset++;
+ chunk++;
+ }
- if ((offset + len) > end_packet)
- return -1;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, len, "Chunk string: %s",
- format_text(&pd[offset], len));
- offset += len;
- }
return offset;
}
static int
-dissect_rtcp_sdes(rtcp_hdr_t *hdr, const u_char *pd, int offset,
- int start_packet, int end_packet, proto_tree *rtcp_tree)
+dissect_rtcp_rr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
+ int count )
{
- int cn;
+ unsigned int counter = 1;
+ proto_tree *ssrc_tree = (proto_tree*) NULL;
+ proto_tree *ssrc_sub_tree = (proto_tree*) NULL;
+ proto_tree *high_sec_tree = (proto_tree*) NULL;
+ proto_item *ti = (proto_item*) NULL;
+ guint8 rr_flt;
+ unsigned int cum_nr = 0;
+
+ while ( counter <= count ) {
+ /* Create a new subtree for a length of 24 bytes */
+ ti = proto_tree_add_text(tree, tvb, offset, 24,
+ "Source %u", counter );
+ ssrc_tree = proto_item_add_subtree( ti, ett_ssrc );
+
+ /* SSRC_n source identifier, 32 bits */
+ proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ ti = proto_tree_add_text(ssrc_tree, tvb, offset, 20, "SSRC contents" );
+ ssrc_sub_tree = proto_item_add_subtree( ti, ett_ssrc_item );
+
+ /* Fraction lost, 8bits */
+ rr_flt = tvb_get_guint8( tvb, offset );
+ proto_tree_add_uint_format( ssrc_sub_tree, hf_rtcp_ssrc_fraction, tvb,
+ offset, 1, rr_flt, "Fraction lost: %u / 256", rr_flt );
+ offset++;
- for (cn = 0; cn < RTCP_COUNT(hdr); cn++) {
- offset = dissect_rtcp_sdes_chunk(hdr, cn, pd, offset,
- start_packet, end_packet, rtcp_tree);
+ /* Cumulative number of packets lost, 24 bits */
+ cum_nr = tvb_get_ntohl( tvb, offset ) >> 8;
+ proto_tree_add_uint( ssrc_sub_tree, hf_rtcp_ssrc_cum_nr, tvb,
+ offset, 3, cum_nr );
+ offset += 3;
+
+ /* Extended highest sequence nr received, 32 bits
+ * Just for the sake of it, let's add another subtree
+ * because this might be a little clearer
+ */
+ ti = proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_ext_high_seq,
+ tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ high_sec_tree = proto_item_add_subtree( ti, ett_ssrc_ext_high );
+ /* Sequence number cycles */
+ proto_tree_add_uint( high_sec_tree, hf_rtcp_ssrc_high_cycles,
+ tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ /* highest sequence number received */
+ proto_tree_add_uint( high_sec_tree, hf_rtcp_ssrc_high_seq,
+ tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ /* Interarrival jitter */
+ proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_jitter, tvb,
+ offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ /* Last SR timestamp */
+ proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_lsr, tvb,
+ offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ /* Delay since last SR timestamp */
+ proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_dlsr, tvb,
+ offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ counter++;
}
+
return offset;
}
static int
-dissect_one_rtcp(const u_char *pd, int offset, frame_data *fd,
- proto_tree *tree)
+dissect_rtcp_sr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
+ int count )
{
- proto_tree *rtcp_tree;
- proto_item *ti;
- const u_char *data, *dataend;
- int end_offset;
- int start_packet;
- int end_packet;
- rtcp_hdr_t hdr;
- const char *ptype;
-
- data = &pd[offset];
- dataend = data + END_OF_FRAME;
- start_packet = offset;
- end_offset = offset + END_OF_FRAME;
-
- ti = proto_tree_add_item(tree, proto_rtcp, NullTVB, offset, END_OF_FRAME, FALSE);
- rtcp_tree = proto_item_add_subtree(ti, ett_rtcp);
-
- memcpy(&hdr, data, END_OF_FRAME < sizeof(rtcp_hdr_t) ?
- END_OF_FRAME : sizeof(rtcp_hdr_t));
- hdr.rtcp_length = ntohs(hdr.rtcp_length);
-
- if (offset >= end_offset)
- return -1;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 1, "Version: %u (%s)",
- RTCP_VERSION(&hdr),
- RTCP_VERSION(&hdr) == 3 ? "New Unknown Version" :
- RTCP_VERSION(&hdr) == 2 ? "RFC 1889 Version" :
- RTCP_VERSION(&hdr) == 1 ? "First Draft Version" :
- "Old Vat Version");
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 1, "Padding: %u",
- RTCP_PADDING(&hdr));
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 1, "Count: %u",
- RTCP_COUNT(&hdr));
- offset++;
-
- if (offset >= end_offset)
- return -1;
- switch (hdr.rtcp_type) {
- case RTCP_TYPE_SR: ptype = "SR: Sender Report"; break;
- case RTCP_TYPE_RR: ptype = "RR: Receiver Report"; break;
- case RTCP_TYPE_SDES: ptype = "SDES: Source Description"; break;
- case RTCP_TYPE_BYE: ptype = "BYE: Goodbye"; break;
- case RTCP_TYPE_APP: ptype = "APP: Application-defined"; break;
- default: ptype = "Unknown"; break;
- }
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 1, "Type: %u (%s)",
- (u_int) hdr.rtcp_type, ptype);
- offset++;
-
- if (offset >= end_offset)
- return -1;
- proto_tree_add_text(rtcp_tree, NullTVB, offset, 2, "Length / 4 - 1: %u",
- (unsigned) hdr.rtcp_length);
- offset += 2;
+ /* gchar buff[ NTP_TS_SIZE ];
+ char* ptime = tvb_get_ptr( tvb, offset, 8 );
+ */
+
+ /* Retreive the NTP timestamp. Using the NTP dissector for this */
+ /*ntp_fmt_ts( ptime, buff );
+ proto_tree_add_string_format( tree, hf_rtcp_ntp, tvb, offset, 8, ( const char* ) &buff, "NTP timestamp: %s", &buff );
+ free( ptime ); ??????????????????????????????????????????????????????????????????
+ */
+
+ proto_tree_add_text( tree, tvb, offset, 8, "Timestamp, format unknown" );
+ offset += 8;
+ /* RTP timestamp, 32 bits */
+ proto_tree_add_uint( tree, hf_rtcp_rtp_timestamp, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ /* Sender's packet count, 32 bits */
+ proto_tree_add_uint( tree, hf_rtcp_sender_pkt_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ /* Sender's octet count, 32 bits */
+ proto_tree_add_uint( tree, hf_rtcp_sender_oct_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
- /*
- * Don't add 1 to length, since it's accounted for above.
- */
- end_packet = offset + hdr.rtcp_length * 4;
-
- switch (hdr.rtcp_type) {
- case RTCP_TYPE_RR:
- offset = dissect_rtcp_rr(&hdr, pd, offset, start_packet,
- end_packet, rtcp_tree);
- break;
- case RTCP_TYPE_SR:
- offset = dissect_rtcp_sr(&hdr, pd, offset, start_packet,
- end_packet, rtcp_tree);
- break;
- case RTCP_TYPE_SDES:
- offset = dissect_rtcp_sdes(&hdr, pd, offset, start_packet,
- end_packet, rtcp_tree);
- break;
- default:
- proto_tree_add_text(rtcp_tree, NullTVB, offset, END_OF_FRAME,
- "TYPE NOT HANDLED YET");
- offset = end_packet;
- break;
- }
+ /* The rest of the packet is equal to the RR packet */
+ if ( count > 0 )
+ offset = dissect_rtcp_rr( tvb, offset, fd, tree, count );
- if (offset > 0 && offset < end_packet) {
- proto_tree_add_text(rtcp_tree, NullTVB, offset, end_packet - offset,
- "Extra data (%d bytes)", end_packet - offset);
- }
- if (offset < 0)
- return offset;
- return end_packet;
+ return offset;
}
void
-dissect_rtcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
{
- int end_offset;
-
- OLD_CHECK_DISPLAY_AS_DATA(proto_rtcp, pd, offset, fd, tree);
-
- if (check_col(fd, COL_PROTOCOL))
- col_add_str(fd, COL_PROTOCOL, "RTCP");
-
- if (!tree)
- return;
-
- end_offset = offset + END_OF_FRAME;
- while (offset > 0 && offset < end_offset) {
- offset = dissect_one_rtcp(pd, offset, fd, tree);
+ proto_item *ti = NULL;
+ proto_tree *rtcp_tree = NULL;
+ unsigned int temp_byte = 0;
+ unsigned int padding_set = 0;
+ unsigned int elem_count = 0;
+ unsigned int packet_type = 0;
+ unsigned int offset = 0;
+ guint16 packet_length = 0;
+
+ pinfo->current_proto = "RTCP";
+
+ if ( check_col( pinfo->fd, COL_PROTOCOL ) ) {
+ col_add_str( pinfo->fd, COL_PROTOCOL, "RTCP" );
}
- if (offset < 0) {
- proto_tree_add_text(tree, NullTVB, end_offset, 0,
- "Unexpected end of packet");
+
+ if ( check_col( pinfo->fd, COL_INFO) ) {
+ /* The second octet contains the packet type */
+ /* switch ( pd[ offset + 1 ] ) { */
+ switch ( tvb_get_guint8( tvb, 1 ) ) {
+ case RTCP_SR:
+ col_add_str( pinfo->fd, COL_INFO, "Sender Report");
+ break;
+ case RTCP_RR:
+ col_add_str( pinfo->fd, COL_INFO, "Receiver Report");
+ break;
+ case RTCP_SDES:
+ col_add_str( pinfo->fd, COL_INFO, "Source Description");
+ break;
+ case RTCP_BYE:
+ col_add_str( pinfo->fd, COL_INFO, "Goodbye");
+ break;
+ case RTCP_APP:
+ col_add_str( pinfo->fd, COL_INFO, "Application defined");
+ break;
+ case RTCP_FIR:
+ col_add_str( pinfo->fd, COL_INFO, "Full Intra-frame Request (H.261)");
+ break;
+ case RTCP_NACK:
+ col_add_str( pinfo->fd, COL_INFO, "Negative Acknowledgement (H.261)");
+ break;
+ default:
+ col_add_str( pinfo->fd, COL_INFO, "Unknown packet type");
+ break;
+ }
+ }
+
+ if ( tree ) {
+
+ /*
+ * Check if there are at least 4 bytes left in the frame,
+ * the last 16 bits of those is the length of the current
+ * RTCP message. The last compound message contains padding,
+ * that enables us to break from the while loop.
+ */
+ /* while ( BYTES_ARE_IN_FRAME( offset, 4 ) ) { */
+ while ( tvb_length_remaining( tvb, offset) >= 4 ) {
+ /*
+ * First retreive the packet_type
+ */
+ packet_type = tvb_get_guint8( tvb, offset + 1 );
+
+ /*
+ * Check if it's a valid type
+ */
+ if ( ( packet_type < 192 ) || ( packet_type > 204 ) )
+ break;
+
+ /*
+ * get the packet-length for the complete RTCP packet
+ */
+ packet_length = ( tvb_get_ntohs( tvb, offset + 2 ) + 1 ) * 4;
+
+ ti = proto_tree_add_item(tree, proto_rtcp, tvb, offset, packet_length, FALSE );
+ rtcp_tree = proto_item_add_subtree( ti, ett_rtcp );
+
+ temp_byte = tvb_get_guint8( tvb, offset );
+
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_version, tvb,
+ offset, 1, RTCP_VERSION( temp_byte ) );
+ padding_set = RTCP_PADDING( temp_byte );
+ proto_tree_add_boolean( rtcp_tree, hf_rtcp_padding, tvb,
+ offset, 1, padding_set );
+ elem_count = RTCP_COUNT( temp_byte );
+
+ switch ( packet_type ) {
+ case RTCP_SR:
+ case RTCP_RR:
+ /* Receiver report count, 5 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_rc, tvb, offset, 1, elem_count );
+ offset++;
+ /* Packet type, 8 bits */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+ /* Packet length in 32 bit words MINUS one, 16 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ /* Sender Synchronization source, 32 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_ssrc_sender, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ if ( packet_type == RTCP_SR ) offset = dissect_rtcp_sr( tvb, offset, pinfo->fd, rtcp_tree, elem_count );
+ else offset = dissect_rtcp_rr( tvb, offset, pinfo->fd, rtcp_tree, elem_count );
+ break;
+ case RTCP_SDES:
+ /* Source count, 5 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, elem_count );
+ offset++;
+ /* Packet type, 8 bits */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+ /* Packet length in 32 bit words MINUS one, 16 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ offset = dissect_rtcp_sdes( tvb, offset, pinfo->fd, rtcp_tree, elem_count );
+ break;
+ case RTCP_BYE:
+ /* Source count, 5 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, elem_count );
+ offset++;
+ /* Packet type, 8 bits */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+ /* Packet length in 32 bit words MINUS one, 16 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ offset = dissect_rtcp_bye( tvb, offset, pinfo->fd, rtcp_tree, elem_count );
+ break;
+ case RTCP_APP:
+ /* Subtype, 5 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_subtype, tvb, offset, 1, elem_count );
+ offset++;
+ /* Packet type, 8 bits */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+ /* Packet length in 32 bit words MINUS one, 16 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ dissect_rtcp_app( tvb, offset,
+ pinfo->fd, rtcp_tree, padding_set,
+ packet_length - 4 );
+ break;
+ case RTCP_FIR:
+ dissect_rtcp_fir( tvb, offset, pinfo->fd, rtcp_tree );
+ break;
+ case RTCP_NACK:
+ dissect_rtcp_nack( tvb, offset, pinfo->fd, rtcp_tree );
+ break;
+ default:
+ /*
+ * To prevent endless loops in case of an unknown message type
+ * increase offset. Some time the while will end :-)
+ */
+ offset++;
+ break;
+ }
+ }
+ /* If the padding bit is set, the last octet of the
+ * packet contains the length of the padding
+ * We only have to check for this at the end of the LAST RTCP message
+ */
+ if ( padding_set ) {
+ /* If everything went according to plan offset should now point to the
+ * first octet of the padding
+ */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_padding_data, tvb, offset, tvb_length_remaining( tvb, offset) - 1, FALSE );
+ offset += tvb_length_remaining( tvb, offset) - 1;
+ proto_tree_add_item( rtcp_tree, hf_rtcp_padding_count, tvb, offset, 1, FALSE );
+ }
}
}
void
proto_register_rtcp(void)
{
-/* static hf_register_info hf[] = {
- { &variable,
- { "Name", "rtcp.abbreviation", TYPE, VALS_POINTER }},
- };*/
- static gint *ett[] = {
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_rtcp_version,
+ {
+ "Version",
+ "rtcp.version",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtcp_version_vals),
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_padding,
+ {
+ "Padding",
+ "rtcp.padding",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_rc,
+ {
+ "Reception report count",
+ "rtcp.rc",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_sc,
+ {
+ "Source count",
+ "rtcp.sc",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_pt,
+ {
+ "Packet type",
+ "rtcp.pt",
+ FT_UINT8,
+ BASE_DEC,
+ VALS( rtcp_packet_type_vals ),
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_length,
+ {
+ "Length",
+ "rtcp.length",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_sender,
+ {
+ "Sender SSRC",
+ "rtcp.senderssrc",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ntp,
+ {
+ "NTP timestamp",
+ "rtcp.timestamp.ntp",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_rtp_timestamp,
+ {
+ "RTP timestamp",
+ "rtcp.timestamp.rtp",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_sender_pkt_cnt,
+ {
+ "Sender's packet count",
+ "rtcp.sender.packetcount",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_sender_oct_cnt,
+ {
+ "Sender's octet count",
+ "rtcp.sender.octetcount",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_source,
+ {
+ "Identifier",
+ "rtcp.ssrc.identifier",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_fraction,
+ {
+ "Fraction lost",
+ "rtcp.ssrc.fraction",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_cum_nr,
+ {
+ "Cumulative number of packets lost",
+ "rtcp.ssrc.cum_nr",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_ext_high_seq,
+ {
+ "Extended highest sequence number received",
+ "rtcp.ssrc.ext_high",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_high_seq,
+ {
+ "Highest sequence number received",
+ "rtcp.ssrc.high_seq",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_high_cycles,
+ {
+ "Sequence number cycles count",
+ "rtcp.ssrc.high_cycles",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_jitter,
+ {
+ "Interarrival jitter",
+ "rtcp.ssrc.jitter",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_lsr,
+ {
+ "Last SR timestamp",
+ "rtcp.ssrc.lsr",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_dlsr,
+ {
+ "Delay since last SR timestamp",
+ "rtcp.ssrc.dlsr",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_csrc,
+ {
+ "SSRC / CSRC identifier",
+ "rtcp.sdes.ssrc_csrc",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_type,
+ {
+ "Type",
+ "rtcp.sdes.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS( rtcp_sdes_type_vals ),
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_length,
+ {
+ "Length",
+ "rtcp.sdes.length",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_text,
+ {
+ "Text",
+ "rtcp.sdes.text",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_prefix_len,
+ {
+ "Prefix length",
+ "rtcp.sdes.prefix.length",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_ssrc_prefix_string,
+ {
+ "Prefix string",
+ "rtcp.sdes.prefix.string",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_subtype,
+ {
+ "Subtype",
+ "rtcp.app.subtype",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_name_ascii,
+ {
+ "Name (ASCII)",
+ "rtcp.app.name",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_app_data,
+ {
+ "Application specific data",
+ "rtcp.app.data",
+ FT_BYTES,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_fsn,
+ {
+ "First sequence number",
+ "rtcp.nack.fsn",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_blp,
+ {
+ "Bitmask of following lost packets",
+ "rtcp.nack.blp",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_padding_count,
+ {
+ "Padding count",
+ "rtcp.padding.count",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtcp_padding_data,
+ {
+ "Padding data",
+ "rtcp.padding.data",
+ FT_BYTES,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+};
+
+ static gint *ett[] =
+ {
&ett_rtcp,
+ &ett_ssrc,
+ &ett_ssrc_item,
+ &ett_ssrc_ext_high,
+ &ett_sdes,
+ &ett_sdes_item,
};
- proto_rtcp = proto_register_protocol("RTP Control Protocol", "rtcp");
- /* proto_register_field_array(proto_rtcp, hf, array_length(hf));*/
+
+ proto_rtcp = proto_register_protocol("Real-time Transport Control Protocol", "rtcp");
+ proto_register_field_array(proto_rtcp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+#if 0
+ register_init_routine( &rtcp_init );
+#endif
}
diff --git a/packet-rtcp.h b/packet-rtcp.h
index 6e935367d3..a2eba6aaf3 100644
--- a/packet-rtcp.h
+++ b/packet-rtcp.h
@@ -1,9 +1,10 @@
/* packet-rtcp.h
- * Declarations for RTCP packet disassembly
*
- * Jason Lango <jal@netapp.com>
- *
- * $Id: packet-rtcp.h,v 1.2 2000/08/11 13:34:01 deniel Exp $
+ * Routines for RTCP dissection
+ * RTCP = Real-time Transport Control Protocol
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Written by Andreas Sikkema <andreas.sikkema@philips.com>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -25,9 +26,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#ifndef __PACKET_RTCP_H__
-#define __PACKET_RTCP_H__
-
-void dissect_rtcp(const u_char *, int, frame_data *, proto_tree *);
-
-#endif
+void rtcp_add_address ( const unsigned char* ip_addr, int prt );
+gboolean dissect_rtcp_heur ( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree );
+void dissect_rtcp ( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree );
+void proto_register_rtcp( void );
diff --git a/packet-rtp.c b/packet-rtp.c
index 88ee2a15bc..6f6008b6ac 100644
--- a/packet-rtp.c
+++ b/packet-rtp.c
@@ -1,9 +1,10 @@
/* packet-rtp.c
- * Routines for RTP packet disassembly
*
- * Jason Lango <jal@netapp.com>
- *
- * $Id: packet-rtp.c,v 1.5 2000/08/13 14:08:43 deniel Exp $
+ * Routines for RTP dissection
+ * RTP = Real time Transport Protocol
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Written by Andreas Sikkema <andreas.sikkema@philips.com>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -23,195 +24,596 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the RTP protocol according to Annex A
+ * of ITU-T Recommendation H.225.0 (02/98) or RFC 1889
*
- *
+ * RTP traffic is handled by an even UDP portnumber. This can be any
+ * port number, but there is a registered port available, port 5004
+ * See Annex B of ITU-T Recommendation H.225.0, section B.7
*/
-#include "config.h"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include "packet.h"
#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+# include <sys/types.h>
#endif
#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
+# include <netinet/in.h>
#endif
+#include <stdio.h>
#include <string.h>
-#include <ctype.h>
-#include <stddef.h>
-#include <glib.h>
-#include "packet.h"
#include "packet-rtp.h"
+#include "packet-h261.h"
+#include "conversation.h"
+
+/* RTP header fields */
+static int proto_rtp = -1;
+static int hf_rtp_version = -1;
+static int hf_rtp_padding = -1;
+static int hf_rtp_extension = -1;
+static int hf_rtp_csrc_count = -1;
+static int hf_rtp_marker = -1;
+static int hf_rtp_payload_type = -1;
+static int hf_rtp_seq_nr = -1;
+static int hf_rtp_timestamp = -1;
+static int hf_rtp_ssrc = -1;
+static int hf_rtp_csrc_item = -1;
+static int hf_rtp_data = -1;
+static int hf_rtp_padding_data = -1;
+static int hf_rtp_padding_count= -1;
+
+/* RTP header extension fields */
+static int hf_rtp_prof_define = -1;
+static int hf_rtp_length = -1;
+static int hf_rtp_hdr_ext = -1;
+
+/* RTP fields defining a sub tree */
+static gint ett_rtp = -1;
+static gint ett_csrc_list = -1;
+static gint ett_hdr_ext = -1;
+
+/*
+ * Fields in the first octet of the RTP header.
+ */
-static int proto_rtp = -1;
+/* Version is the first 2 bits of the first octet*/
+#define RTP_VERSION(octet) ((octet) >> 6)
-static gint ett_rtp = -1;
+/* Padding is the third bit; No need to shift, because true is any value
+ other than 0! */
+#define RTP_PADDING(octet) ((octet) & 0x20)
-#define _RTP_FLAG_BITS(hdr, s, n) \
- ((u_int)(((hdr)->rtp_flag_bits >> (8 - (s) - (n))) & ((1 << (n)) - 1)))
-#define RTP_VERSION(hdr) _RTP_FLAG_BITS(hdr, 0, 2)
-#define RTP_PADDING(hdr) _RTP_FLAG_BITS(hdr, 2, 1)
-#define RTP_EXTENSION(hdr) _RTP_FLAG_BITS(hdr, 3, 1)
-#define RTP_CSRC_COUNT(hdr) _RTP_FLAG_BITS(hdr, 4, 4)
+/* Extension bit is the fourth bit */
+#define RTP_EXTENSION(octet) ((octet) & 0x10)
-#define RTP_MARKER(hdr) ((u_int)((hdr)->rtp_type_bits >> 7))
-#define RTP_PAYLOAD_TYPE(hdr) ((u_int)((hdr)->rtp_type_bits & 0x7F))
+/* CSRC count is the last four bits */
+#define RTP_CSRC_COUNT(octet) ((octet) & 0xF)
-typedef struct rtp_hdr {
- guint8 rtp_flag_bits;
- guint8 rtp_type_bits;
- guint16 rtp_seq;
- guint32 rtp_timestamp;
- guint32 rtp_ssrc;
-} rtp_hdr_t;
+static const value_string rtp_version_vals[] =
+{
+ { 0, "Old VAT Version" },
+ { 1, "First Draft Version" },
+ { 2, "RFC 1889 Version" },
+ { 0, NULL },
+};
+
+/*
+ * Fields in the second octet of the RTP header.
+ */
-typedef struct rtp_hdr_ext {
- guint16 rtp_ext_app; /* defined by RTP profile */
- guint16 rtp_ext_length; /* length of extension data in 32 bit words */
-} rtp_hdr_ext_t;
+/* Marker is the first bit of the second octet */
+#define RTP_MARKER(octet) ((octet) & 0x80)
-void
-dissect_rtp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+/* Payload type is the last 7 bits */
+#define RTP_PAYLOAD_TYPE(octet) ((octet) & 0x7F)
+
+/*
+ * RTP Payload types
+ * Table B.2 / H.225.0
+ */
+#define PT_PCMU 0
+#define PT_PCMA 8
+#define PT_G722 9
+#define PT_G723 4
+#define PT_G728 15
+#define PT_G729 18
+#define PT_H261 31
+#define PT_H263 34
+
+static const value_string rtp_payload_type_vals[] =
+{
+ { PT_PCMU, "ITU-T G.711 PCMU" },
+ { PT_PCMA, "ITU-T G.711 PCMA" },
+ { PT_G722, "ITU-T G.722" },
+ { PT_G723, "ITU-T G.723" },
+ { PT_G728, "ITU-T G.728" },
+ { PT_G729, "ITU-T G.729" },
+ { PT_H261, "ITU-T H.261" },
+ { PT_H263, "ITU-T H.263" },
+ { 0, NULL },
+};
+
+static address fake_addr;
+static int heur_init = FALSE;
+
+static const char rtp_proto[] = "RTP";
+
+void rtp_add_address( const unsigned char* ip_addr, int prt )
{
- proto_tree *rtp_tree;
- proto_item *ti;
- const u_char *data, *dataend;
- rtp_hdr_t hdr;
- int end_offset;
- int ii;
- guint32 *csrc_ptr;
- rtp_hdr_ext_t ext;
-
- OLD_CHECK_DISPLAY_AS_DATA(proto_rtp, pd, offset, fd, tree);
-
- data = &pd[offset];
- dataend = data + END_OF_FRAME;
- end_offset = offset + END_OF_FRAME;
-
- memcpy(&hdr, data, END_OF_FRAME < sizeof(rtp_hdr_t) ?
- END_OF_FRAME : sizeof(rtp_hdr_t));
- hdr.rtp_seq = ntohs(hdr.rtp_seq);
- hdr.rtp_timestamp = ntohl(hdr.rtp_timestamp);
- hdr.rtp_ssrc = ntohl(hdr.rtp_ssrc);
-
- if (check_col(fd, COL_PROTOCOL))
- col_add_str(fd, COL_PROTOCOL, "RTP");
- if (check_col(fd, COL_INFO)) {
- col_add_fstr(fd, COL_INFO, "SSRC=%lu, Seq=%u, Time=%lu%s",
- (u_long) hdr.rtp_ssrc,
- (u_int) hdr.rtp_seq,
- (u_long) hdr.rtp_timestamp,
- RTP_MARKER(&hdr) ? ", Mark" : "");
+ address src_addr;
+ conversation_t* pconv = ( conversation_t* ) NULL;
+
+ src_addr.type = AT_IPv4;
+ src_addr.len = 4;
+ src_addr.data = ip_addr;
+
+ /*
+ * The first time the function is called let the tcp dissector
+ * know that we're interested in traffic
+ */
+ if ( ! heur_init ) {
+ heur_dissector_add( "udp", dissect_rtp_heur );
+ heur_init = TRUE;
}
- rtp_tree = NULL;
+ /*
+ * Check if the ip address an dport combination is not
+ * already registered
+ */
+ pconv = find_conversation( &src_addr, &fake_addr, PT_UDP, prt, 0 );
+
+ /*
+ * If not, add
+ */
+ if ( ! pconv ) {
+ conversation_new( &src_addr, &fake_addr, PT_UDP, (guint32) prt, (guint32) 0, ( void * ) rtp_proto );
+ }
+
+}
+
+#if 0
+static void rtp_init( void )
+{
+ unsigned char* tmp_data;
+ int i;
+
+ /* Create a fake adddress... */
+ fake_addr.type = AT_IPv4;
+ fake_addr.len = 4;
- if (tree) {
- ti = proto_tree_add_item(tree, proto_rtp, NullTVB, offset, END_OF_FRAME,
- FALSE);
- rtp_tree = proto_item_add_subtree(ti, ett_rtp);
+ tmp_data = malloc( fake_addr.len );
+ for ( i = 0; i < fake_addr.len; i++) {
+ tmp_data[i] = 0;
}
+ fake_addr.data = tmp_data;
+}
+#endif
- if (!rtp_tree)
- return;
-
- if (offset >= end_offset)
- goto bad_len;
- proto_tree_add_text(rtp_tree, NullTVB, offset, 1, "Version: %u (%s)",
- RTP_VERSION(&hdr),
- RTP_VERSION(&hdr) == 3 ? "New Unknown Version" :
- RTP_VERSION(&hdr) == 2 ? "RFC 1889 Version" :
- RTP_VERSION(&hdr) == 1 ? "First Draft Version" :
- "Old Vat Version");
- proto_tree_add_text(rtp_tree, NullTVB, offset, 1, "Padding: %u",
- RTP_PADDING(&hdr));
- proto_tree_add_text(rtp_tree, NullTVB, offset, 1, "Extension: %u",
- RTP_EXTENSION(&hdr));
- proto_tree_add_text(rtp_tree, NullTVB, offset, 1, "CSRC Count: %u",
- RTP_CSRC_COUNT(&hdr));
- offset++;
-
- if (offset >= end_offset)
- goto bad_len;
- proto_tree_add_text(rtp_tree, NullTVB, offset, 1, "Marker: %u",
- RTP_MARKER(&hdr));
- proto_tree_add_text(rtp_tree, NullTVB, offset, 1, "Payload Type: %u",
- RTP_PAYLOAD_TYPE(&hdr));
- offset++;
-
- if (offset >= end_offset)
- goto bad_len;
- proto_tree_add_text(rtp_tree, NullTVB, offset, 2, "Seq: %u",
- (u_int) hdr.rtp_seq);
- offset += 2;
-
- if (offset >= end_offset)
- goto bad_len;
- proto_tree_add_text(rtp_tree, NullTVB, offset, 4, "Timestamp: %lu",
- (u_long) hdr.rtp_timestamp);
- offset += 4;
-
- if (offset >= end_offset)
- goto bad_len;
- proto_tree_add_text(rtp_tree, NullTVB, offset, 4, "SSRC: %lu",
- (u_long) hdr.rtp_ssrc);
- offset += 4;
-
- csrc_ptr = (guint32*) (data + sizeof(rtp_hdr_t));
- for (ii = 0; ii < RTP_CSRC_COUNT(&hdr); ii++) {
- guint32 csrc;
- if (offset >= end_offset)
- goto bad_len;
- csrc = pntohl(csrc_ptr);
- proto_tree_add_text(rtp_tree, NullTVB, offset, 4, "CSRC %d: %lu",
- ii + 1, (u_long) csrc);
- offset += 4;
- csrc_ptr++;
+gboolean
+dissect_rtp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ /* This is a heuristic dissector, which means we get all the tcp traffic
+ * not send to a known dissector!
+ * So we first check if the frame is really meant for us.
+ */
+ conversation_t* pconv;
+ if ( ( pconv = find_conversation( &pi.src, &fake_addr, pi.ptype, pi.srcport, 0 ) ) == NULL ) {
+ /*
+ * The source ip:port combination was not what we were looking for, check the destination
+ */
+ if ( ( pconv = find_conversation( &pi.dst, &fake_addr, pi.ptype, pi.destport, 0 ) ) == NULL ) {
+ return FALSE;
+ }
}
- if (RTP_EXTENSION(&hdr)) {
- memcpy(&ext, data + sizeof(rtp_hdr_t),
- END_OF_FRAME < sizeof(rtp_hdr_ext_t) ?
- END_OF_FRAME : sizeof(rtp_hdr_ext_t));
- ext.rtp_ext_app = ntohs(ext.rtp_ext_app);
- ext.rtp_ext_length = ntohs(ext.rtp_ext_length);
+ /*
+ * An RTP conversation always contains data
+ */
+ if ( pconv->data == NULL )
+ return FALSE;
- proto_tree_add_text(rtp_tree, NullTVB, offset, 2,
- "Extension-defined: %x", (u_int) ext.rtp_ext_app);
- offset += 2;
- proto_tree_add_text(rtp_tree, NullTVB, offset, 2,
- "Extension length: %u", (u_int) ext.rtp_ext_length);
- offset += 2;
- proto_tree_add_text(rtp_tree, NullTVB, offset, 4 * ext.rtp_ext_length,
- "Extension Data (%d bytes)",
- (int) 4 * ext.rtp_ext_length);
- offset += 4 * ext.rtp_ext_length;
+ /*
+ * An RTP conversation data always contains "RTP"
+ */
+ if ( strcmp( pconv->data, rtp_proto ) != 0 )
+ return FALSE;
+
+ dissect_rtp( tvb, pinfo, tree );
+
+ return TRUE;
+}
+
+void
+dissect_rtp_data( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *rtp_tree, int offset, unsigned int data_len, unsigned int payload_type )
+{
+ tvbuff_t *newtvb;
+
+ switch( payload_type ) {
+ case PT_H261:
+ /*
+ * What does reported length DO?
+ */
+ newtvb = tvb_new_subset( tvb, offset, data_len, -1 );
+ dissect_h261(newtvb, pinfo, tree);
+ break;
+ default:
+ proto_tree_add_bytes( rtp_tree, hf_rtp_data, tvb, offset, data_len, tvb_get_ptr( tvb, offset, data_len ) );
+ break;
}
+}
- proto_tree_add_text(rtp_tree, NullTVB, offset, END_OF_FRAME,
- "Data (%d bytes)", END_OF_FRAME);
+void
+dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *rtp_tree = NULL;
+ proto_tree *rtp_csrc_tree = NULL;
+ guint8 octet;
+ unsigned int version;
+ gboolean padding_set;
+ gboolean extension_set;
+ unsigned int csrc_count;
+ gboolean marker_set;
+ unsigned int payload_type;
+ unsigned int i = 0;
+ unsigned int hdr_extension= 0;
+ unsigned int padding_count= 0;
+ unsigned int offset = 0;
+ guint16 seq_num;
+ guint32 timestamp;
+ guint32 sync_src;
+ guint32 csrc_item;
+
+ pinfo->current_proto = "RTP";
+
+ /* Get the fields in the first octet */
+ octet = tvb_get_guint8( tvb, offset );
+ version = RTP_VERSION( octet );
+ padding_set = RTP_PADDING( octet );
+ extension_set = RTP_EXTENSION( octet );
+ csrc_count = RTP_CSRC_COUNT( octet );
+
+ /* Get the fields in the second octet */
+ octet = tvb_get_guint8( tvb, offset + 1 );
+ marker_set = RTP_MARKER( octet );
+ payload_type = RTP_PAYLOAD_TYPE( octet );
+
+ /* Get the subsequent fields */
+ seq_num = tvb_get_ntohs( tvb, offset + 2 );
+ timestamp = tvb_get_ntohl( tvb, offset + 4 );
+ sync_src = tvb_get_ntohl( tvb, offset + 8 );
+
+ if ( check_col( pinfo->fd, COL_PROTOCOL ) ) {
+ col_add_str( pinfo->fd, COL_PROTOCOL, "RTP" );
+ }
+
+ if ( check_col( pinfo->fd, COL_INFO) ) {
+ col_add_fstr( pinfo->fd, COL_INFO,
+ "Payload type=%s, SSRC=%u, Seq=%u, Time=%u%s",
+ val_to_str( payload_type, rtp_payload_type_vals,
+ "Unknown (%u)" ),
+ sync_src,
+ seq_num,
+ timestamp,
+ marker_set ? ", Mark" : "");
+ }
+
+ if ( tree ) {
+ ti = proto_tree_add_item( tree, proto_rtp, tvb, offset, tvb_length_remaining( tvb, offset ), FALSE );
+ rtp_tree = proto_item_add_subtree( ti, ett_rtp );
+
+ proto_tree_add_uint( rtp_tree, hf_rtp_version, tvb,
+ offset, 1, version );
+ proto_tree_add_boolean( rtp_tree, hf_rtp_padding, tvb,
+ offset, 1, padding_set );
+ proto_tree_add_boolean( rtp_tree, hf_rtp_extension, tvb,
+ offset, 1, extension_set );
+ proto_tree_add_uint( rtp_tree, hf_rtp_csrc_count, tvb,
+ offset, 1, csrc_count );
+ offset++;
+
+ proto_tree_add_boolean( rtp_tree, hf_rtp_marker, tvb, offset,
+ 1, marker_set );
+ proto_tree_add_uint( rtp_tree, hf_rtp_payload_type, tvb,
+ offset, 1, payload_type );
+ offset++;
+
+ /* Sequence number 16 bits (2 octets) */
+ proto_tree_add_uint( rtp_tree, hf_rtp_seq_nr, tvb, offset, 2, seq_num );
+ offset += 2;
+
+ /* Timestamp 32 bits (4 octets) */
+ proto_tree_add_uint( rtp_tree, hf_rtp_timestamp, tvb, offset, 4, timestamp );
+ offset += 4;
- return;
+ /* Synchronization source identifier 32 bits (4 octets) */
+ proto_tree_add_uint( rtp_tree, hf_rtp_ssrc, tvb, offset, 4, sync_src );
+ offset += 4;
-bad_len:
- proto_tree_add_text(rtp_tree, NullTVB, end_offset, 0,
- "Unexpected end of packet");
+ /* CSRC list*/
+ if ( csrc_count > 0 ) {
+ ti = proto_tree_add_text(rtp_tree, tvb, offset, csrc_count * 4, "Contributing Source identifiers");
+ rtp_csrc_tree = proto_item_add_subtree( ti, ett_csrc_list );
+ for (i = 0; i < csrc_count; i++ ) {
+ csrc_item = tvb_get_ntohl( tvb, offset );
+ proto_tree_add_uint_format( rtp_csrc_tree,
+ hf_rtp_csrc_item, tvb, offset, 4,
+ csrc_item,
+ "CSRC item %d: %u",
+ i, csrc_item );
+ offset += 4;
+ }
+ }
+
+ /* Optional RTP header extension */
+ if ( extension_set ) {
+ /* Defined by profile field is 16 bits (2 octets) */
+ proto_tree_add_uint( rtp_tree, hf_rtp_prof_define, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ hdr_extension = tvb_get_ntohs( tvb, offset );
+ proto_tree_add_uint( rtp_tree, hf_rtp_length, tvb,
+ offset, 2, hdr_extension);
+ if ( hdr_extension > 0 ) {
+ ti = proto_tree_add_text(rtp_tree, tvb, offset, csrc_count * 4, "Header extensions");
+ /* I'm re-using the old tree variable here
+ from the CSRC list!*/
+ rtp_csrc_tree = proto_item_add_subtree( ti,
+ ett_hdr_ext );
+ for (i = 0; i < hdr_extension; i++ ) {
+ proto_tree_add_uint( rtp_csrc_tree, hf_rtp_hdr_ext, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ }
+ }
+ }
+ /* Find the padding
+ * The padding count is found in the LAST octet of the packet
+ * This contains the number of octets that can be ignored at
+ * the end of the packet
+ */
+ if ( padding_set ) {
+ padding_count = tvb_get_guint8( tvb, tvb_length( tvb ) - 1 );
+ if ( padding_count > 0 ) {
+ dissect_rtp_data( tvb, pinfo, tree, rtp_tree, offset, tvb_length( tvb ) - padding_count, payload_type );
+ offset = tvb_length( tvb ) - padding_count;
+ proto_tree_add_item( rtp_tree, hf_rtp_padding_data, tvb, offset, padding_count - 1, FALSE );
+ offset += padding_count - 1;
+ proto_tree_add_item( rtp_tree, hf_rtp_padding_count, tvb, offset, 1, FALSE );
+ }
+ else {
+ proto_tree_add_item( rtp_tree, hf_rtp_padding_count, tvb, tvb_length( tvb ) - 1, 1, FALSE );
+ }
+ }
+ else {
+ dissect_rtp_data( tvb, pinfo, tree, rtp_tree, offset, tvb_length_remaining( tvb, offset ) - padding_count, payload_type );
+ }
+ }
}
void
proto_register_rtp(void)
{
-/* static hf_register_info hf[] = {
- { &variable,
- { "Name", "rtp.abbreviation", TYPE, VALS_POINTER }},
- };*/
- static gint *ett[] = {
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_rtp_version,
+ {
+ "Version",
+ "rtp.version",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtp_version_vals),
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_padding,
+ {
+ "Padding",
+ "rtp.padding",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_extension,
+ {
+ "Extension",
+ "rtp.ext",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_csrc_count,
+ {
+ "Contributing source identifiers count",
+ "rtp.cc",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_marker,
+ {
+ "Marker",
+ "rtp.marker",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_payload_type,
+ {
+ "Payload type",
+ "rtp.p_type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtp_payload_type_vals),
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_seq_nr,
+ {
+ "Sequence number",
+ "rtp.seq",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_timestamp,
+ {
+ "Timestamp",
+ "rtp.timestamp",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_ssrc,
+ {
+ "Synchronization Source identifier",
+ "rtp.ssrc",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_prof_define,
+ {
+ "Defined by profile",
+ "rtp.ext.profile",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_length,
+ {
+ "Extension length",
+ "rtp.ext.len",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_csrc_item,
+ {
+ "CSRC item",
+ "rtp.csrc.item",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_hdr_ext,
+ {
+ "Header extension",
+ "rtp.hdr_ext",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_data,
+ {
+ "Payload",
+ "rtp.payload",
+ FT_BYTES,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_padding_data,
+ {
+ "Padding data",
+ "rtp.padding.data",
+ FT_BYTES,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_rtp_padding_count,
+ {
+ "Padding count",
+ "rtp.padding.count",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+};
+
+ static gint *ett[] =
+ {
&ett_rtp,
+ &ett_csrc_list,
+ &ett_hdr_ext,
};
- proto_rtp = proto_register_protocol("Realtime Transport Protocol", "rtp");
- /* proto_register_field_array(proto_rtp, hf, array_length(hf));*/
+
+ proto_rtp = proto_register_protocol("Real-Time Transport Protocol", "rtp");
+ proto_register_field_array(proto_rtp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+#if 0
+ register_init_routine( &rtp_init );
+#endif
}
diff --git a/packet-rtp.h b/packet-rtp.h
index 8d8ab631bf..8df5092c45 100644
--- a/packet-rtp.h
+++ b/packet-rtp.h
@@ -1,9 +1,10 @@
/* packet-rtp.h
- * Declarations for RTP packet disassembly
*
- * Jason Lango <jal@netapp.com>
- *
- * $Id: packet-rtp.h,v 1.2 2000/08/11 13:34:01 deniel Exp $
+ * Routines for RTP dissection
+ * RTP = Real time Transport Protocol
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Written by Andreas Sikkema <andreas.sikkema@philips.com>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -25,9 +26,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#ifndef __PACKET_RTP_H__
-#define __PACKET_RTP_H__
-
-void dissect_rtp(const u_char *, int, frame_data *, proto_tree *);
-
-#endif
+void rtp_add_address ( const unsigned char* ip_addr, int prt );
+gboolean dissect_rtp_heur ( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree );
+void dissect_rtp ( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree );
+void proto_register_rtp( void );
diff --git a/packet-rtsp.c b/packet-rtsp.c
index 257c4c3207..da9e88087a 100644
--- a/packet-rtsp.c
+++ b/packet-rtsp.c
@@ -4,7 +4,7 @@
* Jason Lango <jal@netapp.com>
* Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
*
- * $Id: packet-rtsp.c,v 1.19 2000/09/30 05:46:27 guy Exp $
+ * $Id: packet-rtsp.c,v 1.20 2000/10/19 06:45:11 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -126,14 +126,14 @@ rtsp_create_conversation(const u_char *trans_begin, const u_char *trans_end)
conv = conversation_new(&pi.src, &pi.dst, PT_UDP, s_data_port,
c_data_port, 0);
- old_conversation_set_dissector(conv, dissect_rtp);
+ conversation_set_dissector(conv, dissect_rtp);
if (!c_mon_port || !s_mon_port)
return;
conv = conversation_new(&pi.src, &pi.dst, PT_UDP, s_mon_port,
c_mon_port, 0);
- old_conversation_set_dissector(conv, dissect_rtcp);
+ conversation_set_dissector(conv, dissect_rtcp);
}
static void dissect_rtsp(const u_char *pd, int offset, frame_data *fd,
diff --git a/packet-tpkt.c b/packet-tpkt.c
new file mode 100644
index 0000000000..fb71911573
--- /dev/null
+++ b/packet-tpkt.c
@@ -0,0 +1,187 @@
+/* packet-tpkt.c
+ *
+ * Routines for TPKT dissection
+ * Copyright 2000, Philips Electronics N.V.
+ * Andreas Sikkema <andreas.sikkema@philips.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the TPKT protocol according to
+ * RFC 1006
+ *
+ * IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT
+ *
+ * Please examine the dissector. It is NOT defined in the normal way!
+ * Some variables are references and the dissector also returns a
+ * value! And no, this is not a heuristic dissector!
+ *
+ * IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include "packet.h"
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-tpkt.h"
+
+/* TPKT header fields */
+static int proto_tpkt = -1;
+static int hf_tpkt_version = -1;
+static int hf_tpkt_reserved = -1;
+static int hf_tpkt_length = -1;
+
+/* TPKT fields defining a sub tree */
+static gint ett_tpkt = -1;
+
+int
+is_tpkt( tvbuff_t *tvb, unsigned int* offset )
+{
+ if ( (*offset) + 4 > tvb_length( tvb ) ) return FALSE;
+ if ( ! ( ( tvb_get_guint8( tvb, ( *offset ) ) == 3 ) &&
+ ( tvb_get_guint8( tvb, ( *offset ) + 1 ) == 0 ) ) ) return FALSE;
+
+ return TRUE;
+}
+
+int
+dissect_tpkt( tvbuff_t *tvb, unsigned int* offset, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *tpkt_tree = NULL;
+ unsigned int data_len = 0;
+
+
+ pinfo->current_proto = "TPKT";
+
+ /* There should at least be 4 bytes left in the frame */
+ if ( (*offset) + 4 > tvb_length( tvb ) ) return -1;
+ /*
+ * The first octet should be 3 and the second one should be 0
+ * The H.323 implementers guide suggests that this migh not
+ * always be the case....
+ */
+ if ( ! ( ( tvb_get_guint8( tvb, ( *offset ) ) == 3 ) &&
+ ( tvb_get_guint8( tvb, ( *offset ) + 1 ) == 0 ) ) ) return -1;
+
+ if ( check_col( pinfo->fd, COL_PROTOCOL ) ) {
+ col_add_str( pinfo->fd, COL_PROTOCOL, "TPKT" );
+ }
+
+ if ( check_col( pinfo->fd, COL_INFO) ) {
+ /*data_len = pntohs( &pd[ (*offset) + 2 ] );*/
+ data_len = tvb_get_ntohs( tvb, (*offset) + 2 );
+
+ col_add_fstr( pinfo->fd, COL_INFO, "TPKT Data length = %d", data_len );
+ }
+
+ if ( tree ) {
+ ti = proto_tree_add_item( tree, proto_tpkt, tvb, (*offset), 4, FALSE );
+ tpkt_tree = proto_item_add_subtree( ti, ett_tpkt );
+ /* Version 1st octet */
+ proto_tree_add_item( tpkt_tree, hf_tpkt_version, tvb, (*offset), 1, FALSE );
+ (*offset)++;
+ /* Reserved octet*/
+ proto_tree_add_item( tpkt_tree, hf_tpkt_reserved, tvb, (*offset), 1, FALSE );
+ (*offset)++;
+ }
+ else {
+ (*offset) += 2;
+ }
+ /* Length, two octets */
+ /*data_len = pntohs( &pd[ (*offset) ] );*/
+ data_len = tvb_get_ntohs( tvb, (*offset) );
+
+ if ( tree )
+ proto_tree_add_uint_format( tpkt_tree, hf_tpkt_length, tvb, (*offset), 2, data_len, "Length: %d", data_len );
+
+ (*offset) += 2;
+ return data_len;
+}
+
+void
+proto_register_tpkt(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_tpkt_version,
+ {
+ "Version",
+ "tpkt.version",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_tpkt_reserved,
+ {
+ "Reserved",
+ "tpkt.reserved",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+ {
+ &hf_tpkt_length,
+ {
+ "Length",
+ "tpkt.length",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ ""
+ }
+ },
+};
+
+ static gint *ett[] =
+ {
+ &ett_tpkt,
+ };
+
+
+ proto_tpkt = proto_register_protocol("TPKT", "tpkt");
+ proto_register_field_array(proto_tpkt, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/packet-tpkt.h b/packet-tpkt.h
new file mode 100644
index 0000000000..2697a20196
--- /dev/null
+++ b/packet-tpkt.h
@@ -0,0 +1,30 @@
+/* packet-tpkt.h
+ *
+ * Routines for TPKT dissection
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Andreas Sikkema <andreas.sikkema@philips.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+int is_tpkt( tvbuff_t *tvb, unsigned int* offset );
+int dissect_tpkt( tvbuff_t *tvb, unsigned int* offset, packet_info *pinfo, proto_tree *tree );
+void proto_register_tpkt( void );