2 * Routines for RObust Header Compression (ROHC) dissection.
4 * Copyright 2011, Anders Broman <anders.broman[at]ericsson.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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.
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
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>
44 /* Initialize the protocol and registered fields */
45 static int proto_rohc = -1;
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;
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;
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;
109 #define ROHC_PROFILE_RTP 1
111 static const value_string rohc_profile_vals[] =
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*/
132 static const value_string rohc_acktype_vals[] =
136 { 2, "STATIC-NACK" },
137 { 3, "reserved (MUST NOT be used. Otherwise unparsable)" },
141 static const value_string rohc_mode_vals[] =
144 { 1, "Unidirectional" },
145 { 2, "Bidirectional Optimistic" },
146 { 3, "Bidirectional Reliable" },
150 static const value_string rohc_rtp_opt_type_vals[] =
154 { 3, "SN-NOT-VALID" },
164 static const value_string rohc_rtp_version_vals[] =
171 static const value_string rohc_var_len_vals[] =
175 { 6, "Three octets" },
176 { 7, "Four octets" },
181 /* 4.5.6. Self-describing variable-length values */
183 get_self_describing_var_len_val(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, guint8 *val_len){
186 int num_bits = 0, bit_offset = offset <<3;
188 oct = tvb_get_guint8(tvb, offset);
193 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
196 }else if((oct&0xc0)==0x20){
199 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 2, ENC_BIG_ENDIAN);
202 val = tvb_get_ntohs(tvb, offset)&0x3fff;
203 }else if((oct&0xe0)==0xc0){
206 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
209 val = tvb_get_ntoh24(tvb, offset)&0x1fffff;
210 }else if ((oct&0xe0)==0xe0){
213 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
216 val = tvb_get_ntohl(tvb, offset)&0x1fffffff;
218 proto_tree_add_bits_item(tree, hf_index, tvb, bit_offset, num_bits, ENC_BIG_ENDIAN);
225 dissect_rohc_feedback_data(tvbuff_t *tvb, proto_tree *tree, int offset, gint16 feedback_data_len, guint8 profile){
228 proto_tree *rohc_feedback_tree;
232 if(feedback_data_len==1){
234 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
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);
246 feedback_data_len-=2;
247 while(feedback_data_len>0){
248 opt = opt_len = tvb_get_guint8(tvb,offset);
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);
258 proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
262 proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_opt_sn, tvb, offset, 1, ENC_BIG_ENDIAN);
265 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "Option data[Not dissected yet]");
268 feedback_data_len = feedback_data_len - opt_len;
269 offset = offset + opt_len;
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);
281 dissect_rohc_ir_rtp_profile_dynamic(tvbuff_t *tvb, proto_tree *tree, int offset, guint8 version){
284 proto_tree *sub_tree;
285 guint8 oct, rx, cc, val_len = 0;
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);
294 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
297 /* Type of Service */
298 proto_tree_add_item(sub_tree, hf_rohc_rtp_tos, tvb, offset, 1, ENC_BIG_ENDIAN);
301 proto_tree_add_item(sub_tree, hf_rohc_rtp_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
304 proto_tree_add_item(sub_tree, hf_rohc_rtp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
306 /* +---+---+---+---+---+---+---+---+
308 * +---+---+---+---+---+---+---+---+
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);
316 proto_tree_add_text(sub_tree, tvb, offset, -1, "Not dissected yet");
323 /* 5.7.7.5. Initialization of UDP Header
327 proto_tree_add_item(sub_tree, hf_rohc_rtp_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
330 /* 5.7.7.6. Initialization of RTP Header
333 * P, X, CC, PT, M, sequence number, timestamp, timestamp stride,
337 * +---+---+---+---+---+---+---+---+
338 * | V=2 | P | RX| CC | (RX is NOT the RTP X bit)
339 * +---+---+---+---+---+---+---+---+
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 * +---+---+---+---+---+---+---+---+
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);
361 rx = (oct >> 4)& 0x01;
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);
366 proto_tree_add_item(sub_tree, hf_rohc_rtp_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
368 proto_tree_add_item(sub_tree, hf_rohc_rtp_timestamp, tvb, offset, 4, ENC_BIG_ENDIAN);
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);
377 /* : Reserved | X | Mode |TIS|TSS: if RX = 1 */
379 proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
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);
388 /* TS_Stride : 1-4 octets, if TSS = 1 */
390 /* TS_Stride encoded as
391 * 4.5.6. Self-describing variable-length values
393 get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_rtp_ts_stride, &val_len);
394 offset = offset + val_len;
397 /* Time_Stride : 1-4 octets, if TIS = 1 */
399 /* Time_Stride encoded as
400 * 4.5.6. Self-describing variable-length values
402 get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_rtp_time_stride, &val_len);
403 offset = offset + val_len;
406 proto_item_set_len(item, offset - start_offset);
407 proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
411 dissect_rohc_ir_rtp_profile_static(tvbuff_t *tvb, proto_tree *tree, int offset, gboolean d){
414 proto_tree *sub_tree;
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);
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);
426 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
431 proto_tree_add_item(sub_tree, hf_rohc_rtp_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
434 proto_tree_add_item(sub_tree, hf_rohc_rtp_ipv4_src, tvb, offset, 4, ENC_BIG_ENDIAN);
436 /* Destination Address */
437 proto_tree_add_item(sub_tree, hf_rohc_rtp_ipv4_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
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? */
447 proto_tree_add_text(sub_tree, tvb, offset, -1, "Error unknown version, only 4 or 6 allowed");
450 /* 5.7.7.5. Initialization of UDP Header [RFC-768].
454 proto_tree_add_item(sub_tree, hf_rohc_rtp_udp_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
456 /* Destination Port */
457 proto_tree_add_item(sub_tree, hf_rohc_rtp_udp_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
461 /* 5.7.7.6. Initialization of RTP Header [RTP]. */
463 proto_tree_add_item(sub_tree, hf_rohc_rtp_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN);
465 proto_item_set_len(item, offset - start_offset);
467 /* D: D = 1 indicates that the dynamic chain is present. */
469 dissect_rohc_ir_rtp_profile_dynamic(tvb, tree, offset, version);
471 proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
477 dissect_rohc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
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;
486 length = tvb_length(tvb);
488 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ROHC");
489 col_clear(pinfo->cinfo, COL_INFO);
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.
497 item = proto_tree_add_text(rohc_tree, tvb, offset, -1, "Small CID configured");
498 PROTO_ITEM_SET_GENERATED(item);
500 item = proto_tree_add_text(rohc_tree, tvb, offset, -1, "Large CID configured");
501 PROTO_ITEM_SET_GENERATED(item);
505 oct = tvb_get_guint8(tvb,offset);
509 oct = tvb_get_guint8(tvb,offset);
511 proto_tree_add_item(rohc_tree, hf_rohc_padding, tvb, 0, offset, ENC_BIG_ENDIAN);
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.
516 if((oct&0xf0) == 0xe0){
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);
522 oct = tvb_get_guint8(tvb,offset);
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.
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");
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
545 * if packet exhausted, stop; otherwise goto 2).
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);
553 size = tvb_get_guint8(tvb,offset);
554 proto_tree_add_item(sub_tree, hf_rohc_size, tvb, offset, 1, ENC_BIG_ENDIAN);
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){
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);
570 item = proto_tree_add_uint(sub_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
571 PROTO_ITEM_SET_GENERATED(item);
574 /* Read Large CID here */
575 /* feedback_data_len - "lenght of large CID" */
577 /* Dissect feedback */
578 dissect_rohc_feedback_data(tvb, sub_tree, offset, feedback_data_len, g_profile);
579 offset = offset + size;
585 /* 5) If the first remaining octet starts with 1111111, this is a segment:
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);
594 proto_tree_add_text(rohc_tree, tvb, offset, -1, "Segment");
597 /* 6) Here, it is known that the rest is forward information (unless the
598 * header is damaged).
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);
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);
609 x_bit_offset = offset;
611 if(g_small_cid==FALSE){
612 /* Handle Large CID:s here */
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);
618 proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
620 proto_tree_add_item(ir_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
623 case ROHC_PROFILE_RTP:
624 dissect_rohc_ir_rtp_profile_static(tvb, ir_tree, offset, d);
627 proto_tree_add_text(ir_tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
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);
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 */
643 profile = tvb_get_guint8(tvb,offset);
644 proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
646 proto_tree_add_item(ir_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
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);
654 proto_tree_add_text(ir_tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
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");
671 proto_register_rohc(void)
674 static hf_register_info hf[] =
677 { "Padding","rohc.pading",
678 FT_BYTES, BASE_NONE, NULL, 0x0,
683 { "Add-CID","rohc.add_cid",
684 FT_UINT8, BASE_HEX, NULL, 0xf0,
689 { "Feedback","rohc.feedback",
690 FT_UINT8, BASE_HEX, NULL, 0xf8,
695 { "Code","rohc.code",
696 FT_UINT8, BASE_DEC, NULL, 0x07,
701 { "Size","rohc.size",
702 FT_UINT8, BASE_DEC, NULL, 0x00,
706 { &hf_rohc_ir_packet,
707 { "IR packet","rohc.ir_packet",
708 FT_UINT8, BASE_DEC, NULL, 0xfe,
712 { &hf_rohc_ir_dyn_packet,
713 { "IR-DYN packet","rohc.ir_dyn_packet",
714 FT_UINT8, BASE_DEC, NULL, 0xff,
718 { &hf_rohc_small_cid,
719 { "Small CID","rohc.small_cid",
720 FT_UINT8, BASE_DEC, NULL, 0x0f,
725 { "Acktype","rohc.acktype",
726 FT_UINT8, BASE_DEC, VALS(rohc_acktype_vals), 0xc0,
731 { "Mode","rohc.mode",
732 FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x30,
737 { "SN(lsb)","rohc.sn",
738 FT_UINT16, BASE_HEX, NULL, 0x0fff,
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,
748 { &hf_rohc_rtp_opt_len,
749 { "Option length","rohc.rtp.opt_length",
750 FT_UINT8, BASE_DEC, NULL, 0x0f,
756 FT_UINT8, BASE_HEX, NULL, 0x0,
760 { &hf_rohc_rtp_opt_sn,
761 { "SN","rohc.opt.sn",
762 FT_UINT8, BASE_HEX, NULL, 0x0,
767 { "Profile","rohc.profile",
768 FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
773 { "D - Dynamic chain","rohc.d",
774 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01,
778 { &hf_rohc_rtp_version,
779 { "Version","rohc.rtp.version",
780 FT_UINT8, BASE_DEC, VALS(rohc_rtp_version_vals), 0xf0,
784 { &hf_rohc_rtp_protocol,
785 { "Protocol","rohc.rtp.protocol",
786 FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&ipproto_val_ext), 0x0,
790 { &hf_rohc_rtp_ipv4_src,
791 { "Source address","rohc.rtp.ipv4_src",
792 FT_IPv4, BASE_NONE, NULL, 0x0,
796 { &hf_rohc_rtp_ipv4_dst,
797 { "Destination address","rohc.rtp.ipv4_dst",
798 FT_IPv4, BASE_NONE, NULL, 0x0,
802 { &hf_rohc_rtp_udp_src_port,
803 { "Source Port","rohc.rtp.udp_src_port",
804 FT_UINT16, BASE_DEC, NULL, 0x0,
808 { &hf_rohc_rtp_udp_dst_port,
809 { "Destination Port","rohc.rtp.udp_dst_port",
810 FT_UINT16, BASE_DEC, NULL, 0x0,
815 { "SSRC","rohc.rtp.ssrc",
816 FT_UINT32, BASE_HEX, NULL, 0x0,
821 { "Type of Service","rohc.rtp.tos",
822 FT_UINT8, BASE_HEX, NULL, 0x0,
827 { "Time to Live","rohc.rtp.ttl",
828 FT_UINT8, BASE_DEC, NULL, 0x0,
833 { "Identification","rohc.rtp.rtp.id",
834 FT_UINT16, BASE_HEX, NULL, 0x0,
839 { "Don't Fragment(DF)","rohc.rtp.df",
840 FT_BOOLEAN, 8, NULL, 0x80,
845 { "RND(IP-ID behaves randomly)","rohc.rtp.rnd",
846 FT_BOOLEAN, 8, NULL, 0x40,
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
856 { &hf_rohc_rtp_checksum,
857 { "Checksum","rohc.rtp.checksum",
858 FT_UINT16, BASE_HEX, NULL, 0x0,
863 { "version","rohc.rtp.v",
864 FT_UINT8, BASE_DEC, NULL, 0xc0,
869 { "Padding(P)","rohc.rtp.p",
870 FT_BOOLEAN, 8, NULL, 0x20,
875 { "RX","rohc.rtp.rx",
876 FT_BOOLEAN, 8, NULL, 0x10,
881 { "CC","rohc.rtp.cc",
882 FT_UINT8, BASE_DEC, NULL, 0x0f,
883 "CSRC counter from original RTP header" , HFILL
887 { "Marker Bit (M)","rohc.rtp.m",
888 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
893 { "Payload Type(PT)","rohc.rtp.pt",
894 FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&rtp_payload_type_vals_ext), 0x7f,
899 { "Sequence Number(SN)","rohc.rtp.sn",
900 FT_UINT16, BASE_HEX, NULL, 0x0,
904 { &hf_rohc_rtp_timestamp,
905 { "RTP Timestamp","rohc.rtp.timestamp",
906 FT_UINT32, BASE_DEC, NULL, 0x0,
912 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
917 { "Mode","rohc.rtp.mode",
918 FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0c,
923 { "TIS","rohc.rtp.tis",
924 FT_BOOLEAN, 8, NULL, 0x02,
929 { "TSS","rohc.rtp.tss",
930 FT_BOOLEAN, 8, NULL, 0x01,
934 { &hf_rohc_rtp_ts_stride,
935 { "TS_Stride","rohc.rtp.ts_stride",
936 FT_UINT32, BASE_DEC, NULL, 0x0,
940 { &hf_rohc_rtp_time_stride,
941 { "Time_Stride","rohc.rtp.time_stride",
942 FT_UINT32, BASE_DEC, NULL, 0x0,
947 { "Variable length","rohc.var_len",
948 FT_UINT8, BASE_DEC, VALS(rohc_var_len_vals), 0x0,
954 /* Setup protocol subtree array */
955 static gint *ett[] = {
961 &ett_rohc_rtp_static,
962 &ett_rohc_rtp_dynamic,
965 /* Register the protocol name and description */
966 proto_rohc = proto_register_protocol("RObust Header Compression (ROHC)", "ROCH", "rohc");
968 register_dissector("rohc", dissect_rohc, proto_rohc);
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));
976 proto_reg_handoff_rohc(void)
978 dissector_handle_t rohc_handle;
980 rohc_handle = create_dissector_handle(dissect_rohc, proto_rohc);
981 dissector_add_uint("ethertype", ETHERTYPE_ROHC, rohc_handle);