bugfix to a bug reported by Ian Schorr:
[obnox/wireshark/wip.git] / packet-rtcp.c
index a80b2e5d182fc963a7193c113dcb443063ff9e60..ed63a096904ff344480d3a345c28863de0f2f8fb 100644 (file)
@@ -1,26 +1,29 @@
 /* packet-rtcp.c
+ *
+ * $Id: packet-rtcp.c,v 1.46 2004/06/30 21:08:58 etxrab 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>
+ * Written by Andreas Sikkema <h323@ramdyne.nl>
+ *
+ * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * 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.
  * 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 
+ * 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
  *
+ * See also http://www.iana.org/assignments/rtp-parameters
  */
 
 
 #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 <epan/packet.h>
 
 #include <stdio.h>
 #include <string.h>
 #if 0
 #include "packet-ntp.h"
 #endif
-#include "conversation.h"
+#include <epan/conversation.h>
+
+#include "prefs.h"
+
 
 /* Version is the first 2 bits of the first octet*/
 #define RTCP_VERSION(octet)    ((octet) >> 6)
@@ -72,7 +71,9 @@
 /* Receiver/ Sender count is the 5 last bits  */
 #define RTCP_COUNT(octet)      ((octet) & 0x1F)
 
-static const value_string rtcp_version_vals[] = 
+static dissector_handle_t rtcp_handle;
+
+static const value_string rtcp_version_vals[] =
 {
        { 0, "Old VAT Version" },
        { 1, "First Draft Version" },
@@ -81,16 +82,18 @@ static const value_string rtcp_version_vals[] =
 };
 
 /* RTCP packet types according to Section A.11.1 */
+/* And http://www.iana.org/assignments/rtp-parameters */
 #define RTCP_SR   200
 #define RTCP_RR   201
 #define RTCP_SDES 202
 #define RTCP_BYE  203
 #define RTCP_APP  204
+#define RTCP_XR          207
 /* 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[] = 
+static const value_string rtcp_packet_type_vals[] =
 {
        { RTCP_SR,   "Sender Report" },
        { RTCP_RR,   "Receiver Report" },
@@ -99,6 +102,7 @@ static const value_string rtcp_packet_type_vals[] =
        { RTCP_APP,  "Application specific" },
        { RTCP_FIR,  "Full Intra-frame Request (H.261)" },
        { RTCP_NACK, "Negative Acknowledgement (H.261)" },
+       { RTCP_XR,   "Extended report"},
        { 0,         NULL },
 };
 
@@ -112,8 +116,9 @@ static const value_string rtcp_packet_type_vals[] =
 #define RTCP_SDES_TOOL   6
 #define RTCP_SDES_NOTE   7
 #define RTCP_SDES_PRIV   8
+#define RTCP_SDES_H323_CADDR   9
 
-static const value_string rtcp_sdes_type_vals[] = 
+static const value_string rtcp_sdes_type_vals[] =
 {
        { RTCP_SDES_END,   "END" },
        { RTCP_SDES_CNAME, "CNAME (user and domain)" },
@@ -124,9 +129,35 @@ static const value_string rtcp_sdes_type_vals[] =
        { RTCP_SDES_TOOL,  "TOOL (name/version of source app)" },
        { RTCP_SDES_NOTE,  "NOTE (note about source)" },
        { RTCP_SDES_PRIV,  "PRIV (private extensions)" },
+       { RTCP_SDES_H323_CADDR,"H323-CADDR (H.323 callable address)"},
        { 0,               NULL },
 };
+/* RTCP Application PoC1 Value strings */
+static const value_string rtcp_app_poc1_floor_cnt_type_vals[] =
+{
+       {  0,   "Floor Request"},
+       {  1,   "Floor Grant"},
+       {  2,   "Floor Taken"},
+       {  3,   "Floor Deny"},
+       {  4,   "Floor Release"},
+       {  5,   "Floor Idle"},
+       {  6,   "Floor Revoke"},
+       {  0,   NULL },
+};
+
+static const value_string rtcp_app_poc1_reason_code1_vals[] =
+{
+       {  1,   "Floor already in use"},
+       {  2,   "Internal PoC server error"},
+       {  0,   NULL },
+};
 
+static const value_string rtcp_app_poc1_reason_code2_vals[] =
+{
+       {  1,   "Only one user"},
+       {  2,   "Talk burst too long"},
+       {  0,   NULL },
+};
 /* RTCP header fields                   */
 static int proto_rtcp                = -1;
 static int hf_rtcp_version           = -1;
@@ -143,7 +174,7 @@ 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 
+/* 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;
@@ -165,111 +196,178 @@ 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;
+static int hf_rtcp_app_poc1_subtype  = -1;
+static int hf_rtcp_app_poc1_sip_uri  = -1;
+static int hf_rtcp_app_poc1_disp_name = -1;
+static int hf_rtcp_app_poc1_last_pkt_seq_no = -1;
+static int hf_rtcp_app_poc1_reason_code1       = -1;
+static int hf_rtcp_app_poc1_item_len           = -1;
+static int hf_rtcp_app_poc1_reason1_phrase     = -1;
+static int hf_rtcp_app_poc1_reason_code2       = -1;
+static int hf_rtcp_app_poc1_additionalinfo     = -1;
+
+/* RTCP setup fields */
+static int hf_rtcp_setup        = -1;
+static int hf_rtcp_setup_frame  = -1;
+static int hf_rtcp_setup_method = -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 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 gint ett_PoC1                   = -1;
+static gint ett_rtcp_setup             = -1;
 
 static address fake_addr;
 static int heur_init = FALSE;
 
-static char rtcp_proto[] = "RTCP";
-
 static gboolean dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo,
     proto_tree *tree );
+static void dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo,
+     proto_tree *tree );
+static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
 
-void rtcp_add_address( const unsigned char* ip_addr, int prt )
+/* Preferences bool to control whether or not setup info should be shown */
+static gboolean global_rtcp_show_setup_info = TRUE;
+
+/* Memory chunk for storing conversation and per-packet info */
+static GMemChunk *rtcp_conversations = NULL;
+
+
+void rtcp_add_address( packet_info *pinfo,
+                       const unsigned char* ip_addr, int port,
+                       int other_port,
+                       gchar *setup_method, guint32 setup_frame_number)
 {
        address src_addr;
-       conversation_t* pconv = ( conversation_t* ) NULL;
+       conversation_t* p_conv;
+       struct _rtcp_conversation_info *p_conv_data = NULL;
+
+       /*
+        * If this isn't the first time this packet has been processed,
+        * we've already done this work, so we don't need to do it
+        * again.
+        */
+       if (pinfo->fd->flags.visited)
+       {
+               return;
+       }
 
-       src_addr.type = AT_IPv4;
-       src_addr.len = 4;
+       src_addr.type = pinfo->net_src.type;
+       src_addr.len = pinfo->net_src.len;
        src_addr.data = ip_addr;
 
        /*
         * The first time the function is called let the udp dissector
         * know that we're interested in traffic
-        */
+        * TODO???
+        *
        if ( ! heur_init ) {
                heur_dissector_add( "udp", dissect_rtcp_heur, proto_rtcp );
                heur_init = TRUE;
        }
+       */
 
        /*
-        * Check if the ip address and port combination is not 
+        * Check if the ip address and port combination is not
         * already registered
         */
-       pconv = find_conversation( &src_addr, &fake_addr, PT_UDP, prt, 0, 0 );
+       p_conv = find_conversation( &src_addr, &src_addr, PT_UDP, port, other_port,
+                                   NO_ADDR_B | (!other_port ? NO_PORT_B : 0));
 
        /*
         * If not, add
         */
-       if ( ! pconv ) {
-               conversation_new( &src_addr, &fake_addr, PT_UDP, (guint32) prt,
-                   (guint32) 0, (void*) rtcp_proto, 0 );
+       if ( ! p_conv ) {
+               /* Create conversation data */
+               p_conv_data = g_mem_chunk_alloc(rtcp_conversations);
+
+               /* Check length first time we look at method string */
+               strncpy(p_conv_data->method, setup_method,
+                       (strlen(setup_method)+1 <= MAX_RTCP_SETUP_METHOD_SIZE) ?
+                           strlen(setup_method)+1 :
+                           MAX_RTCP_SETUP_METHOD_SIZE);
+               p_conv_data->method[MAX_RTCP_SETUP_METHOD_SIZE] = '\0';
+               p_conv_data->frame_number = setup_frame_number;
+
+               /* Create conversation with this data */
+               p_conv = conversation_new( &src_addr, &src_addr, PT_UDP,
+                                          (guint32)port, (guint32)other_port,
+                                          NO_ADDR2 | (!other_port ? NO_PORT2 : 0));
+               conversation_add_proto_data(p_conv, proto_rtcp, p_conv_data);
+
+               /* Set dissector */
+               conversation_set_dissector(p_conv, rtcp_handle);
+       }
+       else
+       {
+               /* Update existing conversation data */
+               p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
+               strcpy(p_conv_data->method, setup_method);
+               p_conv_data->frame_number = setup_frame_number;
        }
-
 }
 
-#if 0
-static void rtcp_init( void ) 
+static void rtcp_init( void )
 {
        unsigned char* tmp_data;
        int i;
 
+       /* (Re)allocate mem chunk for conversations */
+       if (rtcp_conversations)
+       {
+               g_mem_chunk_destroy(rtcp_conversations);
+       }
+       rtcp_conversations = g_mem_chunk_new("rtcp_conversations",
+                                            sizeof(struct _rtcp_conversation_info),
+                                            20 * sizeof(struct _rtcp_conversation_info),
+                                            G_ALLOC_ONLY);
+
+
        /* Create a fake adddress... */
        fake_addr.type = AT_IPv4;
        fake_addr.len = 4;
 
-       tmp_data = malloc( fake_addr.len );
+       tmp_data = g_malloc( fake_addr.len );
        for ( i = 0; i < fake_addr.len; i++) {
                tmp_data[i] = 0;
        }
        fake_addr.data = tmp_data;
 }
-#endif
 
 static gboolean
 dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
 {
        conversation_t* pconv;
 
-       if (!proto_is_protocol_enabled(proto_rtcp))
-               return FALSE;   /* RTCP has been disabled */
-
        /* 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.
         */
-       if ( ( pconv = find_conversation( &pi.src, &fake_addr, pi.ptype,
-           pi.srcport, 0, 0 ) ) == NULL ) {
+       if ( ( pconv = find_conversation( &pinfo->src, &fake_addr, pinfo->ptype,
+           pinfo->srcport, 0, 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, 0 ) ) == NULL ) {
+               if ( ( pconv = find_conversation( &pinfo->dst, &fake_addr,
+                   pinfo->ptype, pinfo->destport, 0, 0 ) ) == NULL ) {
                        return FALSE;
                }
        }
 
 
        /*
-        * An RTCP conversation always contains data
-        */
-       if ( pconv->data == NULL )
-               return FALSE;
-
-       /*
-        * An RTCP conversation data always contains "RTCP"
+        * An RTCP conversation always has a data item for RTCP.
+        * (Its existence is sufficient to indicate that this is an RTCP
+        * conversation.)
         */
-       if ( strcmp( pconv->data, rtcp_proto ) != 0 )
+       if (conversation_get_proto_data(pconv, proto_rtcp) == NULL)
                return FALSE;
 
        /*
@@ -282,10 +380,10 @@ dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
 
 
 static int
-dissect_rtcp_nack( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
+dissect_rtcp_nack( tvbuff_t *tvb, int offset, proto_tree *tree )
 {
        /* Packet type = FIR (H261) */
-       proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 31 );
+       proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
        offset++;
        /* Packet type, 8 bits  = APP */
        proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
@@ -298,7 +396,7 @@ dissect_rtcp_nack( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
        /* 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;
@@ -311,10 +409,10 @@ dissect_rtcp_nack( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
 }
 
 static int
-dissect_rtcp_fir( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
+dissect_rtcp_fir( tvbuff_t *tvb, int offset, proto_tree *tree )
 {
        /* Packet type = FIR (H261) */
-       proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 31 );
+       proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
        offset++;
        /* Packet type, 8 bits  = APP */
        proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
@@ -327,16 +425,25 @@ dissect_rtcp_fir( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
        /* SSRC  */
        proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
        offset += 4;
-       
+
        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 )
+dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree,
+    unsigned int padding, unsigned int packet_len, guint rtcp_subtype )
 {
        unsigned int counter = 0;
        char ascii_name[5];
+       guint sdes_type         = 0;
+       guint item_len          = 0;
+       guint items_start_offset;
+       proto_tree *PoC1_tree;
+       proto_item *PoC1_item;
+
+       /* XXX If more application types are to be dissected it may be useful to use a table like in packet-sip.c */
+       static const char app_name_str[] = "PoC1";
+
 
        /* SSRC / CSRC */
        proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
@@ -350,57 +457,145 @@ dissect_rtcp_app( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
        ascii_name[4] = '\0';
        proto_tree_add_string( tree, hf_rtcp_name_ascii, tvb, offset, 4,
            ascii_name );
-       offset += 4;
-       packet_len -= 4;
+       if ( strncasecmp(ascii_name,app_name_str,4 ) != 0 ){ /* Not PoC1 */
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_fstr(pinfo->cinfo, COL_INFO,"( %s ) subtype=%u",ascii_name, rtcp_subtype);
+               offset += 4;
+               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;
+       }else{/* PoC1 Application */
+               proto_item *item;
+               item = proto_tree_add_uint( tree, hf_rtcp_app_poc1_subtype, tvb, offset - 8, 1, rtcp_subtype );
+               PROTO_ITEM_SET_GENERATED(item);
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_fstr(pinfo->cinfo, COL_INFO,"(%s) subtype=%s",ascii_name,
+                               val_to_str(rtcp_subtype,rtcp_app_poc1_floor_cnt_type_vals,"unknown (%u)") );
+               offset += 4;
+               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 );
+               }
+               /* Create a subtree for the PoC1 Application items; we don't yet know
+                  the length */
+               items_start_offset = offset;
 
-       /* 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;
+               PoC1_item = proto_tree_add_text(tree, tvb, offset, packet_len,
+                   "PoC1 Application specific data");
+               PoC1_tree = proto_item_add_subtree( PoC1_item, ett_PoC1 );
 
-       return offset;
+
+               proto_tree_add_item( PoC1_tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
+               switch ( rtcp_subtype ) {
+                       case 2:
+                               sdes_type = tvb_get_guint8( tvb, offset );
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
+                               offset++;
+                               packet_len--;
+                               /* Item length, 8 bits */
+                               item_len = tvb_get_guint8( tvb, offset );
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
+                               offset++;
+                               packet_len--;
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_sip_uri, tvb, offset, item_len, FALSE );
+                               offset = offset + item_len;
+                               packet_len = packet_len - item_len;
+                               sdes_type = tvb_get_guint8( tvb, offset );
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
+                               offset++;
+                               packet_len--;
+                               /* Item length, 8 bits */
+                               item_len = tvb_get_guint8( tvb, offset );
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
+                               offset++;
+                               packet_len--;
+                               if ( item_len != 0 )
+                                       proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_disp_name, tvb, offset, item_len, FALSE );
+                               offset = offset + item_len;
+                               packet_len = packet_len - item_len;
+                               break;
+                       case 3:
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason_code1, tvb, offset, 1, FALSE );
+                               offset++;
+                               packet_len--;
+                               /* Item length, 8 bits */
+                               item_len = tvb_get_guint8( tvb, offset );
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_item_len, tvb, offset, 1, FALSE );
+                               offset++;
+                               packet_len--;
+                               if ( item_len != 0 )
+                                       proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason1_phrase, tvb, offset, item_len, FALSE );
+                               offset = offset + item_len;
+                               packet_len = packet_len - item_len;
+                               break;
+                       case 4:
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_last_pkt_seq_no, tvb, offset, 2, FALSE );
+                               proto_tree_add_text(PoC1_tree, tvb, offset + 2, 2, "Padding 2 bytes");
+                               offset += 4;
+                               packet_len-=4;
+                               break;
+                       case 6:
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason_code2, tvb, offset, 2, FALSE );
+                               proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_additionalinfo, tvb, offset + 2, 2, FALSE );
+                               offset += 4;
+                               packet_len-=4;
+                               break;
+                       default:
+                               break;
+               }
+               offset += packet_len;
+               return offset;
+       }
 }
 
+
 static int
-dissect_rtcp_bye( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
-    int count )
+dissect_rtcp_bye( tvbuff_t *tvb, int offset, proto_tree *tree,
+    unsigned int count )
 {
        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 ) );
+               proto_tree_add_item( tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
                offset += 4;
+               chunk++;
        }
 
-       /* 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++;
+       if ( tvb_reported_length_remaining( tvb, offset ) > 0 ) {
+               /* 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;
+               reason_text = tvb_get_string(tvb, offset, reason_length);
+               proto_tree_add_string( tree, hf_rtcp_ssrc_text, tvb, offset, reason_length, reason_text );
+               g_free( reason_text );
+               offset += reason_length;
+       }
 
        return offset;
 
 }
 
-static int
-dissect_rtcp_sdes( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
-    int count )
+static void
+dissect_rtcp_sdes( tvbuff_t *tvb, int offset, proto_tree *tree,
+    unsigned int count )
 {
        unsigned int chunk          = 1;
        proto_item *sdes_item;
@@ -415,14 +610,27 @@ dissect_rtcp_sdes( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
        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,
+               if (ssrc == 0) {
+                   /* According to RFC1889 section 6.4:
+                    * "The list of items in each chunk is terminated by one or more
+                    * null octets, the first of which is interpreted as an item type
+                    * of zero to denote the end of the list, and the remainder as
+                    * needed to pad until the next 32-bit boundary.
+                    *
+                    * A chunk with zero items (four null octets) is valid but useless."
+                    */
+                   proto_tree_add_text(tree, tvb, offset, 4, "Padding");
+                   offset += 4;
+                   continue;
+               }
+               sdes_item = proto_tree_add_text(tree, tvb, offset, -1,
                    "Chunk %u, SSRC/CSRC %u", chunk, ssrc);
                sdes_tree = proto_item_add_subtree( sdes_item, ett_sdes );
 
@@ -431,18 +639,18 @@ dissect_rtcp_sdes( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
                offset += 4;
 
                /* Create a subtree for the SDES items; we don't yet know
-                  the length */        
+                  the length */
                items_start_offset = offset;
-               ti = proto_tree_add_text(sdes_tree, tvb, offset, 0,
+               ti = proto_tree_add_text(sdes_tree, tvb, offset, -1,
                    "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_bytes_exist( tvb, offset, 2) ) ) {
+               while ( ( tvb_reported_length_remaining( tvb, offset ) > 0 )
+                   && ( tvb_get_guint8( tvb, offset ) != RTCP_SDES_END ) ) {
                        /* 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 );
@@ -462,32 +670,32 @@ dissect_rtcp_sdes( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
                                proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_prefix_len, tvb, offset, 1, FALSE );
                                offset++;
 
-                               prefix_string = ( char * ) malloc( prefix_len + 1 );
+                               prefix_string = g_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 );
+                               g_free( prefix_string );
                                offset += prefix_len;
                        }
-                       prefix_string = ( char * ) malloc( item_len + 1 );
+                       prefix_string = g_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 );
+                       g_free( prefix_string );
                        offset += item_len;
                }
 
                /* Set the length of the items subtree. */
                proto_item_set_len(ti, offset - items_start_offset);
 
-               /* 32 bits = 4 bytes, so..... 
-                * If offset % 4 != 0, we divide offset by 4, add one and then 
+               /* 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 )
@@ -498,14 +706,11 @@ dissect_rtcp_sdes( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
 
                chunk++;
        }
-
-
-       return offset;
 }
 
 static int
-dissect_rtcp_rr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
-    int count )
+dissect_rtcp_rr( tvbuff_t *tvb, int offset, proto_tree *tree,
+    unsigned int count )
 {
        unsigned int counter = 1;
        proto_tree *ssrc_tree = (proto_tree*) NULL;
@@ -520,11 +725,11 @@ dissect_rtcp_rr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
                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 );
 
@@ -577,8 +782,8 @@ dissect_rtcp_rr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
 }
 
 static int
-dissect_rtcp_sr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
-    int count )
+dissect_rtcp_sr( tvbuff_t *tvb, int offset, proto_tree *tree,
+    unsigned int count )
 {
 #if 0
        gchar buff[ NTP_TS_SIZE ];
@@ -612,13 +817,69 @@ dissect_rtcp_sr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
        offset += 4;
 
        /* The rest of the packet is equal to the RR packet */
-       if ( count > 0 )
-               offset = dissect_rtcp_rr( tvb, offset, fd, tree, count );
+       if ( count != 0 )
+               offset = dissect_rtcp_rr( tvb, offset, tree, count );
 
        return offset;
 }
 
-void
+/* Look for conversation info and display any setup info found */
+void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       /* Conversation and current data */
+       conversation_t *p_conv = NULL;
+       struct _rtcp_conversation_info *p_conv_data = NULL;
+
+       /* Use existing packet data if available */
+       p_conv_data = p_get_proto_data(pinfo->fd, proto_rtcp);
+
+       if (!p_conv_data)
+       {
+               /* First time, get info from conversation */
+               p_conv = find_conversation(&pinfo->net_dst, &pinfo->net_src,
+                                   pinfo->ptype,
+                                   pinfo->destport, pinfo->srcport, NO_ADDR_B);
+
+               if (p_conv)
+               {
+                       /* Create space for packet info */
+                       struct _rtcp_conversation_info *p_conv_packet_data;
+                       p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
+
+                       /* Save this conversation info into packet info */
+                       p_conv_packet_data = g_mem_chunk_alloc(rtcp_conversations);
+                       strcpy(p_conv_packet_data->method, p_conv_data->method);
+                       p_conv_packet_data->frame_number = p_conv_data->frame_number;
+                       p_add_proto_data(pinfo->fd, proto_rtcp, p_conv_packet_data);
+               }
+       }
+
+       /* Create setup info subtree with summary info. */
+       if (p_conv_data)
+       {
+               proto_tree *rtcp_setup_tree;
+               proto_item *ti =  proto_tree_add_string_format(tree, hf_rtcp_setup, tvb, 0, 0,
+                                                              "",
+                                                              "Stream setup by %s (frame %d)",
+                                                              p_conv_data->method,
+                                                              p_conv_data->frame_number);
+               PROTO_ITEM_SET_GENERATED(ti);
+               rtcp_setup_tree = proto_item_add_subtree(ti, ett_rtcp_setup);
+               if (rtcp_setup_tree)
+               {
+                       /* Add details into subtree */
+                       proto_item* item = proto_tree_add_uint(rtcp_setup_tree, hf_rtcp_setup_frame,
+                                                              tvb, 0, 0, p_conv_data->frame_number);
+                       PROTO_ITEM_SET_GENERATED(item);
+                       item = proto_tree_add_string(rtcp_setup_tree, hf_rtcp_setup_method,
+                                                    tvb, 0, 0, p_conv_data->method);
+                       PROTO_ITEM_SET_GENERATED(item);
+               }
+       }
+}
+
+
+static void
 dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
 {
        proto_item *ti           = NULL;
@@ -629,56 +890,55 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
        unsigned int packet_type = 0;
        unsigned int offset      = 0;
        guint16 packet_length    = 0;
+       guint rtcp_subtype               = 0;
 
-       CHECK_DISPLAY_AS_DATA(proto_rtcp, tvb, pinfo, tree);
-
-       pinfo->current_proto = "RTCP";
-
-       if ( check_col( pinfo->fd, COL_PROTOCOL ) )   {
-               col_set_str( pinfo->fd, COL_PROTOCOL, "RTCP" );
+       if ( check_col( pinfo->cinfo, COL_PROTOCOL ) )   {
+               col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTCP" );
        }
-       
-       if ( check_col( pinfo->fd, COL_INFO) ) {
+
+       if ( check_col( pinfo->cinfo, COL_INFO) ) {
                /* The second octet contains the packet type */
                /* switch ( pd[ offset + 1 ] ) { */
                switch ( tvb_get_guint8( tvb, 1 ) ) {
                        case RTCP_SR:
-                               col_set_str( pinfo->fd, COL_INFO, "Sender Report");
+                               col_set_str( pinfo->cinfo, COL_INFO, "Sender Report");
                                break;
                        case RTCP_RR:
-                               col_set_str( pinfo->fd, COL_INFO, "Receiver Report");
+                               col_set_str( pinfo->cinfo, COL_INFO, "Receiver Report");
                                break;
                        case RTCP_SDES:
-                               col_set_str( pinfo->fd, COL_INFO, "Source Description");
+                               col_set_str( pinfo->cinfo, COL_INFO, "Source Description");
                                break;
                        case RTCP_BYE:
-                               col_set_str( pinfo->fd, COL_INFO, "Goodbye");
+                               col_set_str( pinfo->cinfo, COL_INFO, "Goodbye");
                                break;
                        case RTCP_APP:
-                               col_set_str( pinfo->fd, COL_INFO, "Application defined");
+                               col_set_str( pinfo->cinfo, COL_INFO, "Application defined");
+                               break;
+                       case RTCP_XR:
+                               col_set_str( pinfo->cinfo, COL_INFO, "Extended report");
                                break;
                        case RTCP_FIR:
-                               col_set_str( pinfo->fd, COL_INFO, "Full Intra-frame Request (H.261)");
+                               col_set_str( pinfo->cinfo, COL_INFO, "Full Intra-frame Request (H.261)");
                                break;
                        case RTCP_NACK:
-                               col_set_str( pinfo->fd, COL_INFO, "Negative Acknowledgement (H.261)");
+                               col_set_str( pinfo->cinfo, COL_INFO, "Negative Acknowledgement (H.261)");
                                break;
                        default:
-                               col_set_str( pinfo->fd, COL_INFO, "Unknown packet type");
+                               col_set_str( pinfo->cinfo, 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 
+               /*
+                * 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 ( tvb_bytes_exist( tvb, offset, 4) ) {
-                       /* 
+                       /*
                         * First retreive the packet_type
                         */
                        packet_type = tvb_get_guint8( tvb, offset + 1 );
@@ -688,29 +948,37 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                         */
                        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 ); 
+                       ti = proto_tree_add_item(tree, proto_rtcp, tvb, offset, packet_length, FALSE );
                        rtcp_tree = proto_item_add_subtree( ti, ett_rtcp );
 
+
+                       /* Conversation setup info */
+                       if (global_rtcp_show_setup_info)
+                       {
+                               show_setup_info(tvb, pinfo, rtcp_tree);
+                       }
+
+
                        temp_byte = tvb_get_guint8( tvb, offset );
 
                        proto_tree_add_uint( rtcp_tree, hf_rtcp_version, tvb,
-                           offset, 1, RTCP_VERSION( temp_byte ) );
+                           offset, 1, temp_byte);
                        padding_set = RTCP_PADDING( temp_byte );
                        proto_tree_add_boolean( rtcp_tree, hf_rtcp_padding, tvb,
-                           offset, 1, padding_set );
+                           offset, 1, temp_byte );
                        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 );
+                                       proto_tree_add_uint( rtcp_tree, hf_rtcp_rc, tvb, offset, 1, temp_byte );
                                        offset++;
                                        /* Packet type, 8 bits */
                                        proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
@@ -722,12 +990,12 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                                        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 );
+                                       if ( packet_type == RTCP_SR ) offset = dissect_rtcp_sr( tvb, offset, rtcp_tree, elem_count );
+                                       else offset = dissect_rtcp_rr( tvb, offset, 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 );
+                                       proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, temp_byte );
                                        offset++;
                                        /* Packet type, 8 bits */
                                        proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
@@ -735,11 +1003,12 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                                        /* 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 );
+                                       dissect_rtcp_sdes( tvb, offset, rtcp_tree, elem_count );
+                                       offset += packet_length - 4;
                                        break;
                                case RTCP_BYE:
                                        /* Source count, 5 bits */
-                                       proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, elem_count );
+                                       proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, temp_byte );
                                        offset++;
                                        /* Packet type, 8 bits */
                                        proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
@@ -747,10 +1016,11 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                                        /* 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 );
+                                       offset = dissect_rtcp_bye( tvb, offset, rtcp_tree, elem_count );
                                        break;
                                case RTCP_APP:
                                        /* Subtype, 5 bits */
+                                       rtcp_subtype = elem_count;
                                        proto_tree_add_uint( rtcp_tree, hf_rtcp_subtype, tvb, offset, 1, elem_count );
                                        offset++;
                                        /* Packet type, 8 bits */
@@ -759,15 +1029,15 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                                        /* 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 );
+                                       offset = dissect_rtcp_app( tvb, pinfo, offset,
+                                           rtcp_tree, padding_set,
+                                           packet_length - 4, rtcp_subtype );
                                        break;
                                case RTCP_FIR:
-                                       dissect_rtcp_fir( tvb, offset, pinfo->fd, rtcp_tree );
+                                       offset = dissect_rtcp_fir( tvb, offset, rtcp_tree );
                                        break;
                                case RTCP_NACK:
-                                       dissect_rtcp_nack( tvb, offset, pinfo->fd, rtcp_tree );
+                                       offset = dissect_rtcp_nack( tvb, offset, rtcp_tree );
                                        break;
                                default:
                                        /*
@@ -778,13 +1048,13 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                                        break;
                        }
                }
-               /* If the padding bit is set, the last octet of the 
-                * packet contains the length of the padding 
+               /* 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 
+                       /* 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;
@@ -796,407 +1066,552 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
 void
 proto_register_rtcp(void)
 {
-       static hf_register_info hf[] = 
+       static hf_register_info hf[] =
        {
-               { 
+               {
                        &hf_rtcp_version,
-                       { 
-                               "Version", 
-                               "rtcp.version", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               VALS(rtcp_version_vals), 
-                               0x0,
-                               "" 
+                       {
+                               "Version",
+                               "rtcp.version",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS(rtcp_version_vals),
+                               0xC0,
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_padding,
-                       { 
-                               "Padding", 
-                               "rtcp.padding", 
-                               FT_BOOLEAN, 
-                               BASE_NONE, 
-                               NULL, 
-                               0x0,
-                               "" 
+                       {
+                               "Padding",
+                               "rtcp.padding",
+                               FT_BOOLEAN,
+                               8,
+                               NULL,
+                               0x20,
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_rc,
-                       { 
-                               "Reception report count", 
-                               "rtcp.rc", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               NULL, 
-                               0x0,
-                               "" 
+                       {
+                               "Reception report count",
+                               "rtcp.rc",
+                               FT_UINT8,
+                               BASE_DEC,
+                               NULL,
+                               0x1F,
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_sc,
-                       { 
-                               "Source count", 
-                               "rtcp.sc", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               NULL, 
-                               0x0,
-                               "" 
+                       {
+                               "Source count",
+                               "rtcp.sc",
+                               FT_UINT8,
+                               BASE_DEC,
+                               NULL,
+                               0x1F,
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_pt,
-                       { 
-                               "Packet type", 
-                               "rtcp.pt", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               VALS( rtcp_packet_type_vals ), 
+                       {
+                               "Packet type",
+                               "rtcp.pt",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS( rtcp_packet_type_vals ),
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_length,
-                       { 
-                               "Length", 
-                               "rtcp.length", 
-                               FT_UINT16, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Length",
+                               "rtcp.length",
+                               FT_UINT16,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_sender,
-                       { 
-                               "Sender SSRC", 
-                               "rtcp.senderssrc", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Sender SSRC",
+                               "rtcp.senderssrc",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ntp,
-                       { 
-                               "NTP timestamp", 
-                               "rtcp.timestamp.ntp", 
-                               FT_STRING, 
-                               BASE_NONE, 
-                               NULL, 
+                       {
+                               "NTP timestamp",
+                               "rtcp.timestamp.ntp",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_rtp_timestamp,
-                       { 
-                               "RTP timestamp", 
-                               "rtcp.timestamp.rtp", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "RTP timestamp",
+                               "rtcp.timestamp.rtp",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_sender_pkt_cnt,
-                       { 
-                               "Sender's packet count", 
-                               "rtcp.sender.packetcount", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Sender's packet count",
+                               "rtcp.sender.packetcount",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_sender_oct_cnt,
-                       { 
-                               "Sender's octet count", 
-                               "rtcp.sender.octetcount", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Sender's octet count",
+                               "rtcp.sender.octetcount",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_source,
-                       { 
-                               "Identifier", 
-                               "rtcp.ssrc.identifier", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Identifier",
+                               "rtcp.ssrc.identifier",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_fraction,
-                       { 
-                               "Fraction lost", 
-                               "rtcp.ssrc.fraction", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Fraction lost",
+                               "rtcp.ssrc.fraction",
+                               FT_UINT8,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_cum_nr,
-                       { 
-                               "Cumulative number of packets lost", 
-                               "rtcp.ssrc.cum_nr", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Cumulative number of packets lost",
+                               "rtcp.ssrc.cum_nr",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_ext_high_seq,
-                       { 
-                               "Extended highest sequence number received", 
-                               "rtcp.ssrc.ext_high", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Extended highest sequence number received",
+                               "rtcp.ssrc.ext_high",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_high_seq,
-                       { 
-                               "Highest sequence number received", 
-                               "rtcp.ssrc.high_seq", 
-                               FT_UINT16, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Highest sequence number received",
+                               "rtcp.ssrc.high_seq",
+                               FT_UINT16,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_high_cycles,
-                       { 
-                               "Sequence number cycles count", 
-                               "rtcp.ssrc.high_cycles", 
-                               FT_UINT16, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Sequence number cycles count",
+                               "rtcp.ssrc.high_cycles",
+                               FT_UINT16,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_jitter,
-                       { 
-                               "Interarrival jitter", 
-                               "rtcp.ssrc.jitter", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Interarrival jitter",
+                               "rtcp.ssrc.jitter",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_lsr,
-                       { 
-                               "Last SR timestamp", 
-                               "rtcp.ssrc.lsr", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Last SR timestamp",
+                               "rtcp.ssrc.lsr",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_dlsr,
-                       { 
-                               "Delay since last SR timestamp", 
-                               "rtcp.ssrc.dlsr", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Delay since last SR timestamp",
+                               "rtcp.ssrc.dlsr",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_csrc,
-                       { 
-                               "SSRC / CSRC identifier", 
-                               "rtcp.sdes.ssrc_csrc", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "SSRC / CSRC identifier",
+                               "rtcp.sdes.ssrc_csrc",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_type,
-                       { 
-                               "Type", 
-                               "rtcp.sdes.type", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               VALS( rtcp_sdes_type_vals ), 
+                       {
+                               "Type",
+                               "rtcp.sdes.type",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS( rtcp_sdes_type_vals ),
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_length,
-                       { 
-                               "Length", 
-                               "rtcp.sdes.length", 
-                               FT_UINT32, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Length",
+                               "rtcp.sdes.length",
+                               FT_UINT32,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_text,
-                       { 
-                               "Text", 
-                               "rtcp.sdes.text", 
-                               FT_STRING, 
-                               BASE_NONE, 
-                               NULL, 
+                       {
+                               "Text",
+                               "rtcp.sdes.text",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_prefix_len,
-                       { 
-                               "Prefix length", 
-                               "rtcp.sdes.prefix.length", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Prefix length",
+                               "rtcp.sdes.prefix.length",
+                               FT_UINT8,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_ssrc_prefix_string,
-                       { 
-                               "Prefix string", 
-                               "rtcp.sdes.prefix.string", 
-                               FT_STRING, 
-                               BASE_NONE, 
-                               NULL, 
+                       {
+                               "Prefix string",
+                               "rtcp.sdes.prefix.string",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_subtype,
-                       { 
-                               "Subtype", 
-                               "rtcp.app.subtype", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Subtype",
+                               "rtcp.app.subtype",
+                               FT_UINT8,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_name_ascii,
-                       { 
-                               "Name (ASCII)", 
-                               "rtcp.app.name", 
-                               FT_STRING, 
-                               BASE_NONE, 
-                               NULL, 
+                       {
+                               "Name (ASCII)",
+                               "rtcp.app.name",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_app_data,
-                       { 
-                               "Application specific data", 
-                               "rtcp.app.data", 
-                               FT_BYTES, 
-                               BASE_NONE, 
-                               NULL, 
+                       {
+                               "Application specific data",
+                               "rtcp.app.data",
+                               FT_BYTES,
+                               BASE_NONE,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
+                       &hf_rtcp_app_poc1_subtype,
+                       {
+                               "Subtype",
+                               "rtcp.app.PoC1.subtype",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS(rtcp_app_poc1_floor_cnt_type_vals),
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_app_poc1_sip_uri,
+                       {
+                               "SIP URI",
+                               "rtcp.app.poc1.sip.uri",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_app_poc1_disp_name,
+                       {
+                               "Display Name",
+                               "rtcp.app.poc1.disp.name",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_app_poc1_last_pkt_seq_no,
+                       {
+                               "Seq. no of last RTP packet",
+                               "rtcp.app.poc1.last.pkt.seq.no",
+                               FT_UINT16,
+                               BASE_DEC,
+                               NULL,
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_app_poc1_reason_code1,
+                       {
+                               "Reason code",
+                               "rtcp.app.poc1.reason.code",
+                               FT_UINT8,
+                               BASE_DEC,
+                               VALS(rtcp_app_poc1_reason_code1_vals),
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_app_poc1_item_len,
+                       {
+                               "Item length",
+                               "rtcp.app.poc1.item.len",
+                               FT_UINT8,
+                               BASE_DEC,
+                               NULL,
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_app_poc1_reason1_phrase,
+                       {
+                               "Reason Phrase",
+                               "rtcp.app.poc1.reason.phrase",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_app_poc1_reason_code2,
+                       {
+                               "Reason code",
+                               "rtcp.app.poc1.reason.code",
+                               FT_UINT16,
+                               BASE_DEC,
+                               VALS(rtcp_app_poc1_reason_code2_vals),
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_app_poc1_additionalinfo,
+                       {
+                               "additional information",
+                               "rtcp.app.poc1.add.info",
+                               FT_UINT16,
+                               BASE_DEC,
+                               NULL,
+                               0x0,
+                               "", HFILL
+                       }
+               },
+               {
                        &hf_rtcp_fsn,
-                       { 
-                               "First sequence number", 
-                               "rtcp.nack.fsn", 
-                               FT_UINT16, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "First sequence number",
+                               "rtcp.nack.fsn",
+                               FT_UINT16,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_blp,
-                       { 
-                               "Bitmask of following lost packets", 
-                               "rtcp.nack.blp", 
-                               FT_UINT16, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Bitmask of following lost packets",
+                               "rtcp.nack.blp",
+                               FT_UINT16,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_padding_count,
-                       { 
-                               "Padding count", 
-                               "rtcp.padding.count", 
-                               FT_UINT8, 
-                               BASE_DEC, 
-                               NULL, 
+                       {
+                               "Padding count",
+                               "rtcp.padding.count",
+                               FT_UINT8,
+                               BASE_DEC,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-               { 
+               {
                        &hf_rtcp_padding_data,
-                       { 
-                               "Padding data", 
-                               "rtcp.padding.data", 
-                               FT_BYTES, 
-                               BASE_NONE, 
-                               NULL, 
+                       {
+                               "Padding data",
+                               "rtcp.padding.data",
+                               FT_BYTES,
+                               BASE_NONE,
+                               NULL,
                                0x0,
-                               "" 
+                               "", HFILL
                        }
                },
-};
-       
-       static gint *ett[] = 
+               {
+                       &hf_rtcp_setup,
+                       {
+                               "Stream setup",
+                               "rtcp.setup",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               "Stream setup, method and frame number", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_setup_frame,
+                       {
+                               "Setup frame",
+                               "rtcp.setup-frame",
+                               FT_FRAMENUM,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               "Frame that set up this stream", HFILL
+                       }
+               },
+               {
+                       &hf_rtcp_setup_method,
+                       {
+                               "Setup Method",
+                               "rtcp.setup-method",
+                               FT_STRING,
+                               BASE_NONE,
+                               NULL,
+                               0x0,
+                               "Method used to set up this stream", HFILL
+                       }
+               }
+
+       };
+
+       static gint *ett[] =
        {
                &ett_rtcp,
                &ett_ssrc,
@@ -1204,25 +1619,37 @@ proto_register_rtcp(void)
                &ett_ssrc_ext_high,
                &ett_sdes,
                &ett_sdes_item,
+               &ett_PoC1,
+               &ett_rtcp_setup
        };
 
+       module_t *rtcp_module;
 
        proto_rtcp = proto_register_protocol("Real-time Transport Control Protocol",
            "RTCP", "rtcp");
        proto_register_field_array(proto_rtcp, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
-#if 0
+       register_dissector("rtcp", dissect_rtcp, proto_rtcp);
+
+       rtcp_module = prefs_register_protocol(proto_rtcp, NULL);
+
+       prefs_register_bool_preference(rtcp_module, "show_setup_info",
+               "Show stream setup information",
+               "Where available, show which protocol and frame caused "
+               "this RTCP stream to be created",
+               &global_rtcp_show_setup_info);
+
        register_init_routine( &rtcp_init );
-#endif
 }
 
 void
 proto_reg_handoff_rtcp(void)
 {
        /*
-        * Register this dissector as one that can be assigned to a
-        * UDP conversation.
+        * Register this dissector as one that can be selected by a
+        * UDP port number.
         */
-       conv_dissector_add("udp", dissect_rtcp, proto_rtcp);
+       rtcp_handle = find_dissector("rtcp");
+       dissector_add_handle("udp.port", rtcp_handle);
 }