3 * $Id: packet-rtcp.c,v 1.30 2002/01/21 07:36:41 guy Exp $
5 * Routines for RTCP dissection
6 * RTCP = Real-time Transport Control Protocol
8 * Copyright 2000, Philips Electronics N.V.
9 * Written by Andreas Sikkema <andreas.sikkema@philips.com>
11 * Ethereal - Network traffic analyzer
12 * By Gerald Combs <gerald@ethereal.com>
13 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 * This dissector tries to dissect the RTCP protocol according to Annex A
32 * of ITU-T Recommendation H.225.0 (02/98) and RFC 1889
33 * H.225.0 literally copies RFC 1889, but omitting a few sections.
35 * RTCP traffic is handled by an uneven UDP portnumber. This can be any
36 * port number, but there is a registered port available, port 5005
37 * See Annex B of ITU-T Recommendation H.225.0, section B.7
47 #include <epan/packet.h>
49 #ifdef HAVE_SYS_TYPES_H
50 # include <sys/types.h>
53 #ifdef HAVE_NETINET_IN_H
54 # include <netinet/in.h>
60 #include "packet-rtcp.h"
62 #include "packet-ntp.h"
64 #include <epan/conversation.h>
66 /* Version is the first 2 bits of the first octet*/
67 #define RTCP_VERSION(octet) ((octet) >> 6)
69 /* Padding is the third bit; no need to shift, because true is any value
71 #define RTCP_PADDING(octet) ((octet) & 0x20)
73 /* Receiver/ Sender count is the 5 last bits */
74 #define RTCP_COUNT(octet) ((octet) & 0x1F)
76 static const value_string rtcp_version_vals[] =
78 { 0, "Old VAT Version" },
79 { 1, "First Draft Version" },
80 { 2, "RFC 1889 Version" },
84 /* RTCP packet types according to Section A.11.1 */
90 /* Supplemental H.261 specific RTCP packet types according to Section C.3.5 */
94 static const value_string rtcp_packet_type_vals[] =
96 { RTCP_SR, "Sender Report" },
97 { RTCP_RR, "Receiver Report" },
98 { RTCP_SDES, "Source description" },
99 { RTCP_BYE, "Goodbye" },
100 { RTCP_APP, "Application specific" },
101 { RTCP_FIR, "Full Intra-frame Request (H.261)" },
102 { RTCP_NACK, "Negative Acknowledgement (H.261)" },
106 /* RTCP SDES types (Section A.11.2) */
107 #define RTCP_SDES_END 0
108 #define RTCP_SDES_CNAME 1
109 #define RTCP_SDES_NAME 2
110 #define RTCP_SDES_EMAIL 3
111 #define RTCP_SDES_PHONE 4
112 #define RTCP_SDES_LOC 5
113 #define RTCP_SDES_TOOL 6
114 #define RTCP_SDES_NOTE 7
115 #define RTCP_SDES_PRIV 8
117 static const value_string rtcp_sdes_type_vals[] =
119 { RTCP_SDES_END, "END" },
120 { RTCP_SDES_CNAME, "CNAME (user and domain)" },
121 { RTCP_SDES_NAME, "NAME (common name)" },
122 { RTCP_SDES_EMAIL, "EMAIL (e-mail address)" },
123 { RTCP_SDES_PHONE, "PHONE (phone number)" },
124 { RTCP_SDES_LOC, "LOC (geographic location)" },
125 { RTCP_SDES_TOOL, "TOOL (name/version of source app)" },
126 { RTCP_SDES_NOTE, "NOTE (note about source)" },
127 { RTCP_SDES_PRIV, "PRIV (private extensions)" },
131 /* RTCP header fields */
132 static int proto_rtcp = -1;
133 static int hf_rtcp_version = -1;
134 static int hf_rtcp_padding = -1;
135 static int hf_rtcp_rc = -1;
136 static int hf_rtcp_sc = -1;
137 static int hf_rtcp_pt = -1;
138 static int hf_rtcp_length = -1;
139 static int hf_rtcp_ssrc_sender = -1;
140 static int hf_rtcp_ntp = -1;
141 static int hf_rtcp_rtp_timestamp = -1;
142 static int hf_rtcp_sender_pkt_cnt = -1;
143 static int hf_rtcp_sender_oct_cnt = -1;
144 static int hf_rtcp_ssrc_source = -1;
145 static int hf_rtcp_ssrc_fraction = -1;
146 static int hf_rtcp_ssrc_cum_nr = -1;
147 /* First the 32 bit number, then the split
148 * up 16 bit values */
149 /* These two are added to a subtree */
150 static int hf_rtcp_ssrc_ext_high_seq = -1;
151 static int hf_rtcp_ssrc_high_seq = -1;
152 static int hf_rtcp_ssrc_high_cycles = -1;
153 static int hf_rtcp_ssrc_jitter = -1;
154 static int hf_rtcp_ssrc_lsr = -1;
155 static int hf_rtcp_ssrc_dlsr = -1;
156 static int hf_rtcp_ssrc_csrc = -1;
157 static int hf_rtcp_ssrc_type = -1;
158 static int hf_rtcp_ssrc_length = -1;
159 static int hf_rtcp_ssrc_text = -1;
160 static int hf_rtcp_ssrc_prefix_len = -1;
161 static int hf_rtcp_ssrc_prefix_string= -1;
162 static int hf_rtcp_subtype = -1;
163 static int hf_rtcp_name_ascii = -1;
164 static int hf_rtcp_app_data = -1;
165 static int hf_rtcp_fsn = -1;
166 static int hf_rtcp_blp = -1;
167 static int hf_rtcp_padding_count = -1;
168 static int hf_rtcp_padding_data = -1;
170 /* RTCP fields defining a sub tree */
171 static gint ett_rtcp = -1;
172 static gint ett_ssrc = -1;
173 static gint ett_ssrc_item = -1;
174 static gint ett_ssrc_ext_high = -1;
175 static gint ett_sdes = -1;
176 static gint ett_sdes_item = -1;
178 static address fake_addr;
179 static int heur_init = FALSE;
181 static gboolean dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo,
183 static void dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo,
186 void rtcp_add_address( packet_info *pinfo, const unsigned char* ip_addr,
190 conversation_t* pconv;
193 * If this isn't the first time this packet has been processed,
194 * we've already done this work, so we don't need to do it
197 if (pinfo->fd->flags.visited)
200 src_addr.type = AT_IPv4;
202 src_addr.data = ip_addr;
205 * The first time the function is called let the udp dissector
206 * know that we're interested in traffic
209 heur_dissector_add( "udp", dissect_rtcp_heur, proto_rtcp );
214 * Check if the ip address and port combination is not
217 pconv = find_conversation( &src_addr, &fake_addr, PT_UDP, prt, 0, 0 );
221 * XXX - use wildcard address and port B?
224 pconv = conversation_new( &src_addr, &fake_addr, PT_UDP,
225 (guint32) prt, (guint32) 0, 0 );
226 conversation_add_proto_data(pconv, proto_rtcp, NULL);
232 static void rtcp_init( void )
234 unsigned char* tmp_data;
237 /* Create a fake adddress... */
238 fake_addr.type = AT_IPv4;
241 tmp_data = malloc( fake_addr.len );
242 for ( i = 0; i < fake_addr.len; i++) {
245 fake_addr.data = tmp_data;
250 dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
252 conversation_t* pconv;
254 /* This is a heuristic dissector, which means we get all the UDP
255 * traffic not sent to a known dissector and not claimed by
256 * a heuristic dissector called before us!
257 * So we first check if the frame is really meant for us.
259 if ( ( pconv = find_conversation( &pinfo->src, &fake_addr, pinfo->ptype,
260 pinfo->srcport, 0, 0 ) ) == NULL ) {
262 * The source ip:port combination was not what we were
263 * looking for, check the destination
265 if ( ( pconv = find_conversation( &pinfo->dst, &fake_addr,
266 pinfo->ptype, pinfo->destport, 0, 0 ) ) == NULL ) {
273 * An RTCP conversation always has a data item for RTCP.
274 * (Its existence is sufficient to indicate that this is an RTCP
277 if (conversation_get_proto_data(pconv, proto_rtcp) == NULL)
281 * The message is a valid RTCP message!
283 dissect_rtcp( tvb, pinfo, tree );
290 dissect_rtcp_nack( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
292 /* Packet type = FIR (H261) */
293 proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 31 );
295 /* Packet type, 8 bits = APP */
296 proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
299 /* Packet length in 32 bit words minus one */
300 proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
304 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
308 proto_tree_add_uint( tree, hf_rtcp_fsn, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
312 proto_tree_add_uint( tree, hf_rtcp_blp, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
319 dissect_rtcp_fir( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree )
321 /* Packet type = FIR (H261) */
322 proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 31 );
324 /* Packet type, 8 bits = APP */
325 proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
328 /* Packet length in 32 bit words minus one */
329 proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
333 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
340 dissect_rtcp_app( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
341 unsigned int padding, unsigned int packet_len )
343 unsigned int counter = 0;
347 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
352 for( counter = 0; counter < 4; counter++ )
353 ascii_name[ counter ] = tvb_get_guint8( tvb, offset + counter );
354 /* strncpy( ascii_name, pd + offset, 4 ); */
355 ascii_name[4] = '\0';
356 proto_tree_add_string( tree, hf_rtcp_name_ascii, tvb, offset, 4,
361 /* Applications specific data */
363 /* If there's padding present, we have to remove that from the data part
364 * The last octet of the packet contains the length of the padding
366 packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
368 proto_tree_add_item( tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
369 offset += packet_len;
375 dissect_rtcp_bye( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
378 unsigned int chunk = 1;
379 unsigned int reason_length = 0;
380 unsigned int counter = 0;
381 char* reason_text = NULL;
383 while ( chunk <= count ) {
384 /* source identifier, 32 bits */
385 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
389 if ( tvb_reported_length_remaining( tvb, offset ) > 0 ) {
390 /* Bye reason consists of an 8 bit length l and a string with length l */
391 reason_length = tvb_get_guint8( tvb, offset );
392 proto_tree_add_item( tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
395 reason_text = ( char* ) malloc( reason_length + 1 );
396 for ( counter = 0; counter < reason_length; counter++ ) reason_text[ counter ] = tvb_get_guint8( tvb, offset + counter );
397 /* strncpy( reason_text, pd + offset, reason_length ); */
398 reason_text[ reason_length ] = '\0';
399 proto_tree_add_string( tree, hf_rtcp_ssrc_text, tvb, offset, reason_length, reason_text );
401 offset += reason_length;
409 dissect_rtcp_sdes( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
412 unsigned int chunk = 1;
413 proto_item *sdes_item;
414 proto_tree *sdes_tree;
415 proto_tree *sdes_item_tree;
418 int items_start_offset;
420 unsigned int item_len = 0;
421 unsigned int sdes_type = 0;
422 unsigned int counter = 0;
423 unsigned int prefix_len = 0;
424 char *prefix_string = NULL;
426 while ( chunk <= count ) {
427 /* Create a subtree for this chunk; we don't yet know
429 start_offset = offset;
431 ssrc = tvb_get_ntohl( tvb, offset );
432 sdes_item = proto_tree_add_text(tree, tvb, offset, -1,
433 "Chunk %u, SSRC/CSRC %u", chunk, ssrc);
434 sdes_tree = proto_item_add_subtree( sdes_item, ett_sdes );
436 /* SSRC_n source identifier, 32 bits */
437 proto_tree_add_uint( sdes_tree, hf_rtcp_ssrc_source, tvb, offset, 4, ssrc );
440 /* Create a subtree for the SDES items; we don't yet know
442 items_start_offset = offset;
443 ti = proto_tree_add_text(sdes_tree, tvb, offset, -1,
445 sdes_item_tree = proto_item_add_subtree( ti, ett_sdes_item );
448 * Not every message is ended with "null" bytes, so check for
449 * end of frame instead.
451 while ( ( tvb_reported_length_remaining( tvb, offset ) > 0 )
452 && ( tvb_get_guint8( tvb, offset ) != RTCP_SDES_END ) ) {
454 sdes_type = tvb_get_guint8( tvb, offset );
455 proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
458 /* Item length, 8 bits */
459 item_len = tvb_get_guint8( tvb, offset );
460 proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
463 if ( sdes_type == RTCP_SDES_PRIV ) {
464 /* PRIV adds two items between the SDES length
465 * and value - an 8 bit length giving the
466 * length of a "prefix string", and the string.
468 prefix_len = tvb_get_guint8( tvb, offset );
469 proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_prefix_len, tvb, offset, 1, FALSE );
472 prefix_string = ( char * ) malloc( prefix_len + 1 );
473 for ( counter = 0; counter < prefix_len; counter++ )
474 prefix_string[ counter ] =
475 tvb_get_guint8( tvb, offset + counter );
476 /* strncpy( prefix_string, pd + offset, prefix_len ); */
477 prefix_string[ prefix_len ] = '\0';
478 proto_tree_add_string( sdes_item_tree, hf_rtcp_ssrc_prefix_string, tvb, offset, prefix_len, prefix_string );
479 free( prefix_string );
480 offset += prefix_len;
482 prefix_string = ( char * ) malloc( item_len + 1 );
483 for ( counter = 0; counter < item_len; counter++ )
484 prefix_string[ counter ] =
485 tvb_get_guint8( tvb, offset + counter );
486 /* strncpy( prefix_string, pd + offset, item_len ); */
487 prefix_string[ item_len] = 0;
488 proto_tree_add_string( sdes_item_tree, hf_rtcp_ssrc_text, tvb, offset, item_len, prefix_string );
489 free( prefix_string );
493 /* Set the length of the items subtree. */
494 proto_item_set_len(ti, offset - items_start_offset);
496 /* 32 bits = 4 bytes, so.....
497 * If offset % 4 != 0, we divide offset by 4, add one and then
498 * multiply by 4 again to reach the boundary
500 if ( offset % 4 != 0 )
501 offset = ((offset / 4) + 1 ) * 4;
503 /* Set the length of this chunk. */
504 proto_item_set_len(sdes_item, offset - start_offset);
514 dissect_rtcp_rr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
517 unsigned int counter = 1;
518 proto_tree *ssrc_tree = (proto_tree*) NULL;
519 proto_tree *ssrc_sub_tree = (proto_tree*) NULL;
520 proto_tree *high_sec_tree = (proto_tree*) NULL;
521 proto_item *ti = (proto_item*) NULL;
523 unsigned int cum_nr = 0;
525 while ( counter <= count ) {
526 /* Create a new subtree for a length of 24 bytes */
527 ti = proto_tree_add_text(tree, tvb, offset, 24,
528 "Source %u", counter );
529 ssrc_tree = proto_item_add_subtree( ti, ett_ssrc );
531 /* SSRC_n source identifier, 32 bits */
532 proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
535 ti = proto_tree_add_text(ssrc_tree, tvb, offset, 20, "SSRC contents" );
536 ssrc_sub_tree = proto_item_add_subtree( ti, ett_ssrc_item );
538 /* Fraction lost, 8bits */
539 rr_flt = tvb_get_guint8( tvb, offset );
540 proto_tree_add_uint_format( ssrc_sub_tree, hf_rtcp_ssrc_fraction, tvb,
541 offset, 1, rr_flt, "Fraction lost: %u / 256", rr_flt );
544 /* Cumulative number of packets lost, 24 bits */
545 cum_nr = tvb_get_ntohl( tvb, offset ) >> 8;
546 proto_tree_add_uint( ssrc_sub_tree, hf_rtcp_ssrc_cum_nr, tvb,
550 /* Extended highest sequence nr received, 32 bits
551 * Just for the sake of it, let's add another subtree
552 * because this might be a little clearer
554 ti = proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_ext_high_seq,
555 tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
556 high_sec_tree = proto_item_add_subtree( ti, ett_ssrc_ext_high );
557 /* Sequence number cycles */
558 proto_tree_add_uint( high_sec_tree, hf_rtcp_ssrc_high_cycles,
559 tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
561 /* highest sequence number received */
562 proto_tree_add_uint( high_sec_tree, hf_rtcp_ssrc_high_seq,
563 tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
566 /* Interarrival jitter */
567 proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_jitter, tvb,
568 offset, 4, tvb_get_ntohl( tvb, offset ) );
571 /* Last SR timestamp */
572 proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_lsr, tvb,
573 offset, 4, tvb_get_ntohl( tvb, offset ) );
576 /* Delay since last SR timestamp */
577 proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_dlsr, tvb,
578 offset, 4, tvb_get_ntohl( tvb, offset ) );
587 dissect_rtcp_sr( tvbuff_t *tvb, int offset, frame_data *fd, proto_tree *tree,
591 gchar buff[ NTP_TS_SIZE ];
592 char* ptime = tvb_get_ptr( tvb, offset, 8 );
594 /* Retreive the NTP timestamp. Using the NTP dissector for this */
595 ntp_fmt_ts( ptime, buff );
596 proto_tree_add_string_format( tree, hf_rtcp_ntp, tvb, offset, 8, ( const char* ) &buff, "NTP timestamp: %s", &buff );
597 free( ptime ); ??????????????????????????????????????????????????????????????????
601 * XXX - RFC 1889 says this is an NTP timestamp, but that appears
602 * not to be the case.
604 proto_tree_add_text(tree, tvb, offset, 4, "Timestamp, MSW: %u",
605 tvb_get_ntohl(tvb, offset));
607 proto_tree_add_text(tree, tvb, offset, 4, "Timestamp, LSW: %u",
608 tvb_get_ntohl(tvb, offset));
611 /* RTP timestamp, 32 bits */
612 proto_tree_add_uint( tree, hf_rtcp_rtp_timestamp, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
614 /* Sender's packet count, 32 bits */
615 proto_tree_add_uint( tree, hf_rtcp_sender_pkt_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
617 /* Sender's octet count, 32 bits */
618 proto_tree_add_uint( tree, hf_rtcp_sender_oct_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
621 /* The rest of the packet is equal to the RR packet */
623 offset = dissect_rtcp_rr( tvb, offset, fd, tree, count );
629 dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
631 proto_item *ti = NULL;
632 proto_tree *rtcp_tree = NULL;
633 unsigned int temp_byte = 0;
634 unsigned int padding_set = 0;
635 unsigned int elem_count = 0;
636 unsigned int packet_type = 0;
637 unsigned int offset = 0;
638 guint16 packet_length = 0;
640 if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) {
641 col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTCP" );
644 if ( check_col( pinfo->cinfo, COL_INFO) ) {
645 /* The second octet contains the packet type */
646 /* switch ( pd[ offset + 1 ] ) { */
647 switch ( tvb_get_guint8( tvb, 1 ) ) {
649 col_set_str( pinfo->cinfo, COL_INFO, "Sender Report");
652 col_set_str( pinfo->cinfo, COL_INFO, "Receiver Report");
655 col_set_str( pinfo->cinfo, COL_INFO, "Source Description");
658 col_set_str( pinfo->cinfo, COL_INFO, "Goodbye");
661 col_set_str( pinfo->cinfo, COL_INFO, "Application defined");
664 col_set_str( pinfo->cinfo, COL_INFO, "Full Intra-frame Request (H.261)");
667 col_set_str( pinfo->cinfo, COL_INFO, "Negative Acknowledgement (H.261)");
670 col_set_str( pinfo->cinfo, COL_INFO, "Unknown packet type");
678 * Check if there are at least 4 bytes left in the frame,
679 * the last 16 bits of those is the length of the current
680 * RTCP message. The last compound message contains padding,
681 * that enables us to break from the while loop.
683 while ( tvb_bytes_exist( tvb, offset, 4) ) {
685 * First retreive the packet_type
687 packet_type = tvb_get_guint8( tvb, offset + 1 );
690 * Check if it's a valid type
692 if ( ( packet_type < 192 ) || ( packet_type > 204 ) )
696 * get the packet-length for the complete RTCP packet
698 packet_length = ( tvb_get_ntohs( tvb, offset + 2 ) + 1 ) * 4;
700 ti = proto_tree_add_item(tree, proto_rtcp, tvb, offset, packet_length, FALSE );
701 rtcp_tree = proto_item_add_subtree( ti, ett_rtcp );
703 temp_byte = tvb_get_guint8( tvb, offset );
705 proto_tree_add_uint( rtcp_tree, hf_rtcp_version, tvb,
706 offset, 1, RTCP_VERSION( temp_byte ) );
707 padding_set = RTCP_PADDING( temp_byte );
708 proto_tree_add_boolean( rtcp_tree, hf_rtcp_padding, tvb,
709 offset, 1, padding_set );
710 elem_count = RTCP_COUNT( temp_byte );
712 switch ( packet_type ) {
715 /* Receiver report count, 5 bits */
716 proto_tree_add_uint( rtcp_tree, hf_rtcp_rc, tvb, offset, 1, elem_count );
718 /* Packet type, 8 bits */
719 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
721 /* Packet length in 32 bit words MINUS one, 16 bits */
722 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
724 /* Sender Synchronization source, 32 bits */
725 proto_tree_add_uint( rtcp_tree, hf_rtcp_ssrc_sender, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
728 if ( packet_type == RTCP_SR ) offset = dissect_rtcp_sr( tvb, offset, pinfo->fd, rtcp_tree, elem_count );
729 else offset = dissect_rtcp_rr( tvb, offset, pinfo->fd, rtcp_tree, elem_count );
732 /* Source count, 5 bits */
733 proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, elem_count );
735 /* Packet type, 8 bits */
736 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
738 /* Packet length in 32 bit words MINUS one, 16 bits */
739 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
741 offset = dissect_rtcp_sdes( tvb, offset, pinfo->fd, rtcp_tree, elem_count );
744 /* Source count, 5 bits */
745 proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, elem_count );
747 /* Packet type, 8 bits */
748 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
750 /* Packet length in 32 bit words MINUS one, 16 bits */
751 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
753 offset = dissect_rtcp_bye( tvb, offset, pinfo->fd, rtcp_tree, elem_count );
756 /* Subtype, 5 bits */
757 proto_tree_add_uint( rtcp_tree, hf_rtcp_subtype, tvb, offset, 1, elem_count );
759 /* Packet type, 8 bits */
760 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
762 /* Packet length in 32 bit words MINUS one, 16 bits */
763 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
765 offset = dissect_rtcp_app( tvb, offset,
766 pinfo->fd, rtcp_tree, padding_set,
770 offset = dissect_rtcp_fir( tvb, offset, pinfo->fd, rtcp_tree );
773 offset = dissect_rtcp_nack( tvb, offset, pinfo->fd, rtcp_tree );
777 * To prevent endless loops in case of an unknown message type
778 * increase offset. Some time the while will end :-)
784 /* If the padding bit is set, the last octet of the
785 * packet contains the length of the padding
786 * We only have to check for this at the end of the LAST RTCP message
789 /* If everything went according to plan offset should now point to the
790 * first octet of the padding
792 proto_tree_add_item( rtcp_tree, hf_rtcp_padding_data, tvb, offset, tvb_length_remaining( tvb, offset) - 1, FALSE );
793 offset += tvb_length_remaining( tvb, offset) - 1;
794 proto_tree_add_item( rtcp_tree, hf_rtcp_padding_count, tvb, offset, 1, FALSE );
800 proto_register_rtcp(void)
802 static hf_register_info hf[] =
811 VALS(rtcp_version_vals),
831 "Reception report count",
859 VALS( rtcp_packet_type_vals ),
877 &hf_rtcp_ssrc_sender,
892 "rtcp.timestamp.ntp",
901 &hf_rtcp_rtp_timestamp,
904 "rtcp.timestamp.rtp",
913 &hf_rtcp_sender_pkt_cnt,
915 "Sender's packet count",
916 "rtcp.sender.packetcount",
925 &hf_rtcp_sender_oct_cnt,
927 "Sender's octet count",
928 "rtcp.sender.octetcount",
937 &hf_rtcp_ssrc_source,
940 "rtcp.ssrc.identifier",
949 &hf_rtcp_ssrc_fraction,
952 "rtcp.ssrc.fraction",
961 &hf_rtcp_ssrc_cum_nr,
963 "Cumulative number of packets lost",
973 &hf_rtcp_ssrc_ext_high_seq,
975 "Extended highest sequence number received",
976 "rtcp.ssrc.ext_high",
985 &hf_rtcp_ssrc_high_seq,
987 "Highest sequence number received",
988 "rtcp.ssrc.high_seq",
997 &hf_rtcp_ssrc_high_cycles,
999 "Sequence number cycles count",
1000 "rtcp.ssrc.high_cycles",
1009 &hf_rtcp_ssrc_jitter,
1011 "Interarrival jitter",
1023 "Last SR timestamp",
1035 "Delay since last SR timestamp",
1047 "SSRC / CSRC identifier",
1048 "rtcp.sdes.ssrc_csrc",
1063 VALS( rtcp_sdes_type_vals ),
1069 &hf_rtcp_ssrc_length,
1093 &hf_rtcp_ssrc_prefix_len,
1096 "rtcp.sdes.prefix.length",
1105 &hf_rtcp_ssrc_prefix_string,
1108 "rtcp.sdes.prefix.string",
1129 &hf_rtcp_name_ascii,
1143 "Application specific data",
1155 "First sequence number",
1167 "Bitmask of following lost packets",
1177 &hf_rtcp_padding_count,
1180 "rtcp.padding.count",
1189 &hf_rtcp_padding_data,
1192 "rtcp.padding.data",
1202 static gint *ett[] =
1213 proto_rtcp = proto_register_protocol("Real-time Transport Control Protocol",
1215 proto_register_field_array(proto_rtcp, hf, array_length(hf));
1216 proto_register_subtree_array(ett, array_length(ett));
1218 register_dissector("rtcp", dissect_rtcp, proto_rtcp);
1221 register_init_routine( &rtcp_init );
1226 proto_reg_handoff_rtcp(void)
1228 dissector_handle_t rtcp_handle;
1231 * Register this dissector as one that can be selected by a
1234 rtcp_handle = find_dissector("rtcp");
1235 dissector_add_handle("udp.port", rtcp_handle);