Use correct offset.
[obnox/wireshark/wip.git] / epan / dissectors / packet-rohc.c
1 /* packet-rohc.c
2  * Routines for RObust Header Compression (ROHC) dissection.
3  *
4  * Copyright 2011, Anders Broman <anders.broman[at]ericsson.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * Ref:
27  * http://www.ietf.org/rfc/rfc3095.txt         RObust Header Compression (ROHC): Framework and four profiles: RTP, UDP, ESP, and uncompressed
28  * http://datatracker.ietf.org/doc/rfc4815/    RObust Header Compression (ROHC): Corrections and Clarifications to RFC 3095
29  * http://datatracker.ietf.org/doc/rfc5225/    RObust Header Compression Version 2 (ROHCv2): Profiles for RTP, UDP, IP, ESP and UDP-Lite
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36
37 #include <epan/packet.h>
38 #include <epan/etypes.h>
39 #include <epan/ipproto.h>
40 #include <epan/rtp_pt.h>
41 #include <epan/expert.h>
42
43 #include "packet-rohc.h"
44 /* Initialize the protocol and registered fields */
45 static int proto_rohc                   = -1;
46
47
48 static int hf_rohc_padding = -1;
49 static int hf_rohc_add_cid = -1;
50 static int hf_rohc_feedback = -1;
51 static int hf_rohc_code = -1;
52 static int hf_rohc_size = -1;
53 static int hf_rohc_ir_packet = -1;
54 static int hf_rohc_ir_dyn_packet = -1;
55 static int hf_rohc_small_cid = -1;
56 static int hf_rohc_large_cid = -1;
57 static int hf_rohc_acktype = -1;
58 static int hf_rohc_mode = -1;
59 static int hf_rohc_sn = -1;
60 static int hf_rohc_fb1_sn = -1;
61 static int hf_rohc_rtp_opt_type = -1;
62 static int hf_rohc_rtp_opt_len = -1;
63 static int hf_rohc_rtp_crc = -1;
64 static int hf_rohc_rtp_opt_sn = -1;
65 static int hf_rohc_feedback_option_clock = -1;
66 static int hf_rohc_profile = -1;
67 static int hf_rohc_d_bit = -1;
68 static int hf_rohc_rtp_version = -1;
69 static int hf_rohc_rtp_protocol = -1;
70 static int hf_rohc_rtp_ipv4_src = -1;
71 static int hf_rohc_rtp_ipv4_dst = -1;
72 static int hf_rohc_rtp_udp_src_port = -1;
73 static int hf_rohc_rtp_udp_dst_port = -1;
74 static int hf_rohc_rtp_ssrc = -1;
75 static int hf_rohc_rtp_tos = -1;
76 static int hf_rohc_rtp_ttl = -1;
77 static int hf_rohc_rtp_id = -1;
78 static int hf_rohc_rtp_df = -1;
79 static int hf_rohc_rtp_rnd = -1;
80 static int hf_rohc_rtp_nbo = -1;
81 static int hf_rohc_rtp_checksum = -1;
82 static int hf_rohc_dynamic_udp_seqnum = -1;
83 static int hf_rohc_rtp_v = -1;
84 static int hf_rohc_rtp_p = -1;
85 static int hf_rohc_rtp_rx = -1;
86 static int hf_rohc_rtp_cc = -1;
87 static int hf_rohc_rtp_m = -1;
88 static int hf_rohc_rtp_pt = -1;
89 static int hf_rohc_rtp_sn = -1;
90 static int hf_rohc_rtp_timestamp = -1;
91 static int hf_rohc_rtp_x = -1;
92 static int hf_rohc_rtp_mode = -1;
93 static int hf_rohc_rtp_tis = -1;
94 static int hf_rohc_rtp_tss = -1;
95 static int hf_rohc_rtp_ts_stride = -1;
96 static int hf_rohc_rtp_time_stride = -1;
97 static int hf_rohc_var_len = -1;
98
99 static int ett_rohc = -1;
100 static int ett_rohc_fb = -1;
101 static int ett_rohc_feedback = -1;
102 static int ett_rohc_ir = -1;
103 static int ett_rohc_ir_dyn = -1;
104 static int ett_rohc_rtp_static = -1;
105 static int ett_rohc_rtp_dynamic = -1;
106
107 /* RTP profile and IPv4 hard wired for now */
108 static guint8 g_profile = 1;
109 static guint8 g_version = 4;
110
111 /* ROHC Profiles */
112 #define ROHC_PROFILE_RTP        1
113 #define ROHC_PROFILE_UDP        2
114
115 static const value_string rohc_profile_vals[] =
116 {
117    { 0x0000,    "ROHC uncompressed" },          /*RFC 5795*/
118    { 0x0001,    "ROHC RTP" },                   /*RFC 3095*/
119    { 0x0002,    "ROHC UDP" },                   /*RFC 3095*/
120    { 0x0003,    "ROHC ESP" },                   /*RFC 3095*/
121    { 0x0004,    "ROHC IP" },                    /*RFC 3843*/
122    { 0x0005,    "ROHC LLA" },                   /*RFC 3242*/
123    { 0x0105,    "ROHC LLA with R-mode" },       /*RFC 3408*/
124    { 0x0006,    "ROHC TCP" },                   /*RFC 4996*/
125    { 0x0007,    "ROHC RTP/UDP-Lite" },          /*RFC 4019*/
126    { 0x0008,    "ROHC UDP-Lite" },              /*RFC 4019*/
127    { 0x0101,    "ROHCv2 RTP" },                 /*RFC 5225*/
128    { 0x0102,    "ROHCv2 UDP" },                 /*RFC 5225*/
129    { 0x0103,    "ROHCv2 ESP" },                 /*RFC 5225*/
130    { 0x0104,    "ROHCv2 IP" },                  /*RFC 5225*/
131    { 0x0107,    "ROHCv2 RTP/UDP-Lite" },        /*RFC 5225*/
132    { 0x0108,    "ROHCv2 UDP-Lite" },            /*RFC 5225*/
133   { 0, NULL },
134 };
135
136 static const value_string rohc_acktype_vals[] =
137 {
138   { 0,    "ACK" },
139   { 1,    "NACK" },
140   { 2,    "STATIC-NACK" },
141   { 3,    "reserved (MUST NOT be used.  Otherwise unparsable)" },
142   { 0, NULL },
143 };
144
145 static const value_string rohc_mode_vals[] =
146 {
147   { 0,    "Reserved" },
148   { 1,    "Unidirectional" },
149   { 2,    "Bidirectional Optimistic" },
150   { 3,    "Bidirectional Reliable" },
151   { 0, NULL },
152 };
153
154 static const value_string rohc_rtp_opt_type_vals[] =
155 {
156   { 1,    "CRC" },
157   { 2,    "Reject" },
158   { 3,    "SN-NOT-VALID" },
159   { 4,    "SN" },
160   { 5,    "Clock" },
161   { 6,    "Jitter" },
162   { 7,    "LOSS" },
163   { 0, NULL },
164 };
165
166
167
168 static const value_string rohc_rtp_version_vals[] =
169 {
170   { 4,    "IPv4" },
171   { 6,    "IPv6" },
172   { 0, NULL },
173 };
174
175 static const value_string rohc_var_len_vals[] =
176 {
177   { 0,    "One octet" },
178   { 2,    "Two octets" },
179   { 6,    "Three octets" },
180   { 7,    "Four octets" },
181   { 0, NULL },
182 };
183
184
185 /* 4.5.6.  Self-describing variable-length values */
186 static guint32
187 get_self_describing_var_len_val(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, guint8 *val_len){
188         guint8 oct;
189         guint32 val = 0;
190         int num_bits = 0, bit_offset = offset <<3;
191
192         oct = tvb_get_guint8(tvb, offset);
193         if((oct&0x80)==0){
194                 /* One octet */
195                 *val_len = 1;
196                 val = (oct&0x7f);
197                 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
198                 num_bits = 7;
199                 bit_offset++;
200         }else if((oct&0xc0)==0x80){
201                 /* Two octets */
202                 *val_len = 2;
203                 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 2, ENC_BIG_ENDIAN);
204                 bit_offset+=2;
205                 num_bits = 14;
206                 val =  tvb_get_ntohs(tvb, offset)&0x3fff;
207         }else if((oct&0xe0)==0xc0){
208                 /* Three octets */
209                 *val_len = 3;
210                 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
211                 bit_offset+=3;
212                 num_bits = 21;
213                 val = tvb_get_ntoh24(tvb, offset)&0x1fffff;
214         }else if ((oct&0xe0)==0xe0){
215                 /* Four octets */
216                 *val_len = 4;
217                 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
218                 bit_offset+=3;
219                 num_bits = 29;
220                 val = tvb_get_ntohl(tvb, offset)&0x1fffffff;
221         }
222         proto_tree_add_bits_item(tree, hf_index, tvb, bit_offset, num_bits, ENC_BIG_ENDIAN);
223
224         return val;
225
226 }
227
228 static void
229 dissect_rohc_feedback_data(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, gint16 feedback_data_len, rohc_info *p_rohc_info){
230
231         proto_item *ti;
232         proto_tree *rohc_feedback_tree;
233         guint8 opt, opt_len, oct;
234
235
236         if(feedback_data_len==1){
237                 /* FEEDBACK-1 */
238                 proto_item_append_text(p_rohc_info->last_created_item, " (type 1)");
239                 switch(p_rohc_info->profile){
240                         case ROHC_PROFILE_RTP: /* 1 */
241                                 /*
242                                  *     0   1   2   3   4   5   6   7
243                                  *   +---+---+---+---+---+---+---+---+
244                                  *   |              SN               |
245                                  *   +---+---+---+---+---+---+---+---+
246                                  *
247                                  */
248
249                                 oct = tvb_get_guint8(tvb, offset);
250                                 proto_tree_add_item(tree, hf_rohc_fb1_sn, tvb, offset, 1, ENC_BIG_ENDIAN);
251                                 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", oct);
252                                 break;
253                         default:
254                                 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
255                                 break;
256                 }
257                 return;
258         }
259         /*  FEEDBACK-2 */
260         proto_item_append_text(p_rohc_info->last_created_item, " (type 2)");
261         switch(p_rohc_info->profile){
262                 case ROHC_PROFILE_RTP: /* 1 */
263                         ti = proto_tree_add_text(tree, tvb, offset, feedback_data_len, "RTP profile-specific information");
264                         rohc_feedback_tree = proto_item_add_subtree(ti, ett_rohc_feedback);
265                         proto_tree_add_item(rohc_feedback_tree, hf_rohc_acktype, tvb, offset, 1, ENC_BIG_ENDIAN);
266                         proto_tree_add_item(rohc_feedback_tree, hf_rohc_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
267                         proto_tree_add_item(rohc_feedback_tree, hf_rohc_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
268                         offset+=2;
269                         feedback_data_len-=2;
270                         while(feedback_data_len>0){
271                                 opt = opt_len = tvb_get_guint8(tvb,offset);
272                                 opt = opt >> 4;
273                                 opt_len = opt_len &0x0f;
274                                 proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_opt_type, tvb, offset, 1, ENC_BIG_ENDIAN);
275                                 proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_opt_len, tvb, offset, 1, ENC_BIG_ENDIAN);
276                                 offset++;
277                                 feedback_data_len--;
278                                 switch(opt){
279                                         case 1:
280                                                 /* CRC */
281                                                 proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
282                                                 oct = tvb_get_guint8(tvb, offset);
283                                                 col_append_fstr(pinfo->cinfo, COL_INFO, "CRC=%u ", oct);
284                                                 break;
285                                         case 2:
286                                                 /* REJECT: TODO */
287                                                 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "Option data[Not dissected yet]");
288                                                 break;
289                                         case 3:
290                                                 /* SN-Not-Valid: TODO */
291                                                 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "Option data[Not dissected yet]");
292                                                 break;
293                                         case 4:
294                                                 /* SN */
295                                                 proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_opt_sn, tvb, offset, 1, ENC_BIG_ENDIAN);
296                                                 oct = tvb_get_guint8(tvb, offset);
297                                                 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u ", oct);
298                                                 break;
299                                         case 5:
300                                                 /* Clock */
301                                                 proto_tree_add_item(tree, hf_rohc_feedback_option_clock, tvb, offset, 1, ENC_BIG_ENDIAN);
302                                                 oct = tvb_get_guint8(tvb, offset);
303                                                 col_append_fstr(pinfo->cinfo, COL_INFO, " Clock=%u ", oct);
304                                                 break;
305                                         case 6:
306                                                 /* Jitter: TODO */
307                                                 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "Option data[Not dissected yet]");
308                                                 break;
309                                         case 7:
310                                                 /* Loss: TODO */
311                                                 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "Option data[Not dissected yet]");
312                                                 break;
313                                         default:
314                                                 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "Unknown Option data");
315                                                 break;
316                                 }
317                                 feedback_data_len = feedback_data_len - opt_len;
318                                 offset = offset + opt_len;
319
320                         }
321                         break;
322                 default:
323                         ti = proto_tree_add_text(tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
324                         rohc_feedback_tree = proto_item_add_subtree(ti, ett_rohc_feedback);
325                         proto_tree_add_item(rohc_feedback_tree, hf_rohc_acktype, tvb, offset, 1, ENC_BIG_ENDIAN);
326                         break;
327         }
328 }
329 int
330 dissect_rohc_ir_rtp_profile_dynamic(tvbuff_t *tvb, proto_tree *tree, int offset, rohc_info *p_rohc_info){
331
332         proto_item *item;
333         proto_tree *sub_tree;
334         guint8 oct, rx, cc, val_len = 0;
335         int i, start_offset;
336
337         start_offset = offset;
338         item = proto_tree_add_text(tree, tvb, offset, 0, "RTP Profile Dynamic Chain");
339         sub_tree = proto_item_add_subtree(item, ett_rohc_rtp_dynamic);
340
341         switch(p_rohc_info->rohc_ip_version){
342                 case 4:
343                         /* 5.7.7.4.  Initialization of IPv4 Header [IPv4, section 3.1].
344                          * Dynamic part:
345                          */
346                         /* Type of Service */
347                         proto_tree_add_item(sub_tree, hf_rohc_rtp_tos, tvb, offset, 1, ENC_BIG_ENDIAN);
348                         offset++;
349                         /* Time to Live */
350                         proto_tree_add_item(sub_tree, hf_rohc_rtp_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
351                         offset++;
352                         /* Identification */
353                         proto_tree_add_item(sub_tree, hf_rohc_rtp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
354                         offset+=2;
355                         /*    +---+---+---+---+---+---+---+---+
356                          *    | DF|RND|NBO|         0         |
357                          *    +---+---+---+---+---+---+---+---+
358                          */
359                         proto_tree_add_item(sub_tree, hf_rohc_rtp_df, tvb, offset, 1, ENC_BIG_ENDIAN);
360                         proto_tree_add_item(sub_tree, hf_rohc_rtp_rnd, tvb, offset, 1, ENC_BIG_ENDIAN);
361                         proto_tree_add_item(sub_tree, hf_rohc_rtp_nbo, tvb, offset, 1, ENC_BIG_ENDIAN);
362                         offset++;
363                         break;
364                 case 6:
365                         proto_tree_add_text(sub_tree, tvb, offset, -1, "Not dissected yet");
366                         return offset;
367                         break;
368                 default:
369                         break;
370         }
371
372         /* 5.7.7.5.  Initialization of UDP Header
373          * Dynamic part:
374          * Checksum
375          */
376         proto_tree_add_item(sub_tree, hf_rohc_rtp_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
377         offset+=2;
378         if (p_rohc_info->profile == 2) {
379                 proto_tree_add_item(sub_tree, hf_rohc_dynamic_udp_seqnum, tvb, offset, 2, ENC_BIG_ENDIAN);
380                 offset +=2;
381                 proto_item_set_len(item, offset - start_offset);
382                 proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
383                 return offset;
384         }
385
386         /* 5.7.7.6.  Initialization of RTP Header
387          * Dynamic part:
388          * Checksum
389          *      P, X, CC, PT, M, sequence number, timestamp, timestamp stride,
390          *      CSRC identifiers.
391          *
392          *        0   1   2   3   4   5   6   7
393          *      +---+---+---+---+---+---+---+---+
394          *      |  V=2  | P | RX|      CC       |  (RX is NOT the RTP X bit)
395          *      +---+---+---+---+---+---+---+---+
396          *      | M |            PT             |
397          *      +---+---+---+---+---+---+---+---+
398          *      /      RTP Sequence Number      /  2 octets
399          *      +---+---+---+---+---+---+---+---+
400          *      /   RTP Timestamp (absolute)    /  4 octets
401          *      +---+---+---+---+---+---+---+---+
402          *      /      Generic CSRC list        /  variable length
403          *      +---+---+---+---+---+---+---+---+
404          *      : Reserved  | X |  Mode |TIS|TSS:  if RX = 1
405          *      +---+---+---+---+---+---+---+---+
406          *      :         TS_Stride             :  1-4 octets, if TSS = 1
407          *      +---+---+---+---+---+---+---+---+
408          *      :         Time_Stride           :  1-4 octets, if TIS = 1
409          *      +---+---+---+---+---+---+---+---+
410          */
411         proto_tree_add_item(sub_tree, hf_rohc_rtp_v, tvb, offset, 1, ENC_BIG_ENDIAN);
412         proto_tree_add_item(sub_tree, hf_rohc_rtp_p, tvb, offset, 1, ENC_BIG_ENDIAN);
413         proto_tree_add_item(sub_tree, hf_rohc_rtp_rx, tvb, offset, 1, ENC_BIG_ENDIAN);
414         proto_tree_add_item(sub_tree, hf_rohc_rtp_cc, tvb, offset, 1, ENC_BIG_ENDIAN);
415         oct = tvb_get_guint8(tvb,offset);
416         cc = oct & 0x0f;
417         rx = (oct >> 4)& 0x01;
418         offset++;
419         proto_tree_add_item(sub_tree, hf_rohc_rtp_m, tvb, offset, 1, ENC_BIG_ENDIAN);
420         proto_tree_add_item(sub_tree, hf_rohc_rtp_pt, tvb, offset, 1, ENC_BIG_ENDIAN);
421         offset++;
422         proto_tree_add_item(sub_tree, hf_rohc_rtp_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
423         offset+=2;
424         proto_tree_add_item(sub_tree, hf_rohc_rtp_timestamp, tvb, offset, 4, ENC_BIG_ENDIAN);
425         offset+=4;
426         if(cc > 0){
427                 /* Dissect Generic CSRC list here */
428                 for (i = 0; i < cc; i++ ) {
429                         proto_tree_add_text(sub_tree, tvb, offset, 4, "CSRC item %u",i+1);
430                         offset+=4;
431                 }
432         }
433         /* : Reserved  | X |  Mode |TIS|TSS:  if RX = 1 */
434         if(rx==0){
435                 proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
436                 return offset;
437         }
438         proto_tree_add_item(sub_tree, hf_rohc_rtp_x, tvb, offset, 1, ENC_BIG_ENDIAN);
439         proto_tree_add_item(sub_tree, hf_rohc_rtp_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
440         proto_tree_add_item(sub_tree, hf_rohc_rtp_tis, tvb, offset, 1, ENC_BIG_ENDIAN);
441         proto_tree_add_item(sub_tree, hf_rohc_rtp_tss, tvb, offset, 1, ENC_BIG_ENDIAN);
442         oct = tvb_get_guint8(tvb,offset);
443         offset++;
444         /* TS_Stride             :  1-4 octets, if TSS = 1 */
445         if((oct&0x01)== 1){
446                 /* TS_Stride encoded as
447                  * 4.5.6.  Self-describing variable-length values
448                  */
449                 get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_rtp_ts_stride, &val_len);
450                 offset = offset + val_len;
451         }
452
453         /* Time_Stride           :  1-4 octets, if TIS = 1 */
454         if((oct&0x02)== 2){
455                 /* Time_Stride encoded as
456                  * 4.5.6.  Self-describing variable-length values
457                  */
458                 get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_rtp_time_stride, &val_len);
459                 offset = offset + val_len;
460         }
461
462         proto_item_set_len(item, offset - start_offset);
463         
464         return offset;
465
466 }
467 static void
468 dissect_rohc_ir_rtp_udp_profile_static(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, gboolean d, rohc_info *p_rohc_info){
469
470         proto_item *item;
471         proto_tree *sub_tree;
472         guint8 version;
473         int start_offset;
474
475         start_offset = offset;
476         item = proto_tree_add_text(tree, tvb, offset, 0, "RTP/UDP Profile Static Chain");
477         sub_tree = proto_item_add_subtree(item, ett_rohc_rtp_static);
478
479         version = tvb_get_guint8(tvb,offset)>>4;
480         proto_tree_add_item(sub_tree, hf_rohc_rtp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
481         if(p_rohc_info->rohc_ip_version != version){
482                 expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN,
483                         "Configured IP version %u, differs from actual IP version %u, Dissection of other packets may be faulty",
484                         p_rohc_info->rohc_ip_version, version);
485         }
486
487         switch(version){
488                 case 4:
489                         /* 5.7.7.4.  Initialization of IPv4 Header [IPv4, section 3.1].
490                          * Static part:
491                          */
492                         offset++;
493                         /* Protocol */
494                         proto_tree_add_item(sub_tree, hf_rohc_rtp_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
495                         offset++;
496                         /* Source Address */
497                         proto_tree_add_item(sub_tree, hf_rohc_rtp_ipv4_src, tvb, offset, 4, ENC_BIG_ENDIAN);
498                         offset+=4;
499                         /* Destination Address */
500                         proto_tree_add_item(sub_tree, hf_rohc_rtp_ipv4_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
501                         offset+=4;
502                         break;
503                 case 6:
504                         /* 5.7.7.3.  Initialization of IPv6 Header [IPv6]*/
505                         proto_tree_add_text(tree, tvb, offset, -1, "Not dissected yet");
506                         /* TODO: Short term, Calculate length and continue? */
507                         return;
508                         break;
509                 default:
510                         proto_tree_add_text(sub_tree, tvb, offset, -1, "Error unknown version, only 4 or 6 allowed");
511                         return;
512         }
513         if ((p_rohc_info->profile == ROHC_PROFILE_RTP) ||
514                 (p_rohc_info->profile == ROHC_PROFILE_UDP)) {
515                 /* 5.7.7.5.  Initialization of UDP Header [RFC-768].
516                  * Static part
517                  */
518                 /* Source Port */
519                 proto_tree_add_item(sub_tree, hf_rohc_rtp_udp_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
520                 offset+=2;
521                 /* Destination Port */
522                 proto_tree_add_item(sub_tree, hf_rohc_rtp_udp_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
523                 offset+=2;
524                 if(p_rohc_info->profile == ROHC_PROFILE_UDP){
525                         if(d==TRUE){
526                                 offset = dissect_rohc_ir_rtp_profile_dynamic(tvb, tree, offset, p_rohc_info);
527                         }
528                         proto_item_set_len(item, offset - start_offset);
529                         proto_tree_add_text(tree, tvb, offset, -1, "UDP data");
530                         return;
531                 }
532
533                 /* 5.7.7.6.  Initialization of RTP Header [RTP]. */
534                 /* SSRC */
535                 proto_tree_add_item(sub_tree, hf_rohc_rtp_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN);
536                 offset+=4;
537                 proto_item_set_len(item, offset - start_offset);
538
539                 /* D:   D = 1 indicates that the dynamic chain is present. */
540                 if(d==TRUE){
541                         offset = dissect_rohc_ir_rtp_profile_dynamic(tvb, tree, offset, p_rohc_info);
542                 }
543                 proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
544         }
545 }
546
547
548 static void
549 dissect_rohc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
550 {
551         proto_item *ti, *item, *ir_item;
552         proto_tree *rohc_tree, *ir_tree, *sub_tree = NULL;
553         int offset = 0, length, x_bit_offset;
554         guint8 oct, code, size , cid, profile, val_len;
555         gint16 feedback_data_len = 0;
556         gboolean is_add_cid = FALSE, d = FALSE;
557         rohc_info *p_rohc_info = NULL;
558         rohc_info g_rohc_info;
559
560
561         if(pinfo->private_data != NULL){
562                 p_rohc_info = pinfo->private_data;
563                 memset(&g_rohc_info, 0, sizeof(rohc_info));
564         }else{
565                 g_rohc_info.rohc_compression    = FALSE;
566                 g_rohc_info.rohc_ip_version             = g_version;
567                 g_rohc_info.cid_inclusion_info  = FALSE;
568                 g_rohc_info.large_cid_present   = FALSE;
569                 g_rohc_info.mode                                = RELIABLE_BIDIRECTIONAL;
570                 g_rohc_info.rnd                                 = FALSE;
571                 g_rohc_info.udp_checkum_present = FALSE;
572                 g_rohc_info.profile                             = g_profile;
573                 g_rohc_info.last_created_item   = NULL;
574                 p_rohc_info = &g_rohc_info;
575         }
576
577         length = tvb_length(tvb);
578
579         /* If this is ROHC ethertype clear col */
580         if ( pinfo->src.type == AT_ETHER ){
581                 col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "ROHC(%s)",
582                         val_to_str(p_rohc_info->profile, rohc_profile_vals, "Unknown"));
583                 col_clear(pinfo->cinfo, COL_INFO);
584         }else{
585                 col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
586                         val_to_str(p_rohc_info->profile, rohc_profile_vals, "Unknown"));
587                 /* Append a space if we add stuff to existing col info */
588                 col_append_str(pinfo->cinfo, COL_INFO, " ");
589         }
590         /*if (tree) {*/
591                 ti = proto_tree_add_item(tree, proto_rohc, tvb, 0, -1, ENC_NA);
592                 rohc_tree = proto_item_add_subtree(ti, ett_rohc);
593                 /*    1) If the first octet is a Padding Octet (11100000),
594                  *       strip away all initial Padding Octets and goto next step.
595                  */
596                 if(p_rohc_info->large_cid_present == FALSE){
597                         item = proto_tree_add_text(rohc_tree, tvb, offset, -1, "Small CID configured");
598                         PROTO_ITEM_SET_GENERATED(item);
599                 }else{
600                         item = proto_tree_add_text(rohc_tree, tvb, offset, -1, "Large CID configured");
601                         PROTO_ITEM_SET_GENERATED(item);
602                 }
603 start_over:
604                 cid = 0;
605                 oct = tvb_get_guint8(tvb,offset);
606                 if(oct== 0xe0){
607                         while(oct == 0xe0){
608                                 offset++;
609                                 oct = tvb_get_guint8(tvb,offset);
610                         }
611                         proto_tree_add_item(rohc_tree, hf_rohc_padding, tvb, 0, offset, ENC_NA);
612                 }
613                 /* 2) If the first remaining octet starts with 1110, it is an Add-CID octet:
614                  *    remember the Add-CID octet; remove the octet.
615                  */
616                 if((oct&0xf0) == 0xe0){
617                         is_add_cid = TRUE;
618                         cid = oct & 0x0f;
619                         proto_tree_add_item(rohc_tree, hf_rohc_add_cid, tvb, offset, 1, ENC_BIG_ENDIAN);
620                         proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, offset, 1, cid);
621                         offset++;
622                         oct = tvb_get_guint8(tvb,offset);
623                 }
624                 /* feedback ?
625                  * Feedback (begins with 11110)
626                  */
627                 if((oct&0xf8) == 0xf0){
628                 /* 3) If the first remaining octet starts with 11110, and an Add-CID
629                  *    octet was found in step 2), an error has occurred;
630                  *    the header MUST be discarded without further action.
631                  */
632
633                         if(is_add_cid){
634                                 proto_tree_add_item(rohc_tree, hf_rohc_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
635                                 col_append_str(pinfo->cinfo, COL_INFO, "Error packet");
636                                 proto_tree_add_text(rohc_tree, tvb, offset, -1, "Error packet");
637                                 return;
638                         }else{
639                                 col_append_str(pinfo->cinfo, COL_INFO, "Feedback ");
640                                 /* 4) If the first remaining octet starts with 11110, and an Add-CID
641                                  *    octet was not found in step 2), this is feedback:
642                                  *        find the size of the feedback data, call it s;
643                                  *        remove the feedback type octet;
644                                  *        remove the Size octet if Code is 0;
645                                  *        send feedback data of length s to the same-side associated
646                                  *        compressor;
647                                  *        if packet exhausted, stop; otherwise goto 2).
648                                  */
649                                 p_rohc_info->last_created_item = proto_tree_add_item(rohc_tree, hf_rohc_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
650                                 sub_tree = proto_item_add_subtree(g_rohc_info.last_created_item, ett_rohc_fb);
651                                 proto_tree_add_item(sub_tree, hf_rohc_code, tvb, offset, 1, ENC_BIG_ENDIAN);
652                                 code = oct&0x7;
653                                 offset++;
654                                 if(code==0){
655                                         size = tvb_get_guint8(tvb,offset);
656                                         proto_tree_add_item(sub_tree, hf_rohc_size, tvb, offset, 1, ENC_BIG_ENDIAN);
657                                         offset++;
658                                 }else{
659                                         size = code;
660                                 }
661                                 feedback_data_len = size;
662                                 if(p_rohc_info->large_cid_present == FALSE){
663                                         /* Check for Add-CID octet */
664                                         oct = tvb_get_guint8(tvb,offset);
665                                         if((oct&0xf0) == 0xe0){
666                                                 cid = oct & 0x0f;
667                                                 proto_tree_add_item(sub_tree, hf_rohc_add_cid, tvb, offset, 1, ENC_BIG_ENDIAN);
668                                                 proto_tree_add_uint(sub_tree, hf_rohc_small_cid, tvb, offset, 1, cid);
669                                                 offset++;
670                                                 feedback_data_len--;
671                                         }else{
672                                                 item = proto_tree_add_uint(sub_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
673                                                 PROTO_ITEM_SET_GENERATED(item);
674                                         }
675                                 }else{
676                                         /* Read Large CID here */
677                                         get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_large_cid, &val_len);
678                                         /* feedback_data_len - "lenght of large CID" */
679                                         feedback_data_len = feedback_data_len - val_len;
680                                 }
681                                 /* Dissect feedback */
682                                 dissect_rohc_feedback_data(tvb, sub_tree, pinfo, offset, feedback_data_len, p_rohc_info);
683                                 offset = offset + size;
684                                 if(offset<length)
685                                         goto start_over;
686                                 return;
687                         }
688                 }/*feedback */
689                 /* 5) If the first remaining octet starts with 1111111, this is a segment:
690                  *
691                  */
692                 if((oct&0xfe) == 0xfe){
693                         col_append_str(pinfo->cinfo, COL_INFO, "Segment");
694                         if((p_rohc_info->large_cid_present == FALSE) && (is_add_cid == FALSE)){
695                                 item = proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
696                                 PROTO_ITEM_SET_GENERATED(item);
697                         }
698                         proto_tree_add_text(rohc_tree, tvb, offset, -1, "Segment [Desegmentation not implemented yet]");
699                         return;
700                 }
701                 /* 6) Here, it is known that the rest is forward information (unless the
702                  *    header is damaged).
703                  */
704                 if((oct&0xfe) == 0xfc){
705                         col_append_str(pinfo->cinfo, COL_INFO, "IR packet");
706                         if((p_rohc_info->large_cid_present == FALSE) && (is_add_cid == FALSE)){
707                                 item = proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
708                                 PROTO_ITEM_SET_GENERATED(item);
709                         }
710                         ir_item = proto_tree_add_item(rohc_tree, hf_rohc_ir_packet, tvb, offset, 1, ENC_BIG_ENDIAN);
711                         ir_tree = proto_item_add_subtree(ir_item, ett_rohc_ir);
712                         d = oct & 0x01;
713                         x_bit_offset = offset;
714                         offset++;
715                         if(p_rohc_info->large_cid_present == TRUE){
716                                 /* Handle Large CID:s here */
717                                 get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_large_cid, &val_len);
718                                 offset = offset + val_len;
719                         }
720                         profile = tvb_get_guint8(tvb,offset);
721                         if(profile==ROHC_PROFILE_RTP){
722                                 proto_tree_add_item(ir_tree, hf_rohc_d_bit, tvb, x_bit_offset, 1, ENC_BIG_ENDIAN);
723                         }
724                         item = proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
725                         if(p_rohc_info->profile != profile){
726                                 expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN,
727                                         "Configured profile %u, differs from actual profile %u, Dissection of other packets may be faulty",
728                                         p_rohc_info->profile, profile);
729                                 /* Oweride the configured profile */
730                                 p_rohc_info->profile = profile;
731                         }
732                         offset++;
733                         proto_tree_add_item(ir_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
734                         offset++;
735                         switch(profile){
736                                 case ROHC_PROFILE_RTP:
737                                         dissect_rohc_ir_rtp_udp_profile_static(tvb, ir_tree, pinfo, offset, d, p_rohc_info);
738                                         break;
739                                 case ROHC_PROFILE_UDP:
740                                         dissect_rohc_ir_rtp_udp_profile_static(tvb, ir_tree, pinfo, offset, d, p_rohc_info);
741                                         break;
742                                 default:
743                                         proto_tree_add_text(ir_tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
744                                         break;
745                         }
746                         return;
747                 }
748                 if((oct&0xff) == 0xf8){
749                         col_append_str(pinfo->cinfo, COL_INFO, "IR-DYN packet");
750                         if((p_rohc_info->large_cid_present == FALSE) && (is_add_cid == FALSE)){
751                                 item = proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
752                                 PROTO_ITEM_SET_GENERATED(item);
753                         }
754                         ir_item = proto_tree_add_item(rohc_tree, hf_rohc_ir_dyn_packet, tvb, offset, 1, ENC_BIG_ENDIAN);
755                         ir_tree = proto_item_add_subtree(ir_item, ett_rohc_ir_dyn);
756                         if(p_rohc_info->large_cid_present == TRUE){
757                                 /* Handle Large CID:s here */
758                                 get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_large_cid, &val_len);
759                                 offset = offset + val_len;
760                         }
761                         profile = tvb_get_guint8(tvb,offset);
762                         item = proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
763                         offset++;
764                         if(p_rohc_info->profile != profile){
765                                 expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN,
766                                         "Configured profile %u, differs from actual profile %u, Dissection of other packets may be faulty",
767                                         p_rohc_info->profile, profile);
768                                 /* Oweride the configured profile */
769                                 p_rohc_info->profile = profile;
770                         }
771                         proto_tree_add_item(ir_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
772                         offset++;
773                         switch(profile){
774                                 case ROHC_PROFILE_RTP:
775                                         /* TODO: Currently IPv4 Hardwired, use conversation info or preference ? */
776                                         dissect_rohc_ir_rtp_profile_dynamic(tvb, ir_tree, offset, p_rohc_info);
777                                         break;
778                                 default:
779                                         proto_tree_add_text(ir_tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
780                                         break;
781                         }
782                         return;
783                 }
784
785                 if((oct&0x80)==0){
786                         col_set_str(pinfo->cinfo, COL_INFO, "Paket type 0");
787                 }else if ((oct&0xc0)==0x80){
788                         col_set_str(pinfo->cinfo, COL_INFO, "Paket type 1");
789                 }else if ((oct&0xe0)==0xc0){
790                         col_set_str(pinfo->cinfo, COL_INFO, "Paket type 2");
791                 }
792         /*}*//* if tree */
793 }
794
795 void
796 proto_register_rohc(void)
797 {
798
799         static hf_register_info hf[] =
800         {
801                 { &hf_rohc_padding,
802                         { "Padding","rohc.pading",
803                         FT_BYTES, BASE_NONE, NULL, 0x0,
804                         NULL , HFILL
805                         }
806                 },
807                 { &hf_rohc_add_cid,
808                         { "Add-CID","rohc.add_cid",
809                         FT_UINT8, BASE_HEX, NULL, 0xf0,
810                         NULL , HFILL
811                         }
812                 },
813                 { &hf_rohc_feedback,
814                         { "Feedback","rohc.feedback",
815                         FT_UINT8, BASE_HEX, NULL, 0xf8,
816                         NULL , HFILL
817                         }
818                 },
819                 { &hf_rohc_code,
820                         { "Code","rohc.code",
821                         FT_UINT8, BASE_DEC, NULL, 0x07,
822                         NULL , HFILL
823                         }
824                 },
825                 { &hf_rohc_size,
826                         { "Size","rohc.size",
827                         FT_UINT8, BASE_DEC, NULL, 0x00,
828                         NULL , HFILL
829                         }
830                 },
831                 { &hf_rohc_ir_packet,
832                         { "IR packet","rohc.ir_packet",
833                         FT_UINT8, BASE_DEC, NULL, 0xfe,
834                         NULL , HFILL
835                         }
836                 },
837                 { &hf_rohc_ir_dyn_packet,
838                         { "IR-DYN packet","rohc.ir_dyn_packet",
839                         FT_UINT8, BASE_DEC, NULL, 0xff,
840                         NULL , HFILL
841                         }
842                 },
843                 { &hf_rohc_small_cid,
844                         { "Small CID","rohc.small_cid",
845                         FT_UINT8, BASE_DEC, NULL, 0x0f,
846                         NULL , HFILL
847                         }
848                 },
849                 { &hf_rohc_large_cid,
850                         { "Large CID","rohc.large_cid",
851                         FT_UINT16, BASE_DEC, NULL, 0x0,
852                         NULL , HFILL
853                         }
854                 },
855                 { &hf_rohc_acktype,
856                         { "Acktype","rohc.acktype",
857                         FT_UINT8, BASE_DEC, VALS(rohc_acktype_vals), 0xc0,
858                         NULL , HFILL
859                         }
860                 },
861                 { &hf_rohc_mode,
862                         { "Mode","rohc.mode",
863                         FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x30,
864                         NULL , HFILL
865                         }
866                 },
867                 { &hf_rohc_sn,
868                         { "SN(lsb)","rohc.sn",
869                         FT_UINT16, BASE_HEX, NULL, 0x0fff,
870                         NULL , HFILL
871                         }
872                 },
873                 { &hf_rohc_fb1_sn,
874                         { "SN","rohc.fb1_sn",
875                         FT_UINT16, BASE_HEX, NULL, 0x0,
876                         NULL , HFILL
877                         }
878                 },
879                 { &hf_rohc_rtp_opt_type,
880                         { "Option type","rohc.rtp.opt_type",
881                         FT_UINT8, BASE_DEC, VALS(rohc_rtp_opt_type_vals), 0xf0,
882                         NULL , HFILL
883                         }
884                 },
885                 { &hf_rohc_rtp_opt_len,
886                         { "Option length","rohc.rtp.opt_length",
887                         FT_UINT8, BASE_DEC, NULL, 0x0f,
888                         NULL , HFILL
889                         }
890                 },
891                 { &hf_rohc_rtp_crc,
892                         { "CRC","rohc.crc",
893                         FT_UINT8, BASE_HEX, NULL, 0x0,
894                         NULL , HFILL
895                         }
896                 },
897                 { &hf_rohc_rtp_opt_sn,
898                         { "SN","rohc.opt.sn",
899                         FT_UINT8, BASE_HEX, NULL, 0x0,
900                         NULL , HFILL
901                         }
902                 },
903                 { &hf_rohc_feedback_option_clock,
904                         { "Clock", "rohc.feedback-option-clock",
905                         FT_UINT8, BASE_DEC, NULL, 0x0,
906                         "Feedback Option Clock", HFILL
907                         }
908                 },
909                 { &hf_rohc_profile,
910                         { "Profile","rohc.profile",
911                         FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
912                         NULL , HFILL
913                         }
914                 },
915                 { &hf_rohc_d_bit,
916                         { "D - Dynamic chain","rohc.d",
917                         FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01,
918                         NULL , HFILL
919                         }
920                 },
921                 { &hf_rohc_rtp_version,
922                         { "Version","rohc.rtp.version",
923                         FT_UINT8, BASE_DEC, VALS(rohc_rtp_version_vals), 0xf0,
924                         NULL , HFILL
925                         }
926                 },
927                 { &hf_rohc_rtp_protocol,
928                         { "Protocol","rohc.rtp.protocol",
929                         FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&ipproto_val_ext), 0x0,
930                         NULL , HFILL
931                         }
932                 },
933                 { &hf_rohc_rtp_ipv4_src,
934                         { "Source address","rohc.rtp.ipv4_src",
935                         FT_IPv4, BASE_NONE, NULL, 0x0,
936                         NULL, HFILL
937                         }
938                 },
939                 { &hf_rohc_rtp_ipv4_dst,
940                         { "Destination address","rohc.rtp.ipv4_dst",
941                         FT_IPv4, BASE_NONE, NULL, 0x0,
942                         NULL, HFILL
943                         }
944                 },
945                 { &hf_rohc_rtp_udp_src_port,
946                         { "Source Port","rohc.rtp.udp_src_port",
947                         FT_UINT16, BASE_DEC, NULL, 0x0,
948                         NULL , HFILL
949                         }
950                 },
951                 { &hf_rohc_rtp_udp_dst_port,
952                         { "Destination Port","rohc.rtp.udp_dst_port",
953                         FT_UINT16, BASE_DEC, NULL, 0x0,
954                         NULL , HFILL
955                         }
956                 },
957                 { &hf_rohc_rtp_ssrc,
958                         { "SSRC","rohc.rtp.ssrc",
959                         FT_UINT32, BASE_HEX, NULL, 0x0,
960                         NULL , HFILL
961                         }
962                 },
963                 { &hf_rohc_rtp_tos,
964                         { "Type of Service","rohc.rtp.tos",
965                         FT_UINT8, BASE_HEX, NULL, 0x0,
966                         NULL , HFILL
967                         }
968                 },
969                 { &hf_rohc_rtp_ttl,
970                         { "Time to Live","rohc.rtp.ttl",
971                         FT_UINT8, BASE_DEC, NULL, 0x0,
972                         NULL , HFILL
973                         }
974                 },
975                 { &hf_rohc_rtp_id,
976                         { "Identification","rohc.rtp.rtp.id",
977                         FT_UINT16, BASE_HEX, NULL, 0x0,
978                         NULL , HFILL
979                         }
980                 },
981                 { &hf_rohc_rtp_df,
982                         { "Don't Fragment(DF)","rohc.rtp.df",
983                         FT_BOOLEAN, 8, NULL, 0x80,
984                         NULL , HFILL
985                         }
986                 },
987                 { &hf_rohc_rtp_rnd,
988                         { "RND(IP-ID behaves randomly)","rohc.rtp.rnd",
989                         FT_BOOLEAN, 8, NULL, 0x40,
990                         NULL , HFILL
991                         }
992                 },
993                 { &hf_rohc_rtp_nbo,
994                         { "Network Byte Order (NBO)","rohc.rtp.nbo",
995                         FT_BOOLEAN, 8, NULL, 0x20,
996                         "Whether the IP-ID is in Network Byte Order" , HFILL
997                         }
998                 },
999                 { &hf_rohc_rtp_checksum,
1000                         { "Checksum","rohc.rtp.checksum",
1001                         FT_UINT16, BASE_HEX, NULL, 0x0,
1002                         NULL , HFILL
1003                         }
1004                 },
1005                 { &hf_rohc_dynamic_udp_seqnum,
1006                         { "UDP Sequence Number", "rohc.dynamic.udp.seqnum",
1007                         FT_UINT16, BASE_HEX, NULL, 0x0,
1008                         NULL, HFILL
1009                         }
1010         },
1011                 { &hf_rohc_rtp_v,
1012                         { "version","rohc.rtp.v",
1013                         FT_UINT8, BASE_DEC, NULL, 0xc0,
1014                         NULL , HFILL
1015                         }
1016                 },
1017                 { &hf_rohc_rtp_p,
1018                         { "Padding(P)","rohc.rtp.p",
1019                         FT_BOOLEAN, 8, NULL, 0x20,
1020                         NULL , HFILL
1021                         }
1022                 },
1023                 { &hf_rohc_rtp_rx,
1024                         { "RX","rohc.rtp.rx",
1025                         FT_BOOLEAN, 8, NULL, 0x10,
1026                         NULL , HFILL
1027                         }
1028                 },
1029                 { &hf_rohc_rtp_cc,
1030                         { "CC","rohc.rtp.cc",
1031                         FT_UINT8, BASE_DEC, NULL, 0x0f,
1032                         "CSRC counter from original RTP header" , HFILL
1033                         }
1034                 },
1035                 { &hf_rohc_rtp_m,
1036                         { "Marker Bit (M)","rohc.rtp.m",
1037                         FT_BOOLEAN, 8,  TFS(&tfs_set_notset), 0x80,
1038                         NULL , HFILL
1039                         }
1040                 },
1041                 { &hf_rohc_rtp_pt,
1042                         { "Payload Type(PT)","rohc.rtp.pt",
1043                         FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&rtp_payload_type_vals_ext), 0x7f,
1044                         NULL , HFILL
1045                         }
1046                 },
1047                 { &hf_rohc_rtp_sn,
1048                         { "Sequence Number(SN)","rohc.rtp.sn",
1049                         FT_UINT16, BASE_HEX, NULL, 0x0,
1050                         NULL , HFILL
1051                         }
1052                 },
1053                 { &hf_rohc_rtp_timestamp,
1054                         { "RTP Timestamp","rohc.rtp.timestamp",
1055                         FT_UINT32, BASE_DEC, NULL, 0x0,
1056                         NULL , HFILL
1057                         }
1058                 },
1059                 { &hf_rohc_rtp_x,
1060                         { "X","rohc.rtp.x",
1061                         FT_BOOLEAN, 8,  TFS(&tfs_set_notset), 0x80,
1062                         NULL , HFILL
1063                         }
1064                 },
1065                 { &hf_rohc_rtp_mode,
1066                         { "Mode","rohc.rtp.mode",
1067                         FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0c,
1068                         NULL , HFILL
1069                         }
1070                 },
1071                 { &hf_rohc_rtp_tis,
1072                         { "TIS","rohc.rtp.tis",
1073                         FT_BOOLEAN, 8,  NULL, 0x02,
1074                         NULL , HFILL
1075                         }
1076                 },
1077                 { &hf_rohc_rtp_tss,
1078                         { "TSS","rohc.rtp.tss",
1079                         FT_BOOLEAN, 8,  NULL, 0x01,
1080                         NULL , HFILL
1081                         }
1082                 },
1083                 { &hf_rohc_rtp_ts_stride,
1084                         { "TS_Stride","rohc.rtp.ts_stride",
1085                         FT_UINT32, BASE_DEC, NULL, 0x0,
1086                         NULL , HFILL
1087                         }
1088                 },
1089                 { &hf_rohc_rtp_time_stride,
1090                         { "Time_Stride","rohc.rtp.time_stride",
1091                         FT_UINT32, BASE_DEC, NULL, 0x0,
1092                         NULL , HFILL
1093                         }
1094                 },
1095                 { &hf_rohc_var_len,
1096                         { "Variable length","rohc.var_len",
1097                         FT_UINT8, BASE_DEC, VALS(rohc_var_len_vals), 0x0,
1098                         NULL , HFILL
1099                         }
1100                 },
1101         };
1102
1103         /* Setup protocol subtree array */
1104         static gint *ett[] = {
1105         &ett_rohc,
1106         &ett_rohc_fb,
1107         &ett_rohc_feedback,
1108         &ett_rohc_ir,
1109         &ett_rohc_ir_dyn,
1110         &ett_rohc_rtp_static,
1111         &ett_rohc_rtp_dynamic,
1112         };
1113
1114         /* Register the protocol name and description */
1115         proto_rohc = proto_register_protocol("RObust Header Compression (ROHC)", "ROHC", "rohc");
1116
1117         register_dissector("rohc", dissect_rohc, proto_rohc);
1118
1119         /* Required function calls to register the header fields and subtrees used */
1120         proto_register_field_array(proto_rohc, hf, array_length(hf));
1121         proto_register_subtree_array(ett, array_length(ett));
1122 }
1123
1124 void
1125 proto_reg_handoff_rohc(void)
1126 {
1127         dissector_handle_t rohc_handle;
1128
1129         rohc_handle = create_dissector_handle(dissect_rohc, proto_rohc);
1130         dissector_add_uint("ethertype", ETHERTYPE_ROHC, rohc_handle);
1131
1132 }