5 * Routines for RTCP dissection
6 * RTCP = Real-time Transport Control Protocol
8 * Copyright 2000, Philips Electronics N.V.
9 * Written by Andreas Sikkema <h323@ramdyne.nl>
11 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
13 * Copyright 2005, Nagarjuna Venna <nvenna@brixnet.com>
15 * Ethereal - Network traffic analyzer
16 * By Gerald Combs <gerald@ethereal.com>
17 * Copyright 1998 Gerald Combs
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 * This dissector tries to dissect the RTCP protocol according to Annex A
36 * of ITU-T Recommendation H.225.0 (02/98) and RFC 1889
37 * H.225.0 literally copies RFC 1889, but omitting a few sections.
39 * RTCP traffic is handled by an uneven UDP portnumber. This can be any
40 * port number, but there is a registered port available, port 5005
41 * See Annex B of ITU-T Recommendation H.225.0, section B.7
43 * RTCP XR is specified in RFC 3611.
45 * See also http://www.iana.org/assignments/rtp-parameters
54 #include <epan/packet.h>
59 #include "packet-rtcp.h"
61 #include "packet-ntp.h"
63 #include <epan/conversation.h>
65 #include <epan/prefs.h>
68 /* Version is the first 2 bits of the first octet*/
69 #define RTCP_VERSION(octet) ((octet) >> 6)
71 /* Padding is the third bit; no need to shift, because true is any value
73 #define RTCP_PADDING(octet) ((octet) & 0x20)
75 /* Receiver/ Sender count is the 5 last bits */
76 #define RTCP_COUNT(octet) ((octet) & 0x1F)
78 static dissector_handle_t rtcp_handle;
80 static const value_string rtcp_version_vals[] =
82 { 0, "Old VAT Version" },
83 { 1, "First Draft Version" },
84 { 2, "RFC 1889 Version" },
88 /* RTCP packet types according to Section A.11.1 */
89 /* And http://www.iana.org/assignments/rtp-parameters */
96 /* Supplemental H.261 specific RTCP packet types according to Section C.3.5 */
100 static const value_string rtcp_packet_type_vals[] =
102 { RTCP_SR, "Sender Report" },
103 { RTCP_RR, "Receiver Report" },
104 { RTCP_SDES, "Source description" },
105 { RTCP_BYE, "Goodbye" },
106 { RTCP_APP, "Application specific" },
107 { RTCP_FIR, "Full Intra-frame Request (H.261)" },
108 { RTCP_NACK, "Negative Acknowledgement (H.261)" },
109 { RTCP_XR, "Extended report (RFC 3611)"},
113 /* RTCP SDES types (Section A.11.2) */
114 #define RTCP_SDES_END 0
115 #define RTCP_SDES_CNAME 1
116 #define RTCP_SDES_NAME 2
117 #define RTCP_SDES_EMAIL 3
118 #define RTCP_SDES_PHONE 4
119 #define RTCP_SDES_LOC 5
120 #define RTCP_SDES_TOOL 6
121 #define RTCP_SDES_NOTE 7
122 #define RTCP_SDES_PRIV 8
123 #define RTCP_SDES_H323_CADDR 9
125 static const value_string rtcp_sdes_type_vals[] =
127 { RTCP_SDES_END, "END" },
128 { RTCP_SDES_CNAME, "CNAME (user and domain)" },
129 { RTCP_SDES_NAME, "NAME (common name)" },
130 { RTCP_SDES_EMAIL, "EMAIL (e-mail address)" },
131 { RTCP_SDES_PHONE, "PHONE (phone number)" },
132 { RTCP_SDES_LOC, "LOC (geographic location)" },
133 { RTCP_SDES_TOOL, "TOOL (name/version of source app)" },
134 { RTCP_SDES_NOTE, "NOTE (note about source)" },
135 { RTCP_SDES_PRIV, "PRIV (private extensions)" },
136 { RTCP_SDES_H323_CADDR,"H323-CADDR (H.323 callable address)"},
140 /* RTCP XR Blocks (Section 4, RTC 3611) */
141 #define RTCP_XR_LOSS_RLE 1
142 #define RTCP_XR_DUP_RLE 2
143 #define RTCP_XR_PKT_RXTIMES 3
144 #define RTCP_XR_REF_TIME 4
145 #define RTCP_XR_DLRR 5
146 #define RTCP_XR_STATS_SUMRY 6
147 #define RTCP_XR_VOIP_METRCS 7
149 static const value_string rtcp_xr_type_vals[] =
151 { RTCP_XR_LOSS_RLE, "Loss Run Length Encoding Report Block" },
152 { RTCP_XR_DUP_RLE, "Duplicate Run Length Encoding Report Block" },
153 { RTCP_XR_PKT_RXTIMES, "Packet Receipt Times Report Block" },
154 { RTCP_XR_REF_TIME, "Receiver Reference Time Report Block" },
155 { RTCP_XR_DLRR, "DLRR Report Block" },
156 { RTCP_XR_STATS_SUMRY, "Statistics Summary Report Block" },
157 { RTCP_XR_VOIP_METRCS, "VoIP Metrics Report Block" },
160 /* XR VoIP Metrics Block - PLC Algorithms */
161 static const value_string rtcp_xr_plc_algo_vals[] =
163 { 0, "Unspecified" },
169 /* XR VoIP Metrics Block - JB Adaptive */
170 static const value_string rtcp_xr_jb_adaptive_vals[] =
174 { 2, "Non-Adaptive" },
178 /* XR Stats Summary Block - IP TTL or Hop Limit */
179 static const value_string rtcp_xr_ip_ttl_vals[] =
181 { 0, "No TTL Values" },
187 /* RTCP Application PoC1 Value strings */
188 static const value_string rtcp_app_poc1_floor_cnt_type_vals[] =
190 { 0, "Floor Request"},
194 { 4, "Floor Release"},
196 { 6, "Floor Revoke"},
200 static const value_string rtcp_app_poc1_reason_code1_vals[] =
202 { 1, "Floor already in use"},
203 { 2, "Internal PoC server error"},
204 { 3, "Only one participant in the group "},
208 static const value_string rtcp_app_poc1_reason_code2_vals[] =
210 { 1, "Only one user"},
211 { 2, "Talk burst too long"},
212 { 3, "No access to floor"},
215 /* RTCP header fields */
216 static int proto_rtcp = -1;
217 static int hf_rtcp_version = -1;
218 static int hf_rtcp_padding = -1;
219 static int hf_rtcp_rc = -1;
220 static int hf_rtcp_sc = -1;
221 static int hf_rtcp_pt = -1;
222 static int hf_rtcp_length = -1;
223 static int hf_rtcp_ssrc_sender = -1;
224 static int hf_rtcp_ntp = -1;
225 static int hf_rtcp_rtp_timestamp = -1;
226 static int hf_rtcp_sender_pkt_cnt = -1;
227 static int hf_rtcp_sender_oct_cnt = -1;
228 static int hf_rtcp_ssrc_source = -1;
229 static int hf_rtcp_ssrc_fraction = -1;
230 static int hf_rtcp_ssrc_cum_nr = -1;
231 static int hf_rtcp_ssrc_discarded = -1;
232 /* First the 32 bit number, then the split
233 * up 16 bit values */
234 /* These two are added to a subtree */
235 static int hf_rtcp_ssrc_ext_high_seq = -1;
236 static int hf_rtcp_ssrc_high_seq = -1;
237 static int hf_rtcp_ssrc_high_cycles = -1;
238 static int hf_rtcp_ssrc_jitter = -1;
239 static int hf_rtcp_ssrc_lsr = -1;
240 static int hf_rtcp_ssrc_dlsr = -1;
241 static int hf_rtcp_ssrc_csrc = -1;
242 static int hf_rtcp_ssrc_type = -1;
243 static int hf_rtcp_ssrc_length = -1;
244 static int hf_rtcp_ssrc_text = -1;
245 static int hf_rtcp_ssrc_prefix_len = -1;
246 static int hf_rtcp_ssrc_prefix_string= -1;
247 static int hf_rtcp_subtype = -1;
248 static int hf_rtcp_name_ascii = -1;
249 static int hf_rtcp_app_data = -1;
250 static int hf_rtcp_fsn = -1;
251 static int hf_rtcp_blp = -1;
252 static int hf_rtcp_padding_count = -1;
253 static int hf_rtcp_padding_data = -1;
254 static int hf_rtcp_app_poc1_subtype = -1;
255 static int hf_rtcp_app_poc1_sip_uri = -1;
256 static int hf_rtcp_app_poc1_disp_name = -1;
257 static int hf_rtcp_app_poc1_last_pkt_seq_no = -1;
258 static int hf_rtcp_app_poc1_reason_code1 = -1;
259 static int hf_rtcp_app_poc1_item_len = -1;
260 static int hf_rtcp_app_poc1_reason1_phrase = -1;
261 static int hf_rtcp_app_poc1_reason_code2 = -1;
262 static int hf_rtcp_app_poc1_additionalinfo = -1;
263 static int hf_rtcp_xr_block_type = -1;
264 static int hf_rtcp_xr_block_specific = -1;
265 static int hf_rtcp_xr_block_length = -1;
266 static int hf_rtcp_xr_thinning = -1;
267 static int hf_rtcp_xr_voip_metrics_burst_density = -1;
268 static int hf_rtcp_xr_voip_metrics_gap_density = -1;
269 static int hf_rtcp_xr_voip_metrics_burst_duration = -1;
270 static int hf_rtcp_xr_voip_metrics_gap_duration = -1;
271 static int hf_rtcp_xr_voip_metrics_rtdelay = -1;
272 static int hf_rtcp_xr_voip_metrics_esdelay = -1;
273 static int hf_rtcp_xr_voip_metrics_siglevel = -1;
274 static int hf_rtcp_xr_voip_metrics_noiselevel = -1;
275 static int hf_rtcp_xr_voip_metrics_rerl = -1;
276 static int hf_rtcp_xr_voip_metrics_gmin = -1;
277 static int hf_rtcp_xr_voip_metrics_rfactor = -1;
278 static int hf_rtcp_xr_voip_metrics_extrfactor = -1;
279 static int hf_rtcp_xr_voip_metrics_moslq = -1;
280 static int hf_rtcp_xr_voip_metrics_moscq = -1;
281 static int hf_rtcp_xr_voip_metrics_plc = -1;
282 static int hf_rtcp_xr_voip_metrics_jbadaptive = -1;
283 static int hf_rtcp_xr_voip_metrics_jbrate = -1;
284 static int hf_rtcp_xr_voip_metrics_jbnominal = -1;
285 static int hf_rtcp_xr_voip_metrics_jbmax = -1;
286 static int hf_rtcp_xr_voip_metrics_jbabsmax = -1;
287 static int hf_rtcp_xr_stats_loss_flag = -1;
288 static int hf_rtcp_xr_stats_dup_flag = -1;
289 static int hf_rtcp_xr_stats_jitter_flag = -1;
290 static int hf_rtcp_xr_stats_ttl = -1;
291 static int hf_rtcp_xr_beginseq = -1;
292 static int hf_rtcp_xr_endseq = -1;
293 static int hf_rtcp_xr_stats_lost = -1;
294 static int hf_rtcp_xr_stats_dups = -1;
295 static int hf_rtcp_xr_stats_minjitter = -1;
296 static int hf_rtcp_xr_stats_maxjitter = -1;
297 static int hf_rtcp_xr_stats_meanjitter = -1;
298 static int hf_rtcp_xr_stats_devjitter = -1;
299 static int hf_rtcp_xr_stats_minttl = -1;
300 static int hf_rtcp_xr_stats_maxttl = -1;
301 static int hf_rtcp_xr_stats_meanttl = -1;
302 static int hf_rtcp_xr_stats_devttl = -1;
303 static int hf_rtcp_xr_lrr = -1;
304 static int hf_rtcp_xr_dlrr = -1;
306 /* RTCP setup fields */
307 static int hf_rtcp_setup = -1;
308 static int hf_rtcp_setup_frame = -1;
309 static int hf_rtcp_setup_method = -1;
311 /* RTCP roundtrip delay fields */
312 static int hf_rtcp_roundtrip_delay = -1;
313 static int hf_rtcp_roundtrip_delay_frame = -1;
314 static int hf_rtcp_roundtrip_delay_delay = -1;
318 /* RTCP fields defining a sub tree */
319 static gint ett_rtcp = -1;
320 static gint ett_ssrc = -1;
321 static gint ett_ssrc_item = -1;
322 static gint ett_ssrc_ext_high = -1;
323 static gint ett_sdes = -1;
324 static gint ett_sdes_item = -1;
325 static gint ett_PoC1 = -1;
326 static gint ett_rtcp_setup = -1;
327 static gint ett_rtcp_roundtrip_delay = -1;
328 static gint ett_xr_block = -1;
329 static gint ett_xr_block_contents = -1;
330 static gint ett_xr_ssrc = -1;
331 static gint ett_xr_loss_chunk = -1;
333 /* Main dissection function */
334 static void dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo,
337 /* Heuristic dissection */
338 static gboolean global_rtcp_heur = FALSE;
339 static gboolean dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo,
342 /* Displaying set info */
343 static gboolean global_rtcp_show_setup_info = TRUE;
344 static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
346 /* Related to roundtrip calculation (using LSR and DLSR) */
347 static gboolean global_rtcp_show_roundtrip_calculation = FALSE;
348 #define MIN_ROUNDTRIP_TO_REPORT_DEFAULT 10
349 static guint global_rtcp_show_roundtrip_calculation_minimum = MIN_ROUNDTRIP_TO_REPORT_DEFAULT;
350 static void remember_outgoing_sr(packet_info *pinfo, long lsr);
351 static void calculate_roundtrip_delay(tvbuff_t *tvb, packet_info *pinfo,
352 proto_tree *tree, guint32 lsr, guint32 dlsr);
353 static void add_roundtrip_delay_info(tvbuff_t *tvb, packet_info *pinfo,
354 proto_tree *tree, guint frame, guint delay);
357 /* Memory chunk for storing conversation and per-packet info */
358 static GMemChunk *rtcp_conversations = NULL;
360 /* Set up an RTCP conversation using the info given */
361 void rtcp_add_address( packet_info *pinfo,
362 address *addr, int port,
364 gchar *setup_method, guint32 setup_frame_number)
367 conversation_t* p_conv;
368 struct _rtcp_conversation_info *p_conv_data = NULL;
371 * If this isn't the first time this packet has been processed,
372 * we've already done this work, so we don't need to do it
375 if (pinfo->fd->flags.visited)
380 SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
383 * Check if the ip address and port combination is not
384 * already registered as a conversation.
386 p_conv = find_conversation( pinfo->fd->num, addr, &null_addr, PT_UDP, port, other_port,
387 NO_ADDR_B | (!other_port ? NO_PORT_B : 0));
390 * If not, create a new conversation.
393 p_conv = conversation_new( pinfo->fd->num, addr, &null_addr, PT_UDP,
394 (guint32)port, (guint32)other_port,
395 NO_ADDR2 | (!other_port ? NO_PORT2 : 0));
399 conversation_set_dissector(p_conv, rtcp_handle);
402 * Check if the conversation has data associated with it.
404 p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
407 * If not, add a new data item.
409 if ( ! p_conv_data ) {
410 /* Create conversation data */
411 p_conv_data = g_mem_chunk_alloc(rtcp_conversations);
416 memset(p_conv_data, 0, sizeof(struct _rtcp_conversation_info));
417 conversation_add_proto_data(p_conv, proto_rtcp, p_conv_data);
421 * Update the conversation data.
423 p_conv_data->setup_method_set = TRUE;
424 strncpy(p_conv_data->setup_method, setup_method, MAX_RTCP_SETUP_METHOD_SIZE);
425 p_conv_data->setup_method[MAX_RTCP_SETUP_METHOD_SIZE] = '\0';
426 p_conv_data->setup_frame_number = setup_frame_number;
429 static void rtcp_init( void )
431 /* (Re)allocate mem chunk for conversations */
432 if (rtcp_conversations)
434 g_mem_chunk_destroy(rtcp_conversations);
436 rtcp_conversations = g_mem_chunk_new("rtcp_conversations",
437 sizeof(struct _rtcp_conversation_info),
438 20 * sizeof(struct _rtcp_conversation_info),
443 dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
445 unsigned int offset = 0;
446 unsigned int first_byte;
447 unsigned int packet_type;
449 /* This is a heuristic dissector, which means we get all the UDP
450 * traffic not sent to a known dissector and not claimed by
451 * a heuristic dissector called before us!
454 if (!global_rtcp_heur)
459 /* Was it sent between 2 odd-numbered ports? */
460 if (!(pinfo->srcport % 2) || !(pinfo->destport % 2))
465 /* Look at first byte */
466 first_byte = tvb_get_guint8(tvb, offset);
468 /* Are version bits set to 2? */
469 if (((first_byte & 0xC0) >> 6) != 2)
474 /* Look at packet type */
475 packet_type = tvb_get_guint8(tvb, offset + 1);
477 /* First packet within compound packet is supposed to be a sender
478 or receiver report. Also see BYE so allow this... */
479 if (!((packet_type == RTCP_SR) || (packet_type == RTCP_RR) ||
480 packet_type == RTCP_BYE))
485 /* Overall length must be a multiple of 4 bytes */
486 if (tvb_length(tvb) % 4)
491 /* OK, dissect as RTCP */
492 dissect_rtcp(tvb, pinfo, tree);
498 dissect_rtcp_nack( tvbuff_t *tvb, int offset, proto_tree *tree )
500 /* Packet type = FIR (H261) */
501 proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
503 /* Packet type, 8 bits = APP */
504 proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
507 /* Packet length in 32 bit words minus one */
508 proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
512 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
516 proto_tree_add_uint( tree, hf_rtcp_fsn, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
520 proto_tree_add_uint( tree, hf_rtcp_blp, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
527 dissect_rtcp_fir( tvbuff_t *tvb, int offset, proto_tree *tree )
529 /* Packet type = FIR (H261) */
530 proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
532 /* Packet type, 8 bits = APP */
533 proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
536 /* Packet length in 32 bit words minus one */
537 proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
541 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
548 dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree,
549 unsigned int padding, unsigned int packet_len, guint rtcp_subtype )
551 unsigned int counter = 0;
555 guint items_start_offset;
556 proto_tree *PoC1_tree;
557 proto_item *PoC1_item;
559 /* XXX If more application types are to be dissected it may be useful to use a table like in packet-sip.c */
560 static const char app_name_str[] = "PoC1";
564 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
569 for( counter = 0; counter < 4; counter++ )
570 ascii_name[ counter ] = tvb_get_guint8( tvb, offset + counter );
571 /* strncpy( ascii_name, pd + offset, 4 ); */
572 ascii_name[4] = '\0';
573 proto_tree_add_string( tree, hf_rtcp_name_ascii, tvb, offset, 4,
575 if ( strncasecmp(ascii_name,app_name_str,4 ) != 0 ){ /* Not PoC1 */
576 if (check_col(pinfo->cinfo, COL_INFO))
577 col_append_fstr(pinfo->cinfo, COL_INFO,"( %s ) subtype=%u",ascii_name, rtcp_subtype);
580 /* Applications specific data */
582 /* If there's padding present, we have to remove that from the data part
583 * The last octet of the packet contains the length of the padding
585 packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
587 proto_tree_add_item( tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
588 offset += packet_len;
591 }else{/* PoC1 Application */
593 item = proto_tree_add_uint( tree, hf_rtcp_app_poc1_subtype, tvb, offset - 8, 1, rtcp_subtype );
594 PROTO_ITEM_SET_GENERATED(item);
595 if (check_col(pinfo->cinfo, COL_INFO))
596 col_append_fstr(pinfo->cinfo, COL_INFO,"(%s) subtype=%s",ascii_name,
597 val_to_str(rtcp_subtype,rtcp_app_poc1_floor_cnt_type_vals,"unknown (%u)") );
600 /* Applications specific data */
602 /* If there's padding present, we have to remove that from the data part
603 * The last octet of the packet contains the length of the padding
605 packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
607 /* Create a subtree for the PoC1 Application items; we don't yet know
609 items_start_offset = offset;
611 PoC1_item = proto_tree_add_text(tree, tvb, offset, packet_len,
612 "PoC1 Application specific data");
613 PoC1_tree = proto_item_add_subtree( PoC1_item, ett_PoC1 );
616 proto_tree_add_item( PoC1_tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
617 switch ( rtcp_subtype ) {
619 sdes_type = tvb_get_guint8( tvb, offset );
620 proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
623 /* Item length, 8 bits */
624 item_len = tvb_get_guint8( tvb, offset );
625 proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
628 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_sip_uri, tvb, offset, item_len, FALSE );
629 offset = offset + item_len;
630 packet_len = packet_len - item_len;
631 sdes_type = tvb_get_guint8( tvb, offset );
632 proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
635 /* Item length, 8 bits */
636 item_len = tvb_get_guint8( tvb, offset );
637 proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
641 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_disp_name, tvb, offset, item_len, FALSE );
642 offset = offset + item_len;
643 packet_len = packet_len - item_len;
646 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason_code1, tvb, offset, 1, FALSE );
649 /* Item length, 8 bits */
650 item_len = tvb_get_guint8( tvb, offset );
651 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_item_len, tvb, offset, 1, FALSE );
655 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason1_phrase, tvb, offset, item_len, FALSE );
656 offset = offset + item_len;
657 packet_len = packet_len - item_len;
660 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_last_pkt_seq_no, tvb, offset, 2, FALSE );
661 proto_tree_add_text(PoC1_tree, tvb, offset + 2, 2, "Padding 2 bytes");
666 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason_code2, tvb, offset, 2, FALSE );
667 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_additionalinfo, tvb, offset + 2, 2, FALSE );
674 offset += packet_len;
681 dissect_rtcp_bye( tvbuff_t *tvb, int offset, proto_tree *tree,
684 unsigned int chunk = 1;
685 unsigned int reason_length = 0;
686 char* reason_text = NULL;
688 while ( chunk <= count ) {
689 /* source identifier, 32 bits */
690 proto_tree_add_item( tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
695 if ( tvb_reported_length_remaining( tvb, offset ) > 0 ) {
696 /* Bye reason consists of an 8 bit length l and a string with length l */
697 reason_length = tvb_get_guint8( tvb, offset );
698 proto_tree_add_item( tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
701 reason_text = tvb_get_string(tvb, offset, reason_length);
702 proto_tree_add_string( tree, hf_rtcp_ssrc_text, tvb, offset, reason_length, reason_text );
703 g_free( reason_text );
704 offset += reason_length;
712 dissect_rtcp_sdes( tvbuff_t *tvb, int offset, proto_tree *tree,
715 unsigned int chunk = 1;
716 proto_item *sdes_item;
717 proto_tree *sdes_tree;
718 proto_tree *sdes_item_tree;
721 int items_start_offset;
723 unsigned int item_len = 0;
724 unsigned int sdes_type = 0;
725 unsigned int counter = 0;
726 unsigned int prefix_len = 0;
727 char *prefix_string = NULL;
729 while ( chunk <= count ) {
730 /* Create a subtree for this chunk; we don't yet know
732 start_offset = offset;
734 ssrc = tvb_get_ntohl( tvb, offset );
735 sdes_item = proto_tree_add_text(tree, tvb, offset, -1,
736 "Chunk %u, SSRC/CSRC %u", chunk, ssrc);
737 sdes_tree = proto_item_add_subtree( sdes_item, ett_sdes );
739 /* SSRC_n source identifier, 32 bits */
740 proto_tree_add_uint( sdes_tree, hf_rtcp_ssrc_source, tvb, offset, 4, ssrc );
743 /* Create a subtree for the SDES items; we don't yet know
745 items_start_offset = offset;
746 ti = proto_tree_add_text(sdes_tree, tvb, offset, -1,
748 sdes_item_tree = proto_item_add_subtree( ti, ett_sdes_item );
751 * Not every message is ended with "null" bytes, so check for
752 * end of frame as well.
754 while ( tvb_reported_length_remaining( tvb, offset ) > 0 ) {
756 sdes_type = tvb_get_guint8( tvb, offset );
757 proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
760 if ( sdes_type == RTCP_SDES_END ) {
765 /* Item length, 8 bits */
766 item_len = tvb_get_guint8( tvb, offset );
767 proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
770 if ( sdes_type == RTCP_SDES_PRIV ) {
771 /* PRIV adds two items between the SDES length
772 * and value - an 8 bit length giving the
773 * length of a "prefix string", and the string.
775 prefix_len = tvb_get_guint8( tvb, offset );
776 proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_prefix_len, tvb, offset, 1, FALSE );
779 prefix_string = g_malloc( prefix_len + 1 );
780 for ( counter = 0; counter < prefix_len; counter++ )
781 prefix_string[ counter ] =
782 tvb_get_guint8( tvb, offset + counter );
783 /* strncpy( prefix_string, pd + offset, prefix_len ); */
784 prefix_string[ prefix_len ] = '\0';
785 proto_tree_add_string( sdes_item_tree, hf_rtcp_ssrc_prefix_string, tvb, offset, prefix_len, prefix_string );
786 g_free( prefix_string );
787 offset += prefix_len;
789 prefix_string = g_malloc( item_len + 1 );
790 for ( counter = 0; counter < item_len; counter++ )
791 prefix_string[ counter ] =
792 tvb_get_guint8( tvb, offset + counter );
793 /* strncpy( prefix_string, pd + offset, item_len ); */
794 prefix_string[ item_len] = 0;
795 proto_tree_add_string( sdes_item_tree, hf_rtcp_ssrc_text, tvb, offset, item_len, prefix_string );
796 g_free( prefix_string );
800 /* Set the length of the items subtree. */
801 proto_item_set_len(ti, offset - items_start_offset);
803 /* 32 bits = 4 bytes, so.....
804 * If offset % 4 != 0, we divide offset by 4, add one and then
805 * multiply by 4 again to reach the boundary
807 if ( offset % 4 != 0 )
808 offset = ((offset / 4) + 1 ) * 4;
810 /* Set the length of this chunk. */
811 proto_item_set_len(sdes_item, offset - start_offset);
817 static void parse_xr_type_specific_field(tvbuff_t *tvb, gint offset, guint block_type, proto_tree *tree)
819 guint8 flags = tvb_get_guint8(tvb, offset);
821 switch (block_type) {
822 case RTCP_XR_LOSS_RLE:
823 case RTCP_XR_DUP_RLE:
824 case RTCP_XR_PKT_RXTIMES:
825 proto_tree_add_uint(tree, hf_rtcp_xr_thinning, tvb, offset, 1, flags);
828 case RTCP_XR_STATS_SUMRY:
829 proto_tree_add_boolean(tree, hf_rtcp_xr_stats_loss_flag, tvb, offset, 1, flags);
830 proto_tree_add_boolean(tree, hf_rtcp_xr_stats_dup_flag, tvb, offset, 1, flags);
831 proto_tree_add_boolean(tree, hf_rtcp_xr_stats_jitter_flag, tvb, offset, 1, flags);
832 proto_tree_add_uint(tree, hf_rtcp_xr_stats_ttl, tvb, offset, 1, flags);
836 proto_tree_add_uint(tree, hf_rtcp_xr_block_specific, tvb, offset, 1, flags);
841 static gboolean validate_xr_block_length(tvbuff_t *tvb, int offset, guint block_type, guint block_len, proto_tree *tree)
843 proto_tree_add_uint(tree, hf_rtcp_xr_block_length, tvb, offset, 2, block_len);
844 switch (block_type) {
845 case RTCP_XR_REF_TIME:
847 proto_tree_add_text(tree, tvb, offset, 2, "Invalid block length, should be 2");
850 case RTCP_XR_STATS_SUMRY:
852 proto_tree_add_text(tree, tvb, offset, 2, "Invalid block length, should be 9");
855 case RTCP_XR_VOIP_METRCS:
857 proto_tree_add_text(tree, tvb, offset, 2, "Invalid block length, should be 8");
867 dissect_rtcp_xr(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree, gint packet_len)
871 /* Packet length should at least be 4 */
872 if (packet_len < 4) {
873 proto_tree_add_text(tree, tvb, offset, packet_len, "Missing Sender SSRC");
874 return offset + packet_len;
878 proto_tree_add_item( tree, hf_rtcp_ssrc_sender, tvb, offset, 4, FALSE );
882 for(;packet_len > 0; block_num++) {
883 guint block_type = tvb_get_guint8(tvb, offset), block_length = 0;
884 gint content_length = 0;
885 gboolean valid = TRUE;
887 /* Create a subtree for this block, dont know the length yet*/
888 proto_item *block = proto_tree_add_text(tree, tvb, offset, -1, "Block %u", block_num);
889 proto_tree *xr_block_tree = proto_item_add_subtree(block, ett_xr_block);
890 proto_item *contents = NULL;
891 proto_item *content_tree = NULL;
893 proto_tree_add_item(xr_block_tree, hf_rtcp_xr_block_type, tvb, offset, 1, FALSE);
895 if (packet_len >= 2) {
896 parse_xr_type_specific_field(tvb, offset + 1, block_type, xr_block_tree);
897 if (packet_len >= 4) {
898 block_length = tvb_get_ntohs(tvb, offset + 2);
899 valid = validate_xr_block_length(tvb, offset + 2, block_type, block_length, xr_block_tree);
902 proto_tree_add_text(xr_block_tree, tvb, offset + 1, packet_len, "Missing Required Block Headers");
903 return offset + packet_len;
906 content_length = block_length * 4;
907 proto_item_set_len(block, content_length + 4);
909 if (content_length > packet_len) {
910 proto_tree_add_text(xr_block_tree, tvb, offset + 2, 2, "Block length is greater than packet length");
916 contents = proto_tree_add_text(xr_block_tree, tvb, offset, content_length, "Contents");
917 content_tree = proto_item_add_subtree(contents, ett_xr_block_contents);
919 switch (block_type) {
920 case RTCP_XR_VOIP_METRCS: {
921 guint fraction_rate, value;
924 proto_tree_add_item(content_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
928 fraction_rate = tvb_get_guint8(tvb, offset);
929 proto_tree_add_uint_format(content_tree, hf_rtcp_ssrc_fraction, tvb, offset, 1,
930 fraction_rate, "Fraction lost: %u / 256", fraction_rate);
934 fraction_rate = tvb_get_guint8(tvb, offset);
935 proto_tree_add_uint_format(content_tree, hf_rtcp_ssrc_discarded, tvb, offset, 1,
936 fraction_rate, "Fraction Discarded: %u / 256", fraction_rate);
940 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_burst_density, tvb, offset, 1, FALSE);
944 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_gap_density, tvb, offset, 1, FALSE);
948 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_burst_duration, tvb, offset, 2, FALSE);
952 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_gap_duration, tvb, offset, 2, FALSE);
955 /* Round Trip Delay */
956 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_rtdelay, tvb, offset, 2, FALSE);
959 /* End System Delay */
960 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_esdelay, tvb, offset, 2, FALSE);
964 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_siglevel, tvb, offset, 1, FALSE);
968 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_noiselevel, tvb, offset, 1, FALSE);
972 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_rerl, tvb, offset, 1, FALSE);
976 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_gmin, tvb, offset, 1, FALSE);
980 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_rfactor, tvb, offset, 1, FALSE);
983 /* external R Factor */
984 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_extrfactor, tvb, offset, 1, FALSE);
988 proto_tree_add_float(content_tree, hf_rtcp_xr_voip_metrics_moslq, tvb, offset, 1,
989 (gfloat)tvb_get_guint8(tvb, offset) / 10);
993 proto_tree_add_float(content_tree, hf_rtcp_xr_voip_metrics_moscq, tvb, offset, 1,
994 (gfloat)tvb_get_guint8(tvb, offset) / 10);
997 /* PLC, JB Adaptive, JB Rate */
998 value = tvb_get_guint8(tvb, offset);
999 proto_tree_add_uint(content_tree, hf_rtcp_xr_voip_metrics_plc, tvb, offset, 1, value);
1000 proto_tree_add_uint(content_tree, hf_rtcp_xr_voip_metrics_jbadaptive, tvb, offset, 1, value);
1001 proto_tree_add_uint(content_tree, hf_rtcp_xr_voip_metrics_jbrate, tvb, offset, 1, value);
1002 offset += 2; /* skip over reseved bit */
1005 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_jbnominal, tvb, offset, 2, FALSE);
1009 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_jbmax, tvb, offset, 2, FALSE);
1013 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_jbabsmax, tvb, offset, 2, FALSE);
1019 case RTCP_XR_STATS_SUMRY: {
1021 proto_tree_add_item(content_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1025 proto_tree_add_item(content_tree, hf_rtcp_xr_beginseq, tvb, offset, 2, FALSE);
1029 proto_tree_add_item(content_tree, hf_rtcp_xr_endseq, tvb, offset, 2, FALSE);
1033 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_lost, tvb, offset, 4, FALSE);
1037 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_dups, tvb, offset, 4, FALSE);
1041 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_minjitter, tvb, offset, 4, FALSE);
1045 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_maxjitter, tvb, offset, 4, FALSE);
1049 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_meanjitter, tvb, offset, 4, FALSE);
1053 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_devjitter, tvb, offset, 4, FALSE);
1057 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_minttl, tvb, offset, 1, FALSE);
1061 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_maxttl, tvb, offset, 1, FALSE);
1065 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_meanttl, tvb, offset, 1, FALSE);
1069 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_devttl, tvb, offset, 1, FALSE);
1075 case RTCP_XR_REF_TIME: {
1076 guint32 ts_msw, ts_lsw;
1078 ts_msw = tvb_get_ntohl(tvb, offset);
1079 proto_tree_add_text(content_tree, tvb, offset, 4, "Timestamp, MSW: %u", ts_msw);
1081 ts_lsw = tvb_get_ntohl(tvb, offset);
1082 proto_tree_add_text(content_tree, tvb, offset, 4, "Timestamp, LSW: %u", ts_lsw);
1088 case RTCP_XR_DLRR: {
1089 /* Each report block is 12 bytes */
1090 gint sources = content_length / 12;
1092 for(counter = 0; counter < sources; counter++) {
1093 /* Create a new subtree for a length of 12 bytes */
1094 proto_tree *ti = proto_tree_add_text(content_tree, tvb, offset, 12, "Source %u", counter + 1);
1095 proto_tree *ssrc_tree = proto_item_add_subtree(ti, ett_xr_ssrc);
1097 /* SSRC_n source identifier, 32 bits */
1098 proto_tree_add_item(ssrc_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1101 /* Last RR timestamp */
1102 proto_tree_add_item(ssrc_tree, hf_rtcp_xr_lrr, tvb, offset, 4, FALSE);
1105 /* Delay since last RR timestamp */
1106 proto_tree_add_item(ssrc_tree, hf_rtcp_xr_dlrr, tvb, offset, 4, FALSE);
1110 if (content_length % 12 != 0)
1111 offset += content_length % 12;
1115 case RTCP_XR_PKT_RXTIMES: {
1116 /* 8 bytes of fixed header */
1117 gint count = 0, skip = 8;
1121 proto_tree_add_item(content_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1125 begin = tvb_get_ntohs(tvb, offset);
1126 proto_tree_add_uint(content_tree, hf_rtcp_xr_beginseq, tvb, offset, 2, begin);
1130 proto_tree_add_item(content_tree, hf_rtcp_xr_endseq, tvb, offset, 2, FALSE);
1133 for(count = 0; skip < content_length; skip += 4, count++) {
1134 proto_tree_add_text(content_tree, tvb, offset, 4, "Seq: %u, Timestamp: %u",
1135 (begin + count) % 65536, FALSE);
1141 case RTCP_XR_LOSS_RLE:
1142 case RTCP_XR_DUP_RLE: {
1143 /* 8 bytes of fixed header */
1144 gint count = 0, skip = 8;
1146 proto_item *chunks_item;
1147 proto_tree *chunks_tree;
1150 proto_tree_add_item(content_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1154 begin = tvb_get_ntohs(tvb, offset);
1155 proto_tree_add_uint(content_tree, hf_rtcp_xr_beginseq, tvb, offset, 2, begin);
1159 proto_tree_add_item(content_tree, hf_rtcp_xr_endseq, tvb, offset, 2, FALSE);
1163 chunks_item = proto_tree_add_text(content_tree, tvb, offset, content_length,"Report Chunks");
1164 chunks_tree = proto_item_add_subtree(chunks_item, ett_xr_loss_chunk);
1166 for(count = 1; skip < content_length; skip += 2, count++) {
1167 guint value = tvb_get_ntohs(tvb, offset);
1170 proto_tree_add_text(chunks_tree, tvb, offset, 2,
1171 "Chunk: %u -- Null Terminator ",
1173 } else if (( value & 0x8000 )) {
1174 gchar* run_type = (value & 0x4000) ? "1s" : "0s";
1176 proto_tree_add_text(chunks_tree, tvb, offset, 2,
1177 "Chunk: %u -- Lenght Run %s, lenght: %u",
1178 count, run_type, value);
1181 bits = decode_boolean_bitfield(value, 0x00007FFF, 16,"0","1");
1185 proto_tree_add_text(chunks_tree, tvb, offset, 2,
1186 "Chunk: %u -- Bit Vector, bits: %s",
1196 /* skip over the unknown block */
1197 offset += content_length;
1200 packet_len -= content_length;
1206 dissect_rtcp_rr( packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree,
1207 unsigned int count )
1209 unsigned int counter = 1;
1210 proto_tree *ssrc_tree = (proto_tree*) NULL;
1211 proto_tree *ssrc_sub_tree = (proto_tree*) NULL;
1212 proto_tree *high_sec_tree = (proto_tree*) NULL;
1213 proto_item *ti = (proto_item*) NULL;
1215 unsigned int cum_nr = 0;
1217 while ( counter <= count ) {
1220 /* Create a new subtree for a length of 24 bytes */
1221 ti = proto_tree_add_text(tree, tvb, offset, 24,
1222 "Source %u", counter );
1223 ssrc_tree = proto_item_add_subtree( ti, ett_ssrc );
1225 /* SSRC_n source identifier, 32 bits */
1226 proto_tree_add_item( ssrc_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE );
1229 ti = proto_tree_add_text(ssrc_tree, tvb, offset, 20, "SSRC contents" );
1230 ssrc_sub_tree = proto_item_add_subtree( ti, ett_ssrc_item );
1232 /* Fraction lost, 8bits */
1233 rr_flt = tvb_get_guint8( tvb, offset );
1234 proto_tree_add_uint_format( ssrc_sub_tree, hf_rtcp_ssrc_fraction, tvb,
1235 offset, 1, rr_flt, "Fraction lost: %u / 256", rr_flt );
1238 /* Cumulative number of packets lost, 24 bits */
1239 cum_nr = tvb_get_ntohl( tvb, offset ) >> 8;
1240 proto_tree_add_uint( ssrc_sub_tree, hf_rtcp_ssrc_cum_nr, tvb,
1241 offset, 3, cum_nr );
1244 /* Extended highest sequence nr received, 32 bits
1245 * Just for the sake of it, let's add another subtree
1246 * because this might be a little clearer
1248 ti = proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_ext_high_seq,
1249 tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1250 high_sec_tree = proto_item_add_subtree( ti, ett_ssrc_ext_high );
1251 /* Sequence number cycles */
1252 proto_tree_add_item( high_sec_tree, hf_rtcp_ssrc_high_cycles,
1253 tvb, offset, 2, FALSE );
1255 /* highest sequence number received */
1256 proto_tree_add_item( high_sec_tree, hf_rtcp_ssrc_high_seq,
1257 tvb, offset, 2, FALSE );
1260 /* Interarrival jitter */
1261 proto_tree_add_item( ssrc_tree, hf_rtcp_ssrc_jitter, tvb,
1265 /* Last SR timestamp */
1266 lsr = tvb_get_ntohl( tvb, offset );
1267 proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_lsr, tvb,
1271 /* Delay since last SR timestamp */
1272 dlsr = tvb_get_ntohl( tvb, offset );
1273 proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_dlsr, tvb,
1277 /* Do roundtrip calculation */
1278 if (global_rtcp_show_roundtrip_calculation)
1280 /* Based on delay since SR was send in other direction */
1281 calculate_roundtrip_delay(tvb, pinfo, ssrc_tree, lsr, dlsr);
1291 dissect_rtcp_sr( packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree,
1292 unsigned int count )
1295 gchar buff[ NTP_TS_SIZE ];
1296 char* ptime = tvb_get_ptr( tvb, offset, 8 );
1298 /* Retreive the NTP timestamp. Using the NTP dissector for this */
1299 ntp_fmt_ts( ptime, buff );
1300 proto_tree_add_string_format( tree, hf_rtcp_ntp, tvb, offset, 8, ( const char* ) &buff, "NTP timestamp: %s", &buff );
1301 free( ptime ); ??????????????????????????????????????????????????????????????????
1305 * XXX - RFC 1889 says this is an NTP timestamp, but that appears
1306 * not to be the case.
1308 guint32 ts_msw, ts_lsw;
1310 ts_msw = tvb_get_ntohl(tvb, offset);
1311 proto_tree_add_text(tree, tvb, offset, 4, "Timestamp, MSW: %u", ts_msw);
1313 ts_lsw = tvb_get_ntohl(tvb, offset);
1314 proto_tree_add_text(tree, tvb, offset, 4, "Timestamp, LSW: %u", ts_lsw);
1317 /* RTP timestamp, 32 bits */
1318 proto_tree_add_uint( tree, hf_rtcp_rtp_timestamp, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1320 /* Sender's packet count, 32 bits */
1321 proto_tree_add_uint( tree, hf_rtcp_sender_pkt_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1323 /* Sender's octet count, 32 bits */
1324 proto_tree_add_uint( tree, hf_rtcp_sender_oct_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1327 /* Record the time of this packet in the sender's conversation */
1328 if (global_rtcp_show_roundtrip_calculation)
1330 /* Use middle 32 bits of 64-bit time value */
1331 guint32 lsr = ((ts_msw & 0x0000ffff) << 16 | (ts_lsw & 0xffff0000) >> 16);
1333 /* Record the time that we sent this in appropriate conversation */
1334 remember_outgoing_sr(pinfo, lsr);
1337 /* The rest of the packet is equal to the RR packet */
1339 offset = dissect_rtcp_rr( pinfo, tvb, offset, tree, count );
1344 /* Look for conversation info and display any setup info found */
1345 void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1347 /* Conversation and current data */
1348 conversation_t *p_conv = NULL;
1349 struct _rtcp_conversation_info *p_conv_data = NULL;
1351 /* Use existing packet data if available */
1352 p_conv_data = p_get_proto_data(pinfo->fd, proto_rtcp);
1356 /* First time, get info from conversation */
1357 p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
1359 pinfo->destport, pinfo->srcport, NO_ADDR_B);
1363 /* Look for data in conversation */
1364 struct _rtcp_conversation_info *p_conv_packet_data;
1365 p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
1369 /* Save this conversation info into packet info */
1370 p_conv_packet_data = g_mem_chunk_alloc(rtcp_conversations);
1371 if (!p_conv_packet_data)
1375 memcpy(p_conv_packet_data, p_conv_data,
1376 sizeof(struct _rtcp_conversation_info));
1378 p_add_proto_data(pinfo->fd, proto_rtcp, p_conv_packet_data);
1383 /* Create setup info subtree with summary info. */
1384 if (p_conv_data && p_conv_data->setup_method_set)
1386 proto_tree *rtcp_setup_tree;
1387 proto_item *ti = proto_tree_add_string_format(tree, hf_rtcp_setup, tvb, 0, 0,
1389 "Stream setup by %s (frame %d)",
1390 p_conv_data->setup_method,
1391 p_conv_data->setup_frame_number);
1392 PROTO_ITEM_SET_GENERATED(ti);
1393 rtcp_setup_tree = proto_item_add_subtree(ti, ett_rtcp_setup);
1394 if (rtcp_setup_tree)
1396 /* Add details into subtree */
1397 proto_item* item = proto_tree_add_uint(rtcp_setup_tree, hf_rtcp_setup_frame,
1398 tvb, 0, 0, p_conv_data->setup_frame_number);
1399 PROTO_ITEM_SET_GENERATED(item);
1400 item = proto_tree_add_string(rtcp_setup_tree, hf_rtcp_setup_method,
1401 tvb, 0, 0, p_conv_data->setup_method);
1402 PROTO_ITEM_SET_GENERATED(item);
1408 /* Update conversation data to record time that outgoing rr/sr was sent */
1409 static void remember_outgoing_sr(packet_info *pinfo, long lsr)
1411 conversation_t *p_conv = NULL;
1412 struct _rtcp_conversation_info *p_conv_data = NULL;
1413 struct _rtcp_conversation_info *p_packet_data = NULL;
1415 /* This information will be accessed when an incoming packet comes back to
1416 the side that sent this packet, so no use storing in the packet
1417 info. However, do store the fact that we've already set this info
1421 /**************************************************************************/
1422 /* First of all, see if we've already stored this information for this sr */
1424 /* Look first in packet info */
1425 p_packet_data = p_get_proto_data(pinfo->fd, proto_rtcp);
1426 if (p_packet_data && p_packet_data->last_received_set &&
1427 p_packet_data->last_received_frame_number >= pinfo->fd->num)
1429 /* We already did this, OK */
1434 /**************************************************************************/
1435 /* Otherwise, we want to find/create the conversation and update it */
1437 /* First time, get info from conversation.
1438 Even though we think of this as an outgoing packet being sent,
1439 we store the time as being received by the destination. */
1440 p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
1442 pinfo->destport, pinfo->srcport, NO_ADDR_B);
1444 /* If the conversation doesn't exist, create it now. */
1447 p_conv = conversation_new(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src, PT_UDP,
1448 pinfo->destport, pinfo->srcport,
1452 /* Give up if can't create it */
1458 /****************************************************/
1459 /* Now find/create conversation data */
1460 p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
1463 /* Allocate memory for data */
1464 p_conv_data = g_mem_chunk_alloc(rtcp_conversations);
1467 /* Give up if couldn't allocate space for memory */
1470 memset(p_conv_data, 0, sizeof(struct _rtcp_conversation_info));
1472 /* Add it to conversation. */
1473 conversation_add_proto_data(p_conv, proto_rtcp, p_conv_data);
1476 /*******************************************************/
1477 /* Update conversation data */
1478 p_conv_data->last_received_set = TRUE;
1479 p_conv_data->last_received_frame_number = pinfo->fd->num;
1480 p_conv_data->last_received_time_secs = pinfo->fd->abs_secs;
1481 p_conv_data->last_received_time_usecs = pinfo->fd->abs_usecs;
1482 p_conv_data->last_received_ts = lsr;
1485 /****************************************************************/
1486 /* Update packet info to record conversation state */
1488 /* Will use/create packet info */
1491 p_packet_data = g_mem_chunk_alloc(rtcp_conversations);
1494 /* Give up if allocation fails */
1497 memset(p_packet_data, 0, sizeof(struct _rtcp_conversation_info));
1499 p_add_proto_data(pinfo->fd, proto_rtcp, p_packet_data);
1502 /* Copy current conversation data into packet info */
1503 p_packet_data->last_received_set = TRUE;
1504 p_packet_data->last_received_frame_number = p_conv_data->last_received_frame_number;
1505 p_packet_data->last_received_time_secs = p_conv_data->last_received_time_secs;
1506 p_packet_data->last_received_time_usecs = p_conv_data->last_received_time_usecs;
1510 /* Use received sr to work out what the roundtrip delay is
1511 (at least between capture point and the other endpoint involved in
1512 the conversation) */
1513 static void calculate_roundtrip_delay(tvbuff_t *tvb, packet_info *pinfo,
1514 proto_tree *tree, guint32 lsr, guint32 dlsr)
1516 /*****************************************************/
1517 /* This is called dissecting an SR. We need to:
1518 - look in the packet info for stored calculation. If found, use.
1519 - look up the conversation of the sending side to see when the
1520 'last SR' was detected (received)
1521 - calculate the network delay using the that packet time,
1522 this packet time, and dlsr
1523 *****************************************************/
1525 conversation_t *p_conv = NULL;
1526 struct _rtcp_conversation_info *p_conv_data = NULL;
1527 struct _rtcp_conversation_info *p_packet_data = NULL;
1530 /*************************************************/
1531 /* Look for previously stored calculation result */
1532 p_packet_data = p_get_proto_data(pinfo->fd, proto_rtcp);
1533 if (p_packet_data && p_packet_data->calculated_delay_set)
1536 add_roundtrip_delay_info(tvb, pinfo, tree,
1537 p_packet_data->calculated_delay_used_frame,
1538 p_packet_data->calculated_delay);
1543 /********************************************************************/
1544 /* Look for captured timestamp of last SR in conversation of sender */
1545 /* of this packet */
1546 p_conv = find_conversation(pinfo->fd->num, &pinfo->net_src, &pinfo->net_dst,
1548 pinfo->srcport, pinfo->destport, NO_ADDR_B);
1554 /* Look for conversation data */
1555 p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
1561 if (p_conv_data->last_received_set)
1563 /* Store result of calculation in packet info */
1566 /* Create packet info if it doesn't exist */
1567 p_packet_data = g_mem_chunk_alloc(rtcp_conversations);
1570 /* Give up if allocation fails */
1574 memset(p_packet_data, 0, sizeof(struct _rtcp_conversation_info));
1576 /* Set as packet info */
1577 p_add_proto_data(pinfo->fd, proto_rtcp, p_packet_data);
1580 /* Any previous report must match the lsr given here */
1581 if (p_conv_data->last_received_ts == lsr)
1583 /* Look at time of since original packet was sent */
1584 gint seconds_between_packets =
1585 pinfo->fd->abs_secs - p_conv_data->last_received_time_secs;
1586 gint useconds_between_packets =
1587 pinfo->fd->abs_usecs - p_conv_data->last_received_time_usecs;
1590 gint total_gap = ((seconds_between_packets*1000000) +
1591 useconds_between_packets) / 1000;
1592 gint delay = total_gap - (int)(((double)dlsr/(double)65536) * 1000.0);
1594 /* No useful calculation can be done if dlsr not set... */
1600 p_packet_data->calculated_delay_set = TRUE;
1601 p_packet_data->calculated_delay = delay;
1602 p_packet_data->calculated_delay_used_frame = p_conv_data->last_received_frame_number;
1605 add_roundtrip_delay_info(tvb, pinfo, tree, p_conv_data->last_received_frame_number, delay);
1610 /* Show the calcaulted roundtrip delay info by adding protocol tree items
1611 and appending text to the info column */
1612 static void add_roundtrip_delay_info(tvbuff_t *tvb, packet_info *pinfo,
1613 proto_tree *tree, guint frame, guint delay)
1615 proto_tree *rtcp_roundtrip_delay_tree;
1618 /* Don't report on calculated delays below the threshold */
1619 if (delay < global_rtcp_show_roundtrip_calculation_minimum)
1624 /* Add labelled subtree for roundtrip delay info */
1625 ti = proto_tree_add_string_format(tree, hf_rtcp_roundtrip_delay, tvb, 0, 0,
1627 "Calculated Roundtrip delay <-> %s = %dms, using frame %d",
1628 address_to_str(&pinfo->net_src), delay,
1631 PROTO_ITEM_SET_GENERATED(ti);
1632 rtcp_roundtrip_delay_tree = proto_item_add_subtree(ti, ett_rtcp_roundtrip_delay);
1633 if (rtcp_roundtrip_delay_tree)
1635 /* Add details into subtree */
1636 proto_item* item = proto_tree_add_uint(rtcp_roundtrip_delay_tree,
1637 hf_rtcp_roundtrip_delay_frame,
1639 PROTO_ITEM_SET_GENERATED(item);
1640 item = proto_tree_add_uint(rtcp_roundtrip_delay_tree, hf_rtcp_roundtrip_delay_delay,
1642 PROTO_ITEM_SET_GENERATED(item);
1645 /* Report delay in INFO column */
1646 if (check_col(pinfo->cinfo, COL_INFO))
1648 col_append_fstr(pinfo->cinfo, COL_INFO,
1649 " (roundtrip delay <-> %s = %dms, using frame %d)",
1650 address_to_str(&pinfo->net_src), delay, frame);
1657 dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1659 proto_item *ti = NULL;
1660 proto_tree *rtcp_tree = NULL;
1661 unsigned int temp_byte = 0;
1662 unsigned int padding_set = 0;
1663 unsigned int elem_count = 0;
1664 unsigned int packet_type = 0;
1665 unsigned int offset = 0;
1666 guint16 packet_length = 0;
1667 guint rtcp_subtype = 0;
1669 if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) {
1670 col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTCP" );
1673 if ( check_col( pinfo->cinfo, COL_INFO) ) {
1674 /* The second octet contains the packet type */
1675 /* switch ( pd[ offset + 1 ] ) { */
1676 switch ( tvb_get_guint8( tvb, 1 ) ) {
1678 col_set_str( pinfo->cinfo, COL_INFO, "Sender Report");
1681 col_set_str( pinfo->cinfo, COL_INFO, "Receiver Report");
1684 col_set_str( pinfo->cinfo, COL_INFO, "Source Description");
1687 col_set_str( pinfo->cinfo, COL_INFO, "Goodbye");
1690 col_set_str( pinfo->cinfo, COL_INFO, "Application defined");
1693 col_set_str( pinfo->cinfo, COL_INFO, "Extended report");
1696 col_set_str( pinfo->cinfo, COL_INFO, "Full Intra-frame Request (H.261)");
1699 col_set_str( pinfo->cinfo, COL_INFO, "Negative Acknowledgement (H.261)");
1702 col_set_str( pinfo->cinfo, COL_INFO, "Unknown packet type");
1708 * Check if there are at least 4 bytes left in the frame,
1709 * the last 16 bits of those is the length of the current
1710 * RTCP message. The last compound message contains padding,
1711 * that enables us to break from the while loop.
1713 while ( tvb_bytes_exist( tvb, offset, 4) ) {
1715 * First retreive the packet_type
1717 packet_type = tvb_get_guint8( tvb, offset + 1 );
1720 * Check if it's a valid type
1722 if ( ( packet_type < 192 ) || ( packet_type > 207 ) )
1726 * get the packet-length for the complete RTCP packet
1728 packet_length = ( tvb_get_ntohs( tvb, offset + 2 ) + 1 ) * 4;
1730 ti = proto_tree_add_item(tree, proto_rtcp, tvb, offset, packet_length, FALSE );
1731 rtcp_tree = proto_item_add_subtree( ti, ett_rtcp );
1733 /* Conversation setup info */
1734 if (global_rtcp_show_setup_info)
1736 show_setup_info(tvb, pinfo, rtcp_tree);
1740 temp_byte = tvb_get_guint8( tvb, offset );
1742 proto_tree_add_uint( rtcp_tree, hf_rtcp_version, tvb,
1743 offset, 1, temp_byte);
1744 padding_set = RTCP_PADDING( temp_byte );
1746 proto_tree_add_boolean( rtcp_tree, hf_rtcp_padding, tvb,
1747 offset, 1, temp_byte );
1748 elem_count = RTCP_COUNT( temp_byte );
1750 switch ( packet_type ) {
1753 /* Receiver report count, 5 bits */
1754 proto_tree_add_uint( rtcp_tree, hf_rtcp_rc, tvb, offset, 1, temp_byte );
1756 /* Packet type, 8 bits */
1757 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
1759 /* Packet length in 32 bit words MINUS one, 16 bits */
1760 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
1762 /* Sender Synchronization source, 32 bits */
1763 proto_tree_add_uint( rtcp_tree, hf_rtcp_ssrc_sender, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1766 if ( packet_type == RTCP_SR ) offset = dissect_rtcp_sr( pinfo, tvb, offset, rtcp_tree, elem_count );
1767 else offset = dissect_rtcp_rr( pinfo, tvb, offset, rtcp_tree, elem_count );
1770 /* Source count, 5 bits */
1771 proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, temp_byte );
1773 /* Packet type, 8 bits */
1774 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
1776 /* Packet length in 32 bit words MINUS one, 16 bits */
1777 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
1779 dissect_rtcp_sdes( tvb, offset, rtcp_tree, elem_count );
1780 offset += packet_length - 4;
1783 /* Source count, 5 bits */
1784 proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, temp_byte );
1786 /* Packet type, 8 bits */
1787 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
1789 /* Packet length in 32 bit words MINUS one, 16 bits */
1790 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
1792 offset = dissect_rtcp_bye( tvb, offset, rtcp_tree, elem_count );
1795 /* Subtype, 5 bits */
1796 rtcp_subtype = elem_count;
1797 proto_tree_add_uint( rtcp_tree, hf_rtcp_subtype, tvb, offset, 1, elem_count );
1799 /* Packet type, 8 bits */
1800 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
1802 /* Packet length in 32 bit words MINUS one, 16 bits */
1803 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
1805 offset = dissect_rtcp_app( tvb, pinfo, offset,
1806 rtcp_tree, padding_set,
1807 packet_length - 4, rtcp_subtype );
1810 /* Reserved, 5 bits, Ignore */
1812 /* Packet type, 8 bits */
1813 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
1815 /* Packet length in 32 bit words MINUS one, 16 bits */
1816 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
1818 offset = dissect_rtcp_xr( tvb, pinfo, offset, rtcp_tree, packet_length - 4 );
1821 offset = dissect_rtcp_fir( tvb, offset, rtcp_tree );
1824 offset = dissect_rtcp_nack( tvb, offset, rtcp_tree );
1828 * To prevent endless loops in case of an unknown message type
1829 * increase offset. Some time the while will end :-)
1835 /* If the padding bit is set, the last octet of the
1836 * packet contains the length of the padding
1837 * We only have to check for this at the end of the LAST RTCP message
1839 if ( padding_set ) {
1840 /* If everything went according to plan offset should now point to the
1841 * first octet of the padding
1843 proto_tree_add_item( rtcp_tree, hf_rtcp_padding_data, tvb, offset, tvb_length_remaining( tvb, offset) - 1, FALSE );
1844 offset += tvb_length_remaining( tvb, offset) - 1;
1845 proto_tree_add_item( rtcp_tree, hf_rtcp_padding_count, tvb, offset, 1, FALSE );
1850 proto_register_rtcp(void)
1852 static hf_register_info hf[] =
1861 VALS(rtcp_version_vals),
1881 "Reception report count",
1909 VALS( rtcp_packet_type_vals ),
1927 &hf_rtcp_ssrc_sender,
1942 "rtcp.timestamp.ntp",
1951 &hf_rtcp_rtp_timestamp,
1954 "rtcp.timestamp.rtp",
1963 &hf_rtcp_sender_pkt_cnt,
1965 "Sender's packet count",
1966 "rtcp.sender.packetcount",
1975 &hf_rtcp_sender_oct_cnt,
1977 "Sender's octet count",
1978 "rtcp.sender.octetcount",
1987 &hf_rtcp_ssrc_source,
1990 "rtcp.ssrc.identifier",
1999 &hf_rtcp_ssrc_fraction,
2002 "rtcp.ssrc.fraction",
2011 &hf_rtcp_ssrc_cum_nr,
2013 "Cumulative number of packets lost",
2023 &hf_rtcp_ssrc_ext_high_seq,
2025 "Extended highest sequence number received",
2026 "rtcp.ssrc.ext_high",
2035 &hf_rtcp_ssrc_high_seq,
2037 "Highest sequence number received",
2038 "rtcp.ssrc.high_seq",
2047 &hf_rtcp_ssrc_high_cycles,
2049 "Sequence number cycles count",
2050 "rtcp.ssrc.high_cycles",
2059 &hf_rtcp_ssrc_jitter,
2061 "Interarrival jitter",
2073 "Last SR timestamp",
2085 "Delay since last SR timestamp",
2097 "SSRC / CSRC identifier",
2098 "rtcp.sdes.ssrc_csrc",
2113 VALS( rtcp_sdes_type_vals ),
2119 &hf_rtcp_ssrc_length,
2143 &hf_rtcp_ssrc_prefix_len,
2146 "rtcp.sdes.prefix.length",
2155 &hf_rtcp_ssrc_prefix_string,
2158 "rtcp.sdes.prefix.string",
2179 &hf_rtcp_name_ascii,
2193 "Application specific data",
2203 &hf_rtcp_app_poc1_subtype,
2206 "rtcp.app.PoC1.subtype",
2209 VALS(rtcp_app_poc1_floor_cnt_type_vals),
2215 &hf_rtcp_app_poc1_sip_uri,
2218 "rtcp.app.poc1.sip.uri",
2227 &hf_rtcp_app_poc1_disp_name,
2230 "rtcp.app.poc1.disp.name",
2239 &hf_rtcp_app_poc1_last_pkt_seq_no,
2241 "Seq. no of last RTP packet",
2242 "rtcp.app.poc1.last.pkt.seq.no",
2251 &hf_rtcp_app_poc1_reason_code1,
2254 "rtcp.app.poc1.reason.code",
2257 VALS(rtcp_app_poc1_reason_code1_vals),
2263 &hf_rtcp_app_poc1_item_len,
2266 "rtcp.app.poc1.item.len",
2275 &hf_rtcp_app_poc1_reason1_phrase,
2278 "rtcp.app.poc1.reason.phrase",
2287 &hf_rtcp_app_poc1_reason_code2,
2290 "rtcp.app.poc1.reason.code",
2293 VALS(rtcp_app_poc1_reason_code2_vals),
2299 &hf_rtcp_app_poc1_additionalinfo,
2301 "additional information",
2302 "rtcp.app.poc1.add.info",
2313 "First sequence number",
2325 "Bitmask of following lost packets",
2335 &hf_rtcp_padding_count,
2338 "rtcp.padding.count",
2347 &hf_rtcp_padding_data,
2350 "rtcp.padding.data",
2367 "Stream setup, method and frame number", HFILL
2371 &hf_rtcp_setup_frame,
2379 "Frame that set up this stream", HFILL
2383 &hf_rtcp_setup_method,
2386 "rtcp.setup-method",
2391 "Method used to set up this stream", HFILL
2395 &hf_rtcp_roundtrip_delay,
2398 "rtcp.roundtrip-delay",
2403 "Calculated roundtrip delay, frame and ms value", HFILL
2407 &hf_rtcp_roundtrip_delay_frame,
2409 "Previous SR frame used in calculation",
2410 "rtcp.roundtrip-previous-sr-frame",
2415 "Frame used to calculate roundtrip delay", HFILL
2419 &hf_rtcp_roundtrip_delay_delay,
2421 "Roundtrip Delay(ms)",
2422 "rtcp.roundtrip-delay-delay",
2427 "Calculated roundtrip delay in ms", HFILL
2431 &hf_rtcp_xr_block_type,
2437 VALS(rtcp_xr_type_vals),
2443 &hf_rtcp_xr_block_specific,
2455 &hf_rtcp_xr_block_length,
2463 "Block Length", HFILL
2467 &hf_rtcp_ssrc_discarded,
2469 "Fraction discarded",
2470 "rtcp.ssrc.discarded",
2475 "Discard Rate", HFILL
2479 &hf_rtcp_xr_voip_metrics_burst_density,
2482 "rtcp.xr.voipmetrics.burstdensity",
2491 &hf_rtcp_xr_voip_metrics_gap_density,
2494 "rtcp.xr.voipmetrics.gapdensity",
2503 &hf_rtcp_xr_voip_metrics_burst_duration,
2505 "Burst Duration(ms)",
2506 "rtcp.xr.voipmetrics.burstduration",
2515 &hf_rtcp_xr_voip_metrics_gap_duration,
2518 "rtcp.xr.voipmetrics.gapduration",
2527 &hf_rtcp_xr_voip_metrics_rtdelay,
2529 "Round Trip Delay(ms)",
2530 "rtcp.xr.voipmetrics.rtdelay",
2539 &hf_rtcp_xr_voip_metrics_esdelay,
2541 "End System Delay(ms)",
2542 "rtcp.xr.voipmetrics.esdelay",
2551 &hf_rtcp_xr_voip_metrics_siglevel,
2554 "rtcp.xr.voipmetrics.signallevel",
2559 "Signal level of 127 indicates this parameter is unavailable", HFILL
2563 &hf_rtcp_xr_voip_metrics_noiselevel,
2566 "rtcp.xr.voipmetrics.noiselevel",
2571 "Noise level of 127 indicates this parameter is unavailable", HFILL
2575 &hf_rtcp_xr_voip_metrics_rerl,
2577 "Residual Echo Return Loss",
2578 "rtcp.xr.voipmetrics.rerl",
2587 &hf_rtcp_xr_voip_metrics_gmin,
2590 "rtcp.xr.voipmetrics.gmin",
2599 &hf_rtcp_xr_voip_metrics_rfactor,
2602 "rtcp.xr.voipmetrics.rfactor",
2607 "R Factor is in the range of 0 to 100; 127 indicates this parameter is unavailable", HFILL
2611 &hf_rtcp_xr_voip_metrics_extrfactor,
2613 "External R Factor",
2614 "rtcp.xr.voipmetrics.extrfactor",
2619 "R Factor is in the range of 0 to 100; 127 indicates this parameter is unavailable", HFILL
2623 &hf_rtcp_xr_voip_metrics_moslq,
2625 "MOS - Listening Quality",
2626 "rtcp.xr.voipmetrics.moslq",
2631 "MOS is in the range of 1 to 5; 127 indicates this parameter is unavailable", HFILL
2635 &hf_rtcp_xr_voip_metrics_moscq,
2637 "MOS - Conversational Quality",
2638 "rtcp.xr.voipmetrics.moscq",
2643 "MOS is in the range of 1 to 5; 127 indicates this parameter is unavailable", HFILL
2647 &hf_rtcp_xr_voip_metrics_plc,
2649 "Packet Loss Conealment Algorithm",
2650 "rtcp.xr.voipmetrics.plc",
2653 VALS(rtcp_xr_plc_algo_vals),
2659 &hf_rtcp_xr_voip_metrics_jbadaptive,
2661 "Adaptive Jitter Buffer Algorithm",
2662 "rtcp.xr.voipmetrics.jba",
2665 VALS(rtcp_xr_jb_adaptive_vals),
2671 &hf_rtcp_xr_voip_metrics_jbrate,
2673 "Jitter Buffer Rate",
2674 "rtcp.xr.voipmetrics.jbrate",
2683 &hf_rtcp_xr_voip_metrics_jbnominal,
2685 "Nominal Jitter Buffer Size",
2686 "rtcp.xr.voipmetrics.jbnominal",
2695 &hf_rtcp_xr_voip_metrics_jbmax,
2697 "Maximum Jitter Buffer Size",
2698 "rtcp.xr.voipmetrics.jbmax",
2707 &hf_rtcp_xr_voip_metrics_jbabsmax,
2709 "Absolute Maximum Jitter Buffer Size",
2710 "rtcp.xr.voipmetrics.jbabsmax",
2719 &hf_rtcp_xr_thinning,
2731 &hf_rtcp_xr_stats_loss_flag,
2734 "rtcp.xr.stats.lrflag",
2743 &hf_rtcp_xr_stats_dup_flag,
2745 "Duplicates Report Flag",
2746 "rtcp.xr.stats.dupflag",
2755 &hf_rtcp_xr_stats_jitter_flag,
2757 "Jitter Report Flag",
2758 "rtcp.xr.stats.jitterflag",
2767 &hf_rtcp_xr_stats_ttl,
2769 "TTL or Hop Limit Flag",
2770 "rtcp.xr.stats.ttl",
2773 VALS(rtcp_xr_ip_ttl_vals),
2781 "End Sequence Number",
2791 &hf_rtcp_xr_beginseq,
2793 "Begin Sequence Number",
2803 &hf_rtcp_xr_stats_lost,
2806 "rtcp.xr.stats.lost",
2815 &hf_rtcp_xr_stats_dups,
2817 "Duplicate Packets",
2818 "rtcp.xr.stats.dups",
2827 &hf_rtcp_xr_stats_minjitter,
2830 "rtcp.xr.stats.minjitter",
2839 &hf_rtcp_xr_stats_maxjitter,
2842 "rtcp.xr.stats.maxjitter",
2851 &hf_rtcp_xr_stats_meanjitter,
2854 "rtcp.xr.stats.meanjitter",
2863 &hf_rtcp_xr_stats_devjitter,
2865 "Standard Deviation of Jitter",
2866 "rtcp.xr.stats.devjitter",
2875 &hf_rtcp_xr_stats_minttl,
2877 "Minimum TTL or Hop Limit",
2878 "rtcp.xr.stats.minttl",
2887 &hf_rtcp_xr_stats_maxttl,
2889 "Maximum TTL or Hop Limit",
2890 "rtcp.xr.stats.maxttl",
2899 &hf_rtcp_xr_stats_meanttl,
2901 "Mean TTL or Hop Limit",
2902 "rtcp.xr.stats.meanttl",
2911 &hf_rtcp_xr_stats_devttl,
2913 "Standard Deviation of TTL",
2914 "rtcp.xr.stats.devttl",
2925 "Last RR timestamp",
2937 "Delay since last RR timestamp",
2948 static gint *ett[] =
2958 &ett_rtcp_roundtrip_delay,
2960 &ett_xr_block_contents,
2965 module_t *rtcp_module;
2967 proto_rtcp = proto_register_protocol("Real-time Transport Control Protocol",
2969 proto_register_field_array(proto_rtcp, hf, array_length(hf));
2970 proto_register_subtree_array(ett, array_length(ett));
2972 register_dissector("rtcp", dissect_rtcp, proto_rtcp);
2974 rtcp_module = prefs_register_protocol(proto_rtcp, NULL);
2976 prefs_register_bool_preference(rtcp_module, "show_setup_info",
2977 "Show stream setup information",
2978 "Where available, show which protocol and frame caused "
2979 "this RTCP stream to be created",
2980 &global_rtcp_show_setup_info);
2982 prefs_register_bool_preference(rtcp_module, "heuristic_rtcp",
2983 "Try to decode RTCP outside of conversations ",
2984 "If call control SIP/H.323/RTSP/.. messages are missing in the trace, "
2985 "RTCP isn't decoded without this",
2988 prefs_register_bool_preference(rtcp_module, "show_roundtrip_calculation",
2989 "Show relative roundtrip calculations",
2990 "Try to work out network delay by comparing time between packets "
2991 "as captured and delays as seen by endpoint",
2992 &global_rtcp_show_roundtrip_calculation);
2994 prefs_register_uint_preference(rtcp_module, "roundtrip_min_threshhold",
2995 "Minimum roundtrip calculations to report (ms)",
2996 "Minimum calculated roundtrip delay time in milliseconds that "
2997 "should be reported",
2998 MIN_ROUNDTRIP_TO_REPORT_DEFAULT, &global_rtcp_show_roundtrip_calculation_minimum);
3001 register_init_routine( &rtcp_init );
3005 proto_reg_handoff_rtcp(void)
3008 * Register this dissector as one that can be selected by a
3011 rtcp_handle = find_dissector("rtcp");
3012 dissector_add_handle("udp.port", rtcp_handle);
3014 heur_dissector_add( "udp", dissect_rtcp_heur, proto_rtcp);