From Didier Gautheron:
[obnox/wireshark/wip.git] / epan / dissectors / packet-rdt.c
1 /* packet-rdt.c
2  *
3  * Routines for RDT dissection
4  * RDT = Real Data Transport
5  *
6  * Copyright 2005
7  * Written by Martin Mathieson and Tom Marshall
8  *
9  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
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.
19  *
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.
24  *
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.
28  */
29
30 /* Information sources:
31  * helixcommunity.org sources, in particular
32  * server/protocol/transport/rdt/pub/tngpkt.pm
33  */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <glib.h>
40 #include <stdio.h>
41 #include <string.h>
42
43 #include <epan/packet.h>
44 #include <epan/conversation.h>
45 #include <epan/prefs.h>
46 #include <epan/emem.h>
47 #include <epan/strutil.h>
48
49 #include "packet-rdt.h"
50
51 static dissector_handle_t rdt_handle;
52
53 static gint    proto_rdt                        = -1;
54
55 /* Packet fields */
56 static gint    hf_rdt_packet                    = -1;
57
58 /* flags1: shared */
59 static gint    hf_rdt_len_included              = -1;
60
61 /* flags1: data packet */
62 static gint    hf_rdt_data_flags1               = -1;
63 static gint    hf_rdt_data_need_reliable        = -1;
64 static gint    hf_rdt_data_stream_id            = -1;
65 static gint    hf_rdt_data_is_reliable          = -1;
66
67 /* flags2: data packet */
68 static gint    hf_rdt_data_flags2               = -1;
69 static gint    hf_rdt_data_backtoback           = -1;
70 static gint    hf_rdt_data_slowdata             = -1;
71 static gint    hf_rdt_data_asmrule              = -1;
72
73 /* flags1: asm action packet */
74 static gint    hf_rdt_aact_flags                = -1;
75 static gint    hf_rdt_aact_stream_id            = -1;
76
77 /* flags1: ack packet */
78 static gint    hf_rdt_ack_flags                 = -1;
79 static gint    hf_rdt_ack_lost_high             = -1;
80
81 /* flags1: latency report packet */
82 static gint    hf_rdt_latency_report_flags      = -1;
83
84 /* flags1: bandwidth report packet */
85 static gint    hf_rdt_bandwidth_report_flags    = -1;
86
87 /* flags1: stream end packet */
88 static gint    hf_rdt_stre_flags                = -1;
89 static gint    hf_rdt_stre_need_reliable        = -1;
90 static gint    hf_rdt_stre_stream_id            = -1;
91 static gint    hf_rdt_stre_packet_sent          = -1;
92 static gint    hf_rdt_stre_ext_flag             = -1;
93
94 static gint    hf_rdt_rtt_request_flags         = -1;
95 static gint    hf_rdt_rtt_response_flags        = -1;
96 static gint    hf_rdt_congestion_flags          = -1;
97 static gint    hf_rdt_report_flags              = -1;
98 static gint    hf_rdt_tirq_flags                = -1;
99 static gint    hf_rdt_tirp_flags                = -1;
100 static gint    hf_rdt_bw_probing_flags          = -1;
101
102 /* Octets 1-2: sequence number or packet type */
103 static gint    hf_rdt_sequence_number           = -1;
104 static gint    hf_rdt_packet_type               = -1;
105
106 /* Only present if length_included */
107 static gint    hf_rdt_packet_length             = -1;
108
109 /* General shared fields */
110 static gint    hf_rdt_timestamp                 = -1;
111 static gint    hf_rdt_stream_id_ex              = -1;
112 static gint    hf_rdt_asmrule_ex                = -1;
113 static gint    hf_rdt_total_reliable            = -1;
114 static gint    hf_rdt_data                      = -1;
115
116 /* Special use fields */
117 static gint    hf_rdt_aact_reliable_seqno       = -1;
118 static gint    hf_rdt_brpt_interval             = -1;
119 static gint    hf_rdt_brpt_bandwidth            = -1;
120 static gint    hf_rdt_brpt_sequence             = -1;
121 static gint    hf_rdt_rtrp_ts_sec               = -1;
122 static gint    hf_rdt_rtrp_ts_usec              = -1;
123 static gint    hf_rdt_cong_xmit_mult            = -1;
124 static gint    hf_rdt_cong_recv_mult            = -1;
125 static gint    hf_rdt_stre_seqno                = -1;
126 static gint    hf_rdt_stre_dummy_flags1         = -1;
127 static gint    hf_rdt_stre_dummy_type           = -1;
128 static gint    hf_rdt_stre_reason_code          = -1;
129 static gint    hf_rdt_lrpt_server_out_time      = -1;
130 static gint    hf_rdt_tirq_request_rtt_info     = -1;
131 static gint    hf_rdt_tirq_request_buffer_info  = -1;
132 static gint    hf_rdt_tirq_request_time_msec    = -1;
133 static gint    hf_rdt_tirp_has_rtt_info         = -1;
134 static gint    hf_rdt_tirp_is_delayed           = -1;
135 static gint    hf_rdt_tirp_has_buffer_info      = -1;
136 static gint    hf_rdt_tirp_request_time_msec    = -1;
137 static gint    hf_rdt_tirp_response_time_msec   = -1;
138 static gint    hf_rdt_tirp_buffer_info          = -1;
139 static gint    hf_rdt_tirp_buffer_info_count    = -1;
140 static gint    hf_rdt_tirp_buffer_info_stream_id         = -1;
141 static gint    hf_rdt_tirp_buffer_info_lowest_timestamp  = -1;
142 static gint    hf_rdt_tirp_buffer_info_highest_timestamp = -1;
143 static gint    hf_rdt_tirp_buffer_info_bytes_buffered    = -1;
144 static gint    hf_rdt_bwpp_seqno                = -1;
145 static gint    hf_rdt_unk_flags1                = -1;
146
147 /* RDT setup fields */
148 static gint    hf_rdt_setup                     = -1;
149 static gint    hf_rdt_setup_frame               = -1;
150 static gint    hf_rdt_setup_method              = -1;
151 static gint    hf_rdt_feature_level             = -1;
152
153 /* RDT fields defining a sub tree */
154 static gint    ett_rdt                          = -1;
155 static gint    ett_rdt_packet                   = -1;
156 static gint    ett_rdt_setup                    = -1;
157 static gint    ett_rdt_data_flags1              = -1;
158 static gint    ett_rdt_data_flags2              = -1;
159 static gint    ett_rdt_aact_flags               = -1;
160 static gint    ett_rdt_ack_flags                = -1;
161 static gint    ett_rdt_latency_report_flags     = -1;
162 static gint    ett_rdt_bandwidth_report_flags   = -1;
163 static gint    ett_rdt_stre_flags               = -1;
164 static gint    ett_rdt_rtt_request_flags        = -1;
165 static gint    ett_rdt_rtt_response_flags       = -1;
166 static gint    ett_rdt_congestion_flags         = -1;
167 static gint    ett_rdt_report_flags             = -1;
168 static gint    ett_rdt_tirq_flags               = -1;
169 static gint    ett_rdt_tirp_flags               = -1;
170 static gint    ett_rdt_tirp_buffer_info         = -1;
171 static gint    ett_rdt_bw_probing_flags         = -1;
172
173 /* Port preference settings */
174 static gboolean global_rdt_register_udp_port = FALSE;
175 static guint    global_rdt_udp_port = 6970;
176
177 void proto_register_rdt(void);
178 void proto_reg_handoff_rdt(void);
179
180 /* Main dissection function */
181 static void dissect_rdt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
182
183 /* Parse individual packet types */
184 static guint dissect_rdt_data_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
185 static guint dissect_rdt_asm_action_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
186 static guint dissect_rdt_bandwidth_report_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
187 static guint dissect_rdt_ack_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
188 static guint dissect_rdt_rtt_request_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
189 static guint dissect_rdt_rtt_response_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
190 static guint dissect_rdt_congestion_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
191 static guint dissect_rdt_stream_end_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
192 static guint dissect_rdt_report_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
193 static guint dissect_rdt_latency_report_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
194 static guint dissect_rdt_transport_info_request_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
195 static guint dissect_rdt_transport_info_response_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
196 static guint dissect_rdt_bw_probing_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
197 static guint dissect_rdt_unknown_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
198
199 static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
200
201 /* Preferences bool to control whether or not setup info should be shown */
202 static gboolean global_rdt_show_setup_info = TRUE;
203
204 /* Packet types */
205 #define RDT_ASMACTIION_PACKET               0xff00
206 #define RDT_BANDWIDTHREPORT_PACKET          0xff01
207 #define RDT_ACK_PACKET                      0xff02
208 #define RDT_RTTREQUEST_PACKET               0xff03
209 #define RDT_RTTRESPONSE_PACKET              0xff04
210 #define RDT_CONGESTION_PACKET               0xff05
211 #define RDT_STREAMEND_PACKET                0xff06
212 #define RDT_REPORT_PACKET                   0xff07
213 #define RDT_LATENCYREPORT_PACKET            0xff08
214 #define RDT_TRANSPORTINFO_PACKET            0xff09
215 #define RDT_TRANSPORTINFORESPONSE_PACKET    0xff0a
216 #define RDT_BWPROBING_PACKET                0xff0b
217
218 static const value_string packet_type_vals[] =
219 {
220     { RDT_ASMACTIION_PACKET,             "Asm action"  },
221     { RDT_BANDWIDTHREPORT_PACKET,        "Bandwidth report"  },
222     { RDT_ACK_PACKET,                    "Ack"  },
223     { RDT_RTTREQUEST_PACKET,             "RTT request"  },
224     { RDT_RTTRESPONSE_PACKET,            "RTT response"  },
225     { RDT_CONGESTION_PACKET,             "Congestion"  },
226     { RDT_STREAMEND_PACKET,              "Stream end" },
227     { RDT_REPORT_PACKET,                 "Report" },
228     { RDT_LATENCYREPORT_PACKET,          "Latency report" },
229     { RDT_TRANSPORTINFO_PACKET,          "Transport info" },
230     { RDT_TRANSPORTINFORESPONSE_PACKET,  "Transport info response" },
231     { RDT_BWPROBING_PACKET,              "BW probing" },
232     { 0, NULL }
233 };
234
235
236 /* Set up an RDT conversation */
237 void rdt_add_address(packet_info *pinfo,
238                      address *addr, int port,
239                      int other_port,
240                      const gchar *setup_method,
241                      gint  rdt_feature_level)
242 {
243     address null_addr;
244     conversation_t* p_conv;
245     struct _rdt_conversation_info *p_conv_data = NULL;
246
247     /* If this isn't the first time this packet has been processed,
248        we've already done this work, so we don't need to do it
249       again. */
250     if (pinfo->fd->flags.visited)
251     {
252         return;
253     }
254
255     SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
256
257     /* Check if the ip address and port combination is not already registered
258        as a conversation. */
259     p_conv = find_conversation(pinfo->fd->num, addr, &null_addr, PT_UDP, port, other_port,
260                                NO_ADDR_B | (!other_port ? NO_PORT_B : 0));
261
262     /* If not, create a new conversation. */
263     if ( !p_conv || p_conv->setup_frame != pinfo->fd->num)
264     {
265         p_conv = conversation_new(pinfo->fd->num, addr, &null_addr, PT_UDP,
266                                   (guint32)port, (guint32)other_port,
267                                   NO_ADDR2 | (!other_port ? NO_PORT2 : 0));
268     }
269
270     /* Set dissector */
271     conversation_set_dissector(p_conv, rdt_handle);
272
273     /* Check if the conversation has data associated with it. */
274     p_conv_data = conversation_get_proto_data(p_conv, proto_rdt);
275
276     /* If not, add a new data item. */
277     if (!p_conv_data)
278     {
279         /* Create conversation data */
280         p_conv_data = se_alloc(sizeof(struct _rdt_conversation_info));
281         conversation_add_proto_data(p_conv, proto_rdt, p_conv_data);
282     }
283
284     /* Update the conversation data. */
285     g_strlcpy(p_conv_data->method, setup_method, MAX_RDT_SETUP_METHOD_SIZE);
286     p_conv_data->frame_number = pinfo->fd->num;
287     p_conv_data->feature_level = rdt_feature_level;
288 }
289
290
291
292 /****************************************************************************/
293 /* Main dissection function                                                 */
294 /****************************************************************************/
295 static void dissect_rdt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
296 {
297     guint       previous_offset = 0;
298     gint        offset = 0;
299     proto_item  *ti = NULL;
300     proto_tree  *rdt_tree = NULL;
301     proto_tree  *rdt_packet_tree = NULL;
302     guint16     packet_type;
303
304     /* Set/clear columns */
305     col_set_str(pinfo->cinfo, COL_PROTOCOL, "RDT");
306     col_clear(pinfo->cinfo, COL_INFO);
307
308     /* Create RDT protocol tree */
309     if (tree)
310     {
311         ti = proto_tree_add_item(tree, proto_rdt, tvb, offset, -1, FALSE);
312         rdt_tree = proto_item_add_subtree(ti, ett_rdt);
313     }
314
315     /* Conversation setup info */
316     if (global_rdt_show_setup_info)
317     {
318         show_setup_info(tvb, pinfo, rdt_tree);
319     }
320
321     /* Parse all RDT packets found in the frame */
322     while (offset != -1 && tvb_length_remaining(tvb, offset))
323     {
324         /* Every packet type should have at least 3 bytes */
325         tvb_ensure_bytes_exist(tvb, offset, 3);
326
327         /* 2nd & 3rd bytes determine packet type */
328         packet_type = tvb_get_ntohs(tvb, offset+1);
329
330         /* Add a tree for the next individual packet */
331         ti =  proto_tree_add_string_format(rdt_tree, hf_rdt_packet, tvb, offset, -1,
332                                            "",
333                                            "RDT packet (%s)",
334                                            packet_type < 0xff00 ? "Data" :
335                                                val_to_str(packet_type, packet_type_vals, "Unknown"));
336         rdt_packet_tree = proto_item_add_subtree(ti, ett_rdt_packet);
337
338         /* Dissect the details of the next packet in this frame */
339         if (packet_type < 0xff00)
340         {
341             offset = dissect_rdt_data_packet(tvb, pinfo, rdt_packet_tree, offset);
342         }
343         else
344         {
345             switch (packet_type)
346             {
347             case RDT_ASMACTIION_PACKET:
348                 offset = dissect_rdt_asm_action_packet(tvb, pinfo, rdt_packet_tree, offset);
349                 break;
350             case RDT_BANDWIDTHREPORT_PACKET:
351                 offset = dissect_rdt_bandwidth_report_packet(tvb, pinfo, rdt_packet_tree, offset);
352                 break;
353             case RDT_ACK_PACKET:
354                 offset = dissect_rdt_ack_packet(tvb, pinfo, rdt_packet_tree, offset);
355                 break;
356             case RDT_RTTREQUEST_PACKET:
357                 offset = dissect_rdt_rtt_request_packet(tvb, pinfo, rdt_packet_tree, offset);
358                 break;
359             case RDT_RTTRESPONSE_PACKET:
360                 offset = dissect_rdt_rtt_response_packet(tvb, pinfo, rdt_packet_tree, offset);
361                 break;
362             case RDT_CONGESTION_PACKET:
363                 offset = dissect_rdt_congestion_packet(tvb, pinfo, rdt_packet_tree, offset);
364                 break;
365             case RDT_STREAMEND_PACKET:
366                 offset = dissect_rdt_stream_end_packet(tvb, pinfo, rdt_packet_tree, offset);
367                 break;
368             case RDT_REPORT_PACKET:
369                 offset = dissect_rdt_report_packet(tvb, pinfo, rdt_packet_tree, offset);
370                 break;
371             case RDT_LATENCYREPORT_PACKET:
372                 offset = dissect_rdt_latency_report_packet(tvb, pinfo, rdt_packet_tree, offset);
373                 break;
374             case RDT_TRANSPORTINFO_PACKET:
375                 offset = dissect_rdt_transport_info_request_packet(tvb, pinfo, rdt_packet_tree, offset);
376                 break;
377             case RDT_TRANSPORTINFORESPONSE_PACKET:
378                 offset = dissect_rdt_transport_info_response_packet(tvb, pinfo, rdt_packet_tree, offset);
379                 break;
380             case RDT_BWPROBING_PACKET:
381                 offset = dissect_rdt_bw_probing_packet(tvb, pinfo, rdt_packet_tree, offset);
382                 break;
383
384             default:
385                 /* Unknown control packet */
386                 offset = dissect_rdt_unknown_control(tvb, pinfo, rdt_packet_tree, offset);
387                 break;
388             }
389         }
390
391         /* Select correct number of bytes for the tree showing this packet */
392         if (offset != -1)
393         {
394             proto_item_set_len(rdt_packet_tree, offset-previous_offset);
395         }
396         previous_offset = offset;
397     }
398 }
399
400
401
402 /************************************************/
403 /* Functions to dissect individual packet types */
404 /************************************************/
405
406 /* Dissect a data packet */
407 guint dissect_rdt_data_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
408 {
409     guint       start_offset = offset;
410     guint16     packet_length;
411     guint8      flags1;
412     guint8      length_included_flag;
413     guint8      need_reliable_flag;
414     guint16     stream_id;
415     guint16     sequence_number;
416     guint8      is_reliable_flag;
417     guint8      flags2;
418     guint32     timestamp;
419     guint16     asm_rule_number;
420     guint8      back_to_back;
421     guint8      slow_data;
422     proto_tree  *flags_tree1 = NULL;
423     proto_tree  *flags_tree2 = NULL;
424     proto_item  *ti = NULL;
425
426     /* Flags in first byte */
427     flags1 = tvb_get_guint8(tvb, offset);
428     length_included_flag = (flags1 & 0x80) >> 7;
429     need_reliable_flag = (flags1 & 0x40) >> 6;
430     stream_id = (flags1 & 0x3e) >> 1;
431     is_reliable_flag = flags1 & 0x01;
432
433     /* Create subtree for flags1 fields */
434     if (tree)
435     {
436         ti =  proto_tree_add_string_format(tree, hf_rdt_data_flags1, tvb, offset, 1,
437                                            "",
438                                            "Length-included=%u, need-reliable=%u, stream-id=%u, is-reliable=%u",
439                                            length_included_flag,
440                                            need_reliable_flag,
441                                            stream_id,
442                                            is_reliable_flag);
443         flags_tree1 = proto_item_add_subtree(ti, ett_rdt_data_flags1);
444
445         proto_tree_add_item(flags_tree1, hf_rdt_len_included, tvb, offset, 1, FALSE);
446         proto_tree_add_item(flags_tree1, hf_rdt_data_need_reliable, tvb, offset, 1, FALSE);
447         proto_tree_add_item(flags_tree1, hf_rdt_data_stream_id, tvb, offset, 1, FALSE);
448         proto_tree_add_item(flags_tree1, hf_rdt_data_is_reliable, tvb, offset, 1, FALSE);
449     }
450
451     offset++;
452
453     /* Sequence number */
454     sequence_number = tvb_get_ntohs(tvb, offset);
455     proto_tree_add_item(tree, hf_rdt_sequence_number, tvb, offset, 2, FALSE);
456     offset += 2;
457
458     /* Length field is optional */
459     if (length_included_flag)
460     {
461         packet_length = tvb_get_ntohs(tvb, offset);
462         proto_tree_add_item(tree, hf_rdt_packet_length, tvb, offset, 2, FALSE);
463         offset += 2;
464
465         /* Check that there are as many bytes as reported */
466         tvb_ensure_bytes_exist(tvb, start_offset, packet_length);
467     }
468     else
469     {
470         packet_length = tvb_length_remaining(tvb, start_offset);
471     }
472
473     /* More flags */
474     flags2 = tvb_get_guint8(tvb, offset);
475     back_to_back = (flags2 & 0x80) >> 7;
476     slow_data = (flags2 & 0x40) >> 6;
477     asm_rule_number = flags2 & 0x3f;
478
479
480     /* Create subtree for flags2 fields */
481     if (tree)
482     {
483         ti =  proto_tree_add_string_format(tree, hf_rdt_data_flags2, tvb, offset, 1,
484                                            "",
485                                            "Back-to-back=%u, slow-data=%u, asm-rule=%u",
486                                            back_to_back,
487                                            slow_data,
488                                            asm_rule_number);
489
490         /* Create subtree for flags and add fields */
491         flags_tree2 = proto_item_add_subtree(ti, ett_rdt_data_flags2);
492
493         proto_tree_add_item(flags_tree2, hf_rdt_data_backtoback, tvb, offset, 1, FALSE);
494         proto_tree_add_item(flags_tree2, hf_rdt_data_slowdata, tvb, offset, 1, FALSE);
495         proto_tree_add_item(flags_tree2, hf_rdt_data_asmrule, tvb, offset, 1, FALSE);
496     }
497     offset++;
498
499     /* Timestamp */
500     timestamp = tvb_get_ntohl(tvb, offset);
501     proto_tree_add_item(tree, hf_rdt_timestamp, tvb, offset, 4, FALSE);
502     offset += 4;
503
504     /* Stream ID expansion */
505     if (stream_id == 31)
506     {
507         stream_id = tvb_get_ntohs(tvb, offset);
508         proto_tree_add_item(tree, hf_rdt_stream_id_ex, tvb, offset, 2, FALSE);
509         offset += 2;
510     }
511
512     /* Total reliable */
513     if (need_reliable_flag)
514     {
515         proto_tree_add_item(tree, hf_rdt_total_reliable, tvb, offset, 2, FALSE);
516         offset += 2;
517     }
518
519     /* Asm rule number */
520     if (asm_rule_number == 63)
521     {
522         asm_rule_number = tvb_get_ntohs(tvb, offset);
523         proto_tree_add_item(tree, hf_rdt_asmrule_ex, tvb, offset, 2, FALSE);
524         offset += 2;
525     }
526
527     if (check_col(pinfo->cinfo, COL_INFO))
528     {
529         col_append_fstr(pinfo->cinfo, COL_INFO,
530                         "DATA: stream-id=%02u asm-rule=%02u seq=%05u ts=%05u  ",
531                         stream_id, asm_rule_number, sequence_number, timestamp);
532     }
533
534     /* The remaining data is unparsed. */
535     proto_tree_add_item(tree, hf_rdt_data, tvb, offset, -1, FALSE);
536     offset += tvb_length_remaining(tvb, offset);
537
538     if (packet_length < (offset - start_offset) ||
539         packet_length > tvb_length_remaining(tvb, start_offset))
540     {
541         proto_tree_add_text(tree, tvb, 0, 0, "Packet length invalid");
542         packet_length = tvb_length_remaining(tvb, start_offset);
543     }
544
545     return start_offset + packet_length;
546 }
547
548 /* Dissect an asm-action packet */
549 guint dissect_rdt_asm_action_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
550 {
551     guint       start_offset = offset;
552     guint16     packet_length;
553     guint8      flags1;
554     guint8      length_included_flag;
555     guint16     stream_id;
556     guint16     rel_seqno;
557     proto_tree  *flags_tree = NULL;
558     proto_item  *ti = NULL;
559
560     /* Flags in first byte */
561     flags1 = tvb_get_guint8(tvb, offset);
562     length_included_flag = (flags1 & 0x80) >> 7;
563     stream_id = (flags1 & 0x7c) >> 2;
564
565     /* Create subtree for flags fields */
566     if (tree)
567     {
568         ti = proto_tree_add_item(tree, proto_rdt, tvb, offset, -1, FALSE);
569         ti =  proto_tree_add_string_format(tree, hf_rdt_aact_flags, tvb, offset, 1,
570                                            "",
571                                            "Length-included=%u, stream_id=%u",
572                                            length_included_flag,
573                                            stream_id);
574         flags_tree = proto_item_add_subtree(ti, ett_rdt_aact_flags);
575
576         proto_tree_add_item(flags_tree, hf_rdt_len_included, tvb, offset, 1, FALSE);
577         proto_tree_add_item(flags_tree, hf_rdt_aact_stream_id, tvb, offset, 1, FALSE);
578     }
579     offset++;
580
581     /* Packet type */
582     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
583     offset += 2;
584
585     rel_seqno = tvb_get_ntohs(tvb, offset);
586     proto_tree_add_item(tree, hf_rdt_aact_reliable_seqno, tvb, offset, 2, FALSE);
587     offset += 2;
588
589     /* Length field is optional */
590     if (length_included_flag)
591     {
592         packet_length = tvb_get_ntohs(tvb, offset);
593         proto_tree_add_item(tree, hf_rdt_packet_length, tvb, offset, 2, FALSE);
594         offset += 2;
595
596         /* Check that there are as many bytes as reported */
597         tvb_ensure_bytes_exist(tvb, start_offset, packet_length);
598     }
599     else
600     {
601         packet_length = tvb_length_remaining(tvb, start_offset);
602     }
603
604     /* Stream ID expansion */
605     if (stream_id == 31)
606     {
607         stream_id = tvb_get_ntohs(tvb, offset);
608         proto_tree_add_item(tree, hf_rdt_stream_id_ex, tvb, offset, 2, FALSE);
609         offset += 2;
610     }
611
612     if (check_col(pinfo->cinfo, COL_INFO))
613     {
614         col_append_fstr(pinfo->cinfo, COL_INFO,
615                         "ASM-ACTION: stream-id=%02u rel-seqno=%05u  ",
616                         stream_id, rel_seqno);
617     }
618
619     /* The remaining data is unparsed. */
620     proto_tree_add_item(tree, hf_rdt_data, tvb, offset, -1, FALSE);
621
622     if (packet_length < (offset - start_offset) ||
623         packet_length > tvb_length_remaining(tvb, start_offset))
624     {
625         proto_tree_add_text(tree, tvb, 0, 0, "Packet length invalid");
626         packet_length = tvb_length_remaining(tvb, start_offset);
627     }
628
629     return start_offset + packet_length;
630 }
631
632 /* Dissect an bandwidth-report packet */
633 guint dissect_rdt_bandwidth_report_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
634 {
635     guint       start_offset = offset;
636     guint16     packet_length;
637     guint8      flags1;
638     guint8      length_included_flag;
639     proto_tree  *flags_tree = NULL;
640     proto_item  *ti = NULL;
641
642     /* Flags in first byte */
643     flags1 = tvb_get_guint8(tvb, offset);
644     length_included_flag = (flags1 & 0x80) >> 7;
645
646     /* Create subtree for flags fields */
647     if (tree)
648     {
649         ti =  proto_tree_add_string_format(tree, hf_rdt_bandwidth_report_flags, tvb, offset, 1,
650                                            "",
651                                            "Length-included=%u",
652                                            length_included_flag);
653         flags_tree = proto_item_add_subtree(ti, ett_rdt_bandwidth_report_flags);
654
655         proto_tree_add_item(flags_tree, hf_rdt_len_included, tvb, offset, 1, FALSE);
656     }
657     offset++;
658
659     /* Packet type */
660     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
661     offset += 2;
662
663     /* Length field is optional */
664     if (length_included_flag)
665     {
666         packet_length = tvb_get_ntohs(tvb, offset);
667         proto_tree_add_item(tree, hf_rdt_packet_length, tvb, offset, 2, FALSE);
668         offset += 2;
669
670         /* Check that there are as many bytes as reported */
671         tvb_ensure_bytes_exist(tvb, start_offset, packet_length);
672     }
673     else
674     {
675         packet_length = tvb_length_remaining(tvb, start_offset);
676     }
677
678     proto_tree_add_item(tree, hf_rdt_brpt_interval, tvb, offset, 2, FALSE);
679     offset += 2;
680     proto_tree_add_item(tree, hf_rdt_brpt_bandwidth, tvb, offset, 4, FALSE);
681     offset += 4;
682     proto_tree_add_item(tree, hf_rdt_brpt_sequence, tvb, offset, 1, FALSE);
683     offset += 1;
684
685     col_append_str(pinfo->cinfo, COL_INFO, "BANDWIDTH-REPORT:  ");
686
687     if (packet_length < (offset - start_offset) ||
688         packet_length > tvb_length_remaining(tvb, start_offset))
689     {
690         proto_tree_add_text(tree, tvb, 0, 0, "Packet length invalid");
691         packet_length = tvb_length_remaining(tvb, start_offset);
692     }
693
694     return start_offset + packet_length;
695 }
696
697 /* Dissect an ack packet */
698 guint dissect_rdt_ack_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
699 {
700     guint       start_offset = offset;
701     guint16     packet_length;
702     guint8      flags1;
703     guint8      length_included_flag;
704     guint8      lost_high_flag;
705     proto_tree  *flags_tree = NULL;
706     proto_item  *ti = NULL;
707
708     /* Flags in first byte */
709     flags1 = tvb_get_guint8(tvb, offset);
710     length_included_flag = (flags1 & 0x80) >> 7;
711     lost_high_flag = (flags1 & 0x40) >> 6;
712
713     /* Create subtree for flags fields */
714     if (tree)
715     {
716         ti =  proto_tree_add_string_format(tree, hf_rdt_ack_flags, tvb, offset, 1,
717                                            "",
718                                            "Length-included=%u, lost-high=%u",
719                                            length_included_flag,
720                                            lost_high_flag);
721         flags_tree = proto_item_add_subtree(ti, ett_rdt_ack_flags);
722
723         proto_tree_add_item(flags_tree, hf_rdt_len_included, tvb, offset, 1, FALSE);
724         proto_tree_add_item(flags_tree, hf_rdt_ack_lost_high, tvb, offset, 1, FALSE);
725     }
726     offset++;
727
728     /* Packet type */
729     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
730     offset += 2;
731
732     /* Length field is optional */
733     if (length_included_flag)
734     {
735         packet_length = tvb_get_ntohs(tvb, offset);
736         proto_tree_add_item(tree, hf_rdt_packet_length, tvb, offset, 2, FALSE);
737         offset += 2;
738
739         /* Check that there are as many bytes as reported */
740         tvb_ensure_bytes_exist(tvb, start_offset, packet_length);
741     }
742     else
743     {
744         packet_length = tvb_length_remaining(tvb, start_offset);
745     }
746
747     /* XXX: The remaining data is unparsed. */
748     proto_tree_add_item(tree, hf_rdt_data, tvb, offset, -1, FALSE);
749
750     if (check_col(pinfo->cinfo, COL_INFO))
751     {
752         col_append_fstr(pinfo->cinfo, COL_INFO, "ACK: lh=%u  ", lost_high_flag);
753     }
754
755     if (packet_length < (offset - start_offset) ||
756         packet_length > tvb_length_remaining(tvb, start_offset))
757     {
758         proto_tree_add_text(tree, tvb, 0, 0, "Packet length invalid");
759         packet_length = tvb_length_remaining(tvb, start_offset);
760     }
761
762     return start_offset + packet_length;
763 }
764
765 /* Dissect an att-request packet */
766 guint dissect_rdt_rtt_request_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
767 {
768     guint8      flags1;
769
770     /* Flags in first byte */
771     flags1 = tvb_get_guint8(tvb, offset);
772     offset++;
773
774     /* Packet type */
775     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
776     offset += 2;
777
778     col_append_str(pinfo->cinfo, COL_INFO, "RTT-REQUEST:  ");
779
780     return offset;
781 }
782
783 /* Dissect an att-response packet */
784 guint dissect_rdt_rtt_response_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
785 {
786     guint8      flags1;
787
788     /* Flags in first byte */
789     flags1 = tvb_get_guint8(tvb, offset);
790     offset++;
791
792     /* Packet type */
793     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
794     offset += 2;
795
796     proto_tree_add_item(tree, hf_rdt_rtrp_ts_sec, tvb, offset, 4, FALSE);
797     offset += 4;
798     proto_tree_add_item(tree, hf_rdt_rtrp_ts_usec, tvb, offset, 4, FALSE);
799     offset += 4;
800
801     col_append_str(pinfo->cinfo, COL_INFO, "RTT-RESPONSE:  ");
802
803     return offset;
804 }
805
806 /* Dissect an congestion packet */
807 guint dissect_rdt_congestion_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
808 {
809     guint8      flags1;
810
811     /* Flags in first byte */
812     flags1 = tvb_get_guint8(tvb, offset);
813     offset++;
814
815     /* Packet type */
816     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
817     offset += 2;
818
819     proto_tree_add_item(tree, hf_rdt_cong_xmit_mult, tvb, offset, 4, FALSE);
820     offset += 4;
821     proto_tree_add_item(tree, hf_rdt_cong_recv_mult, tvb, offset, 4, FALSE);
822     offset += 4;
823
824     col_append_str(pinfo->cinfo, COL_INFO, "CONGESTION:  ");
825
826     return offset;
827 }
828
829 /* Dissect an stream-end packet */
830 guint dissect_rdt_stream_end_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
831 {
832     guint8      flags1;
833     guint8      need_reliable;
834     guint16     stream_id;
835     guint8      packet_sent;
836     guint8      ext_flag;
837     proto_tree  *flags_tree = NULL;
838     proto_item  *ti = NULL;
839
840     /* Flags in first byte */
841     flags1 = tvb_get_guint8(tvb, offset);
842     need_reliable = (flags1 & 0x80) >> 7;
843     stream_id = (flags1 & 0x7c) >> 2;
844     packet_sent = (flags1 & 0x2) >> 1;
845     ext_flag = flags1 & 0x1;
846
847     /* Create subtree for flags fields */
848     if (tree)
849     {
850         ti =  proto_tree_add_string_format(tree, hf_rdt_stre_flags, tvb, offset, 1,
851                                            "",
852                                            "Need-reliable=%u, stream-id=%u, packet-sent=%u, ext-flag=%u",
853                                            need_reliable,
854                                            stream_id,
855                                            packet_sent,
856                                            ext_flag);
857         flags_tree = proto_item_add_subtree(ti, ett_rdt_stre_flags);
858
859         proto_tree_add_item(flags_tree, hf_rdt_stre_need_reliable, tvb, offset, 1, FALSE);
860         proto_tree_add_item(flags_tree, hf_rdt_stre_stream_id, tvb, offset, 1, FALSE);
861         proto_tree_add_item(flags_tree, hf_rdt_stre_packet_sent, tvb, offset, 1, FALSE);
862         proto_tree_add_item(flags_tree, hf_rdt_stre_ext_flag, tvb, offset, 1, FALSE);
863     }
864     offset++;
865
866     /* Packet type */
867     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
868     offset += 2;
869
870     proto_tree_add_item(tree, hf_rdt_stre_seqno, tvb, offset, 2, FALSE);
871     offset += 2;
872     proto_tree_add_item(tree, hf_rdt_timestamp, tvb, offset, 4, FALSE);
873     offset += 4;
874
875     /* Stream ID expansion */
876     if (stream_id == 31)
877     {
878         stream_id = tvb_get_ntohs(tvb, offset);
879         proto_tree_add_item(tree, hf_rdt_stream_id_ex, tvb, offset, 2, FALSE);
880         offset += 2;
881     }
882
883     /* Total reliable */
884     if (need_reliable)
885     {
886         proto_tree_add_item(tree, hf_rdt_total_reliable, tvb, offset, 2, FALSE);
887         offset += 2;
888     }
889
890     if (ext_flag)
891     {
892         proto_tree_add_item(tree, hf_rdt_stre_dummy_flags1, tvb, offset, 1, FALSE);
893         offset += 1;
894         proto_tree_add_item(tree, hf_rdt_stre_dummy_type, tvb, offset, 2, FALSE);
895         offset += 2;
896         proto_tree_add_item(tree, hf_rdt_stre_reason_code, tvb, offset, 4, FALSE);
897         offset += 4;
898         /* XXX: Remainder is reason_text */
899         offset += tvb_length_remaining(tvb, offset);
900     }
901
902     if (check_col(pinfo->cinfo, COL_INFO))
903     {
904         col_append_fstr(pinfo->cinfo, COL_INFO, "STREAM-END: stream-id=%02u  ", stream_id);
905     }
906
907     return offset;
908 }
909
910 /* Dissect an report packet */
911 guint dissect_rdt_report_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
912 {
913     guint       start_offset = offset;
914     guint16     packet_length;
915     guint8      flags1;
916     guint8      length_included_flag;
917     proto_tree  *flags_tree = NULL;
918     proto_item  *ti = NULL;
919
920     /* Flags in first byte */
921     flags1 = tvb_get_guint8(tvb, offset);
922     length_included_flag = (flags1 & 0x80) >> 7;
923
924     /* Create subtree for flags fields */
925     if (tree)
926     {
927         ti =  proto_tree_add_string_format(tree, hf_rdt_report_flags, tvb, offset, 1,
928                                            "",
929                                            "Length-included=%u",
930                                            length_included_flag);
931         flags_tree = proto_item_add_subtree(ti, ett_rdt_report_flags);
932
933         proto_tree_add_item(flags_tree, hf_rdt_len_included, tvb, offset, 1, FALSE);
934     }
935     offset++;
936
937     /* Packet type */
938     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
939     offset += 2;
940
941     /* Length field is optional */
942     if (length_included_flag)
943     {
944         packet_length = tvb_get_ntohs(tvb, offset);
945         proto_tree_add_item(tree, hf_rdt_packet_length, tvb, offset, 2, FALSE);
946         offset += 2;
947
948         /* Check that there are as many bytes as reported */
949         tvb_ensure_bytes_exist(tvb, start_offset, packet_length);
950     }
951     else
952     {
953         packet_length = tvb_length_remaining(tvb, start_offset);
954     }
955
956     col_append_str(pinfo->cinfo, COL_INFO, "REPORT:  ");
957
958     /* The remaining data is unparsed. */
959     proto_tree_add_item(tree, hf_rdt_data, tvb, offset, -1, FALSE);
960
961     if (packet_length < (offset - start_offset) ||
962         packet_length > tvb_length_remaining(tvb, start_offset))
963     {
964         proto_tree_add_text(tree, tvb, 0, 0, "Packet length invalid");
965         packet_length = tvb_length_remaining(tvb, start_offset);
966     }
967
968     return start_offset + packet_length;
969 }
970
971 /* Dissect an latency-report packet */
972 guint dissect_rdt_latency_report_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
973 {
974     guint       start_offset = offset;
975     guint16     packet_length;
976     guint8      flags1;
977     guint8      length_included_flag;
978     guint32     server_out_time;
979     proto_tree  *flags_tree = NULL;
980     proto_item  *ti = NULL;
981
982     /* Flags in first byte */
983     flags1 = tvb_get_guint8(tvb, offset);
984     length_included_flag = (flags1 & 0x80) >> 7;
985
986     /* Create subtree for flags fields */
987     if (tree)
988     {
989         ti =  proto_tree_add_string_format(tree, hf_rdt_latency_report_flags, tvb, offset, 1,
990                                            "",
991                                            "Length-included=%u",
992                                            length_included_flag);
993         flags_tree = proto_item_add_subtree(ti, ett_rdt_latency_report_flags);
994
995         proto_tree_add_item(flags_tree, hf_rdt_len_included, tvb, offset, 1, FALSE);
996     }
997     offset++;
998
999     /* Packet type */
1000     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
1001     offset += 2;
1002
1003     /* Length field is optional */
1004     if (length_included_flag)
1005     {
1006         packet_length = tvb_get_ntohs(tvb, offset);
1007         proto_tree_add_item(tree, hf_rdt_packet_length, tvb, offset, 2, FALSE);
1008         offset += 2;
1009
1010         /* Check that there are as many bytes as reported */
1011         tvb_ensure_bytes_exist(tvb, start_offset, packet_length);
1012     }
1013     else
1014     {
1015         packet_length = tvb_length_remaining(tvb, start_offset);
1016     }
1017
1018     server_out_time = tvb_get_ntohl(tvb, offset);
1019     proto_tree_add_item(tree, hf_rdt_lrpt_server_out_time, tvb, offset, 4, FALSE);
1020     offset += 4;
1021
1022     if (check_col(pinfo->cinfo, COL_INFO))
1023     {
1024         col_append_fstr(pinfo->cinfo, COL_INFO, "LATENCY-REPORT: t=%u  ", server_out_time);
1025     }
1026
1027     if (packet_length < (offset - start_offset) ||
1028         packet_length > tvb_length_remaining(tvb, start_offset))
1029     {
1030         proto_tree_add_text(tree, tvb, 0, 0, "Packet length invalid");
1031         packet_length = tvb_length_remaining(tvb, start_offset);
1032     }
1033
1034     return start_offset + packet_length;
1035 }
1036
1037 /* Dissect a transport-info packet */
1038 guint dissect_rdt_transport_info_request_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
1039 {
1040     guint8      flags1;
1041     guint8      request_rtt_info_flag;
1042     guint8      request_buffer_info_flag;
1043     guint32     request_time_msec;
1044     proto_tree  *flags_tree = NULL;
1045     proto_item  *ti = NULL;
1046
1047     /* Flags in first byte */
1048     flags1 = tvb_get_guint8(tvb, offset);
1049     request_rtt_info_flag = (flags1 & 0x2) >> 1;
1050     request_buffer_info_flag = (flags1 & 0x01);
1051
1052     /* Create subtree for flags fields */
1053     if (tree)
1054     {
1055         ti =  proto_tree_add_string_format(tree, hf_rdt_ack_flags, tvb, offset, 1,
1056                                            "",
1057                                            "Request-rtt-info=%u, request-buffer-info=%u",
1058                                            request_rtt_info_flag,
1059                                            request_buffer_info_flag);
1060         flags_tree = proto_item_add_subtree(ti, ett_rdt_tirq_flags);
1061
1062         proto_tree_add_item(flags_tree, hf_rdt_tirq_request_rtt_info, tvb, offset, 1, FALSE);
1063         proto_tree_add_item(flags_tree, hf_rdt_tirq_request_buffer_info, tvb, offset, 1, FALSE);
1064     }
1065     offset++;
1066
1067     /* Packet type */
1068     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
1069     offset += 2;
1070
1071     if (request_rtt_info_flag)
1072     {
1073         request_time_msec = tvb_get_ntohl(tvb, offset);
1074         proto_tree_add_item(tree, hf_rdt_tirq_request_time_msec, tvb, offset, 4, FALSE);
1075         offset += 4;
1076     }
1077
1078     col_append_str(pinfo->cinfo, COL_INFO, "TRANSPORT-INFO-REQUEST:  ");
1079
1080     return offset;
1081 }
1082
1083 /* Dissect an transport-info-response packet */
1084 guint dissect_rdt_transport_info_response_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
1085 {
1086     guint8      flags1;
1087     guint8      has_rtt_info;
1088     guint8      is_delayed;
1089     guint8      has_buffer_info;
1090     guint32     request_time_msec;
1091     guint32     response_time_msec;    
1092     proto_tree  *flags_tree = NULL;
1093     proto_item  *ti = NULL;
1094
1095     /* Flags in first byte */
1096     flags1 = tvb_get_guint8(tvb, offset);
1097     has_rtt_info = (flags1 & 0x4) >> 2;
1098     is_delayed = (flags1 & 0x2) >> 1;
1099     has_buffer_info = (flags1 & 0x1);
1100
1101     /* Create subtree for flags fields */
1102     if (tree)
1103     {
1104         ti =  proto_tree_add_string_format(tree, hf_rdt_tirp_flags, tvb, offset, 1,
1105                                            "",
1106                                            "Has-rtt-info=%u, is-delayed=%u, has-buffer-info=%u",
1107                                            has_rtt_info,
1108                                            is_delayed,
1109                                            has_buffer_info);
1110         flags_tree = proto_item_add_subtree(ti, ett_rdt_tirp_flags);
1111
1112         proto_tree_add_item(flags_tree, hf_rdt_tirp_has_rtt_info, tvb, offset, 1, FALSE);
1113         proto_tree_add_item(flags_tree, hf_rdt_tirp_is_delayed, tvb, offset, 1, FALSE);
1114         proto_tree_add_item(flags_tree, hf_rdt_tirp_has_buffer_info, tvb, offset, 1, FALSE);
1115     }
1116     offset++;
1117
1118     /* Packet type */
1119     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
1120     offset += 2;
1121
1122     /* RTT info */
1123     if (has_rtt_info)
1124     {
1125         request_time_msec = tvb_get_ntohl(tvb, offset);
1126         proto_tree_add_item(tree, hf_rdt_tirp_request_time_msec, tvb, offset, 4, FALSE);
1127         offset += 4;
1128         
1129         if (is_delayed)
1130         {
1131             response_time_msec = tvb_get_ntohl(tvb, offset);
1132             proto_tree_add_item(tree, hf_rdt_tirp_response_time_msec, tvb, offset, 4, FALSE);
1133             offset += 4;            
1134         }
1135     }
1136     
1137     /* Buffer info */
1138     if (has_buffer_info)
1139     {
1140         guint16 n;
1141         
1142         /* Read number of buffers */
1143         guint16 buffer_info_count = tvb_get_ntohs(tvb, offset);
1144         proto_tree_add_item(tree, hf_rdt_tirp_buffer_info_count, tvb, offset, 2, FALSE);
1145         offset += 2;
1146         
1147         for (n=0; n < buffer_info_count; n++)
1148         {
1149             proto_tree  *buffer_info_tree = NULL;
1150             proto_item  *ti = NULL;
1151
1152             /* Each buffer info in a new subtree */
1153             ti =  proto_tree_add_string_format(tree, hf_rdt_tirp_buffer_info, tvb, offset, 14,
1154                                                "",
1155                                                "Buffer info %u",
1156                                                n+1);
1157             buffer_info_tree = proto_item_add_subtree(ti, ett_rdt_tirp_buffer_info);
1158
1159             /* Read individual buffer info */
1160             proto_tree_add_item(buffer_info_tree, hf_rdt_tirp_buffer_info_stream_id, tvb, offset, 2, FALSE);
1161             offset += 2;
1162             proto_tree_add_item(buffer_info_tree, hf_rdt_tirp_buffer_info_lowest_timestamp, tvb, offset, 4, FALSE);
1163             offset += 4;
1164             proto_tree_add_item(buffer_info_tree, hf_rdt_tirp_buffer_info_highest_timestamp, tvb, offset, 4, FALSE);
1165             offset += 4;
1166             proto_tree_add_item(buffer_info_tree, hf_rdt_tirp_buffer_info_bytes_buffered, tvb, offset, 4, FALSE);
1167             offset += 4;
1168         }
1169     }
1170     
1171     /* Report what is left */
1172     offset += tvb_length_remaining(tvb, offset);
1173
1174     col_append_str(pinfo->cinfo, COL_INFO, "RESPONSE:  ");
1175
1176     return offset;
1177 }
1178
1179 /* Dissect a bw-probing packet */
1180 guint dissect_rdt_bw_probing_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
1181 {
1182     guint       start_offset = offset;
1183     guint16     packet_length;
1184     guint8      flags1;
1185     guint8      length_included_flag;
1186     proto_tree  *flags_tree = NULL;
1187     proto_item  *ti = NULL;
1188
1189     /* Flags in first byte */
1190     flags1 = tvb_get_guint8(tvb, offset);
1191     length_included_flag = (flags1 & 0x80) >> 7;
1192
1193     /* Create subtree for flags fields */
1194     if (tree)
1195     {
1196         ti =  proto_tree_add_string_format(tree, hf_rdt_bw_probing_flags, tvb, offset, 1,
1197                                            "",
1198                                            "Length-included=%u",
1199                                            length_included_flag);
1200         flags_tree = proto_item_add_subtree(ti, ett_rdt_bw_probing_flags);
1201
1202         proto_tree_add_item(flags_tree, hf_rdt_len_included, tvb, offset, 1, FALSE);
1203     }
1204     offset++;
1205
1206     /* Packet type */
1207     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
1208     offset += 2;
1209
1210     /* Length field is optional */
1211     if (length_included_flag)
1212     {
1213         packet_length = tvb_get_ntohs(tvb, offset);
1214         proto_tree_add_item(tree, hf_rdt_packet_length, tvb, offset, 2, FALSE);
1215         offset += 2;
1216
1217         /* Check that there are as many bytes as reported */
1218         tvb_ensure_bytes_exist(tvb, start_offset, packet_length);
1219     }
1220     else
1221     {
1222         packet_length = tvb_length_remaining(tvb, start_offset);
1223     }
1224
1225     proto_tree_add_item(tree, hf_rdt_bwpp_seqno, tvb, offset, 1, FALSE);
1226     offset += 1;
1227     proto_tree_add_item(tree, hf_rdt_timestamp, tvb, offset, 1, FALSE);
1228     offset += 4;
1229
1230     col_append_str(pinfo->cinfo, COL_INFO, "BW-PROBING:  ");
1231
1232     if (packet_length < (offset - start_offset) ||
1233         packet_length > tvb_length_remaining(tvb, start_offset))
1234     {
1235         proto_tree_add_text(tree, tvb, 0, 0, "Packet length invalid");
1236         packet_length = tvb_length_remaining(tvb, start_offset);
1237     }
1238
1239     return start_offset + packet_length;
1240 }
1241
1242 /* Dissect an unknown control packet */
1243 guint dissect_rdt_unknown_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
1244 {
1245     guint8      flags1;
1246
1247     /* Flags in first byte */
1248     flags1 = tvb_get_guint8(tvb, offset);
1249     proto_tree_add_item(tree, hf_rdt_unk_flags1, tvb, offset, 1, FALSE);
1250     offset++;
1251
1252     /* Packet type */
1253     proto_tree_add_item(tree, hf_rdt_packet_type, tvb, offset, 2, FALSE);
1254     offset += 2;
1255
1256     /* The remaining data is unparsed. */
1257     proto_tree_add_item(tree, hf_rdt_data, tvb, offset, -1, FALSE);
1258     offset += tvb_length_remaining(tvb, offset);
1259
1260     col_append_str(pinfo->cinfo, COL_INFO, "UNKNOWN-CTL:  ");
1261
1262     return offset;
1263 }
1264
1265 /* Look for conversation info and display any setup info found */
1266 static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1267 {
1268     /* Conversation and current data */
1269     conversation_t *p_conv = NULL;
1270     struct _rdt_conversation_info *p_conv_data = NULL;
1271
1272     /* Use existing packet info if available */
1273     p_conv_data = p_get_proto_data(pinfo->fd, proto_rdt);
1274
1275     if (!p_conv_data)
1276     {
1277         /* First time, get info from conversation */
1278         p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
1279                                    pinfo->ptype,
1280                                    pinfo->destport, pinfo->srcport, NO_ADDR_B);
1281         if (p_conv)
1282         {
1283             /* Create space for conversation info */
1284             struct _rdt_conversation_info *p_conv_packet_data;
1285             p_conv_data = conversation_get_proto_data(p_conv, proto_rdt);
1286
1287             if (p_conv_data)
1288             {
1289                 /* Save this conversation info into packet info */
1290                 p_conv_packet_data = se_alloc(sizeof(struct _rdt_conversation_info));
1291                 g_snprintf(p_conv_packet_data->method, MAX_RDT_SETUP_METHOD_SIZE, "%s", p_conv_data->method);
1292                 p_conv_packet_data->method[MAX_RDT_SETUP_METHOD_SIZE]=0;
1293                 p_conv_packet_data->frame_number = p_conv_data->frame_number;
1294                 p_conv_packet_data->feature_level = p_conv_data->feature_level;
1295                 p_add_proto_data(pinfo->fd, proto_rdt, p_conv_packet_data);
1296             }
1297         }
1298     }
1299
1300     /* Create setup info subtree with summary info. */
1301     if (p_conv_data)
1302     {
1303         proto_tree *rdt_setup_tree;
1304         proto_item *ti =  proto_tree_add_string_format(tree, hf_rdt_setup, tvb, 0, 0,
1305                                                        "",
1306                                                        "Stream setup by %s (frame %u), feature level %d",
1307                                                        p_conv_data->method,
1308                                                        p_conv_data->frame_number,
1309                                                        p_conv_data->feature_level);
1310         PROTO_ITEM_SET_GENERATED(ti);
1311         rdt_setup_tree = proto_item_add_subtree(ti, ett_rdt_setup);
1312         if (rdt_setup_tree)
1313         {
1314             /* Add details into subtree */
1315             proto_item* item = proto_tree_add_uint(rdt_setup_tree, hf_rdt_setup_frame,
1316                                                    tvb, 0, 0, p_conv_data->frame_number);
1317             PROTO_ITEM_SET_GENERATED(item);
1318             item = proto_tree_add_string(rdt_setup_tree, hf_rdt_setup_method,
1319                                          tvb, 0, 0, p_conv_data->method);
1320             PROTO_ITEM_SET_GENERATED(item);
1321             item = proto_tree_add_int(rdt_setup_tree, hf_rdt_feature_level,
1322                                       tvb, 0, 0, p_conv_data->feature_level);
1323             PROTO_ITEM_SET_GENERATED(item);
1324         }
1325     }
1326 }
1327
1328
1329 void proto_register_rdt(void)
1330 {
1331     static hf_register_info hf[] =
1332     {
1333         {
1334             &hf_rdt_packet,
1335             {
1336                 "RDT packet",
1337                 "rdt.packet",
1338                 FT_STRING,
1339                 BASE_NONE,
1340                 NULL,
1341                 0x0,
1342                 NULL, HFILL
1343             }
1344         },
1345         {
1346             &hf_rdt_data_flags1,
1347             {
1348                 "RDT data flags 1",
1349                 "rdt.data-flags1",
1350                 FT_STRING,
1351                 BASE_NONE,
1352                 NULL,
1353                 0x0,
1354                 NULL, HFILL
1355             }
1356         },
1357         {
1358             &hf_rdt_len_included,
1359             {
1360                 "Length included",
1361                 "rdt.length-included",
1362                 FT_UINT8,
1363                 BASE_DEC,
1364                 NULL,
1365                 0x80,
1366                 NULL, HFILL
1367             }
1368         },
1369         {
1370             &hf_rdt_data_need_reliable,
1371             {
1372                 "Need reliable",
1373                 "rdt.need-reliable",
1374                 FT_UINT8,
1375                 BASE_DEC,
1376                 NULL,
1377                 0x40,
1378                 NULL, HFILL
1379             }
1380         },
1381         {
1382             &hf_rdt_data_stream_id,
1383             {
1384                 "Stream ID",
1385                 "rdt.stream-id",
1386                 FT_UINT8,
1387                 BASE_DEC,
1388                 NULL,
1389                 0x3e,
1390                 NULL, HFILL
1391             }
1392         },
1393         {
1394             &hf_rdt_data_is_reliable,
1395             {
1396                 "Is reliable",
1397                 "rdt.is-reliable",
1398                 FT_UINT8,
1399                 BASE_DEC,
1400                 NULL,
1401                 0x01,
1402                 NULL, HFILL
1403             }
1404         },
1405         {
1406             &hf_rdt_data_flags2,
1407             {
1408                 "RDT data flags 2",
1409                 "rdt.data-flags2",
1410                 FT_STRING,
1411                 BASE_NONE,
1412                 NULL,
1413                 0x0,
1414                 "RDT data flags2", HFILL
1415             }
1416         },
1417         {
1418             &hf_rdt_data_backtoback,
1419             {
1420                 "Back-to-back",
1421                 "rdt.back-to-back",
1422                 FT_UINT8,
1423                 BASE_DEC,
1424                 NULL,
1425                 0x80,
1426                 NULL, HFILL
1427             }
1428         },
1429         {
1430             &hf_rdt_data_slowdata,
1431             {
1432                 "Slow data",
1433                 "rdt.slow-data",
1434                 FT_UINT8,
1435                 BASE_DEC,
1436                 NULL,
1437                 0x40,
1438                 NULL, HFILL
1439             }
1440         },
1441         {
1442             &hf_rdt_data_asmrule,
1443             {
1444                 "asm rule",
1445                 "rdt.asm-rule",
1446                 FT_UINT8,
1447                 BASE_DEC,
1448                 NULL,
1449                 0x3f,
1450                 NULL, HFILL
1451             }
1452         },
1453         {
1454             &hf_rdt_aact_flags,
1455             {
1456                 "RDT asm-action flags 1",
1457                 "rdt.aact-flags",
1458                 FT_STRING,
1459                 BASE_NONE,
1460                 NULL,
1461                 0x0,
1462                 "RDT aact flags", HFILL
1463             }
1464         },
1465         {
1466             &hf_rdt_aact_stream_id,
1467             {
1468                 "Stream ID",
1469                 "rdt.stream-id",
1470                 FT_UINT8,
1471                 BASE_DEC,
1472                 NULL,
1473                 0x7c,
1474                 NULL, HFILL
1475             }
1476         },
1477         {
1478             &hf_rdt_sequence_number,
1479             {
1480                 "Sequence number",
1481                 "rdt.sequence-number",
1482                 FT_UINT16,
1483                 BASE_DEC,
1484                 NULL,
1485                 0x0,
1486                 NULL, HFILL
1487             }
1488         },
1489         {
1490             &hf_rdt_packet_type,
1491             {
1492                 "Packet type",
1493                 "rdt.packet-type",
1494                 FT_UINT16,
1495                 BASE_HEX,
1496                 VALS(packet_type_vals),
1497                 0x0,
1498                 NULL, HFILL
1499             }
1500         },
1501         {
1502             &hf_rdt_ack_flags,
1503             {
1504                 "RDT ack flags",
1505                 "rdt.ack-flags",
1506                 FT_STRING,
1507                 BASE_NONE,
1508                 NULL,
1509                 0x0,
1510                 NULL, HFILL
1511             }
1512         },
1513         {
1514             &hf_rdt_ack_lost_high,
1515             {
1516                 "Lost high",
1517                 "rdt.lost-high",
1518                 FT_UINT8,
1519                 BASE_DEC,
1520                 NULL,
1521                 0x40,
1522                 NULL, HFILL
1523             }
1524         },
1525         {
1526             &hf_rdt_latency_report_flags,
1527             {
1528                 "RDT latency report flags",
1529                 "rdt.latency-report-flags",
1530                 FT_STRING,
1531                 BASE_NONE,
1532                 NULL,
1533                 0x0,
1534                 NULL, HFILL
1535             }
1536         },
1537         {
1538             &hf_rdt_bandwidth_report_flags,
1539             {
1540                 "RDT bandwidth report flags",
1541                 "rdt.bandwidth-report-flags",
1542                 FT_STRING,
1543                 BASE_NONE,
1544                 NULL,
1545                 0x0,
1546                 NULL, HFILL
1547             }
1548         },
1549         {
1550             &hf_rdt_stre_flags,
1551             {
1552                 "RDT stream end flags",
1553                 "rdt.stream-end-flags",
1554                 FT_STRING,
1555                 BASE_NONE,
1556                 NULL,
1557                 0x0,
1558                 NULL, HFILL
1559             }
1560         },
1561         {
1562             &hf_rdt_rtt_request_flags,
1563             {
1564                 "RDT rtt request flags",
1565                 "rdt.rtt-request-flags",
1566                 FT_STRING,
1567                 BASE_NONE,
1568                 NULL,
1569                 0x0,
1570                 "RDT RTT request flags", HFILL
1571             }
1572         },
1573         {
1574             &hf_rdt_rtt_response_flags,
1575             {
1576                 "RDT rtt response flags",
1577                 "rdt.rtt-response-flags",
1578                 FT_STRING,
1579                 BASE_NONE,
1580                 NULL,
1581                 0x0,
1582                 "RDT RTT response flags", HFILL
1583             }
1584         },
1585         {
1586             &hf_rdt_congestion_flags,
1587             {
1588                 "RDT congestion flags",
1589                 "rdt.congestion-flags",
1590                 FT_STRING,
1591                 BASE_NONE,
1592                 NULL,
1593                 0x0,
1594                 NULL, HFILL
1595             }
1596         },
1597         {
1598             &hf_rdt_report_flags,
1599             {
1600                 "RDT report flags",
1601                 "rdt.report-flags",
1602                 FT_STRING,
1603                 BASE_NONE,
1604                 NULL,
1605                 0x0,
1606                 NULL, HFILL
1607             }
1608         },
1609         {
1610             &hf_rdt_tirq_flags,
1611             {
1612                 "RDT transport info request flags",
1613                 "rdt.transport-info-request-flags",
1614                 FT_STRING,
1615                 BASE_NONE,
1616                 NULL,
1617                 0x0,
1618                 NULL, HFILL
1619             }
1620         },
1621         {
1622             &hf_rdt_tirp_flags,
1623             {
1624                 "RDT transport info response flags",
1625                 "rdt.transport-info-response-flags",
1626                 FT_STRING,
1627                 BASE_NONE,
1628                 NULL,
1629                 0x0,
1630                 NULL, HFILL
1631             }
1632         },
1633         {
1634             &hf_rdt_bw_probing_flags,
1635             {
1636                 "RDT bw probing flags",
1637                 "rdt.bw-probing-flags",
1638                 FT_STRING,
1639                 BASE_NONE,
1640                 NULL,
1641                 0x0,
1642                 NULL, HFILL
1643             }
1644         },
1645         {
1646             &hf_rdt_packet_length,
1647             {
1648                 "Packet length",
1649                 "rdt.packet-length",
1650                 FT_UINT16,
1651                 BASE_DEC,
1652                 NULL,
1653                 0x0,
1654                 NULL, HFILL
1655             }
1656         },
1657         {
1658             &hf_rdt_timestamp,
1659             {
1660                 "Timestamp",
1661                 "rdt.timestamp",
1662                 FT_UINT32,
1663                 BASE_DEC,
1664                 NULL,
1665                 0x0,
1666                 NULL, HFILL
1667             }
1668         },
1669         {
1670             &hf_rdt_stream_id_ex,
1671             {
1672                 "Stream-id expansion",
1673                 "rdt.stream-id-expansion",
1674                 FT_UINT16,
1675                 BASE_DEC,
1676                 NULL,
1677                 0x0,
1678                 NULL, HFILL
1679             }
1680         },
1681         {
1682             &hf_rdt_asmrule_ex,
1683             {
1684                 "Asm rule expansion",
1685                 "rdt.asm-rule-expansion",
1686                 FT_UINT16,
1687                 BASE_DEC,
1688                 NULL,
1689                 0x0,
1690                 NULL, HFILL
1691             }
1692         },
1693         {
1694             &hf_rdt_total_reliable,
1695             {
1696                 "Total reliable",
1697                 "rdt.total-reliable",
1698                 FT_UINT16,
1699                 BASE_DEC,
1700                 NULL,
1701                 0x0,
1702                 NULL, HFILL
1703             }
1704         },
1705         {
1706             &hf_rdt_data,
1707             {
1708                 "Data",
1709                 "rdt.data",
1710                 FT_NONE,
1711                 BASE_NONE,
1712                 NULL,
1713                 0x0,
1714                NULL, HFILL
1715             }
1716         },
1717         {
1718             &hf_rdt_aact_reliable_seqno,
1719             {
1720                 "Reliable sequence number",
1721                 "rdt.reliable-seq-no",
1722                 FT_UINT16,
1723                 BASE_DEC,
1724                 NULL,
1725                 0x0,
1726                 NULL, HFILL
1727             }
1728         },
1729         {
1730             &hf_rdt_brpt_interval,
1731             {
1732                 "Bandwidth report interval",
1733                 "rdt.bwid-report-interval",
1734                 FT_UINT16,
1735                 BASE_DEC,
1736                 NULL,
1737                 0x0,
1738                 NULL, HFILL
1739             }
1740         },
1741         {
1742             &hf_rdt_brpt_bandwidth,
1743             {
1744                 "Bandwidth report bandwidth",
1745                 "rdt.bwid-report-bandwidth",
1746                 FT_UINT32,
1747                 BASE_DEC,
1748                 NULL,
1749                 0x0,
1750                 NULL, HFILL
1751             }
1752         },
1753         {
1754             &hf_rdt_brpt_sequence,
1755             {
1756                 "Bandwidth report sequence",
1757                 "rdt.bwid-report-sequence",
1758                 FT_UINT16,
1759                 BASE_DEC,
1760                 NULL,
1761                 0x0,
1762                 NULL, HFILL
1763             }
1764         },
1765         {
1766             &hf_rdt_rtrp_ts_sec,
1767             {
1768                 "Round trip response timestamp seconds",
1769                 "rdt.rtrp-ts-sec",
1770                 FT_UINT32,
1771                 BASE_DEC,
1772                 NULL,
1773                 0x0,
1774                 NULL, HFILL
1775             }
1776         },
1777         {
1778             &hf_rdt_rtrp_ts_usec,
1779             {
1780                 "Round trip response timestamp microseconds",
1781                 "rdt.rtrp-ts-usec",
1782                 FT_UINT32,
1783                 BASE_DEC,
1784                 NULL,
1785                 0x0,
1786                 NULL, HFILL
1787             }
1788         },
1789         {
1790             &hf_rdt_cong_xmit_mult,
1791             {
1792                 "Congestion transmit multiplier",
1793                 "rdt.cong-xmit-mult",
1794                 FT_UINT32,
1795                 BASE_DEC,
1796                 NULL,
1797                 0x0,
1798                 NULL, HFILL
1799             }
1800         },
1801         {
1802             &hf_rdt_cong_recv_mult,
1803             {
1804                 "Congestion receive multiplier",
1805                 "rdt.cong-recv-mult",
1806                 FT_UINT32,
1807                 BASE_DEC,
1808                 NULL,
1809                 0x0,
1810                 NULL, HFILL
1811             }
1812         },
1813         {
1814             &hf_rdt_stre_need_reliable,
1815             {
1816                 "Need reliable",
1817                 "rdt.stre-need-reliable",
1818                 FT_UINT8,
1819                 BASE_DEC,
1820                 NULL,
1821                 0x80,
1822                 NULL, HFILL
1823             }
1824         },
1825         {
1826             &hf_rdt_stre_stream_id,
1827             {
1828                 "Stream id",
1829                 "rdt.stre-stream-id",
1830                 FT_UINT8,
1831                 BASE_DEC,
1832                 NULL,
1833                 0x7c,
1834                 NULL, HFILL
1835             }
1836         },
1837         {
1838             &hf_rdt_stre_packet_sent,
1839             {
1840                 "Packet sent",
1841                 "rdt.stre-packet-sent",
1842                 FT_UINT8,
1843                 BASE_DEC,
1844                 NULL,
1845                 0x02,
1846                 NULL, HFILL
1847             }
1848         },
1849         {
1850             &hf_rdt_stre_ext_flag,
1851             {
1852                 "Ext flag",
1853                 "rdt.stre-ext-flag",
1854                 FT_UINT8,
1855                 BASE_DEC,
1856                 NULL,
1857                 0x01,
1858                 NULL, HFILL
1859             }
1860         },
1861
1862         {
1863             &hf_rdt_stre_seqno,
1864             {
1865                 "Stream end sequence number",
1866                 "rdt.stre-seqno",
1867                 FT_UINT16,
1868                 BASE_DEC,
1869                 NULL,
1870                 0x0,
1871                 NULL, HFILL
1872             }
1873         },
1874         {
1875             &hf_rdt_stre_dummy_flags1,
1876             {
1877                 "Stream end reason dummy flags1",
1878                 "rdt.stre-reason-dummy-flags1",
1879                 FT_UINT8,
1880                 BASE_HEX,
1881                 NULL,
1882                 0x0,
1883                 NULL, HFILL
1884             }
1885         },
1886         {
1887             &hf_rdt_stre_dummy_type,
1888             {
1889                 "Stream end reason dummy type",
1890                 "rdt.stre-reason-dummy-type",
1891                 FT_UINT16,
1892                 BASE_HEX,
1893                 NULL,
1894                 0x0,
1895                 NULL, HFILL
1896             }
1897         },
1898         {
1899             &hf_rdt_stre_reason_code,
1900             {
1901                 "Stream end reason code",
1902                 "rdt.stre-reason-code",
1903                 FT_UINT32,
1904                 BASE_HEX,
1905                 NULL,
1906                 0x0,
1907                 NULL, HFILL
1908             }
1909         },
1910         {
1911             &hf_rdt_lrpt_server_out_time,
1912             {
1913                 "Latency report server out time",
1914                 "rdt.lrpt-server-out-time",
1915                 FT_UINT32,
1916                 BASE_DEC,
1917                 NULL,
1918                 0x0,
1919                 NULL, HFILL
1920             }
1921         },
1922         {
1923             &hf_rdt_tirq_request_rtt_info,
1924             {
1925                 "Transport info request rtt info flag",
1926                 "rdt.tirq-request-rtt-info",
1927                 FT_UINT8,
1928                 BASE_DEC,
1929                 NULL,
1930                 0x2,
1931                 NULL, HFILL
1932             }
1933         },
1934         {
1935             &hf_rdt_tirq_request_buffer_info,
1936             {
1937                 "Transport info request buffer info flag",
1938                 "rdt.tirq-request-buffer-info",
1939                 FT_UINT8,
1940                 BASE_DEC,
1941                 NULL,
1942                 0x1,
1943                 NULL, HFILL
1944             }
1945         },
1946         {
1947             &hf_rdt_tirq_request_time_msec,
1948             {
1949                 "Transport info request time msec",
1950                 "rdt.tirq-request-time-msec",
1951                 FT_UINT32,
1952                 BASE_DEC,
1953                 NULL,
1954                 0x0,
1955                 NULL, HFILL
1956             }
1957         },
1958         {
1959             &hf_rdt_tirp_has_rtt_info,
1960             {
1961                 "Transport info response has rtt info flag",
1962                 "rdt.tirp-has-rtt-info",
1963                 FT_UINT8,
1964                 BASE_DEC,
1965                 NULL,
1966                 0x4,
1967                 NULL, HFILL
1968             }
1969         },
1970         {
1971             &hf_rdt_tirp_is_delayed,
1972             {
1973                 "Transport info response is delayed",
1974                 "rdt.tirp-is-delayed",
1975                 FT_UINT8,
1976                 BASE_DEC,
1977                 NULL,
1978                 0x2,
1979                 NULL, HFILL
1980             }
1981         },
1982         {
1983             &hf_rdt_tirp_has_buffer_info,
1984             {
1985                 "Transport info response has buffer info",
1986                 "rdt.tirp-has-buffer-info",
1987                 FT_UINT8,
1988                 BASE_DEC,
1989                 NULL,
1990                 0x1,
1991                 NULL, HFILL
1992             }
1993         },
1994         {
1995             &hf_rdt_tirp_request_time_msec,
1996             {
1997                 "Transport info request time msec",
1998                 "rdt.tirp-request-time-msec",
1999                 FT_UINT32,
2000                 BASE_DEC,
2001                 NULL,
2002                 0x0,
2003                 NULL, HFILL
2004             }
2005         },
2006         {
2007             &hf_rdt_tirp_response_time_msec,
2008             {
2009                 "Transport info response time msec",
2010                 "rdt.tirp-response-time-msec",
2011                 FT_UINT32,
2012                 BASE_DEC,
2013                 NULL,
2014                 0x0,
2015                 NULL, HFILL
2016             }
2017         },
2018         {
2019             &hf_rdt_tirp_buffer_info_count,
2020             {
2021                 "Transport info buffer into count",
2022                 "rdt.tirp-buffer-info-count",
2023                 FT_UINT16,
2024                 BASE_DEC,
2025                 NULL,
2026                 0x0,
2027                 NULL, HFILL
2028             }
2029         },
2030         {
2031             &hf_rdt_tirp_buffer_info,
2032             {
2033                 "RDT buffer info",
2034                 "rdt.tirp-buffer-info",
2035                 FT_STRING,
2036                 BASE_NONE,
2037                 NULL,
2038                 0x0,
2039                 NULL, HFILL
2040             }
2041         },
2042         {
2043             &hf_rdt_tirp_buffer_info_stream_id,
2044             {
2045                 "Buffer info stream-id",
2046                 "rdt.tirp-buffer-info-stream-id",
2047                 FT_UINT16,
2048                 BASE_DEC,
2049                 NULL,
2050                 0x0,
2051                 NULL, HFILL
2052             }
2053         },
2054         {
2055             &hf_rdt_tirp_buffer_info_lowest_timestamp,
2056             {
2057                 "Lowest timestamp",
2058                 "rdt.tirp-buffer-info-lowest-timestamp",
2059                 FT_UINT32,
2060                 BASE_DEC,
2061                 NULL,
2062                 0x0,
2063                 NULL, HFILL
2064             }
2065         },
2066         {
2067             &hf_rdt_tirp_buffer_info_highest_timestamp,
2068             {
2069                 "Highest timestamp",
2070                 "rdt.tirp-buffer-info-highest-timestamp",
2071                 FT_UINT32,
2072                 BASE_DEC,
2073                 NULL,
2074                 0x0,
2075                 NULL, HFILL
2076             }
2077         },
2078         {
2079             &hf_rdt_tirp_buffer_info_bytes_buffered,
2080             {
2081                 "Bytes buffered",
2082                 "rdt.tirp-buffer-info-bytes-buffered",
2083                 FT_UINT32,
2084                 BASE_DEC,
2085                 NULL,
2086                 0x0,
2087                 NULL, HFILL
2088             }
2089         },
2090         {
2091             &hf_rdt_bwpp_seqno,
2092             {
2093                 "Bandwidth probing packet seqno",
2094                 "rdt.bwpp-seqno",
2095                 FT_UINT8,
2096                 BASE_DEC,
2097                 NULL,
2098                 0x0,
2099                 NULL, HFILL
2100             }
2101         },
2102         {
2103             &hf_rdt_unk_flags1,
2104             {
2105                 "Unknown packet flags",
2106                 "rdt.unk-flags1",
2107                 FT_UINT8,
2108                 BASE_DEC,
2109                 NULL,
2110                 0x0,
2111                 NULL, HFILL
2112             }
2113         },
2114         {
2115             &hf_rdt_setup,
2116             {
2117                 "Stream setup",
2118                 "rdt.setup",
2119                 FT_STRING,
2120                 BASE_NONE,
2121                 NULL,
2122                 0x0,
2123                 "Stream setup, method and frame number", HFILL
2124             }
2125         },
2126         {
2127             &hf_rdt_setup_frame,
2128             {
2129                 "Setup frame",
2130                 "rdt.setup-frame",
2131                 FT_FRAMENUM,
2132                 BASE_NONE,
2133                 NULL,
2134                 0x0,
2135                 "Frame that set up this stream", HFILL
2136             }
2137         },
2138         {
2139             &hf_rdt_setup_method,
2140             {
2141                 "Setup Method",
2142                 "rdt.setup-method",
2143                 FT_STRING,
2144                 BASE_NONE,
2145                 NULL,
2146                 0x0,
2147                 "Method used to set up this stream", HFILL
2148             }
2149         },
2150         {
2151             &hf_rdt_feature_level,
2152             {
2153                 "RDT feature level",
2154                 "rdt.feature-level",
2155                 FT_INT32,
2156                 BASE_DEC,
2157                 NULL,
2158                 0x0,
2159                 NULL, HFILL
2160             }
2161         },
2162     };
2163
2164     static gint *ett[] =
2165     {
2166         &ett_rdt,
2167         &ett_rdt_packet,
2168         &ett_rdt_setup,
2169         &ett_rdt_data_flags1,
2170         &ett_rdt_data_flags2,
2171         &ett_rdt_aact_flags,
2172         &ett_rdt_ack_flags,
2173         &ett_rdt_latency_report_flags,
2174         &ett_rdt_bandwidth_report_flags,
2175         &ett_rdt_stre_flags,
2176         &ett_rdt_rtt_request_flags,
2177         &ett_rdt_rtt_response_flags,
2178         &ett_rdt_congestion_flags,
2179         &ett_rdt_report_flags,
2180         &ett_rdt_tirq_flags,
2181         &ett_rdt_tirp_flags,
2182         &ett_rdt_tirp_buffer_info,
2183         &ett_rdt_bw_probing_flags
2184     };
2185
2186     module_t *rdt_module;
2187
2188     /* Register protocol and fields */
2189     proto_rdt = proto_register_protocol("Real Data Transport", "RDT", "rdt");
2190     proto_register_field_array(proto_rdt, hf, array_length(hf));
2191     proto_register_subtree_array(ett, array_length(ett));
2192     register_dissector("rdt", dissect_rdt, proto_rdt);
2193
2194     /* Preference settings */
2195     rdt_module = prefs_register_protocol(proto_rdt, proto_reg_handoff_rdt);
2196     prefs_register_bool_preference(rdt_module, "show_setup_info",
2197                                    "Show stream setup information",
2198                                    "Where available, show which protocol and frame caused "
2199                                    "this RDT stream to be created",
2200                                    &global_rdt_show_setup_info);
2201
2202     prefs_register_bool_preference(rdt_module, "register_udp_port",
2203                                    "Register default UDP client port",
2204                                    "Register a client UDP port for RDT traffic",
2205                                    &global_rdt_register_udp_port);
2206
2207     /* TODO: better to specify a range of ports instead? */
2208     prefs_register_uint_preference(rdt_module, "default_udp_port",
2209                                    "Default UDP client port",
2210                                    "Set the UDP port for clients",
2211                                    10, &global_rdt_udp_port);
2212
2213 }
2214
2215 void proto_reg_handoff_rdt(void)
2216 {
2217     static gboolean rdt_prefs_initialized = FALSE;
2218     /* Also store this so can delete registered setting properly */
2219     static gboolean  rdt_register_udp_port;
2220     static guint     rdt_udp_port;
2221
2222     if (!rdt_prefs_initialized)
2223     {
2224         /* Register this dissector as one that can be selected by a
2225            UDP port number. */
2226         rdt_handle = find_dissector("rdt");
2227         dissector_add_handle("udp.port", rdt_handle);
2228         rdt_prefs_initialized = TRUE;
2229     }
2230     else
2231     {
2232         /* Undo any current port registrations */
2233         if (rdt_register_udp_port)
2234         {
2235             dissector_delete("udp.port", rdt_udp_port, rdt_handle);
2236         }
2237     }
2238
2239     /* Remember whether a port is set for next time */
2240     rdt_register_udp_port = global_rdt_register_udp_port;
2241
2242     /* Add any new port registration */
2243     if (global_rdt_register_udp_port)
2244     {
2245         /* Set our port number for future use */
2246         rdt_udp_port = global_rdt_udp_port;
2247
2248         /* And register with this port */
2249         dissector_add("udp.port", global_rdt_udp_port, rdt_handle);
2250     }
2251 }
2252