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