aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-rohc.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2011-04-16 11:44:05 +0000
committerAnders Broman <anders.broman@ericsson.com>2011-04-16 11:44:05 +0000
commit0a1437bfac4e7e7a591d4ef2e3fffe50588d5080 (patch)
treef507c325e4e18d2ca3cbc096e23e408300db6ba9 /epan/dissectors/packet-rohc.c
parent960376a8f358c30afd76f9fb9aaf880b3e7c69e4 (diff)
Add a basic ROCH dissector.
Limitations: - Small CID - RTP profile - IPv4 svn path=/trunk/; revision=36659
Diffstat (limited to 'epan/dissectors/packet-rohc.c')
-rw-r--r--epan/dissectors/packet-rohc.c984
1 files changed, 984 insertions, 0 deletions
diff --git a/epan/dissectors/packet-rohc.c b/epan/dissectors/packet-rohc.c
new file mode 100644
index 0000000000..7fce4da1b1
--- /dev/null
+++ b/epan/dissectors/packet-rohc.c
@@ -0,0 +1,984 @@
+/* packet-rohc.c
+ * Routines for RObust Header Compression (ROHC) dissection.
+ *
+ * Copyright 2011, Anders Broman <anders.broman[at]ericsson.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Ref:
+ * http://www.ietf.org/rfc/rfc3095.txt RObust Header Compression (ROHC): Framework and four profiles: RTP, UDP, ESP, and uncompressed
+ * http://datatracker.ietf.org/doc/rfc4815/ RObust Header Compression (ROHC): Corrections and Clarifications to RFC 3095
+ * http://datatracker.ietf.org/doc/rfc5225/ RObust Header Compression Version 2 (ROHCv2): Profiles for RTP, UDP, IP, ESP and UDP-Lite
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <epan/packet.h>
+#include <epan/proto.h>
+#include <epan/etypes.h>
+#include <epan/ipproto.h>
+#include <epan/rtp_pt.h>
+
+
+/* Initialize the protocol and registered fields */
+static int proto_rohc = -1;
+
+
+static int hf_rohc_padding = -1;
+static int hf_rohc_add_cid = -1;
+static int hf_rohc_feedback = -1;
+static int hf_rohc_code = -1;
+static int hf_rohc_size = -1;
+static int hf_rohc_ir_packet = -1;
+static int hf_rohc_ir_dyn_packet = -1;
+static int hf_rohc_small_cid = -1;
+static int hf_rohc_acktype = -1;
+static int hf_rohc_mode = -1;
+static int hf_rohc_sn = -1;
+static int hf_rohc_rtp_opt_type = -1;
+static int hf_rohc_rtp_opt_len = -1;
+static int hf_rohc_rtp_crc = -1;
+static int hf_rohc_rtp_opt_sn = -1;
+static int hf_rohc_profile = -1;
+static int hf_rohc_d_bit = -1;
+static int hf_rohc_rtp_version = -1;
+static int hf_rohc_rtp_protocol = -1;
+static int hf_rohc_rtp_ipv4_src = -1;
+static int hf_rohc_rtp_ipv4_dst = -1;
+static int hf_rohc_rtp_udp_src_port = -1;
+static int hf_rohc_rtp_udp_dst_port = -1;
+static int hf_rohc_rtp_ssrc = -1;
+static int hf_rohc_rtp_tos = -1;
+static int hf_rohc_rtp_ttl = -1;
+static int hf_rohc_rtp_id = -1;
+static int hf_rohc_rtp_df = -1;
+static int hf_rohc_rtp_rnd = -1;
+static int hf_rohc_rtp_nbo = -1;
+static int hf_rohc_rtp_checksum = -1;
+static int hf_rohc_rtp_v = -1;
+static int hf_rohc_rtp_p = -1;
+static int hf_rohc_rtp_rx = -1;
+static int hf_rohc_rtp_cc = -1;
+static int hf_rohc_rtp_m = -1;
+static int hf_rohc_rtp_pt = -1;
+static int hf_rohc_rtp_sn = -1;
+static int hf_rohc_rtp_timestamp = -1;
+static int hf_rohc_rtp_x = -1;
+static int hf_rohc_rtp_mode = -1;
+static int hf_rohc_rtp_tis = -1;
+static int hf_rohc_rtp_tss = -1;
+static int hf_rohc_rtp_ts_stride = -1;
+static int hf_rohc_rtp_time_stride = -1;
+static int hf_rohc_var_len = -1;
+
+static int ett_rohc = -1;
+static int ett_rohc_fb = -1;
+static int ett_rohc_feedback = -1;
+static int ett_rohc_ir = -1;
+static int ett_rohc_ir_dyn = -1;
+static int ett_rohc_rtp_static = -1;
+static int ett_rohc_rtp_dynamic = -1;
+
+static gboolean g_small_cid = TRUE;
+/* RTP profile and IPv4 hard wired for now */
+static guint8 g_profile = 1;
+static guint8 g_version = 4;
+
+/* ROHC Profiles */
+#define ROHC_PROFILE_RTP 1
+
+static const value_string rohc_profile_vals[] =
+{
+ { 0x0000, "ROHC uncompressed" }, /*RFC 5795*/
+ { 0x0001, "ROHC RTP" }, /*RFC 3095*/
+ { 0x0002, "ROHC UDP" }, /*RFC 3095*/
+ { 0x0003, "ROHC ESP" }, /*RFC 3095*/
+ { 0x0004, "ROHC IP" }, /*RFC 3843*/
+ { 0x0005, "ROHC LLA" }, /*RFC 3242*/
+ { 0x0105, "ROHC LLA with R-mode" }, /*RFC 3408*/
+ { 0x0006, "ROHC TCP" }, /*RFC 4996*/
+ { 0x0007, "ROHC RTP/UDP-Lite" }, /*RFC 4019*/
+ { 0x0008, "ROHC UDP-Lite" }, /*RFC 4019*/
+ { 0x0101, "ROHCv2 RTP" }, /*RFC 5225*/
+ { 0x0102, "ROHCv2 UDP" }, /*RFC 5225*/
+ { 0x0103, "ROHCv2 ESP" }, /*RFC 5225*/
+ { 0x0104, "ROHCv2 IP" }, /*RFC 5225*/
+ { 0x0107, "ROHCv2 RTP/UDP-Lite" }, /*RFC 5225*/
+ { 0x0108, "ROHCv2 UDP-Lite" }, /*RFC 5225*/
+ { 0, NULL },
+};
+
+static const value_string rohc_acktype_vals[] =
+{
+ { 0, "ACK" },
+ { 1, "NACK" },
+ { 2, "STATIC-NACK" },
+ { 3, "reserved (MUST NOT be used. Otherwise unparsable)" },
+ { 0, NULL },
+};
+
+static const value_string rohc_mode_vals[] =
+{
+ { 0, "Reserved" },
+ { 1, "Unidirectional" },
+ { 2, "Bidirectional Optimistic" },
+ { 3, "Bidirectional Reliable" },
+ { 0, NULL },
+};
+
+static const value_string rohc_rtp_opt_type_vals[] =
+{
+ { 1, "CRC" },
+ { 2, "Reject" },
+ { 3, "SN-NOT-VALID" },
+ { 4, "SN" },
+ { 5, "Clock" },
+ { 6, "Jitter" },
+ { 7, "LOSS" },
+ { 0, NULL },
+};
+
+
+
+static const value_string rohc_rtp_version_vals[] =
+{
+ { 4, "IPv4" },
+ { 6, "IPv6" },
+ { 0, NULL },
+};
+
+static const value_string rohc_var_len_vals[] =
+{
+ { 0, "One octet" },
+ { 2, "Two octets" },
+ { 6, "Three octets" },
+ { 7, "Four octets" },
+ { 0, NULL },
+};
+
+
+/* 4.5.6. Self-describing variable-length values */
+static guint32
+get_self_describing_var_len_val(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, guint8 *val_len){
+ guint8 oct;
+ guint32 val;
+ int num_bits, bit_offset = offset <<3;
+
+ oct = tvb_get_guint8(tvb, offset);
+ if((oct&0x80)==0){
+ /* One octet */
+ *val_len = 1;
+ val = (oct&0x7f);
+ proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
+ num_bits = 7;
+ bit_offset++;
+ }else if((oct&0xc0)==0x20){
+ /* Two octets */
+ *val_len = 2;
+ proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 2, ENC_BIG_ENDIAN);
+ bit_offset+=2;
+ num_bits = 14;
+ val = tvb_get_ntohs(tvb, offset)&0x3fff;
+ }else if((oct&0xe0)==0xc0){
+ /* Three octets */
+ *val_len = 3;
+ proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
+ bit_offset+=3;
+ num_bits = 21;
+ val = tvb_get_ntoh24(tvb, offset)&0x1fffff;
+ }else if ((oct&0xe0)==0xe0){
+ /* Four octets */
+ *val_len = 4;
+ proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
+ bit_offset+=3;
+ num_bits = 29;
+ val = tvb_get_ntohl(tvb, offset)&0x1fffffff;
+ }
+ proto_tree_add_bits_item(tree, hf_index, tvb, bit_offset, num_bits, ENC_BIG_ENDIAN);
+
+ return val;
+
+}
+
+static void
+dissect_rohc_feedback_data(tvbuff_t *tvb, proto_tree *tree, int offset, gint16 feedback_data_len, guint8 profile){
+
+ proto_item *ti;
+ proto_tree *rohc_feedback_tree;
+ guint8 opt, opt_len;
+
+
+ if(feedback_data_len==1){
+ /* FEEDBACK-1 */
+ proto_tree_add_text(tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
+ return;
+ }
+ /* FEEDBACK-2 */
+ switch(profile){
+ case 1:
+ ti = proto_tree_add_text(tree, tvb, offset, feedback_data_len, "RTP profile-specific information");
+ rohc_feedback_tree = proto_item_add_subtree(ti, ett_rohc_feedback);
+ proto_tree_add_item(rohc_feedback_tree, hf_rohc_acktype, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(rohc_feedback_tree, hf_rohc_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(rohc_feedback_tree, hf_rohc_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset+=2;
+ feedback_data_len-=2;
+ while(feedback_data_len>0){
+ opt = opt_len = tvb_get_guint8(tvb,offset);
+ opt = opt >> 4;
+ opt_len = opt_len &0x0f;
+ proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_opt_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_opt_len, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ feedback_data_len--;
+ switch(opt){
+ case 1:
+ /* CRC */
+ proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+ case 4:
+ /* SN */
+ proto_tree_add_item(rohc_feedback_tree, hf_rohc_rtp_opt_sn, tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, feedback_data_len, "Option data[Not dissected yet]");
+ break;
+ }
+ feedback_data_len = feedback_data_len - opt_len;
+ offset = offset + opt_len;
+
+ }
+ break;
+ default:
+ ti = proto_tree_add_text(tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
+ rohc_feedback_tree = proto_item_add_subtree(ti, ett_rohc_feedback);
+ proto_tree_add_item(rohc_feedback_tree, hf_rohc_acktype, tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+ }
+}
+static void
+dissect_rohc_ir_rtp_profile_dynamic(tvbuff_t *tvb, proto_tree *tree, int offset, guint8 version){
+
+ proto_item *item;
+ proto_tree *sub_tree;
+ guint8 oct, rx, cc, val_len;
+ int i, start_offset;
+
+ start_offset = offset;
+ item = proto_tree_add_text(tree, tvb, offset, 0, "RTP Profile Dynamic Chain");
+ sub_tree = proto_item_add_subtree(item, ett_rohc_rtp_dynamic);
+
+ switch(version){
+ case 4:
+ /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
+ * Dynamic part:
+ */
+ /* Type of Service */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_tos, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ /* Time to Live */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ /* Identification */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset+=2;
+ /* +---+---+---+---+---+---+---+---+
+ * | DF|RND|NBO| 0 |
+ * +---+---+---+---+---+---+---+---+
+ */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_df, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_rnd, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_nbo, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ break;
+ case 6:
+ proto_tree_add_text(sub_tree, tvb, offset, -1, "Not dissected yet");
+ return;
+ break;
+ default:
+ break;
+ }
+
+ /* 5.7.7.5. Initialization of UDP Header
+ * Dynamic part:
+ * Checksum
+ */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset+=2;
+
+ /* 5.7.7.6. Initialization of RTP Header
+ * Dynamic part:
+ * Checksum
+ * P, X, CC, PT, M, sequence number, timestamp, timestamp stride,
+ * CSRC identifiers.
+ *
+ * 0 1 2 3 4 5 6 7
+ * +---+---+---+---+---+---+---+---+
+ * | V=2 | P | RX| CC | (RX is NOT the RTP X bit)
+ * +---+---+---+---+---+---+---+---+
+ * | M | PT |
+ * +---+---+---+---+---+---+---+---+
+ * / RTP Sequence Number / 2 octets
+ * +---+---+---+---+---+---+---+---+
+ * / RTP Timestamp (absolute) / 4 octets
+ * +---+---+---+---+---+---+---+---+
+ * / Generic CSRC list / variable length
+ * +---+---+---+---+---+---+---+---+
+ * : Reserved | X | Mode |TIS|TSS: if RX = 1
+ * +---+---+---+---+---+---+---+---+
+ * : TS_Stride : 1-4 octets, if TSS = 1
+ * +---+---+---+---+---+---+---+---+
+ * : Time_Stride : 1-4 octets, if TIS = 1
+ * +---+---+---+---+---+---+---+---+
+ */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_v, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_p, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_rx, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_cc, tvb, offset, 1, ENC_BIG_ENDIAN);
+ oct = tvb_get_guint8(tvb,offset);
+ cc = oct & 0x0f;
+ rx = (oct >> 4)& 0x01;
+ offset++;
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_m, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_pt, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset+=2;
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_timestamp, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset+=4;
+ if(cc > 0){
+ /* Dissect Generic CSRC list here */
+ for (i = 0; i < cc; i++ ) {
+ proto_tree_add_text(sub_tree, tvb, offset, 4, "CSRC item %u",i+1);
+ offset+=4;
+ }
+ }
+ /* : Reserved | X | Mode |TIS|TSS: if RX = 1 */
+ if(rx==0){
+ proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
+ return;
+ }
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_x, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_tis, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_tss, tvb, offset, 1, ENC_BIG_ENDIAN);
+ oct = tvb_get_guint8(tvb,offset);
+ offset++;
+ /* TS_Stride : 1-4 octets, if TSS = 1 */
+ if((oct&0x01)== 1){
+ /* TS_Stride encoded as
+ * 4.5.6. Self-describing variable-length values
+ */
+ get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_rtp_ts_stride, &val_len);
+ offset = offset + val_len;
+ }
+
+ /* Time_Stride : 1-4 octets, if TIS = 1 */
+ if((oct&0x02)== 1){
+ /* Time_Stride encoded as
+ * 4.5.6. Self-describing variable-length values
+ */
+ val_len = 0;
+ get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_rtp_time_stride, &val_len);
+ offset = offset + val_len;
+ }
+
+ proto_item_set_len(item, offset - start_offset);
+ proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
+
+}
+static void
+dissect_rohc_ir_rtp_profile_static(tvbuff_t *tvb, proto_tree *tree, int offset, gboolean d){
+
+ proto_item *item;
+ proto_tree *sub_tree;
+ guint8 version;
+ int start_offset;
+
+ start_offset = offset;
+ item = proto_tree_add_text(tree, tvb, offset, 0, "RTP Profile Static Chain");
+ sub_tree = proto_item_add_subtree(item, ett_rohc_rtp_static);
+
+ version = tvb_get_guint8(tvb,offset)>>4;
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
+ switch(version){
+ case 4:
+ /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
+ * Static part:
+ */
+ offset++;
+ /* Protocol */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ /* Source Address */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_ipv4_src, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset+=4;
+ /* Destination Address */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_ipv4_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset+=4;
+ break;
+ case 6:
+ /* 5.7.7.3. Initialization of IPv6 Header [IPv6]*/
+ proto_tree_add_text(tree, tvb, offset, -1, "Not dissected yet");
+ /* TODO: Short term, Calculate length and continue? */
+ return;
+ break;
+ default:
+ proto_tree_add_text(sub_tree, tvb, offset, -1, "Error unknown version, only 4 or 6 allowed");
+ return;
+ }
+ /* 5.7.7.5. Initialization of UDP Header [RFC-768].
+ * Static part
+ */
+ /* Source Port */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_udp_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset+=2;
+ /* Destination Port */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_udp_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset+=2;
+
+
+ /* 5.7.7.6. Initialization of RTP Header [RTP]. */
+ /* SSRC */
+ proto_tree_add_item(sub_tree, hf_rohc_rtp_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset+=4;
+ proto_item_set_len(item, offset - start_offset);
+
+ /* D: D = 1 indicates that the dynamic chain is present. */
+ if(d==TRUE){
+ dissect_rohc_ir_rtp_profile_dynamic(tvb, tree, offset, version);
+ }else{
+ proto_tree_add_text(tree, tvb, offset, -1, "RTP data");
+ }
+}
+
+
+static void
+dissect_rohc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti, *item, *ir_item;
+ proto_tree *rohc_tree, *ir_tree, *sub_tree;
+ int offset = 0, length, x_bit_offset;
+ guint8 oct, code, size , cid, profile;
+ gint16 feedback_data_len;
+ gboolean is_add_cid = FALSE, d = FALSE;
+
+ length = tvb_length(tvb);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ROHC");
+ col_clear(pinfo->cinfo, COL_INFO);
+ /*if (tree) {*/
+ ti = proto_tree_add_item(tree, proto_rohc, tvb, 0, -1, ENC_BIG_ENDIAN);
+ rohc_tree = proto_item_add_subtree(ti, ett_rohc);
+ /* 1) If the first octet is a Padding Octet (11100000),
+ * strip away all initial Padding Octets and goto next step.
+ */
+ if(g_small_cid){
+ item = proto_tree_add_text(rohc_tree, tvb, offset, -1, "Small CID configured");
+ PROTO_ITEM_SET_GENERATED(item);
+ }else{
+ item = proto_tree_add_text(rohc_tree, tvb, offset, -1, "Large CID configured");
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+start_over:
+ cid = 0;
+ oct = tvb_get_guint8(tvb,offset);
+ if(oct== 0xe0){
+ while(oct == 0xe0){
+ offset++;
+ oct = tvb_get_guint8(tvb,offset);
+ }
+ proto_tree_add_item(rohc_tree, hf_rohc_padding, tvb, 0, offset, ENC_BIG_ENDIAN);
+ }
+ /* 2) If the first remaining octet starts with 1110, it is an Add-CID octet:
+ * remember the Add-CID octet; remove the octet.
+ */
+ if((oct&0xf0) == 0xe0){
+ is_add_cid = TRUE;
+ cid = oct & 0x0f;
+ proto_tree_add_item(rohc_tree, hf_rohc_add_cid, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, offset, 1, cid);
+ offset++;
+ oct = tvb_get_guint8(tvb,offset);
+ }
+ /* feedback ? */
+ if((oct&0xf8) == 0xf0){
+ /* 3) If the first remaining octet starts with 11110, and an Add-CID
+ * octet was found in step 2), an error has occurred;
+ * the header MUST be discarded without further action.
+ */
+
+ if(is_add_cid){
+ proto_tree_add_item(rohc_tree, hf_rohc_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
+ col_append_str(pinfo->cinfo, COL_INFO, "Error packet");
+ proto_tree_add_text(rohc_tree, tvb, offset, -1, "Error packet");
+ return;
+ }else{
+ col_append_str(pinfo->cinfo, COL_INFO, "Feedback ");
+ /* 4) If the first remaining octet starts with 11110, and an Add-CID
+ * octet was not found in step 2), this is feedback:
+ * find the size of the feedback data, call it s;
+ * remove the feedback type octet;
+ * remove the Size octet if Code is 0;
+ * send feedback data of length s to the same-side associated
+ * compressor;
+ * if packet exhausted, stop; otherwise goto 2).
+ */
+ item = proto_tree_add_item(rohc_tree, hf_rohc_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
+ sub_tree = proto_item_add_subtree(item, ett_rohc_fb);
+ proto_tree_add_item(sub_tree, hf_rohc_code, tvb, offset, 1, ENC_BIG_ENDIAN);
+ code = oct&0x7;
+ offset++;
+ if(code==0){
+ size = tvb_get_guint8(tvb,offset);
+ proto_tree_add_item(sub_tree, hf_rohc_size, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ }else{
+ size = code;
+ }
+ feedback_data_len = size;
+ if((g_small_cid==TRUE)){
+ /* Check for Add-CID octet */
+ oct = tvb_get_guint8(tvb,offset);
+ if((oct&0xf0) == 0xe0){
+ cid = oct & 0x0f;
+ proto_tree_add_item(sub_tree, hf_rohc_add_cid, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_uint(sub_tree, hf_rohc_small_cid, tvb, offset, 1, cid);
+ offset++;
+ feedback_data_len--;
+ }else{
+ item = proto_tree_add_uint(sub_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ }else{
+ /* Read Large CID here */
+ /* feedback_data_len - "lenght of large CID" */
+ }
+ /* Dissect feedback */
+ dissect_rohc_feedback_data(tvb, sub_tree, offset, feedback_data_len, g_profile);
+ offset = offset + size;
+ if(offset<length)
+ goto start_over;
+ return;
+ }
+ }/*feedback */
+ /* 5) If the first remaining octet starts with 1111111, this is a segment:
+ *
+ */
+ if((oct&0xfe) == 0xfe){
+ col_append_str(pinfo->cinfo, COL_INFO, "Segment");
+ if((g_small_cid==TRUE) && (is_add_cid == FALSE)){
+ item = proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ proto_tree_add_text(rohc_tree, tvb, offset, -1, "Segment");
+ return;
+ }
+ /* 6) Here, it is known that the rest is forward information (unless the
+ * header is damaged).
+ */
+ if((oct&0xfe) == 0xfc){
+ col_append_str(pinfo->cinfo, COL_INFO, "IR packet");
+ if((g_small_cid==TRUE) && (is_add_cid == FALSE)){
+ item = proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ ir_item = proto_tree_add_item(rohc_tree, hf_rohc_ir_packet, tvb, offset, 1, ENC_BIG_ENDIAN);
+ ir_tree = proto_item_add_subtree(ir_item, ett_rohc_ir);
+ d = oct & 0x01;
+ x_bit_offset = offset;
+ offset++;
+ if(g_small_cid==FALSE){
+ /* Handle Large CID:s here */
+ }
+ profile = tvb_get_guint8(tvb,offset);
+ if(profile==ROHC_PROFILE_RTP){
+ proto_tree_add_item(ir_tree, hf_rohc_d_bit, tvb, x_bit_offset, 1, ENC_BIG_ENDIAN);
+ }
+ proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ proto_tree_add_item(ir_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ switch(profile){
+ case ROHC_PROFILE_RTP:
+ dissect_rohc_ir_rtp_profile_static(tvb, ir_tree, offset, d);
+ break;
+ default:
+ proto_tree_add_text(ir_tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
+ break;
+ }
+ return;
+ }
+ if((oct&0xff) == 0xf8){
+ col_append_str(pinfo->cinfo, COL_INFO, "IR-DYN packet");
+ if((g_small_cid==TRUE) && (is_add_cid == FALSE)){
+ item = proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ ir_item = proto_tree_add_item(rohc_tree, hf_rohc_ir_dyn_packet, tvb, offset, 1, ENC_BIG_ENDIAN);
+ ir_tree = proto_item_add_subtree(ir_item, ett_rohc_ir_dyn);
+ if(g_small_cid==FALSE){
+ /* Handle Large CID:s here */
+ }
+ profile = tvb_get_guint8(tvb,offset);
+ proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ proto_tree_add_item(ir_tree, hf_rohc_rtp_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ switch(profile){
+ case ROHC_PROFILE_RTP:
+ /* TODO: Currently IPv4 Hardwired, use conversation info or preference ? */
+ dissect_rohc_ir_rtp_profile_dynamic(tvb, ir_tree, offset, g_version);
+ break;
+ default:
+ proto_tree_add_text(ir_tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
+ break;
+ }
+ return;
+ }
+
+ if((oct&0x80)==0){
+ col_set_str(pinfo->cinfo, COL_INFO, "Paket type 0");
+ }else if ((oct&0xc0)==0x80){
+ col_set_str(pinfo->cinfo, COL_INFO, "Paket type 1");
+ }else if ((oct&0xe0)==0xc0){
+ col_set_str(pinfo->cinfo, COL_INFO, "Paket type 2");
+ }
+ /*}*//* if tree */
+}
+
+void
+proto_register_rohc(void)
+{
+
+ static hf_register_info hf[] =
+ {
+ { &hf_rohc_padding,
+ { "Padding","rohc.pading",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_add_cid,
+ { "Add-CID","rohc.add_cid",
+ FT_UINT8, BASE_HEX, NULL, 0xf0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_feedback,
+ { "Feedback","rohc.feedback",
+ FT_UINT8, BASE_HEX, NULL, 0xf8,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_code,
+ { "Code","rohc.code",
+ FT_UINT8, BASE_DEC, NULL, 0x07,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_size,
+ { "Size","rohc.size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_ir_packet,
+ { "IR packet","rohc.ir_packet",
+ FT_UINT8, BASE_DEC, NULL, 0xfe,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_ir_dyn_packet,
+ { "IR-DYN packet","rohc.ir_dyn_packet",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_small_cid,
+ { "Small CID","rohc.small_cid",
+ FT_UINT8, BASE_DEC, NULL, 0x0f,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_acktype,
+ { "Acktype","rohc.acktype",
+ FT_UINT8, BASE_DEC, VALS(rohc_acktype_vals), 0xc0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_mode,
+ { "Mode","rohc.mode",
+ FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x30,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_sn,
+ { "SN(lsb)","rohc.sn",
+ FT_UINT16, BASE_HEX, NULL, 0x0fff,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_opt_type,
+ { "Option type","rohc.rtp.opt_type",
+ FT_UINT8, BASE_DEC, VALS(rohc_rtp_opt_type_vals), 0xf0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_opt_len,
+ { "Option length","rohc.rtp.opt_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0f,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_crc,
+ { "CRC","rohc.crc",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_opt_sn,
+ { "SN","rohc.opt.sn",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_profile,
+ { "Profile","rohc.profile",
+ FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_d_bit,
+ { "D - Dynamic chain","rohc.d",
+ FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_version,
+ { "Version","rohc.rtp.version",
+ FT_UINT8, BASE_DEC, VALS(rohc_rtp_version_vals), 0xf0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_protocol,
+ { "Protocol","rohc.rtp.protocol",
+ FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&ipproto_val_ext), 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_ipv4_src,
+ { "Source address","rohc.rtp.ipv4_src",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_rohc_rtp_ipv4_dst,
+ { "Destination address","rohc.rtp.ipv4_dst",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_rohc_rtp_udp_src_port,
+ { "Source Port","rohc.rtp.udp_src_port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_udp_dst_port,
+ { "Destination Port","rohc.rtp.udp_dst_port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_ssrc,
+ { "SSRC","rohc.rtp.ssrc",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_tos,
+ { "Type of Service","rohc.rtp.tos",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_ttl,
+ { "Time to Live","rohc.rtp.ttl",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_id,
+ { "Identification","rohc.rtp.rtp.id",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_df,
+ { "Don't Fragment(DF)","rohc.rtp.df",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_rnd,
+ { "RND(IP-ID behaves randomly)","rohc.rtp.rnd",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_nbo,
+ { "Network Byte Order (NBO)","rohc.rtp.nbo",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ "Whether the IP-ID is in Network Byte Order" , HFILL
+ }
+ },
+ { &hf_rohc_rtp_checksum,
+ { "Checksum","rohc.rtp.checksum",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_v,
+ { "version","rohc.rtp.v",
+ FT_UINT8, BASE_DEC, NULL, 0xc0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_p,
+ { "Padding(P)","rohc.rtp.p",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_rx,
+ { "RX","rohc.rtp.rx",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_cc,
+ { "CC","rohc.rtp.cc",
+ FT_UINT8, BASE_DEC, NULL, 0x0f,
+ "CSRC counter from original RTP header" , HFILL
+ }
+ },
+ { &hf_rohc_rtp_m,
+ { "Marker Bit (M)","rohc.rtp.m",
+ FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_pt,
+ { "Payload Type(PT)","rohc.rtp.pt",
+ FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&rtp_payload_type_vals_ext), 0x7f,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_sn,
+ { "Sequence Number(SN)","rohc.rtp.sn",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_timestamp,
+ { "RTP Timestamp","rohc.rtp.timestamp",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_x,
+ { "X","rohc.rtp.x",
+ FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_mode,
+ { "Mode","rohc.rtp.mode",
+ FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0c,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_tis,
+ { "TIS","rohc.rtp.tis",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_tss,
+ { "TSS","rohc.rtp.tss",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_ts_stride,
+ { "TS_Stride","rohc.rtp.ts_stride",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_rtp_time_stride,
+ { "Time_Stride","rohc.rtp.time_stride",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL , HFILL
+ }
+ },
+ { &hf_rohc_var_len,
+ { "Variable length","rohc.var_len",
+ FT_UINT8, BASE_DEC, VALS(rohc_var_len_vals), 0x0,
+ NULL , HFILL
+ }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_rohc,
+ &ett_rohc_fb,
+ &ett_rohc_feedback,
+ &ett_rohc_ir,
+ &ett_rohc_ir_dyn,
+ &ett_rohc_rtp_static,
+ &ett_rohc_rtp_dynamic,
+ };
+
+ /* Register the protocol name and description */
+ proto_rohc = proto_register_protocol("RObust Header Compression (ROHC)", "ROCH", "rohc");
+
+ register_dissector("rohc", dissect_rohc, proto_rohc);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_rohc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_rohc(void)
+{
+ dissector_handle_t rohc_handle;
+
+ rohc_handle = create_dissector_handle(dissect_rohc, proto_rohc);
+ dissector_add_uint("ethertype", ETHERTYPE_ROHC, rohc_handle);
+
+} \ No newline at end of file