HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-rohc.c
blob3dbb7c845e07dc7bb915dec7337582054ba63cee
1 /* packet-rohc.c
2 * Routines for RObust Header Compression (ROHC) dissection.
4 * Copyright 2011, Anders Broman <anders.broman[at]ericsson.com>
5 * Per Liedberg <per.liedberg [at]ericsson.com>
7 * $Id$
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * Ref:
28 * http://www.ietf.org/rfc/rfc3095.txt RObust Header Compression (ROHC): Framework and four profiles: RTP, UDP, ESP, and uncompressed
29 * http://datatracker.ietf.org/doc/rfc4815/ RObust Header Compression (ROHC): Corrections and Clarifications to RFC 3095
30 * http://datatracker.ietf.org/doc/rfc5225/ RObust Header Compression Version 2 (ROHCv2): Profiles for RTP, UDP, IP, ESP and UDP-Lite
33 #include "config.h"
35 #include <glib.h>
36 #include <epan/proto.h>
37 #include <epan/packet.h>
38 #include <epan/etypes.h>
39 #include <epan/ipproto.h>
40 #include <epan/addr_resolv.h>
41 #include <epan/rtp_pt.h>
42 #include <epan/expert.h>
43 #include <epan/wmem/wmem.h>
45 #include "packet-rohc.h"
48 static GHashTable *rohc_cid_hash = NULL;
50 /* Initialize the protocol and registered fields */
51 static int proto_rohc = -1;
54 static int hf_rohc_padding = -1;
55 static int hf_rohc_add_cid = -1;
56 static int hf_rohc_feedback = -1;
57 static int hf_rohc_code = -1;
58 static int hf_rohc_size = -1;
59 static int hf_rohc_ir_packet = -1;
60 static int hf_rohc_ir_dyn_packet = -1;
61 static int hf_rohc_small_cid = -1;
62 static int hf_rohc_large_cid = -1;
63 static int hf_rohc_acktype = -1;
64 static int hf_rohc_mode = -1;
65 static int hf_rohc_sn = -1;
66 static int hf_rohc_profile_spec_octet = -1;
67 static int hf_rohc_fb1_sn = -1;
68 static int hf_rohc_opt_type = -1;
69 static int hf_rohc_opt_len = -1;
70 static int hf_rohc_crc = -1;
71 static int hf_rohc_opt_sn = -1;
72 static int hf_rohc_ext_sn = -1;
73 static int hf_rohc_opt_clock = -1;
74 static int hf_rohc_opt_jitter = -1;
75 static int hf_rohc_opt_loss = -1;
76 static int hf_rohc_profile = -1;
77 static int hf_rohc_d_bit = -1;
78 static int hf_rohc_ip_version = -1;
79 static int hf_rohc_ip_protocol = -1;
80 static int hf_rohc_static_ipv4 = -1;
81 static int hf_rohc_ipv4_src = -1;
82 static int hf_rohc_ipv4_dst = -1;
83 static int hf_rohc_ipv6_flow = -1;
84 static int hf_rohc_ipv6_nxt_hdr = -1;
85 static int hf_rohc_ipv6_src = -1;
86 static int hf_rohc_ipv6_dst = -1;
87 static int hf_rohc_static_udp = -1;
88 static int hf_rohc_udp_src_port = -1;
89 static int hf_rohc_udp_dst_port = -1;
90 static int hf_rohc_static_rtp = -1;
91 static int hf_rohc_rtp_ssrc = -1;
92 static int hf_rohc_dynamic_ipv4 = -1;
93 static int hf_rohc_dynamic_udp = -1;
94 static int hf_rohc_rtp_tos = -1;
95 static int hf_rohc_rtp_ttl = -1;
96 static int hf_rohc_rtp_id = -1;
97 static int hf_rohc_rtp_df = -1;
98 static int hf_rohc_rtp_rnd = -1;
99 static int hf_rohc_rtp_nbo = -1;
100 static int hf_rohc_dynamic_udp_checksum = -1;
101 static int hf_rohc_dynamic_rtp =-1;
102 static int hf_rohc_rtp_v = -1;
103 static int hf_rohc_rtp_p = -1;
104 static int hf_rohc_rtp_rx = -1;
105 static int hf_rohc_rtp_cc = -1;
106 static int hf_rohc_rtp_m = -1;
107 static int hf_rohc_rtp_pt = -1;
108 static int hf_rohc_rtp_sn = -1;
109 static int hf_rohc_rtp_timestamp = -1;
110 static int hf_rohc_rtp_x = -1;
111 static int hf_rohc_rtp_mode = -1;
112 static int hf_rohc_rtp_tis = -1;
113 static int hf_rohc_rtp_tss = -1;
114 static int hf_rohc_rtp_ts_stride = -1;
115 static int hf_rohc_rtp_time_stride = -1;
116 static int hf_rohc_var_len = -1;
117 static int hf_rohc_ipv6_tc = -1;
118 static int hf_rohc_ipv6_hop_limit = -1;
119 static int hf_rohc_ir_pkt_frame = -1;
120 static int hf_rohc_ir_previous_frame = -1;
121 static int hf_rohc_comp_sn = -1;
122 static int hf_rohc_r_0_crc = -1;
123 static int hf_rohc_x = -1;
124 static int hf_rohc_ts = -1;
125 static int hf_rohc_comp_ip_id = -1;
126 static int hf_rohc_t = -1;
128 static int hf_rohc_compressed_list = -1;
129 static int hf_rohc_compressed_list_et = -1;
130 static int hf_rohc_compressed_list_gp = -1;
131 static int hf_rohc_compressed_list_ps = -1;
132 static int hf_rohc_compressed_list_res = -1;
133 static int hf_rohc_compressed_list_count = -1;
134 static int hf_rohc_compressed_list_cc = -1;
135 static int hf_rohc_compressed_list_xi_1 = -1;
136 static int hf_rohc_compressed_list_gen_id = -1;
137 static int hf_rohc_compressed_list_ref_id = -1;
138 static int hf_rohc_compressed_list_mask_size = -1;
139 static int hf_rohc_compressed_list_ins_bit_mask = -1;
140 static int hf_rohc_compressed_list_rem_bit_mask = -1;
141 static int hf_rohc_spare_bits = -1;
142 static int hf_rohc_ip_id = -1;
143 static int hf_rohc_udp_checksum = -1;
145 static int ett_rohc = -1;
146 static int ett_rohc_conf = -1;
147 static int ett_rohc_fb = -1;
148 static int ett_rohc_feedback = -1;
149 static int ett_rohc_ir = -1;
150 static int ett_rohc_ir_dyn = -1;
151 static int ett_rohc_static_ipv4 = -1;
152 static int ett_rohc_static_udp = -1;
153 static int ett_rohc_static_rtp = -1;
154 static int ett_rohc_rtp_static = -1;
155 static int ett_rohc_rtp_dynamic = -1;
156 static int ett_rohc_dynamic_ipv4 = -1;
157 static int ett_rohc_dynamic_udp = -1;
158 static int ett_rohc_dynamic_rtp = -1;
159 static int ett_rohc_compressed_list = -1;
160 static int ett_rohc_packet = -1;
162 static expert_field ei_rohc_profile_spec_octet = EI_INIT;
163 static expert_field ei_rohc_rohc_opt_clock = EI_INIT;
164 static expert_field ei_rohc_opt_jitter = EI_INIT;
165 static expert_field ei_rohc_feedback_type_2_is_not_applicable_for_uncompressed_profile = EI_INIT;
167 static dissector_handle_t rohc_handle;
169 static dissector_handle_t ip_handle;
170 static dissector_handle_t ipv6_handle;
171 static dissector_handle_t data_handle;
173 typedef struct _rohc_cid_context_t
175 guint16 rohc_ip_version;
176 gboolean large_cid_present;
177 enum rohc_mode mode;
178 enum rohc_d_mode d_mode;
179 gboolean rnd;
180 gboolean udp_checksum_present;
181 guint16 profile;
182 gint prev_ir_frame_number; /* The frame number of the previous IR packet seen */
183 gint ir_frame_number; /* The frame number of the latest IR packet seen */
185 } rohc_cid_context_t;
187 /* ROHC Profiles */
188 #define ROHC_PROFILE_UNCOMPRESSED 0
189 #define ROHC_PROFILE_RTP 1
190 #define ROHC_PROFILE_UDP 2
191 #define ROHC_PROFILE_IP 4
192 #define ROHC_PROFILE_UNKNOWN 0xFFFF
194 static const value_string rohc_profile_vals[] =
196 { 0x0000, "Uncompressed" }, /*RFC 5795*/
197 { 0x0001, "RTP" }, /*RFC 3095*/
198 { 0x0002, "UDP" }, /*RFC 3095*/
199 { 0x0003, "ESP" }, /*RFC 3095*/
200 { 0x0004, "IP" }, /*RFC 3843*/
201 { 0x0005, "LLA" }, /*RFC 3242*/
202 { 0x0105, "LLA with R-mode" }, /*RFC 3408*/
203 { 0x0006, "TCP" }, /*RFC 4996*/
204 { 0x0007, "RTP/UDP-Lite" }, /*RFC 4019*/
205 { 0x0008, "UDP-Lite" }, /*RFC 4019*/
206 { 0x0101, "v2 RTP" }, /*RFC 5225*/
207 { 0x0102, "v2 UDP" }, /*RFC 5225*/
208 { 0x0103, "v2 ESP" }, /*RFC 5225*/
209 { 0x0104, "v2 IP" }, /*RFC 5225*/
210 { 0x0107, "v2 RTP/UDP-Lite" }, /*RFC 5225*/
211 { 0x0108, "v2 UDP-Lite" }, /*RFC 5225*/
212 { 0, NULL },
215 /* IPv4 hard wired for now */
216 static guint16 g_profile = ROHC_PROFILE_UNKNOWN;
217 static guint8 g_version = 4;
219 static const value_string rohc_acktype_vals[] =
221 { 0, "ACK" },
222 { 1, "NACK" },
223 { 2, "STATIC-NACK" },
224 { 3, "reserved (MUST NOT be used. Otherwise unparsable)" },
225 { 0, NULL },
228 static const value_string rohc_mode_vals[] =
230 { 0, "Reserved" },
231 { 1, "Unidirectional" },
232 { 2, "Bidirectional Optimistic" },
233 { 3, "Bidirectional Reliable" },
234 { 0, NULL },
237 static const value_string rohc_opt_type_vals[] =
239 { 1, "CRC" },
240 { 2, "REJECT" },
241 { 3, "SN-NOT-VALID" },
242 { 4, "SN" },
243 { 5, "CLOCK" },
244 { 6, "JITTER" },
245 { 7, "LOSS" },
246 { 0, NULL },
251 static const value_string rohc_ip_version_vals[] =
253 { 4, "IPv4" },
254 { 6, "IPv6" },
255 { 0, NULL },
258 static const value_string rohc_var_len_vals[] =
260 { 0, "One octet" },
261 { 2, "Two octets" },
262 { 6, "Three octets" },
263 { 7, "Four octets" },
264 { 0, NULL },
267 static const value_string compressed_list_encoding_type_vals[] =
269 { 0, "Generic scheme" },
270 { 1, "Insertion only scheme" },
271 { 2, "Removal only scheme" },
272 { 3, "Remove then insert scheme" },
273 { 0, NULL },
276 static const value_string compressed_list_ps_vals[] =
278 { 0, "4-bit XI fields" },
279 { 1, "8-bit XI fields" },
280 { 0, NULL },
283 /* 4.5.6. Self-describing variable-length values */
284 static guint32
285 get_self_describing_var_len_val(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, guint8 *val_len){
286 guint8 oct;
287 guint32 val = 0;
288 int num_bits = 0, bit_offset = offset <<3;
290 oct = tvb_get_guint8(tvb, offset);
291 if((oct&0x80)==0){
292 /* One octet */
293 *val_len = 1;
294 val = (oct&0x7f);
295 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
296 num_bits = 7;
297 bit_offset++;
298 }else if((oct&0xc0)==0x80){
299 /* Two octets */
300 *val_len = 2;
301 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 2, ENC_BIG_ENDIAN);
302 bit_offset+=2;
303 num_bits = 14;
304 val = tvb_get_ntohs(tvb, offset)&0x3fff;
305 }else if((oct&0xe0)==0xc0){
306 /* Three octets */
307 *val_len = 3;
308 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
309 bit_offset+=3;
310 num_bits = 21;
311 val = tvb_get_ntoh24(tvb, offset)&0x1fffff;
312 }else if ((oct&0xe0)==0xe0){
313 /* Four octets */
314 *val_len = 4;
315 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
316 bit_offset+=3;
317 num_bits = 29;
318 val = tvb_get_ntohl(tvb, offset)&0x1fffffff;
320 proto_tree_add_bits_item(tree, hf_index, tvb, bit_offset, num_bits, ENC_BIG_ENDIAN);
322 return val;
325 /* 5.7.1. Packet type 0: UO-0, R-0, R-0-CRC */
326 static int
327 dissect_rohc_pkt_type_0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint8 pkt_type, rohc_cid_context_t *rohc_cid_context)
329 guint8 val_len = 0;
330 guint64 sn;
331 proto_item *ti;
332 proto_tree *pkt_tree;
334 switch(rohc_cid_context->mode){
335 case RELIABLE_BIDIRECTIONAL: /* R-mode */
336 if((pkt_type&0xc0)==0x00){
337 /* R-0
339 * 0 1 2 3 4 5 6 7
340 * +---+---+---+---+---+---+---+---+
341 * | 0 0 | SN |
342 * +===+===+===+===+===+===+===+===+
344 if (rohc_cid_context->large_cid_present == TRUE) {
345 /* Handle Large CID:s here */
346 get_self_describing_var_len_val(tvb, tree, offset+1, hf_rohc_large_cid, &val_len);
348 col_set_str(pinfo->cinfo, COL_INFO, "R-0");
349 ti = proto_tree_add_text(tree, tvb, offset, 1+val_len, "R-0 packet");
350 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
351 sn = tvb_get_bits8(tvb,(offset<<3)+2, 6);
352 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
353 offset += 1 + val_len;
354 /* Show SN in info column */
355 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", (guint)sn);
356 }else if((pkt_type&0xc0)==0x40){
357 /* R-0-CRC
359 * 0 1 2 3 4 5 6 7
360 * +---+---+---+---+---+---+---+---+
361 * | 0 1 | SN |
362 * +===+===+===+===+===+===+===+===+
363 * |SN | CRC |
364 * +---+---+---+---+---+---+---+---+
366 crumb_spec_t rohc_sn_crumbs[] = {
367 { 2, 6},
368 { 8, 1},
369 { 0, 0}
371 if (rohc_cid_context->large_cid_present == TRUE) {
372 /* Handle Large CID:s here */
373 get_self_describing_var_len_val(tvb, tree, offset+1, hf_rohc_large_cid, &val_len);
374 rohc_sn_crumbs[1].crumb_bit_offset += val_len*8;
376 col_set_str(pinfo->cinfo, COL_INFO, "R-0-CRC");
377 ti = proto_tree_add_text(tree, tvb, offset, 2+val_len, "R-0-CRC packet");
378 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
379 proto_tree_add_split_bits_item_ret_val(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3),
380 rohc_sn_crumbs, &sn);
381 offset += 1 + val_len;
382 proto_tree_add_bits_item(pkt_tree, hf_rohc_r_0_crc, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
383 offset++;
384 /* Show SN in info column */
385 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", (guint)sn);
387 break;
388 case UNIDIRECTIONAL: /* U-mode */
389 /* Fall trough */
390 case OPTIMISTIC_BIDIRECTIONAL: /* O-mode */
391 /* UO-0
393 * 0 1 2 3 4 5 6 7
394 * +---+---+---+---+---+---+---+---+
395 * | 0 | SN | CRC |
396 * +===+===+===+===+===+===+===+===+
398 if (rohc_cid_context->large_cid_present == TRUE) {
399 /* Handle Large CID:s here */
400 get_self_describing_var_len_val(tvb, tree, offset+1, hf_rohc_large_cid, &val_len);
402 col_set_str(pinfo->cinfo, COL_INFO, "UO-0");
403 ti = proto_tree_add_text(tree, tvb, offset, 1+val_len, "UO-0 packet");
404 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
405 sn = tvb_get_bits8(tvb,(offset<<3)+1, 4);
406 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+1, 4, ENC_BIG_ENDIAN);
407 proto_tree_add_bits_item(pkt_tree, hf_rohc_r_0_crc, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
408 offset += 1 + val_len;
409 /* Show SN in info column */
410 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", (guint)sn);
411 break;
412 default:
413 col_set_str(pinfo->cinfo, COL_INFO, "Packet type 0");
414 break;
417 return offset;
421 /* 5.7.5. Extension formats */
422 static int
423 dissect_rohc_ext_format(tvbuff_t *tvb, proto_tree *tree, int offset, guint8 t, rohc_cid_context_t *rohc_cid_context)
425 guint8 ext_type = tvb_get_guint8(tvb, offset) & 0xc0;
427 proto_tree_add_bits_item(tree, hf_rohc_comp_sn, tvb, (offset<<3)+2, 3, ENC_BIG_ENDIAN);
428 if (ext_type == 0x00) {
429 /* Extension 0:
431 * 0 1 2 3 4 5 6 7
432 * +---+---+---+---+---+---+---+---+
433 * | 0 0 | SN | +T |
434 * +---+---+---+---+---+---+---+---+
436 if ((t == 0) || (rohc_cid_context->profile == ROHC_PROFILE_UDP)) {
437 proto_tree_add_bits_item(tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
438 } else {
439 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
441 offset++;
442 } else if (ext_type == 0x40) {
443 /* Extension 1:
445 * +---+---+---+---+---+---+---+---+
446 * | 0 1 | SN | +T |
447 * +---+---+---+---+---+---+---+---+
448 * | -T |
449 * +---+---+---+---+---+---+---+---+
451 if (rohc_cid_context->profile == ROHC_PROFILE_UDP) {
452 proto_tree_add_bits_item(tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
453 offset++;
454 }else if (t == 0) {
455 proto_tree_add_bits_item(tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
456 offset++;
457 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
458 } else if (t == 1) {
459 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
460 offset++;
461 proto_tree_add_bits_item(tree, hf_rohc_comp_ip_id, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
462 } else {
463 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
464 offset++;
465 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
467 offset++;
468 } else if (ext_type == 0x80) {
469 /* Extension 2:
471 * +---+---+---+---+---+---+---+---+
472 * | 1 0 | SN | +T |
473 * +---+---+---+---+---+---+---+---+
474 * | +T |
475 * +---+---+---+---+---+---+---+---+
476 * | -T |
477 * +---+---+---+---+---+---+---+---+
479 if (rohc_cid_context->profile == ROHC_PROFILE_UDP) {
480 proto_tree_add_bits_item(tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
481 offset += 2;
482 proto_tree_add_bits_item(tree, hf_rohc_comp_ip_id, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
483 }else if (t == 0) {
484 proto_tree_add_bits_item(tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
485 offset += 2;
486 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
487 } else if (t == 1) {
488 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
489 offset += 2;
490 proto_tree_add_bits_item(tree, hf_rohc_comp_ip_id, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
491 } else {
492 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
493 offset += 2;
494 proto_tree_add_bits_item(tree, hf_rohc_ts, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
496 offset++;
497 } else {
498 proto_tree_add_text(tree, tvb, offset, -1, "extension 3[Not dissected yet]");
499 if (tvb_length_remaining(tvb, offset) > 0)
500 offset += tvb_length_remaining(tvb, offset);
502 return offset;
505 /* 5.7.2. Packet type 1 (R-mode): R-1, R-1-TS, R-1-ID */
506 static int
507 dissect_rohc_pkt_type_1_r_mode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, rohc_cid_context_t *rohc_cid_context)
509 proto_item *ti;
510 proto_tree *pkt_tree;
511 guint8 val_len = 0, x, sn, t = 0xff;
512 int start_offset = offset;
514 if (rohc_cid_context->large_cid_present == TRUE) {
515 /* Handle Large CID:s here */
516 get_self_describing_var_len_val(tvb, tree, offset+1, hf_rohc_large_cid, &val_len);
519 if ((rohc_cid_context->rohc_ip_version != 4) ||
520 (rohc_cid_context->rnd == 1) ||
521 (rohc_cid_context->profile == ROHC_PROFILE_UDP)) {
522 /* R-1 (RTP profile)
524 * 0 1 2 3 4 5 6 7
525 * +---+---+---+---+---+---+---+---+
526 * | 1 0 | SN |
527 * +===+===+===+===+===+===+===+===+
528 * | M | X | TS |
529 * +---+---+---+---+---+---+---+---+
531 /* R-1 (UDP profile)
533 * 0 1 2 3 4 5 6 7
534 * +---+---+---+---+---+---+---+---+
535 * | 1 0 | SN |
536 * +===+===+===+===+===+===+===+===+
537 * | X | IP-ID |
538 * +---+---+---+---+---+---+---+---+
540 col_set_str(pinfo->cinfo, COL_INFO, "R-1");
541 ti = proto_tree_add_text(tree, tvb, offset, -1, "R-1 packet");
542 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
543 sn = tvb_get_bits8(tvb, (offset<<3)+2, 6);
544 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
545 offset += 1 + val_len;
546 /* Show SN in info column */
547 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
548 if (rohc_cid_context->profile == ROHC_PROFILE_UDP) {
549 x= tvb_get_bits8(tvb, (offset<<3), 1);
550 proto_tree_add_bits_item(pkt_tree, hf_rohc_x, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
551 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
552 } else {
553 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
554 x = tvb_get_bits8(tvb, (offset<<3)+1, 1);
555 proto_tree_add_bits_item(pkt_tree, hf_rohc_x, tvb, (offset<<3)+1, 1, ENC_BIG_ENDIAN);
556 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
558 offset++;
559 } else {
560 t = tvb_get_bits8(tvb, ((offset+1+val_len)<<3)+2, 1);
561 if (t == 0) {
562 /* R-1-ID
564 * 0 1 2 3 4 5 6 7
565 * +---+---+---+---+---+---+---+---+
566 * | 1 0 | SN |
567 * +===+===+===+===+===+===+===+===+
568 * | M | X |T=0| IP-ID |
569 * +---+---+---+---+---+---+---+---+
571 col_set_str(pinfo->cinfo, COL_INFO, "R-1-ID");
572 ti = proto_tree_add_text(tree, tvb, offset, -1, "R-1-ID packet");
573 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
574 } else {
575 /* R-1-TS
577 * 0 1 2 3 4 5 6 7
578 * +---+---+---+---+---+---+---+---+
579 * | 1 0 | SN |
580 * +===+===+===+===+===+===+===+===+
581 * | M | X |T=1| TS |
582 * +---+---+---+---+---+---+---+---+
584 col_set_str(pinfo->cinfo, COL_INFO, "R-1-TS");
585 ti = proto_tree_add_text(tree, tvb, offset, -1, "R-1-TS packet");
586 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
588 sn = tvb_get_bits8(tvb, (offset<<3)+2, 6);
589 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
590 offset += 1 + val_len;
591 /* Show SN in info column */
592 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
593 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
594 x = tvb_get_bits8(tvb, (offset<<3)+1, 1);
595 proto_tree_add_bits_item(pkt_tree, hf_rohc_x, tvb, (offset<<3)+1, 1, ENC_BIG_ENDIAN);
596 proto_tree_add_bits_item(pkt_tree, hf_rohc_t, tvb, (offset<<3)+2, 1, ENC_BIG_ENDIAN);
597 if (t == 0) {
598 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
599 } else {
600 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
602 offset++;
604 if (x) {
605 offset = dissect_rohc_ext_format(tvb, pkt_tree, offset, t, rohc_cid_context);
607 proto_item_set_len(ti, offset-start_offset);
609 return offset;
612 /* 5.7.3. Packet type 1 (U/O-mode): UO-1, UO-1-ID, UO-1-TS */
613 static int
614 dissect_rohc_pkt_type_1_u_o_mode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, rohc_cid_context_t *rohc_cid_context)
616 proto_item *ti;
617 proto_tree *pkt_tree;
618 guint8 val_len = 0, x = 0, sn, t = 0xff;
619 int start_offset = offset;
621 if (rohc_cid_context->large_cid_present == TRUE) {
622 /* Handle Large CID:s here */
623 get_self_describing_var_len_val(tvb, tree, offset+1, hf_rohc_large_cid, &val_len);
626 if ((rohc_cid_context->rohc_ip_version != 4) ||
627 (rohc_cid_context->rnd == 1) ||
628 (rohc_cid_context->profile == ROHC_PROFILE_UDP)) {
629 /* UO-1 (RTP profile)
631 * 0 1 2 3 4 5 6 7
632 * +---+---+---+---+---+---+---+---+
633 * | 1 0 | TS |
634 * +===+===+===+===+===+===+===+===+
635 * | M | SN | CRC |
636 * +---+---+---+---+---+---+---+---+
638 /* UO-1 (UDP profile)
640 * 0 1 2 3 4 5 6 7
641 * +---+---+---+---+---+---+---+---+
642 * | 1 0 | IP-ID |
643 * +===+===+===+===+===+===+===+===+
644 * | SN | CRC |
645 * +---+---+---+---+---+---+---+---+
647 col_set_str(pinfo->cinfo, COL_INFO, "UO-1");
648 ti = proto_tree_add_text(tree, tvb, offset, -1, "UO-1 packet");
649 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
650 if (rohc_cid_context->profile == ROHC_PROFILE_UDP) {
651 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
652 offset += 1 + val_len;
653 sn = tvb_get_bits8(tvb, (offset<<3), 5);
654 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3), 5, ENC_BIG_ENDIAN);
655 } else {
656 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
657 offset += 1 + val_len;
658 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
659 sn = tvb_get_bits8(tvb, (offset<<3)+1, 4);
660 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+1, 4, ENC_BIG_ENDIAN);
662 /* Show SN in info column */
663 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
664 proto_tree_add_bits_item(pkt_tree, hf_rohc_crc, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
665 offset++;
666 } else {
667 t = tvb_get_bits8(tvb, ((offset)<<3)+2, 1);
668 if (t == 0) {
669 /* UO-1-ID
671 * 0 1 2 3 4 5 6 7
672 * +---+---+---+---+---+---+---+---+
673 * | 1 0 |T=0| IP-ID |
674 * +===+===+===+===+===+===+===+===+
675 * | X | SN | CRC |
676 * +---+---+---+---+---+---+---+---+
678 col_set_str(pinfo->cinfo, COL_INFO, "UO-1-ID");
679 ti = proto_tree_add_text(tree, tvb, offset, -1, "UO-1-ID packet");
680 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
681 proto_tree_add_bits_item(pkt_tree, hf_rohc_t, tvb, (offset<<3)+2, 1, ENC_BIG_ENDIAN);
682 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
683 offset += 1 + val_len;
684 x = tvb_get_bits8(tvb, (offset<<3), 1);
685 proto_tree_add_bits_item(pkt_tree, hf_rohc_x, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
686 } else {
687 /* UO-1-TS
689 * 0 1 2 3 4 5 6 7
690 * +---+---+---+---+---+---+---+---+
691 * | 1 0 |T=1| TS |
692 * +===+===+===+===+===+===+===+===+
693 * | M | SN | CRC |
694 * +---+---+---+---+---+---+---+---+
696 col_set_str(pinfo->cinfo, COL_INFO, "UO-1-TS");
697 ti = proto_tree_add_text(tree, tvb, offset, -1, "UO-1-TS packet");
698 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
699 proto_tree_add_bits_item(pkt_tree, hf_rohc_t, tvb, (offset<<3)+2, 1, ENC_BIG_ENDIAN);
700 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
701 offset += 1 + val_len;
702 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
704 sn = tvb_get_bits8(tvb, (offset<<3)+1, 4);
705 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+1, 4, ENC_BIG_ENDIAN);
706 /* Show SN in info column */
707 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
708 proto_tree_add_bits_item(pkt_tree, hf_rohc_crc, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
709 offset++;
711 if (x) {
712 offset = dissect_rohc_ext_format(tvb, pkt_tree, offset, t, rohc_cid_context);
714 proto_item_set_len(ti, offset-start_offset);
716 return offset;
719 /* 5.7.4. Packet type 2: UOR-2 */
720 static int
721 dissect_rohc_pkt_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, rohc_cid_context_t *rohc_cid_context)
723 proto_item *ti;
724 proto_tree *pkt_tree;
725 guint8 val_len = 0, x, sn, t = 0xff;
726 int start_offset = offset;
728 if (rohc_cid_context->large_cid_present == TRUE) {
729 /* Handle Large CID:s here */
730 get_self_describing_var_len_val(tvb, tree, offset+1, hf_rohc_large_cid, &val_len);
733 if ((rohc_cid_context->rohc_ip_version != 4) ||
734 (rohc_cid_context->rnd == 1) ||
735 (rohc_cid_context->profile == ROHC_PROFILE_UDP)) {
736 /* UOR-2 (RTP profile)
738 * 0 1 2 3 4 5 6 7
739 * +---+---+---+---+---+---+---+---+
740 * | 1 1 0 | TS |
741 * +===+===+===+===+===+===+===+===+
742 * |TS | M | SN |
743 * +---+---+---+---+---+---+---+---+
744 * | X | CRC |
745 * +---+---+---+---+---+---+---+---+
747 /* UOR-2 (UDP profile)
749 * 0 1 2 3 4 5 6 7
750 * +---+---+---+---+---+---+---+---+
751 * | 1 1 0 | SN |
752 * +===+===+===+===+===+===+===+===+
753 * | X | CRC |
754 * +---+---+---+---+---+---+---+---+
756 col_set_str(pinfo->cinfo, COL_INFO, "UOR-2");
757 ti = proto_tree_add_text(tree, tvb, offset, -1, "UOR-2 packet");
758 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
759 if (rohc_cid_context->profile == ROHC_PROFILE_UDP) {
760 sn = tvb_get_bits8(tvb, (offset<<3)+3, 5);
761 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
762 offset += 1 + val_len;
763 /* Show SN in info column */
764 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
765 } else {
766 crumb_spec_t rohc_ts_crumbs[] = {
767 { 2, 6},
768 { 8, 1},
769 { 0, 0}
771 rohc_ts_crumbs[1].crumb_bit_offset += val_len*8;
772 proto_tree_add_split_bits_item_ret_val(pkt_tree, hf_rohc_ts, tvb, (offset<<3),
773 rohc_ts_crumbs, NULL);
774 offset += 1 + val_len;
775 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3)+1, 1, ENC_BIG_ENDIAN);
776 sn = tvb_get_bits8(tvb, (offset<<3)+2, 6);
777 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
778 offset++;
779 /* Show SN in info column */
780 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
782 x = tvb_get_bits8(tvb, (offset<<3), 1);
783 proto_tree_add_bits_item(pkt_tree, hf_rohc_x, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
784 proto_tree_add_bits_item(pkt_tree, hf_rohc_crc, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
785 offset++;
786 } else {
787 t = tvb_get_bits8(tvb, ((offset+1+val_len)<<3), 1);
788 if (t == 0) {
789 /* UOR-2-ID
791 * 0 1 2 3 4 5 6 7
792 * +---+---+---+---+---+---+---+---+
793 * | 1 1 0 | IP-ID |
794 * +===+===+===+===+===+===+===+===+
795 * |T=0| M | SN |
796 * +---+---+---+---+---+---+---+---+
797 * | X | CRC |
798 * +---+---+---+---+---+---+---+---+
800 col_set_str(pinfo->cinfo, COL_INFO, "UOR-2-ID");
801 ti = proto_tree_add_text(tree, tvb, offset, -1, "UOR-2-ID packet");
802 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
803 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
804 } else {
805 /* UOR-2-TS
807 * 0 1 2 3 4 5 6 7
808 * +---+---+---+---+---+---+---+---+
809 * | 1 1 0 | TS |
810 * +===+===+===+===+===+===+===+===+
811 * |T=1| M | SN |
812 * +---+---+---+---+---+---+---+---+
813 * | X | CRC |
814 * +---+---+---+---+---+---+---+---+
816 col_set_str(pinfo->cinfo, COL_INFO, "UOR-2-TS");
817 ti = proto_tree_add_text(tree, tvb, offset, -1, "UOR-2-TS packet");
818 pkt_tree = proto_item_add_subtree(ti, ett_rohc_packet);
819 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
821 offset += 1 + val_len;
822 proto_tree_add_bits_item(pkt_tree, hf_rohc_t, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
823 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3)+1, 1, ENC_BIG_ENDIAN);
824 sn = tvb_get_bits8(tvb, (offset<<3)+2, 6);
825 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
826 offset++;
827 /* Show SN in info column */
828 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
829 x = tvb_get_bits8(tvb, (offset<<3), 1);
830 proto_tree_add_bits_item(pkt_tree, hf_rohc_x, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
831 proto_tree_add_bits_item(pkt_tree, hf_rohc_crc, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
832 offset++;
834 if (x) {
835 offset = dissect_rohc_ext_format(tvb, pkt_tree, offset, t, rohc_cid_context);
837 proto_item_set_len(ti, offset-start_offset);
839 return offset;
842 static void
843 dissect_rohc_feedback_data(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, gint16 feedback_data_len,
844 rohc_info *p_rohc_info, guint16 cid, gboolean cid_context){
846 proto_item *ti;
847 proto_tree *rohc_feedback_tree;
848 guint8 opt, opt_len, oct;
849 rohc_cid_context_t *rohc_cid_context = NULL;
850 gint key = cid;
851 guint32 sn;
853 if (!pinfo->fd->flags.visited){
854 rohc_cid_context = (rohc_cid_context_t*)g_hash_table_lookup(rohc_cid_hash, GUINT_TO_POINTER(key));
855 if(rohc_cid_context){
856 p_add_proto_data(pinfo->fd, proto_rohc, 0, rohc_cid_context);
858 }else{
859 rohc_cid_context = (rohc_cid_context_t*)p_get_proto_data(pinfo->fd, proto_rohc, 0);
862 if(!rohc_cid_context){
863 if (cid_context) {
864 /* Reuse info coming from private data */
865 rohc_cid_context = wmem_new(wmem_packet_scope(), rohc_cid_context_t);
866 /*rohc_cid_context->d_mode;*/
867 rohc_cid_context->rnd = p_rohc_info->rnd;
868 rohc_cid_context->udp_checksum_present = p_rohc_info->udp_checksum_present;
869 rohc_cid_context->profile = p_rohc_info->profile;
870 rohc_cid_context->mode = p_rohc_info->mode;
871 rohc_cid_context->rohc_ip_version = p_rohc_info->rohc_ip_version;
872 rohc_cid_context->large_cid_present = p_rohc_info->large_cid_present;
873 rohc_cid_context->prev_ir_frame_number = -1;
874 rohc_cid_context->ir_frame_number = -1;
875 } else {
876 /* No context info, not much we can do */
877 proto_item_append_text(p_rohc_info->last_created_item, " (type %d)", (feedback_data_len==1) ? 1 : 2);
878 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "profile-specific information[Profile not known]");
879 return;
883 if(feedback_data_len==1){
884 /* FEEDBACK-1 */
885 proto_item_append_text(p_rohc_info->last_created_item, " (type 1)");
886 oct = tvb_get_guint8(tvb, offset);
887 switch(rohc_cid_context->profile){
888 case ROHC_PROFILE_UNCOMPRESSED: /* 0 */
889 ti = proto_tree_add_item(tree, hf_rohc_profile_spec_octet, tvb, offset, 1, ENC_BIG_ENDIAN);
890 if (oct) {
891 expert_add_info_format(pinfo, ti, &ei_rohc_profile_spec_octet, "Invalid profile-specific octet value (0x%02X)", oct);
893 break;
894 case ROHC_PROFILE_RTP: /* 1 */
895 case ROHC_PROFILE_UDP: /* 2 */
897 * 0 1 2 3 4 5 6 7
898 * +---+---+---+---+---+---+---+---+
899 * | SN |
900 * +---+---+---+---+---+---+---+---+
904 proto_tree_add_item(tree, hf_rohc_fb1_sn, tvb, offset, 1, ENC_BIG_ENDIAN);
905 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", oct);
906 break;
907 default:
908 proto_tree_add_text(tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
909 break;
911 return;
913 /* FEEDBACK-2 */
914 proto_item_append_text(p_rohc_info->last_created_item, " (type 2)");
915 switch(rohc_cid_context->profile){
916 case ROHC_PROFILE_UNCOMPRESSED: /* 0 */
917 expert_add_info(pinfo, p_rohc_info->last_created_item, &ei_rohc_feedback_type_2_is_not_applicable_for_uncompressed_profile);
918 break;
919 case ROHC_PROFILE_RTP: /* 1 */
920 case ROHC_PROFILE_UDP: /* 2 */
921 ti = proto_tree_add_text(tree, tvb, offset, feedback_data_len, "%s profile-specific information",
922 (rohc_cid_context->profile == ROHC_PROFILE_RTP) ? "RTP" : "UDP");
923 rohc_feedback_tree = proto_item_add_subtree(ti, ett_rohc_feedback);
924 /* Set mode at first pass? Do we need a new context for the following frames?
927 rohc_cid_context->mode = (enum rohc_mode)((tvb_get_guint8(tvb,offset) & 0x30)>>4);
928 proto_tree_add_item(rohc_feedback_tree, hf_rohc_acktype, tvb, offset, 1, ENC_BIG_ENDIAN);
929 proto_tree_add_item(rohc_feedback_tree, hf_rohc_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
930 sn = tvb_get_ntohs(tvb, offset) & 0x0fff;
931 proto_tree_add_item(rohc_feedback_tree, hf_rohc_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
932 offset+=2;
933 feedback_data_len-=2;
935 while(feedback_data_len>0){
936 opt = opt_len = tvb_get_guint8(tvb,offset);
937 opt = opt >> 4;
938 opt_len = opt_len &0x0f;
939 ti = proto_tree_add_item(rohc_feedback_tree, hf_rohc_opt_type, tvb, offset, 1, ENC_BIG_ENDIAN);
940 proto_tree_add_item(rohc_feedback_tree, hf_rohc_opt_len, tvb, offset, 1, ENC_BIG_ENDIAN);
941 offset++;
942 feedback_data_len--;
943 switch(opt){
944 case 1:
945 /* CRC */
946 proto_tree_add_item(rohc_feedback_tree, hf_rohc_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
947 oct = tvb_get_guint8(tvb, offset);
948 col_append_fstr(pinfo->cinfo, COL_INFO, "CRC=%u ", oct);
949 break;
950 case 2:
951 /* REJECT */
952 col_append_str(pinfo->cinfo, COL_INFO, "Reject ");
953 break;
954 case 3:
955 /* SN-Not-Valid */
956 col_append_str(pinfo->cinfo, COL_INFO, "SN-Not-Valid ");
957 break;
958 case 4:
959 /* SN */
960 proto_tree_add_item(rohc_feedback_tree, hf_rohc_opt_sn, tvb, offset, 1, ENC_BIG_ENDIAN);
961 sn = (sn << 8) | tvb_get_guint8(tvb, offset);
962 ti = proto_tree_add_uint(rohc_feedback_tree, hf_rohc_ext_sn, tvb, 0, 0, sn);
963 PROTO_ITEM_SET_GENERATED(ti);
964 break;
965 case 5:
966 /* Clock */
967 if (rohc_cid_context->profile == ROHC_PROFILE_RTP) {
968 proto_tree_add_item(rohc_feedback_tree, hf_rohc_opt_clock, tvb, offset, 1, ENC_BIG_ENDIAN);
969 oct = tvb_get_guint8(tvb, offset);
970 col_append_fstr(pinfo->cinfo, COL_INFO, "Clock=%u ", oct);
971 } else {
972 expert_add_info(pinfo, ti, &ei_rohc_rohc_opt_clock);
974 break;
975 case 6:
976 /* Jitter */
977 if (rohc_cid_context->profile == ROHC_PROFILE_RTP) {
978 proto_tree_add_item(rohc_feedback_tree, hf_rohc_opt_jitter, tvb, offset, 1, ENC_BIG_ENDIAN);
979 oct = tvb_get_guint8(tvb, offset);
980 col_append_fstr(pinfo->cinfo, COL_INFO, "Jitter=%u ", oct);
981 }else {
982 expert_add_info(pinfo, ti, &ei_rohc_opt_jitter);
984 break;
985 case 7:
986 /* Loss */
987 proto_tree_add_item(rohc_feedback_tree, hf_rohc_opt_loss, tvb, offset, 1, ENC_BIG_ENDIAN);
988 oct = tvb_get_guint8(tvb, offset);
989 col_append_fstr(pinfo->cinfo, COL_INFO, "Loss=%u ", oct);
990 break;
991 default:
992 proto_tree_add_text(rohc_feedback_tree, tvb, offset, opt_len, "Unknown Option data");
993 break;
995 feedback_data_len = feedback_data_len - opt_len;
996 offset = offset + opt_len;
999 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1000 break;
1001 default:
1002 ti = proto_tree_add_text(tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
1003 rohc_feedback_tree = proto_item_add_subtree(ti, ett_rohc_feedback);
1004 proto_tree_add_item(rohc_feedback_tree, hf_rohc_acktype, tvb, offset, 1, ENC_BIG_ENDIAN);
1005 break;
1010 const true_false_string rohc_cmp_lst_mask_size_vals = { "15-bit mask", "7-bit mask" };
1013 /* 5.8.6. Compressed list formats */
1014 static int
1015 dissect_compressed_list(int expected_encoding_type _U_, packet_info *pinfo _U_,
1016 proto_tree *tree, tvbuff_t *tvb, int offset)
1018 proto_item *list_ti /* , *et_ti */;
1019 proto_item *list_tree;
1020 guint8 first_byte = tvb_get_guint8(tvb, offset);
1021 guint8 ET, GP , PS, CC , bit_mask_size;
1022 int start_offset = offset;
1024 /* Compressed list root */
1025 list_ti = proto_tree_add_item(tree, hf_rohc_compressed_list, tvb, offset, -1, ENC_NA);
1026 list_tree = proto_item_add_subtree(list_ti, ett_rohc_compressed_list);
1028 /* Fixed fields from first byte */
1029 ET = (first_byte & 0xc0) >> 6;
1030 /* et_ti = proto_tree_add_item(list_tree, hf_rohc_compressed_list_et, tvb, offset, 1, ENC_BIG_ENDIAN); */
1031 proto_tree_add_item(list_tree, hf_rohc_compressed_list_et, tvb, offset, 1, ENC_BIG_ENDIAN);
1032 proto_item_append_text(list_ti, " (type=%d - %s)",
1033 ET, val_to_str_const(ET, compressed_list_encoding_type_vals, "Unknown"));
1034 #if 0
1035 if (ET != expected_encoding_type) {
1036 expert_add_info_format(pinfo, et_ti, PI_MALFORMED, PI_ERROR,
1037 "Wrong compressed list encoding type (expected %d, got %d)",
1038 expected_encoding_type, ET);
1039 return offset+1;
1041 #endif
1042 GP = (first_byte & 0x20) >> 5;
1043 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gp, tvb, offset, 1, ENC_BIG_ENDIAN);
1045 switch (ET) {
1046 case 0:
1047 /* 5.8.6.1 Encoding Type 0 (generic scheme)
1049 * 0 1 2 3 4 5 6 7
1050 * +---+---+---+---+---+---+---+---+
1051 * | ET=0 |GP |PS | CC = m |
1052 * +---+---+---+---+---+---+---+---+
1053 * : gen_id : 1 octet, if GP = 1
1054 * +---+---+---+---+---+---+---+---+
1055 * | XI 1, ..., XI m | m octets, or m * 4 bits
1056 * / --- --- --- ---/
1057 * | : Padding : if PS = 0 and m is odd
1058 * +---+---+---+---+---+---+---+---+
1059 * | |
1060 * / item 1, ..., item n / variable
1061 * | |
1062 * +---+---+---+---+---+---+---+---+
1065 /* PS = (first_byte & 0x10) >> 4;
1066 * PS: Indicates size of XI fields:
1067 * PS = 0 indicates 4-bit XI fields;
1068 * PS = 1 indicates 8-bit XI fields.
1070 PS = (first_byte & 0x10) >> 4;
1071 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ps, tvb, offset, 1, ENC_BIG_ENDIAN);
1073 /* CC: CSRC counter from original RTP header. */
1074 CC = first_byte & 0x0f;
1075 proto_tree_add_item(list_tree, hf_rohc_compressed_list_cc, tvb, offset, 1, ENC_BIG_ENDIAN);
1076 offset++;
1078 /* GP: Indicates presence of gen_id field. */
1079 if (GP) {
1080 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gen_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1081 offset++;
1083 if(CC!=0){
1084 /* TODO: calculate how many bytes to skip for items */
1086 * XI 1, ..., XI m: m XI items. The format of an XI item is as
1087 * follows:
1089 * +---+---+---+---+
1090 * PS = 0: | X | Index |
1091 * +---+---+---+---+
1093 * 0 1 2 3 4 5 6 7
1094 * +---+---+---+---+---+---+---+---+
1095 * PS = 1: | X | Index |
1096 * +---+---+---+---+---+---+---+---+
1098 * X = 1 indicates that the item corresponding to the Index
1099 * is sent in the item 0, ..., item n list.
1100 * X = 0 indicates that the item corresponding to the Index is
1101 * not sent.
1103 if(PS){
1104 /* PS = 1 indicates 8-bit XI fields. */
1105 }else{
1106 /* PS = 0 indicates 4-bit XI fields; */
1110 break;
1112 case 1:
1114 * 5.8.6.2. Encoding Type 1 (insertion only scheme)
1116 * 0 1 2 3 4 5 6 7
1117 * +---+---+---+---+---+---+---+---+
1118 * | ET=1 |GP |PS | XI 1 |
1119 * +---+---+---+---+---+---+---+---+
1120 * : gen_id : 1 octet, if GP = 1
1121 * +---+---+---+---+---+---+---+---+
1122 * | ref_id |
1123 * +---+---+---+---+---+---+---+---+
1124 * / insertion bit mask / 1-2 octets
1125 * +---+---+---+---+---+---+---+---+
1126 * | XI list | k octets, or (k - 1) * 4 bits
1127 * / --- --- --- ---/
1128 * | : Padding : if PS = 0 and k is even
1129 * +---+---+---+---+---+---+---+---+
1130 * | |
1131 * / item 1, ..., item n / variable
1132 * | |
1133 * +---+---+---+---+---+---+---+---+
1136 PS = (first_byte & 0x10) >> 4;
1137 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ps, tvb, offset, 1, ENC_BIG_ENDIAN);
1138 /* XI 1: When PS = 0, the first 4-bit XI item is placed here.
1139 * When PS = 1, the field is set to zero when sending, and
1140 * ignored when receiving.
1142 if(PS==0){
1143 proto_tree_add_item(list_tree, hf_rohc_compressed_list_xi_1, tvb, offset, 1, ENC_BIG_ENDIAN);
1145 offset++;
1146 /* GP: Indicates presence of gen_id field. */
1147 if (GP) {
1148 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gen_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1149 offset++;
1151 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ref_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1152 offset++;
1154 * insertion bit mask: Bit mask indicating the positions where new
1155 * items are to be inserted. See Insertion Only scheme in
1156 * section 5.8.3. The bit mask can have either of the
1157 * following two formats:
1160 * 0 1 2 3 4 5 6 7
1161 * +---+---+---+---+---+---+---+---+
1162 * | 0 | 7-bit mask | bit 1 is the first bit
1163 * +---+---+---+---+---+---+---+---+
1165 * +---+---+---+---+---+---+---+---+
1166 * | 1 | | bit 1 is the first bit
1167 * +---+ 15-bit mask +
1168 * | | bit 7 is the last bit
1169 * +---+---+---+---+---+---+---+---+
1171 bit_mask_size = (tvb_get_guint8(tvb,offset)&0x80)>>7;
1172 proto_tree_add_item(list_tree, hf_rohc_compressed_list_mask_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1173 if(bit_mask_size){
1174 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_ins_bit_mask, tvb, (offset<<3)+1, 15, ENC_BIG_ENDIAN);
1175 offset+=2;
1176 }else{
1177 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_ins_bit_mask, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
1178 offset++;
1182 * XI list: XI fields for items to be inserted. When the insertion
1183 * bit mask has k ones, the total number of XI fields is k. When
1184 * PS = 1, all XI fields are in the XI list. When PS = 0, the
1185 * first XI field is in the XI 1 field, and the remaining k - 1
1186 * XI fields are in the XI list.
1188 * Padding: Present when PS = 0 and k is even.
1190 /* TODO: */
1191 break;
1192 case 2:
1194 * 5.8.6.3. Encoding Type 2 (removal only scheme)
1196 * 0 1 2 3 4 5 6 7
1197 * +---+---+---+---+---+---+---+---+
1198 * | ET=2 |GP |res| Count |
1199 * +---+---+---+---+---+---+---+---+
1200 * : gen_id : 1 octet, if GP = 1
1201 * +---+---+---+---+---+---+---+---+
1202 * | ref_id |
1203 * +---+---+---+---+---+---+---+---+
1204 * / removal bit mask / 1-2 octets
1205 * +---+---+---+---+---+---+---+---+
1208 proto_tree_add_item(list_tree, hf_rohc_compressed_list_res, tvb, offset, 1, ENC_BIG_ENDIAN);
1209 /* Count: Number of elements in ref_list. */
1210 proto_tree_add_item(list_tree, hf_rohc_compressed_list_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1211 offset++;
1212 /* GP: Indicates presence of gen_id field. */
1213 if (GP) {
1214 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gen_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1215 offset++;
1217 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ref_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1218 offset++;
1220 * removal bit mask: Indicates the elements in ref_list to be
1221 * removed in order to obtain the current list. See section
1222 * 5.8.3. The removal bit mask has the same format as the
1223 * insertion bit mask of section 5.8.6.3.
1226 bit_mask_size = (tvb_get_guint8(tvb,offset)&0x80)>>7;
1227 proto_tree_add_item(list_tree, hf_rohc_compressed_list_mask_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1228 if(bit_mask_size){
1229 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_rem_bit_mask, tvb, (offset<<3)+1, 15, ENC_BIG_ENDIAN);
1230 offset+=2;
1231 }else{
1232 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_rem_bit_mask, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
1233 offset++;
1235 break;
1236 case 3:
1238 * 5.8.6.4. Encoding Type 3 (remove then insert scheme)
1240 * See section 5.8.3 for a description of the Remove then insert
1241 * scheme.
1243 * 0 1 2 3 4 5 6 7
1244 * +---+---+---+---+---+---+---+---+
1245 * | ET=3 |GP |PS | XI 1 |
1246 * +---+---+---+---+---+---+---+---+
1247 * : gen_id : 1 octet, if GP = 1
1248 * +---+---+---+---+---+---+---+---+
1249 * | ref_id |
1250 * +---+---+---+---+---+---+---+---+
1251 * / removal bit mask / 1-2 octets
1252 * +---+---+---+---+---+---+---+---+
1253 * / insertion bit mask / 1-2 octets
1254 * +---+---+---+---+---+---+---+---+
1255 * | XI list | k octets, or (k - 1) * 4 bits
1256 * / --- --- --- ---/
1257 * | : Padding : if PS = 0 and k is even
1258 * +---+---+---+---+---+---+---+---+
1259 * | |
1260 * / item 1, ..., item n / variable
1261 * | |
1262 * +---+---+---+---+---+---+---+---+
1265 PS = (first_byte & 0x10) >> 4;
1266 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ps, tvb, offset, 1, ENC_BIG_ENDIAN);
1267 /* XI 1: When PS = 0, the first 4-bit XI item is placed here.
1268 * When PS = 1, the field is set to zero when sending, and
1269 * ignored when receiving.
1271 if(PS==0){
1272 proto_tree_add_item(list_tree, hf_rohc_compressed_list_xi_1, tvb, offset, 1, ENC_BIG_ENDIAN);
1274 offset++;
1275 /* GP: Indicates presence of gen_id field. */
1276 if (GP) {
1277 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gen_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1278 offset++;
1280 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ref_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1281 offset++;
1284 * removal bit mask: Indicates the elements in ref_list to be
1285 * removed in order to obtain the current list. See section
1286 * 5.8.3. The removal bit mask has the same format as the
1287 * insertion bit mask of section 5.8.6.3.
1290 bit_mask_size = (tvb_get_guint8(tvb,offset)&0x80)>>7;
1291 proto_tree_add_item(list_tree, hf_rohc_compressed_list_mask_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1292 if(bit_mask_size){
1293 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_rem_bit_mask, tvb, (offset<<3)+1, 15, ENC_BIG_ENDIAN);
1294 offset+=2;
1295 }else{
1296 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_rem_bit_mask, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
1297 offset++;
1301 * insertion bit mask: Bit mask indicating the positions where new
1302 * items are to be inserted. See Insertion Only scheme in
1303 * section 5.8.3. The bit mask can have either of the
1304 * following two formats:
1307 * 0 1 2 3 4 5 6 7
1308 * +---+---+---+---+---+---+---+---+
1309 * | 0 | 7-bit mask | bit 1 is the first bit
1310 * +---+---+---+---+---+---+---+---+
1312 * +---+---+---+---+---+---+---+---+
1313 * | 1 | | bit 1 is the first bit
1314 * +---+ 15-bit mask +
1315 * | | bit 7 is the last bit
1316 * +---+---+---+---+---+---+---+---+
1318 bit_mask_size = (tvb_get_guint8(tvb,offset)&0x80)>>7;
1319 proto_tree_add_item(list_tree, hf_rohc_compressed_list_mask_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1320 if(bit_mask_size){
1321 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_ins_bit_mask, tvb, (offset<<3)+1, 15, ENC_BIG_ENDIAN);
1322 offset+=2;
1323 }else{
1324 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_ins_bit_mask, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
1325 offset++;
1327 /* TODO: */
1328 offset++;
1329 break;
1332 proto_item_set_len(list_ti, offset-start_offset);
1334 return offset;
1337 static int
1338 dissect_rohc_ir_rtp_profile_dynamic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1339 int offset, guint8 profile, rohc_cid_context_t *rohc_cid_context){
1341 proto_item *item, *root_ti;
1342 proto_tree *sub_tree = NULL, *dynamic_ipv4_tree, *dynamic_udp_tree, *dynamic_rtp_tree;
1343 guint8 oct, rx, /* cc, */ val_len = 0;
1344 int start_offset, tree_start_offset;
1345 guint8 tos, ttl, nbo;
1346 guint16 id;
1347 /*guint8 contributing_csrcs;*/
1348 guint16 sequence_number;
1349 guint32 timestamp;
1350 #if 0
1351 guint8 tis = 0, tss=0;
1352 guint64 ts_stride = 0;
1353 #endif
1354 start_offset = offset;
1355 switch(profile){
1357 case ROHC_PROFILE_UNCOMPRESSED:
1358 item = proto_tree_add_text(tree, tvb, offset, 0, "Profile 0x0000 Uncompressed");
1359 break;
1361 case ROHC_PROFILE_RTP:
1362 item = proto_tree_add_text(tree, tvb, offset, 0, "Profile 0x0001 RTP Dynamic Chain");
1363 break;
1365 case ROHC_PROFILE_UDP:
1366 item = proto_tree_add_text(tree, tvb, offset, 0, "Profile 0x0002 UDP Dynamic Chain");
1367 break;
1369 case ROHC_PROFILE_IP:
1370 item = proto_tree_add_text(tree, tvb, offset, 0, "Profile 0x0004 IP Dynamic Chain");
1371 break;
1373 default:
1374 proto_tree_add_text(tree, tvb, offset, 0, "Profile not supported");
1375 return -1;
1378 /* IP dynamic*/
1379 /* for all profiles except uncompressed */
1380 if ( (profile != ROHC_PROFILE_UNCOMPRESSED) ) {
1381 sub_tree = proto_item_add_subtree(item, ett_rohc_rtp_dynamic);
1382 switch(rohc_cid_context->rohc_ip_version){
1383 case 4:
1384 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
1385 * Dynamic part:
1387 /* Create dynamic IPv4 subtree */
1388 tree_start_offset = offset;
1389 root_ti = proto_tree_add_item(sub_tree, hf_rohc_dynamic_ipv4, tvb, offset, -1, ENC_NA);
1390 dynamic_ipv4_tree = proto_item_add_subtree(root_ti, ett_rohc_dynamic_ipv4);
1392 /* Type of Service */
1393 tos = tvb_get_guint8(tvb, offset);
1394 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_tos, tvb, offset, 1, ENC_BIG_ENDIAN);
1395 offset++;
1396 /* Time to Live */
1397 ttl = tvb_get_guint8(tvb, offset);
1398 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
1399 offset++;
1400 /* Identification */
1401 id = tvb_get_ntohs(tvb, offset);
1402 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1403 offset+=2;
1404 /* +---+---+---+---+---+---+---+---+
1405 * | DF|RND|NBO| 0 |
1406 * +---+---+---+---+---+---+---+---+
1408 rohc_cid_context->rnd = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
1409 nbo = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
1410 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_df, tvb, offset, 1, ENC_BIG_ENDIAN);
1411 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_rnd, tvb, offset, 1, ENC_BIG_ENDIAN);
1412 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_nbo, tvb, offset, 1, ENC_BIG_ENDIAN);
1413 proto_tree_add_bits_item(dynamic_ipv4_tree, hf_rohc_spare_bits, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
1414 offset++;
1415 /* Set proper length for subtree */
1416 proto_item_set_len(root_ti, offset-tree_start_offset);
1418 /* +---+---+---+---+---+---+---+---+
1419 * / Generic extension header list / variable length
1420 * +---+---+---+---+---+---+---+---+
1421 * Generic extension header list: Encoded according to section
1422 * 5.8.6.1, with all header items present in uncompressed form.
1424 offset = dissect_compressed_list(0, pinfo, dynamic_ipv4_tree, tvb, offset);
1426 /* Add summary to ipv4 root item */
1427 proto_item_append_text(root_ti, " (ToS=%u, TTL=%u, ID=%u, RND=%u, NBO=%u)",
1428 tos, ttl, id, rohc_cid_context->rnd, nbo);
1430 break;
1431 case 6:
1433 /* Dynamic part:
1434 * +---+---+---+---+---+---+---+---+
1435 * | Traffic Class | 1 octet
1436 * +---+---+---+---+---+---+---+---+
1437 * | Hop Limit | 1 octet
1438 * +---+---+---+---+---+---+---+---+
1439 * / Generic extension header list / variable length
1440 * +---+---+---+---+---+---+---+---+
1442 proto_tree_add_item(sub_tree, hf_rohc_ipv6_tc, tvb, offset, 1, ENC_BIG_ENDIAN);
1443 offset++;
1444 proto_tree_add_item(sub_tree, hf_rohc_ipv6_hop_limit, tvb, offset, 1, ENC_BIG_ENDIAN);
1445 offset++;
1446 /* XXX TODO: use the IPv6 dissector to dissect Generic extension header list ?*/
1447 proto_tree_add_text(sub_tree, tvb, offset, -1, "Not dissected yet");
1448 return -1;
1449 default:
1450 break;
1454 /* UDP dynamic*/
1455 if ( (profile == ROHC_PROFILE_UDP) ||
1456 (profile == ROHC_PROFILE_RTP) ) {
1457 /* 5.7.7.5. Initialization of UDP Header
1458 * Dynamic part:
1460 * +---+---+---+---+---+---+---+---+
1461 * / Checksum / 2 octets
1462 * +---+---+---+---+---+---+---+---+
1464 /* Create dynamic UDP subtree */
1465 root_ti = proto_tree_add_item(sub_tree, hf_rohc_dynamic_udp, tvb, offset, 2, ENC_NA);
1466 dynamic_udp_tree = proto_item_add_subtree(root_ti, ett_rohc_dynamic_udp);
1467 id = tvb_get_ntohs(tvb, offset);
1468 rohc_cid_context->udp_checksum_present = id ? TRUE : FALSE;
1469 proto_tree_add_item(dynamic_udp_tree, hf_rohc_dynamic_udp_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
1470 offset +=2;
1471 proto_item_set_len(item, offset - start_offset);
1474 /* RTP dynamic*/
1475 if (profile == ROHC_PROFILE_RTP) {
1476 /* 5.7.7.6. Initialization of RTP Header
1477 * Dynamic part:
1478 * Checksum
1479 * P, X, CC, PT, M, sequence number, timestamp, timestamp stride,
1480 * CSRC identifiers.
1482 * 0 1 2 3 4 5 6 7
1483 * +---+---+---+---+---+---+---+---+
1484 * | V=2 | P | RX| CC | (RX is NOT the RTP X bit)
1485 * +---+---+---+---+---+---+---+---+
1486 * | M | PT |
1487 * +---+---+---+---+---+---+---+---+
1488 * / RTP Sequence Number / 2 octets
1489 * +---+---+---+---+---+---+---+---+
1490 * / RTP Timestamp (absolute) / 4 octets
1491 * +---+---+---+---+---+---+---+---+
1492 * / Generic CSRC list / variable length
1493 * +---+---+---+---+---+---+---+---+
1494 * : Reserved | X | Mode |TIS|TSS: if RX = 1
1495 * +---+---+---+---+---+---+---+---+
1496 * : TS_Stride : 1-4 octets, if TSS = 1
1497 * +---+---+---+---+---+---+---+---+
1498 * : Time_Stride : 1-4 octets, if TIS = 1
1499 * +---+---+---+---+---+---+---+---+
1502 /* Create dynamic RTP subtree */
1503 root_ti = proto_tree_add_item(sub_tree, hf_rohc_dynamic_rtp, tvb, offset, -1, ENC_NA);
1504 dynamic_rtp_tree = proto_item_add_subtree(root_ti, ett_rohc_dynamic_rtp);
1506 tree_start_offset = offset;
1507 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_v, tvb, offset, 1, ENC_BIG_ENDIAN);
1508 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_p, tvb, offset, 1, ENC_BIG_ENDIAN);
1509 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_rx, tvb, offset, 1, ENC_BIG_ENDIAN);
1510 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_cc, tvb, offset, 1, ENC_BIG_ENDIAN);
1511 oct = tvb_get_guint8(tvb,offset);
1512 /* cc = oct & 0x0f; */
1513 rx = (oct >> 4)& 0x01;
1514 offset++;
1515 proto_tree_add_bits_item(dynamic_rtp_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
1516 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_pt, tvb, offset, 1, ENC_BIG_ENDIAN);
1517 offset++;
1518 sequence_number = tvb_get_ntohs(tvb, offset);
1519 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
1520 offset+=2;
1521 timestamp = tvb_get_ntohl(tvb, offset);
1522 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_timestamp, tvb, offset, 4, ENC_BIG_ENDIAN);
1523 offset+=4;
1524 /* RFC 4815
1525 * This field is always at least one octet in size, even if the
1526 * list is empty (as opposed to the CSRC list in the uncompressed RTP
1527 * header, which is not present when the RTP CC field is set to 0).
1529 * Generic CSRC list: CSRC list encoded according to section
1530 * 5.8.6.1, with all CSRC items present.
1531 * FORMAL ADDITION TO RFC 3095:
1533 * "The first octet in the dynamic part of the RTP header contains a
1534 * CC field, as defined in Section 5.7.7.6. A second occurrence
1535 * appears in the 'Generic CSRC list', which is also in the dynamic
1536 * part of the RTP header, where Encoding Type 0 is used according
1537 * to the format defined in RFC 3095-5.8.6.1.
1539 * The compressor MUST set both occurrences of the CC field to the
1540 * same value.
1542 * The decompressor MUST use the value of the CC field from the
1543 * Encoding Type 0 within the Generic CRSC list, and it MUST thus
1544 * ignore the first occurrence of the CC field."
1547 offset = dissect_compressed_list(0, pinfo, dynamic_rtp_tree, tvb, offset);
1548 /* : Reserved | X | Mode |TIS|TSS: if RX = 1 */
1549 if(rx==0){
1550 return offset;
1552 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_x, tvb, offset, 1, ENC_BIG_ENDIAN);
1553 rohc_cid_context->mode = (enum rohc_mode)((tvb_get_guint8(tvb,offset) & 0x0c)>>2);
1554 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
1555 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_tis, tvb, offset, 1, ENC_BIG_ENDIAN);
1556 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_tss, tvb, offset, 1, ENC_BIG_ENDIAN);
1557 oct = tvb_get_guint8(tvb,offset);
1558 offset++;
1559 /* TS_Stride : 1-4 octets, if TSS = 1 */
1560 if((oct&0x01)== 1){
1561 /* TS_Stride encoded as
1562 * 4.5.6. Self-describing variable-length values
1564 get_self_describing_var_len_val(tvb, dynamic_rtp_tree, offset, hf_rohc_rtp_ts_stride, &val_len);
1565 offset = offset + val_len;
1568 /* Time_Stride : 1-4 octets, if TIS = 1 */
1569 if((oct&0x02)== 2){
1570 /* Time_Stride encoded as
1571 * 4.5.6. Self-describing variable-length values
1573 get_self_describing_var_len_val(tvb, dynamic_rtp_tree, offset, hf_rohc_rtp_time_stride, &val_len);
1574 offset = offset + val_len;
1576 /* Set proper length for subtree */
1577 proto_item_set_len(root_ti, offset-tree_start_offset);
1579 /* Add summary to root item */
1580 proto_item_append_text(root_ti, " (seqnum = %u, timestamp = %u)",
1581 sequence_number, timestamp);
1583 proto_item_set_len(item, offset - start_offset);
1585 return offset;
1588 static int
1589 dissect_rohc_ir_rtp_udp_ip_profile_static(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, int offset, gboolean d, guint8 profile, rohc_cid_context_t *rohc_cid_context){
1591 proto_item *item, *ipv4_item, *udp_item, *rtp_item;
1592 proto_tree *sub_tree = NULL, *static_ipv4_tree, *static_udp_tree, *static_rtp_tree;
1593 guint8 version, protocol;
1594 int start_offset, tree_start_offset;
1596 start_offset = offset;
1597 switch(profile){
1599 case ROHC_PROFILE_UNCOMPRESSED:
1600 item = proto_tree_add_text(tree, tvb, offset, 0, "Profile 0x0000 Uncompressed");
1601 break;
1603 case ROHC_PROFILE_RTP:
1604 item = proto_tree_add_text(tree, tvb, offset, 0, "Profile 0x0001 RTP Static Chain");
1605 break;
1607 case ROHC_PROFILE_UDP:
1608 item = proto_tree_add_text(tree, tvb, offset, 0, "Profile 0x0002 UDP Static Chain");
1609 break;
1611 case ROHC_PROFILE_IP:
1612 item = proto_tree_add_text(tree, tvb, offset, 0, "Profile 0x0004 IP Static Chain");
1613 break;
1615 default:
1616 proto_tree_add_text(tree, tvb, offset, 0, "Profile not supported");
1617 return -1;
1620 /* IP static*/
1621 /* for all profiles except uncompressed */
1622 if (profile != ROHC_PROFILE_UNCOMPRESSED) {
1623 sub_tree = proto_item_add_subtree(item, ett_rohc_rtp_static);
1624 version = tvb_get_guint8(tvb,offset)>>4;
1625 proto_tree_add_item(sub_tree, hf_rohc_ip_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1626 rohc_cid_context->rohc_ip_version = version;
1628 switch(version) {
1629 case 4:
1631 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
1632 * Static part:
1634 guint32 source, dest;
1636 offset++;
1637 tree_start_offset = offset;
1638 /* Create static IPv4 subtree */
1639 ipv4_item = proto_tree_add_item(sub_tree, hf_rohc_static_ipv4, tvb, offset, -1, ENC_NA);
1640 static_ipv4_tree = proto_item_add_subtree(ipv4_item, ett_rohc_static_ipv4);
1641 /* Protocol */
1642 protocol = tvb_get_guint8(tvb, offset);
1643 proto_tree_add_item(static_ipv4_tree, hf_rohc_ip_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
1644 offset++;
1645 /* Source Address */
1646 source = tvb_get_ipv4(tvb, offset);
1647 proto_tree_add_item(static_ipv4_tree, hf_rohc_ipv4_src, tvb, offset, 4, ENC_BIG_ENDIAN);
1648 offset+=4;
1649 /* Destination Address */
1650 dest = tvb_get_ipv4(tvb, offset);
1651 proto_tree_add_item(static_ipv4_tree, hf_rohc_ipv4_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
1652 offset+=4;
1653 /* Set proper length for subtree */
1654 proto_item_set_len(ipv4_item, offset-tree_start_offset);
1656 /* Add summary to root item */
1657 proto_item_append_text(ipv4_item, " (prot=%s: %s -> %s)",
1658 val_to_str_ext_const(protocol, &ipproto_val_ext, "Unknown"),
1659 get_hostname(source),
1660 get_hostname(dest));
1662 break;
1663 case 6:
1665 /* 5.7.7.3. Initialization of IPv6 Header [IPv6]*/
1666 /* Static part:
1668 * +---+---+---+---+---+---+---+---+
1669 * | Version = 6 |Flow Label(msb)| 1 octet
1670 * +---+---+---+---+---+---+---+---+
1671 * / Flow Label (lsb) / 2 octets
1672 * +---+---+---+---+---+---+---+---+
1673 * | Next Header | 1 octet
1674 * +---+---+---+---+---+---+---+---+
1675 * / Source Address / 16 octets
1676 * +---+---+---+---+---+---+---+---+
1677 * / Destination Address / 16 octets
1678 * +---+---+---+---+---+---+---+---+
1681 /* Flow Label */
1682 proto_tree_add_item(sub_tree, hf_rohc_ipv6_flow, tvb, offset, 3, ENC_BIG_ENDIAN);
1683 offset+=3;
1685 /* Next Header */
1686 protocol = tvb_get_guint8(tvb, offset);
1687 proto_tree_add_item(sub_tree, hf_rohc_ipv6_nxt_hdr, tvb, offset, 1, ENC_BIG_ENDIAN);
1688 offset++;
1690 /* Source Address */
1691 proto_tree_add_item(sub_tree, hf_rohc_ipv6_src, tvb, offset, 16, ENC_NA);
1692 offset+=16;
1694 /* Destination Address */
1695 proto_tree_add_item(sub_tree, hf_rohc_ipv6_dst, tvb, offset, 16, ENC_NA);
1696 offset+=16;
1698 break;
1700 default:
1701 proto_tree_add_text(sub_tree, tvb, offset, -1, "Error unknown version, only 4 or 6 allowed");
1702 return -1;
1704 } else {
1705 protocol = 0; /* Something other than UDP (which is checked for below) */
1708 if (protocol == IP_PROTO_UDP) {
1709 /* UDP static */
1710 if ((profile == ROHC_PROFILE_RTP) ||
1711 (profile == ROHC_PROFILE_UDP)) {
1712 /* 5.7.7.5. Initialization of UDP Header [RFC-768].
1713 * Static part
1715 guint16 source_port, dest_port, ssrc;
1717 /* Create static UDP subtree */
1718 tree_start_offset = offset;
1719 udp_item = proto_tree_add_item(sub_tree, hf_rohc_static_udp, tvb, offset, -1, ENC_NA);
1720 static_udp_tree = proto_item_add_subtree(udp_item, ett_rohc_static_udp);
1721 /* Source Port */
1722 source_port = tvb_get_ntohs(tvb, offset);
1723 proto_tree_add_item(static_udp_tree, hf_rohc_udp_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1724 offset+=2;
1725 /* Destination Port */
1726 dest_port = tvb_get_ntohs(tvb, offset);
1727 proto_tree_add_item(static_udp_tree, hf_rohc_udp_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1728 offset+=2;
1729 /* Set proper length for subtree */
1730 proto_item_set_len(udp_item, offset-tree_start_offset);
1731 /* Add summary to root item */
1732 proto_item_append_text(udp_item, " (%u -> %u)", source_port, dest_port);
1734 if (profile == ROHC_PROFILE_UDP) {
1735 proto_item_set_len(item, offset - start_offset);
1736 if (d==TRUE) {
1737 offset = dissect_rohc_ir_rtp_profile_dynamic(tvb, pinfo, tree, offset, profile, rohc_cid_context);
1739 return offset;
1742 /* RTP static */
1743 /* 5.7.7.6. Initialization of RTP Header [RTP]. */
1744 /* Create static RTP subtree */
1745 rtp_item = proto_tree_add_item(sub_tree, hf_rohc_static_rtp, tvb, offset, 4, ENC_NA);
1746 static_rtp_tree = proto_item_add_subtree(rtp_item, ett_rohc_static_rtp);
1748 /* SSRC */
1749 ssrc = tvb_get_ntohl(tvb, offset);
1750 proto_tree_add_item(static_rtp_tree, hf_rohc_rtp_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN);
1751 offset += 4;
1753 /* Add summary to root item */
1754 proto_item_append_text(rtp_item, " (SSRC=%u)", ssrc);
1756 proto_item_set_len(item, offset - start_offset);
1758 /* D: D = 1 indicates that the dynamic chain is present. */
1759 if (d==TRUE) {
1760 offset = dissect_rohc_ir_rtp_profile_dynamic(tvb, pinfo, tree, offset, profile, rohc_cid_context);
1763 } else if (profile == ROHC_PROFILE_IP) {
1764 proto_item_set_len(item, offset - start_offset);
1765 if (d==TRUE) {
1766 offset = dissect_rohc_ir_rtp_profile_dynamic(tvb, pinfo, tree, offset, profile, rohc_cid_context);
1768 return offset;
1769 } else {
1770 proto_tree_add_text(sub_tree, tvb, offset, -1, "[Not dissected yet]");
1772 return offset;
1775 static int
1776 dissect_rohc_ir_packet(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
1777 int offset, guint16 cid, gboolean is_add_cid, rohc_info *p_rohc_info)
1779 proto_item *ir_item, *item;
1780 proto_tree *ir_tree;
1781 int ir_item_start;
1782 int x_bit_offset;
1783 gboolean d = FALSE;
1784 guint8 oct, profile, val_len = 0;
1785 gint16 feedback_data_len = 0;
1786 tvbuff_t *next_tvb;
1787 rohc_cid_context_t *rohc_cid_context = NULL;
1789 /* The cid value must have been dissected and valid
1790 * offset must point to the IR octet see below ( | 1 1 1 1 1 1 0 | D | )
1791 * TODO: CRC validation
1795 0 1 2 3 4 5 6 7
1796 --- --- --- --- --- --- --- ---
1797 | Add-CID octet | if for small CIDs and CID != 0
1798 +---+---+---+---+---+---+---+---+
1799 | 1 1 1 1 1 1 0 | D |
1800 +---+---+---+---+---+---+---+---+
1802 / 0-2 octets of CID info / 1-2 octets if for large CIDs
1804 +---+---+---+---+---+---+---+---+
1805 | Profile | 1 octet
1806 +---+---+---+---+---+---+---+---+
1807 | CRC | 1 octet
1808 +---+---+---+---+---+---+---+---+
1810 | Static chain | variable length
1812 +---+---+---+---+---+---+---+---+
1814 | Dynamic chain | present if D = 1, variable length
1816 - - - - - - - - - - - - - - - -
1818 | Payload | variable length
1820 - - - - - - - - - - - - - - - -
1823 oct = tvb_get_guint8(tvb,offset);
1825 if((p_rohc_info->large_cid_present == FALSE) && (is_add_cid == FALSE)){
1826 item = proto_tree_add_uint(tree, hf_rohc_small_cid, tvb, 0, 0, cid);
1827 PROTO_ITEM_SET_GENERATED(item);
1829 ir_item = proto_tree_add_item(tree, hf_rohc_ir_packet, tvb, offset, 1, ENC_BIG_ENDIAN);
1830 ir_tree = proto_item_add_subtree(ir_item, ett_rohc_ir);
1831 ir_item_start = offset;
1832 d = oct & 0x01;
1833 x_bit_offset = offset;
1834 offset++;
1835 if(p_rohc_info->large_cid_present == TRUE){
1836 /* Handle Large CID:s here */
1837 get_self_describing_var_len_val(tvb, ir_tree, offset, hf_rohc_large_cid, &val_len);
1838 offset = offset + val_len;
1841 /* Read profile */
1842 profile = tvb_get_guint8(tvb,offset);
1844 if(profile==ROHC_PROFILE_RTP){
1845 proto_tree_add_item(ir_tree, hf_rohc_d_bit, tvb, x_bit_offset, 1, ENC_BIG_ENDIAN);
1847 proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
1848 offset++;
1850 proto_tree_add_item(ir_tree, hf_rohc_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
1851 offset++;
1853 /* See if we have an entry for this CID
1854 * Update it if we do otherwise create it
1855 * and fill in the info.
1857 if (!pinfo->fd->flags.visited){
1858 gint key = cid;
1859 rohc_cid_context = (rohc_cid_context_t*)g_hash_table_lookup(rohc_cid_hash, GUINT_TO_POINTER(key));
1860 if (rohc_cid_context != NULL){
1861 /* This is not the first IR packet seen*/
1862 gint tmp_prev_ir_frame_number = rohc_cid_context->ir_frame_number;
1863 gint tmp_prev_rohc_ip_version = rohc_cid_context->rohc_ip_version;
1864 gint tmp_prev_mode = rohc_cid_context->mode;
1865 gboolean tmp_prev_rnd = rohc_cid_context->rnd;
1866 gboolean tmp_prev_udp_checksum_present = rohc_cid_context->udp_checksum_present;
1868 /*g_warning("IR pkt found CID %u",cid);*/
1870 rohc_cid_context = wmem_new(wmem_file_scope(), rohc_cid_context_t);
1871 rohc_cid_context->profile = profile;
1872 rohc_cid_context->prev_ir_frame_number = tmp_prev_ir_frame_number;
1873 rohc_cid_context->ir_frame_number = pinfo->fd->num;
1874 rohc_cid_context->rohc_ip_version = tmp_prev_rohc_ip_version;
1875 rohc_cid_context->mode = (enum rohc_mode)tmp_prev_mode;
1876 rohc_cid_context->rnd = tmp_prev_rnd;
1877 rohc_cid_context->udp_checksum_present = tmp_prev_udp_checksum_present;
1878 rohc_cid_context->large_cid_present = p_rohc_info->large_cid_present;
1880 g_hash_table_replace(rohc_cid_hash, GUINT_TO_POINTER(key), rohc_cid_context);
1881 p_add_proto_data(pinfo->fd, proto_rohc, 0, rohc_cid_context);
1882 }else{
1883 rohc_cid_context = wmem_new(wmem_file_scope(), rohc_cid_context_t);
1884 rohc_cid_context->large_cid_present = p_rohc_info->large_cid_present;
1885 /*rohc_cid_context->mode mode;*/
1886 /*rohc_cid_context->d_mode;*/
1887 rohc_cid_context->rnd = FALSE;
1888 rohc_cid_context->udp_checksum_present = FALSE;
1889 rohc_cid_context->profile = profile;
1890 rohc_cid_context->prev_ir_frame_number = -1;
1891 rohc_cid_context->ir_frame_number = pinfo->fd->num;
1892 rohc_cid_context->rohc_ip_version = p_rohc_info->rohc_ip_version;
1893 rohc_cid_context->mode = p_rohc_info->mode;
1895 /*g_warning("IR pkt New CID %u",cid);*/
1897 g_hash_table_insert(rohc_cid_hash, GUINT_TO_POINTER(key), rohc_cid_context);
1898 p_add_proto_data(pinfo->fd, proto_rohc, 0, rohc_cid_context);
1900 }else{
1901 /* get the stored data */
1902 rohc_cid_context = (rohc_cid_context_t*)p_get_proto_data(pinfo->fd, proto_rohc, 0);
1905 switch(profile){
1906 case ROHC_PROFILE_UNCOMPRESSED:
1907 if (tvb_length_remaining(tvb, offset) > 0) {
1908 oct = tvb_get_guint8(tvb, offset);
1909 if ( (oct&0xf0) == 0x60 ) {
1910 next_tvb = tvb_new_subset_remaining(tvb, offset);
1911 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
1912 offset += tvb_length_remaining(tvb, offset);
1914 else if ( (oct&0xf0) == 0x40 ) {
1915 next_tvb = tvb_new_subset_remaining(tvb, offset);
1916 call_dissector(ip_handle, next_tvb, pinfo, tree);
1917 offset += tvb_length_remaining(tvb, offset);
1919 col_prepend_fstr(pinfo->cinfo, COL_PROTOCOL, "ROHC <");
1920 col_append_str(pinfo->cinfo, COL_PROTOCOL, ">");
1922 break;
1923 case ROHC_PROFILE_RTP:
1924 case ROHC_PROFILE_UDP:
1925 case ROHC_PROFILE_IP:
1926 offset = dissect_rohc_ir_rtp_udp_ip_profile_static(tvb, ir_tree, pinfo, offset, d, profile, rohc_cid_context);
1927 break;
1928 default:
1929 proto_tree_add_text(ir_tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
1930 offset = -1;
1931 break;
1934 if (offset != -1) {
1935 /* Set length of IR header */
1936 proto_item_set_len(ir_item, offset-ir_item_start);
1939 return offset;
1942 static int
1943 dissect_rohc_ir_dyn_packet(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
1944 int offset, guint16 cid, gboolean is_add_cid, rohc_info *p_rohc_info)
1946 proto_item *ir_item, *item;
1947 proto_tree *ir_tree;
1948 gint ir_item_start;
1949 guint8 profile, val_len = 0;
1950 gint16 feedback_data_len = 0;
1951 rohc_cid_context_t *rohc_cid_context;
1953 if((p_rohc_info->large_cid_present == FALSE) && (is_add_cid == FALSE)){
1954 item = proto_tree_add_uint(tree, hf_rohc_small_cid, tvb, 0, 0, cid);
1955 PROTO_ITEM_SET_GENERATED(item);
1958 ir_item = proto_tree_add_item(tree, hf_rohc_ir_dyn_packet, tvb, offset, 1, ENC_BIG_ENDIAN);
1959 ir_tree = proto_item_add_subtree(ir_item, ett_rohc_ir_dyn);
1960 ir_item_start = offset;
1961 offset++;
1963 if(p_rohc_info->large_cid_present == TRUE){
1964 /* Handle Large CID:s here */
1965 get_self_describing_var_len_val(tvb, ir_tree, offset, hf_rohc_large_cid, &val_len);
1966 offset = offset + val_len;
1969 profile = tvb_get_guint8(tvb,offset);
1970 proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
1971 offset++;
1973 /* See if we have an entry for this CID
1974 * Update it if we do otherwise create it
1975 * and fill in the info.
1977 if (!pinfo->fd->flags.visited){
1978 gint key = cid;
1979 rohc_cid_context = (rohc_cid_context_t*)g_hash_table_lookup(rohc_cid_hash, GUINT_TO_POINTER(key));
1981 if (rohc_cid_context){
1982 /* This is not the first IR packet seen*/
1983 gint tmp_prev_ir_frame_number = rohc_cid_context->ir_frame_number;
1984 gint tmp_prev_rohc_ip_version = rohc_cid_context->rohc_ip_version;
1985 gint tmp_prev_mode = rohc_cid_context->mode;
1986 gboolean tmp_prev_rnd = rohc_cid_context->rnd;
1987 gboolean tmp_prev_udp_checksum_present = rohc_cid_context->udp_checksum_present;
1989 /*g_warning("IR pkt found CID %u",cid);*/
1991 rohc_cid_context = wmem_new(wmem_file_scope(), rohc_cid_context_t);
1992 rohc_cid_context->profile = profile;
1993 rohc_cid_context->prev_ir_frame_number = tmp_prev_ir_frame_number;
1994 rohc_cid_context->ir_frame_number = pinfo->fd->num;
1995 rohc_cid_context->rohc_ip_version = tmp_prev_rohc_ip_version;
1996 rohc_cid_context->mode = (enum rohc_mode)tmp_prev_mode;
1997 rohc_cid_context->rnd = tmp_prev_rnd;
1998 rohc_cid_context->udp_checksum_present = tmp_prev_udp_checksum_present;
1999 rohc_cid_context->large_cid_present = p_rohc_info->large_cid_present;
2001 g_hash_table_replace(rohc_cid_hash, GUINT_TO_POINTER(key), rohc_cid_context);
2002 p_add_proto_data(pinfo->fd, proto_rohc, 0, rohc_cid_context);
2003 }else{
2004 rohc_cid_context = wmem_new(wmem_file_scope(), rohc_cid_context_t);
2005 /*rohc_cid_context->rohc_ip_version;*/
2006 rohc_cid_context->large_cid_present = p_rohc_info->large_cid_present;
2007 /*rohc_cid_context->mode mode;*/
2008 /*rohc_cid_context->d_mode;*/
2009 rohc_cid_context->rnd = FALSE;
2010 rohc_cid_context->udp_checksum_present = FALSE;
2011 rohc_cid_context->profile = profile;
2012 rohc_cid_context->prev_ir_frame_number = -1;
2013 rohc_cid_context->ir_frame_number = pinfo->fd->num;
2014 rohc_cid_context->mode = p_rohc_info->mode;
2016 /*g_warning("IR pkt New CID %u",cid);*/
2018 g_hash_table_insert(rohc_cid_hash, GUINT_TO_POINTER(key), rohc_cid_context);
2019 p_add_proto_data(pinfo->fd, proto_rohc, 0, rohc_cid_context);
2021 }else{
2022 /* get the stored data */
2023 rohc_cid_context = (rohc_cid_context_t*)p_get_proto_data(pinfo->fd, proto_rohc, 0);
2026 proto_tree_add_item(ir_tree, hf_rohc_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
2027 offset++;
2029 switch(profile){
2030 case ROHC_PROFILE_RTP:
2031 offset = dissect_rohc_ir_rtp_profile_dynamic(tvb, pinfo, ir_tree, offset, profile, rohc_cid_context);
2032 break;
2033 default:
2034 proto_tree_add_text(ir_tree, tvb, offset, feedback_data_len, "profile-specific information[Not dissected yet]");
2035 break;
2038 /* Set length of IR-DYN header */
2039 proto_item_set_len(ir_item, offset-ir_item_start);
2041 return offset;
2044 static int
2045 dissect_rohc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2047 proto_item *ti, *item, *conf_item;
2048 proto_tree *rohc_tree, *sub_tree = NULL, *conf_tree;
2049 int offset = 0, length;
2050 guint8 oct, code, size, val_len = 0;
2051 gint16 feedback_data_len = 0, cid = 0;
2052 gboolean is_add_cid = FALSE;
2053 rohc_info *p_rohc_info = NULL;
2054 rohc_info g_rohc_info;
2055 tvbuff_t *next_tvb=NULL, *payload_tvb;
2056 rohc_cid_context_t *rohc_cid_context = NULL;
2058 if(data == NULL){
2059 g_rohc_info.rohc_compression = FALSE;
2060 g_rohc_info.rohc_ip_version = g_version;
2061 g_rohc_info.cid_inclusion_info = FALSE;
2062 g_rohc_info.large_cid_present = FALSE;
2063 g_rohc_info.mode = RELIABLE_BIDIRECTIONAL;
2064 g_rohc_info.rnd = FALSE;
2065 g_rohc_info.udp_checksum_present = FALSE;
2066 g_rohc_info.profile = g_profile;
2067 g_rohc_info.last_created_item = NULL;
2068 p_rohc_info = &g_rohc_info;
2069 }else{
2070 p_rohc_info = (rohc_info *)data;
2071 memset(&g_rohc_info, 0, sizeof(rohc_info));
2074 length = tvb_length(tvb);
2076 /* If this is ROHC ethertype clear col */
2077 if ( pinfo->src.type == AT_ETHER ){
2078 col_set_str(pinfo->cinfo, COL_INFO, "ROHC");
2079 col_clear(pinfo->cinfo, COL_INFO);
2080 }else{
2081 col_append_str(pinfo->cinfo, COL_PROTOCOL, "|ROHC");
2082 /* Append a space if we add stuff to existing col info */
2083 col_append_str(pinfo->cinfo, COL_INFO, " ");
2085 ti = proto_tree_add_item(tree, proto_rohc, tvb, 0, -1, ENC_NA);
2086 rohc_tree = proto_item_add_subtree(ti, ett_rohc);
2087 /* 1) If the first octet is a Padding Octet (11100000),
2088 * strip away all initial Padding Octets and goto next step.
2091 /* Put configuration data into the tree */
2092 item = proto_tree_add_text(rohc_tree, tvb, offset, 0, "Global Configuration: (%s)", p_rohc_info->large_cid_present ? "Large CID" : "Small CID");
2093 conf_tree = proto_item_add_subtree(item, ett_rohc_conf);
2094 PROTO_ITEM_SET_GENERATED(item);
2095 rohc_cid_context = (rohc_cid_context_t*)p_get_proto_data(pinfo->fd, proto_rohc, 0);
2096 if(rohc_cid_context){
2097 /* Do we have info from an IR frame? */
2098 if(rohc_cid_context->ir_frame_number>0){
2099 conf_item = proto_tree_add_text(conf_tree, tvb, offset, 0, "Configured by IR packet");
2100 PROTO_ITEM_SET_GENERATED(conf_item);
2101 conf_item = proto_tree_add_uint(conf_tree, hf_rohc_ir_pkt_frame, tvb, 0, 0, rohc_cid_context->ir_frame_number);
2102 PROTO_ITEM_SET_GENERATED(conf_item);
2103 if(rohc_cid_context->prev_ir_frame_number>0){
2104 conf_item = proto_tree_add_uint(conf_tree, hf_rohc_ir_previous_frame, tvb, 0, 0, rohc_cid_context->prev_ir_frame_number);
2105 PROTO_ITEM_SET_GENERATED(conf_item);
2107 conf_item = proto_tree_add_text(conf_tree, tvb, offset, 0, "Profile:(%s)", val_to_str_const(rohc_cid_context->profile, rohc_profile_vals, "Unknown"));
2108 PROTO_ITEM_SET_GENERATED(conf_item);
2109 conf_item = proto_tree_add_text(conf_tree, tvb, offset, 0, "IP version:(%s)", val_to_str_const(rohc_cid_context->rohc_ip_version, rohc_ip_version_vals, "Unknown"));
2110 PROTO_ITEM_SET_GENERATED(conf_item);
2111 if(rohc_cid_context->mode == 0){
2112 conf_item = proto_tree_add_text(conf_tree, tvb, offset, 0, "Mode not known");
2113 PROTO_ITEM_SET_GENERATED(conf_item);
2114 }else{
2115 conf_item = proto_tree_add_text(conf_tree, tvb, offset, 0, "Mode:(%s)", val_to_str_const(rohc_cid_context->mode, rohc_mode_vals, "Unknown"));
2116 PROTO_ITEM_SET_GENERATED(conf_item);
2119 }else{
2120 conf_item = proto_tree_add_text(conf_tree, tvb, offset, 0, "No configuration info");
2121 PROTO_ITEM_SET_GENERATED(conf_item);
2125 start_over:
2126 cid = 0;
2127 oct = tvb_get_guint8(tvb,offset);
2128 if(oct== 0xe0){
2129 while(oct == 0xe0){
2130 offset++;
2131 oct = tvb_get_guint8(tvb,offset);
2133 proto_tree_add_item(rohc_tree, hf_rohc_padding, tvb, 0, offset, ENC_NA);
2135 /* 2) If the first remaining octet starts with 1110, it is an Add-CID octet:
2136 * remember the Add-CID octet; remove the octet.
2138 if((oct&0xf0) == 0xe0){
2139 is_add_cid = TRUE;
2140 cid = oct & 0x0f;
2141 proto_tree_add_item(rohc_tree, hf_rohc_add_cid, tvb, offset, 1, ENC_BIG_ENDIAN);
2142 proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, offset, 1, cid);
2143 offset++;
2145 oct = tvb_get_guint8(tvb,offset);
2147 /* feedback ?
2148 * Feedback (begins with 11110)
2150 if((oct&0xf8) == 0xf0){
2151 /* 3) If the first remaining octet starts with 11110, and an Add-CID
2152 * octet was found in step 2), an error has occurred;
2153 * the header MUST be discarded without further action.
2156 int feedback_start = offset;
2158 if(is_add_cid){
2159 p_rohc_info->last_created_item = proto_tree_add_item(rohc_tree, hf_rohc_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
2160 col_append_str(pinfo->cinfo, COL_INFO, "Error packet");
2161 proto_tree_add_text(rohc_tree, tvb, offset, -1, "Error packet");
2162 return tvb_length(tvb);
2163 }else{
2164 col_append_str(pinfo->cinfo, COL_INFO, "Feedback ");
2165 /* 4) If the first remaining octet starts with 11110, and an Add-CID
2166 * octet was not found in step 2), this is feedback:
2167 * find the size of the feedback data, call it s;
2168 * remove the feedback type octet;
2169 * remove the Size octet if Code is 0;
2170 * send feedback data of length s to the same-side associated
2171 * compressor;
2172 * if packet exhausted, stop; otherwise goto 2).
2174 p_rohc_info->last_created_item = proto_tree_add_item(rohc_tree, hf_rohc_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
2175 sub_tree = proto_item_add_subtree(p_rohc_info->last_created_item, ett_rohc_fb);
2176 proto_tree_add_item(sub_tree, hf_rohc_code, tvb, offset, 1, ENC_BIG_ENDIAN);
2177 code = oct&0x7;
2178 offset++;
2179 if(code==0){
2180 size = tvb_get_guint8(tvb,offset);
2181 proto_tree_add_item(sub_tree, hf_rohc_size, tvb, offset, 1, ENC_BIG_ENDIAN);
2182 offset++;
2183 }else{
2184 size = code;
2186 feedback_data_len = size;
2187 if(p_rohc_info->large_cid_present == FALSE){
2188 /* Check for Add-CID octet */
2189 oct = tvb_get_guint8(tvb,offset);
2190 if((oct&0xf0) == 0xe0){
2191 cid = oct & 0x0f;
2192 proto_tree_add_item(sub_tree, hf_rohc_add_cid, tvb, offset, 1, ENC_BIG_ENDIAN);
2193 proto_tree_add_uint(sub_tree, hf_rohc_small_cid, tvb, offset, 1, cid);
2194 offset++;
2195 feedback_data_len--;
2196 }else{
2197 item = proto_tree_add_uint(sub_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
2198 PROTO_ITEM_SET_GENERATED(item);
2200 }else{
2201 /* Read Large CID here */
2202 get_self_describing_var_len_val(tvb, sub_tree, offset, hf_rohc_large_cid, &val_len);
2203 /* feedback_data_len - "length of large CID" */
2204 feedback_data_len = feedback_data_len - val_len;
2205 offset += val_len;
2208 /* Dissect feedback */
2209 dissect_rohc_feedback_data(tvb, sub_tree, pinfo, offset, feedback_data_len, p_rohc_info, cid, p_rohc_info != &g_rohc_info);
2210 offset = offset + size;
2211 if(offset<length)
2212 goto start_over;
2214 proto_item_set_len(p_rohc_info->last_created_item, offset-feedback_start);
2215 return tvb_length(tvb);
2217 }/*feedback */
2218 /* 5) If the first remaining octet starts with 1111111, this is a segment:
2221 if((oct&0xfe) == 0xfe){
2222 col_append_str(pinfo->cinfo, COL_INFO, "Segment");
2223 if((p_rohc_info->large_cid_present == FALSE) && (is_add_cid == FALSE)){
2224 item = proto_tree_add_uint(rohc_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
2225 PROTO_ITEM_SET_GENERATED(item);
2227 proto_tree_add_text(rohc_tree, tvb, offset, -1, "Segment [Desegmentation not implemented yet]");
2228 return tvb_length(tvb);
2230 /* 6) Here, it is known that the rest is forward information (unless the
2231 * header is damaged).
2233 if((oct&0xfe) == 0xfc){
2234 col_append_str(pinfo->cinfo, COL_INFO, "IR packet");
2235 offset = dissect_rohc_ir_packet(tvb, rohc_tree, pinfo, offset, cid, is_add_cid, p_rohc_info);
2236 if(offset == -1){
2237 /* Could not parse header */
2238 return tvb_length(tvb);
2240 /*proto_tree_add_text(rohc_tree, tvb, offset, -1, "Data");*/
2241 payload_tvb = tvb_new_subset_remaining(tvb, offset);
2242 call_dissector_only(data_handle, payload_tvb, pinfo, rohc_tree, NULL);
2243 return tvb_length(tvb);
2245 if((oct&0xff) == 0xf8){
2246 col_append_str(pinfo->cinfo, COL_INFO, "IR-DYN packet");
2247 offset = dissect_rohc_ir_dyn_packet(tvb, rohc_tree, pinfo, offset, cid, is_add_cid, p_rohc_info);
2248 if(offset == -1){
2249 /* Could not parse header */
2250 return tvb_length(tvb);
2252 /*proto_tree_add_text(rohc_tree, tvb, offset, -1, "Data");*/
2253 payload_tvb = tvb_new_subset_remaining(tvb, offset);
2254 call_dissector_only(data_handle, payload_tvb, pinfo, rohc_tree, NULL);
2255 return tvb_length(tvb);
2258 if (!pinfo->fd->flags.visited){
2259 gint key = cid;
2261 /*g_warning("Lookup CID %u",cid);*/
2262 rohc_cid_context = (rohc_cid_context_t*)g_hash_table_lookup(rohc_cid_hash, GUINT_TO_POINTER(key));
2263 if(rohc_cid_context){
2264 /*g_warning("Found CID %u",cid);*/
2265 }else{
2266 rohc_cid_context = wmem_new(wmem_file_scope(), rohc_cid_context_t);
2267 /*rohc_cid_context->d_mode;*/
2268 rohc_cid_context->rnd = p_rohc_info->rnd;
2269 rohc_cid_context->udp_checksum_present = p_rohc_info->udp_checksum_present;
2270 rohc_cid_context->profile = p_rohc_info->profile;
2271 rohc_cid_context->mode = p_rohc_info->mode;
2272 rohc_cid_context->rohc_ip_version = p_rohc_info->rohc_ip_version;
2273 rohc_cid_context->large_cid_present = p_rohc_info->large_cid_present;
2274 rohc_cid_context->prev_ir_frame_number = -1;
2275 rohc_cid_context->ir_frame_number = -1;
2276 /*g_warning("Store dummy data %u",cid);*/
2278 p_add_proto_data(pinfo->fd, proto_rohc, 0, rohc_cid_context);
2279 } else {
2280 rohc_cid_context = (rohc_cid_context_t*)p_get_proto_data(pinfo->fd, proto_rohc, 0);
2283 /* Call IP for uncompressed*/
2284 DISSECTOR_ASSERT(rohc_cid_context);
2285 if (rohc_cid_context->profile==ROHC_PROFILE_UNCOMPRESSED) {
2286 if (rohc_cid_context->large_cid_present) {
2287 guint8 *payload_data;
2288 gint len;
2289 get_self_describing_var_len_val(tvb, rohc_tree, offset+1, hf_rohc_large_cid, &val_len);
2290 len = tvb_length_remaining(tvb, offset);
2291 if (len >= val_len) {
2292 len -= val_len;
2293 payload_data = (guint8 *)wmem_alloc(pinfo->pool, len);
2294 tvb_memcpy(tvb, payload_data, offset, 1);
2295 tvb_memcpy(tvb, &payload_data[1], offset+1+val_len, len-1);
2296 next_tvb = tvb_new_child_real_data(tvb, payload_data, len, len);
2297 add_new_data_source(pinfo, next_tvb, "Payload");
2300 else {
2301 next_tvb = tvb_new_subset_remaining(tvb, offset);
2303 if ((oct&0xf0)==0x40) {
2304 call_dissector(ip_handle, next_tvb, pinfo, tree);
2306 else if ((oct&0xf0)==0x60) {
2307 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
2309 else {
2310 call_dissector(data_handle, next_tvb, pinfo, tree);
2312 col_prepend_fstr(pinfo->cinfo, COL_PROTOCOL, "ROHC <");
2313 col_append_str(pinfo->cinfo, COL_PROTOCOL, ">");
2314 return tvb_length(tvb);
2316 else if (((oct&0x80)==0x00) && (rohc_cid_context->profile==ROHC_PROFILE_RTP)) {
2317 /* 5.7.1. Packet type 0: UO-0, R-0, R-0-CRC */
2318 offset = dissect_rohc_pkt_type_0(tvb, pinfo, rohc_tree, offset, oct, rohc_cid_context);
2319 } else if ((oct&0xc0)==0x80) {
2320 if (rohc_cid_context->mode == RELIABLE_BIDIRECTIONAL) {
2321 /* 5.7.2. Packet type 1 (R-mode): R-1, R-1-TS, R-1-ID */
2322 offset = dissect_rohc_pkt_type_1_r_mode(tvb, pinfo, rohc_tree, offset, rohc_cid_context);
2324 else {
2325 /* 5.7.3. Packet type 1 (U/O-mode): UO-1, UO-1-ID, UO-1-TS */
2326 offset = dissect_rohc_pkt_type_1_u_o_mode(tvb, pinfo, rohc_tree, offset, rohc_cid_context);
2328 } else if ((oct&0xe0)==0xc0) {
2329 /* 5.7.4. Packet type 2: UOR-2 */
2330 offset = dissect_rohc_pkt_type_2(tvb, pinfo, rohc_tree, offset, rohc_cid_context);
2333 /* IP-ID */
2334 if (rohc_cid_context->rnd) {
2335 proto_tree_add_item(rohc_tree, hf_rohc_ip_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2336 offset += 2;
2339 /* UDP Checksum */
2340 if (rohc_cid_context->udp_checksum_present) {
2341 proto_tree_add_item(rohc_tree, hf_rohc_udp_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
2342 offset += 2;
2345 payload_tvb = tvb_new_subset_remaining(tvb, offset);
2346 call_dissector_only(data_handle, payload_tvb, pinfo, tree, NULL);
2348 return tvb_length(tvb);
2351 /* Set up rohc_cid_hash which holds data for a CID
2352 * needed to dissect subsequent packages.
2353 * XXXX ToDo:
2354 * A better Key than just the CID may have to be devised.
2359 static gint cid_hash_equal(gconstpointer v, gconstpointer v2)
2361 return (v == v2);
2364 static guint cid_hash_func(gconstpointer v)
2366 return GPOINTER_TO_UINT(v);
2370 static void
2371 rohc_init_protocol(void)
2373 /* Destroy any existing hashes. */
2374 if (rohc_cid_hash)
2375 g_hash_table_destroy(rohc_cid_hash);
2377 /* Now create them again */
2378 rohc_cid_hash = g_hash_table_new(cid_hash_func, cid_hash_equal);
2381 void
2382 proto_register_rohc(void)
2385 static hf_register_info hf[] =
2387 { &hf_rohc_padding,
2388 { "Padding","rohc.pading",
2389 FT_BYTES, BASE_NONE, NULL, 0x0,
2390 NULL , HFILL
2393 { &hf_rohc_add_cid,
2394 { "Add-CID","rohc.add_cid",
2395 FT_UINT8, BASE_HEX, NULL, 0xf0,
2396 NULL , HFILL
2399 { &hf_rohc_feedback,
2400 { "Feedback","rohc.feedback",
2401 FT_UINT8, BASE_HEX, NULL, 0xf8,
2402 NULL , HFILL
2405 { &hf_rohc_code,
2406 { "Code","rohc.code",
2407 FT_UINT8, BASE_DEC, NULL, 0x07,
2408 NULL , HFILL
2411 { &hf_rohc_size,
2412 { "Size","rohc.size",
2413 FT_UINT8, BASE_DEC, NULL, 0x00,
2414 NULL , HFILL
2417 { &hf_rohc_ir_packet,
2418 { "IR packet","rohc.ir_packet",
2419 FT_UINT8, BASE_HEX, NULL, 0xfe,
2420 NULL , HFILL
2423 { &hf_rohc_ir_dyn_packet,
2424 { "IR-DYN packet","rohc.ir_dyn_packet",
2425 FT_UINT8, BASE_HEX, NULL, 0xff,
2426 NULL , HFILL
2429 { &hf_rohc_small_cid,
2430 { "Small CID","rohc.small_cid",
2431 FT_UINT8, BASE_DEC, NULL, 0x0f,
2432 NULL , HFILL
2435 { &hf_rohc_large_cid,
2436 { "Large CID","rohc.large_cid",
2437 FT_UINT16, BASE_DEC, NULL, 0x0,
2438 NULL , HFILL
2441 { &hf_rohc_acktype,
2442 { "Acktype","rohc.acktype",
2443 FT_UINT8, BASE_DEC, VALS(rohc_acktype_vals), 0xc0,
2444 NULL , HFILL
2447 { &hf_rohc_mode,
2448 { "Mode","rohc.mode",
2449 FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x30,
2450 NULL , HFILL
2453 { &hf_rohc_sn,
2454 { "SN LSB","rohc.sn",
2455 FT_UINT16, BASE_HEX_DEC, NULL, 0x0fff,
2456 NULL , HFILL
2459 { &hf_rohc_profile_spec_octet,
2460 { "Profile-specific octet","rohc.profile_spec_octet",
2461 FT_UINT8, BASE_HEX, NULL, 0x0,
2462 NULL , HFILL
2465 { &hf_rohc_fb1_sn,
2466 { "SN LSB","rohc.sn",
2467 FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
2468 NULL , HFILL
2471 { &hf_rohc_opt_type,
2472 { "Option type","rohc.opt_type",
2473 FT_UINT8, BASE_DEC, VALS(rohc_opt_type_vals), 0xf0,
2474 NULL , HFILL
2477 { &hf_rohc_opt_len,
2478 { "Option length","rohc.opt_length",
2479 FT_UINT8, BASE_DEC, NULL, 0x0f,
2480 NULL , HFILL
2483 { &hf_rohc_crc,
2484 { "CRC","rohc.crc",
2485 FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
2486 NULL , HFILL
2489 { &hf_rohc_opt_sn,
2490 { "SN additional bits","rohc.opt.sn_add_bits",
2491 FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
2492 "Feedback Option SN", HFILL
2495 { &hf_rohc_ext_sn,
2496 { "SN LSB","rohc.sn",
2497 FT_UINT24, BASE_HEX_DEC, NULL, 0x0,
2498 NULL, HFILL
2501 { &hf_rohc_opt_clock,
2502 { "Clock", "rohc.opt.clock",
2503 FT_UINT8, BASE_DEC, NULL, 0x0,
2504 "Feedback Option Clock", HFILL
2507 { &hf_rohc_opt_jitter,
2508 { "Max Jitter", "rohc.opt.jitter",
2509 FT_UINT8, BASE_DEC, NULL, 0x0,
2510 "Feedback Option Jitter", HFILL
2513 { &hf_rohc_opt_loss,
2514 { "Longest loss event (packets)", "rohc.opt.loss",
2515 FT_UINT8, BASE_DEC, NULL, 0x0,
2516 "Feedback Option Loss", HFILL
2519 { &hf_rohc_profile,
2520 { "Profile","rohc.profile",
2521 FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
2522 NULL , HFILL
2525 { &hf_rohc_d_bit,
2526 { "D - Dynamic chain","rohc.d",
2527 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01,
2528 NULL , HFILL
2531 { &hf_rohc_ip_version,
2532 { "Version","rohc.ip.version",
2533 FT_UINT8, BASE_DEC, VALS(rohc_ip_version_vals), 0xf0,
2534 NULL , HFILL
2537 { &hf_rohc_static_ipv4,
2538 { "Static IPv4 chain",
2539 "rohc.static.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
2540 NULL, HFILL
2543 { &hf_rohc_ip_protocol,
2544 { "Protocol","rohc.ip.protocol",
2545 FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&ipproto_val_ext), 0x0,
2546 NULL , HFILL
2549 { &hf_rohc_ipv4_src,
2550 { "Source address","rohc.ipv4_src",
2551 FT_IPv4, BASE_NONE, NULL, 0x0,
2552 NULL, HFILL
2555 { &hf_rohc_ipv4_dst,
2556 { "Destination address","rohc.ipv4_dst",
2557 FT_IPv4, BASE_NONE, NULL, 0x0,
2558 NULL, HFILL
2561 { &hf_rohc_ipv6_flow,
2562 { "Flow Label","rohc.ipv6.flow",
2563 FT_UINT24, BASE_DEC, NULL, 0x0fffff,
2564 NULL , HFILL
2567 { &hf_rohc_ipv6_nxt_hdr,
2568 { "Next Header","rohc.ipv6.nxt_hdr",
2569 FT_UINT8, BASE_DEC, NULL, 0x0,
2570 NULL , HFILL
2573 { &hf_rohc_ipv6_src,
2574 { "Source Address","rohc.ipv6.src",
2575 FT_IPv6, BASE_NONE, NULL, 0,
2576 NULL , HFILL
2579 { &hf_rohc_ipv6_dst,
2580 { "Destination Address","rohc.ipv6.src",
2581 FT_IPv6, BASE_NONE, NULL, 0,
2582 NULL , HFILL
2585 { &hf_rohc_static_udp,
2586 { "Static UDP chain", "rohc.static.udp",
2587 FT_NONE, BASE_NONE, NULL, 0x0,
2588 NULL, HFILL
2591 { &hf_rohc_udp_src_port,
2592 { "Source Port","rohc.udp_src_port",
2593 FT_UINT16, BASE_DEC, NULL, 0x0,
2594 NULL , HFILL
2597 { &hf_rohc_udp_dst_port,
2598 { "Destination Port","rohc.udp_dst_port",
2599 FT_UINT16, BASE_DEC, NULL, 0x0,
2600 NULL , HFILL
2603 { &hf_rohc_static_rtp,
2604 { "Static RTP chain",
2605 "rohc.static.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
2606 NULL, HFILL
2609 { &hf_rohc_rtp_ssrc,
2610 { "SSRC","rohc.rtp.ssrc",
2611 FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
2612 NULL , HFILL
2615 { &hf_rohc_dynamic_ipv4,
2616 { "Dynamic IPv4 chain",
2617 "rohc.dynamic.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
2618 NULL, HFILL
2621 { &hf_rohc_dynamic_udp,
2622 { "Dynamic UDP chain",
2623 "rohc.dynamic.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2624 NULL, HFILL
2627 { &hf_rohc_rtp_tos,
2628 { "Type of Service","rohc.rtp.tos",
2629 FT_UINT8, BASE_HEX, NULL, 0x0,
2630 NULL , HFILL
2633 { &hf_rohc_rtp_ttl,
2634 { "Time to Live","rohc.rtp.ttl",
2635 FT_UINT8, BASE_DEC, NULL, 0x0,
2636 NULL , HFILL
2639 { &hf_rohc_rtp_id,
2640 { "Identification","rohc.rtp.id",
2641 FT_UINT16, BASE_HEX, NULL, 0x0,
2642 NULL , HFILL
2645 { &hf_rohc_rtp_df,
2646 { "Don't Fragment(DF)","rohc.rtp.df",
2647 FT_BOOLEAN, 8, NULL, 0x80,
2648 NULL , HFILL
2651 { &hf_rohc_rtp_rnd,
2652 { "RND(IP-ID behaves randomly)","rohc.rtp.rnd",
2653 FT_BOOLEAN, 8, NULL, 0x40,
2654 NULL , HFILL
2657 { &hf_rohc_rtp_nbo,
2658 { "Network Byte Order (NBO)","rohc.rtp.nbo",
2659 FT_BOOLEAN, 8, NULL, 0x20,
2660 "Whether the IP-ID is in Network Byte Order" , HFILL
2663 { &hf_rohc_dynamic_udp_checksum,
2664 { "UDP Checksum", "rohc.dynamic.udp.checksum",
2665 FT_UINT16, BASE_HEX, NULL, 0x0,
2666 NULL, HFILL
2669 { &hf_rohc_dynamic_rtp,
2670 { "Dynamic RTP chain",
2671 "rohc.dynamic.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
2672 NULL, HFILL
2675 { &hf_rohc_rtp_v,
2676 { "Version","rohc.rtp.v",
2677 FT_UINT8, BASE_DEC, NULL, 0xc0,
2678 NULL , HFILL
2681 { &hf_rohc_rtp_p,
2682 { "Padding(P)","rohc.rtp.p",
2683 FT_BOOLEAN, 8, NULL, 0x20,
2684 NULL , HFILL
2687 { &hf_rohc_rtp_rx,
2688 { "RX","rohc.rtp.rx",
2689 FT_BOOLEAN, 8, NULL, 0x10,
2690 NULL , HFILL
2693 { &hf_rohc_rtp_cc,
2694 { "CC","rohc.rtp.cc",
2695 FT_UINT8, BASE_DEC, NULL, 0x0f,
2696 "CSRC counter from original RTP header" , HFILL
2699 { &hf_rohc_rtp_m,
2700 { "Marker Bit (M)","rohc.rtp.m",
2701 FT_BOOLEAN, BASE_NONE, TFS(&tfs_set_notset), 0x00,
2702 NULL , HFILL
2705 { &hf_rohc_rtp_pt,
2706 { "Payload Type(PT)","rohc.rtp.pt",
2707 FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&rtp_payload_type_vals_ext), 0x7f,
2708 NULL , HFILL
2711 { &hf_rohc_rtp_sn,
2712 { "Sequence Number(SN)","rohc.rtp.sn",
2713 FT_UINT16, BASE_DEC, NULL, 0x0,
2714 NULL , HFILL
2717 { &hf_rohc_rtp_timestamp,
2718 { "RTP Timestamp","rohc.rtp.timestamp",
2719 FT_UINT32, BASE_DEC, NULL, 0x0,
2720 NULL , HFILL
2723 { &hf_rohc_rtp_x,
2724 { "X","rohc.rtp.x",
2725 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x10,
2726 NULL , HFILL
2729 { &hf_rohc_rtp_mode,
2730 { "Mode","rohc.rtp.mode",
2731 FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0c,
2732 NULL , HFILL
2735 { &hf_rohc_rtp_tis,
2736 { "TIS","rohc.rtp.tis",
2737 FT_BOOLEAN, 8, NULL, 0x02,
2738 NULL , HFILL
2741 { &hf_rohc_rtp_tss,
2742 { "TSS","rohc.rtp.tss",
2743 FT_BOOLEAN, 8, NULL, 0x01,
2744 NULL , HFILL
2747 { &hf_rohc_rtp_ts_stride,
2748 { "TS_Stride","rohc.rtp.ts_stride",
2749 FT_UINT32, BASE_DEC, NULL, 0x0,
2750 NULL , HFILL
2753 { &hf_rohc_rtp_time_stride,
2754 { "Time_Stride","rohc.rtp.time_stride",
2755 FT_UINT32, BASE_DEC, NULL, 0x0,
2756 NULL , HFILL
2759 { &hf_rohc_var_len,
2760 { "Variable length","rohc.var_len",
2761 FT_UINT8, BASE_DEC, VALS(rohc_var_len_vals), 0x0,
2762 NULL , HFILL
2765 { &hf_rohc_ipv6_tc,
2766 { "Traffic class","rohc.tc",
2767 FT_UINT8, BASE_DEC, NULL, 0x0,
2768 NULL , HFILL
2771 { &hf_rohc_ipv6_hop_limit,
2772 { "Hop limit","rohc.hop_limit",
2773 FT_UINT8, BASE_DEC, NULL, 0x0,
2774 NULL , HFILL
2777 { &hf_rohc_ir_previous_frame,
2778 { "Previous IR frame","rohc.ir.prev.frame_num",
2779 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2780 NULL , HFILL
2783 { &hf_rohc_ir_pkt_frame,
2784 { "Setup by IR frame","rohc.ir.frame_num",
2785 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2786 NULL , HFILL
2789 { &hf_rohc_comp_sn,
2790 { "Compressed Sequence Number","rohc.comp.sn",
2791 FT_UINT8, BASE_DEC, NULL, 0x0,
2792 NULL , HFILL
2795 { &hf_rohc_r_0_crc,
2796 { "CRC","rohc.r_0_crc",
2797 FT_UINT8, BASE_HEX, NULL, 0x0,
2798 NULL , HFILL
2801 { &hf_rohc_x,
2802 { "Extension","rohc.x",
2803 FT_BOOLEAN, BASE_NONE, TFS(&tfs_present_not_present), 0x0,
2804 NULL , HFILL
2807 { &hf_rohc_ts,
2808 { "Compressed RTP timestamp","rohc.tp",
2809 FT_UINT16, BASE_DEC, NULL, 0x0,
2810 NULL , HFILL
2813 { &hf_rohc_comp_ip_id,
2814 { "Compressed IP-ID","rohc.comp_ip_id",
2815 FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2816 NULL , HFILL
2819 { &hf_rohc_t,
2820 { "T bit","rohc.t",
2821 FT_UINT8, BASE_DEC, NULL, 0x0,
2822 NULL , HFILL
2825 { &hf_rohc_compressed_list,
2826 { "Compressed List", "rohc.compressed-list",
2827 FT_NONE, BASE_NONE, NULL, 0x0,
2828 NULL , HFILL
2831 { &hf_rohc_compressed_list_et,
2832 { "Encoding Type", "rohc.compressed-list.et",
2833 FT_UINT8, BASE_DEC, VALS(compressed_list_encoding_type_vals), 0xc0,
2834 NULL , HFILL
2837 { &hf_rohc_compressed_list_gp,
2838 { "Gen-id Present", "rohc.compressed-list.gp",
2839 FT_UINT8, BASE_DEC, NULL, 0x20,
2840 NULL , HFILL
2843 { &hf_rohc_compressed_list_ps,
2844 { "PS", "rohc.compressed-list.ps",
2845 FT_UINT8, BASE_DEC, VALS(compressed_list_ps_vals), 0x10,
2846 "Size of xi fields", HFILL
2849 { &hf_rohc_compressed_list_res,
2850 { "Reserved", "rohc.compressed-list.res",
2851 FT_UINT8, BASE_DEC, NULL, 0x10,
2852 NULL, HFILL
2855 { &hf_rohc_compressed_list_count,
2856 { "Count", "rohc.compressed-list.count",
2857 FT_UINT8, BASE_DEC, NULL, 0x0f,
2858 NULL, HFILL
2861 { &hf_rohc_compressed_list_cc,
2862 { "CSRC Counter", "rohc.compressed-list.cc",
2863 FT_UINT8, BASE_DEC, NULL, 0x0f,
2864 "CSRC Counter from original RTP header", HFILL
2867 { &hf_rohc_compressed_list_xi_1,
2868 { "XI 1", "rohc.compressed-list.xi_1",
2869 FT_UINT8, BASE_DEC, NULL, 0x0f,
2870 NULL, HFILL
2873 { &hf_rohc_compressed_list_gen_id,
2874 { "gen_id", "rohc.compressed-list.gen-id",
2875 FT_UINT8, BASE_DEC, NULL, 0x0,
2876 NULL, HFILL
2879 { &hf_rohc_compressed_list_ref_id,
2880 { "ref_id", "rohc.compressed-list.ref-id",
2881 FT_UINT8, BASE_DEC, NULL, 0x0,
2882 NULL, HFILL
2885 { &hf_rohc_compressed_list_mask_size,
2886 { "Mask size","rohc.compressed-list.mask_size",
2887 FT_BOOLEAN, 8, TFS(&rohc_cmp_lst_mask_size_vals), 0x80,
2888 NULL , HFILL
2891 { &hf_rohc_compressed_list_ins_bit_mask,
2892 { "Insertion bit mask","rohc.compressed-list.ins_bit_mask",
2893 FT_UINT16, BASE_HEX, NULL, 0x0,
2894 NULL, HFILL
2897 { &hf_rohc_compressed_list_rem_bit_mask,
2898 { "Removal bit mask","rohc.compressed-list.rem_bit_mask",
2899 FT_UINT16, BASE_HEX, NULL, 0x0,
2900 NULL, HFILL
2903 { &hf_rohc_spare_bits,
2904 { "Spare bits(0)", "rohc.spare_bits",
2905 FT_UINT8, BASE_DEC, NULL, 0x0,
2906 NULL, HFILL
2909 { &hf_rohc_ip_id,
2910 { "IP-ID", "rohc.ip-id",
2911 FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2912 NULL, HFILL
2915 { &hf_rohc_udp_checksum,
2916 { "UDP checksum", "rohc.udp_checksum",
2917 FT_UINT16, BASE_HEX, NULL, 0x0,
2918 NULL, HFILL
2924 /* Setup protocol subtree array */
2925 static gint *ett[] = {
2926 &ett_rohc,
2927 &ett_rohc_conf,
2928 &ett_rohc_fb,
2929 &ett_rohc_feedback,
2930 &ett_rohc_ir,
2931 &ett_rohc_ir_dyn,
2932 &ett_rohc_static_ipv4,
2933 &ett_rohc_static_udp,
2934 &ett_rohc_static_rtp,
2935 &ett_rohc_rtp_static,
2936 &ett_rohc_rtp_dynamic,
2937 &ett_rohc_dynamic_ipv4,
2938 &ett_rohc_dynamic_udp,
2939 &ett_rohc_dynamic_rtp,
2940 &ett_rohc_compressed_list,
2941 &ett_rohc_packet
2944 static ei_register_info ei[] = {
2945 { &ei_rohc_profile_spec_octet, { "rohc.profile_spec_octet.bad", PI_PROTOCOL, PI_WARN, "Invalid profile-specific octet value", EXPFILL }},
2946 { &ei_rohc_feedback_type_2_is_not_applicable_for_uncompressed_profile, { "rohc.feedback.type_2_is_not_applicable_for_uncompressed_profile", PI_PROTOCOL, PI_WARN, "Feedback type 2 is not applicable for uncompressed profile", EXPFILL }},
2947 { &ei_rohc_rohc_opt_clock, { "rohc.opt.clock.udp", PI_MALFORMED, PI_ERROR, "CLOCK option should not be used for UDP", EXPFILL }},
2948 { &ei_rohc_opt_jitter, { "rohc.opt.jitter.udp", PI_MALFORMED, PI_ERROR, "JITTER option should not be used for UDP", EXPFILL }},
2951 expert_module_t* expert_rohc;
2953 /* Register the protocol name and description */
2954 proto_rohc = proto_register_protocol("RObust Header Compression (ROHC)", "ROHC", "rohc");
2956 rohc_handle = new_register_dissector("rohc", dissect_rohc, proto_rohc);
2958 register_init_routine(&rohc_init_protocol);
2960 /* Required function calls to register the header fields and subtrees used */
2961 proto_register_field_array(proto_rohc, hf, array_length(hf));
2962 proto_register_subtree_array(ett, array_length(ett));
2963 expert_rohc = expert_register_protocol(proto_rohc);
2964 expert_register_field_array(expert_rohc, ei, array_length(ei));
2967 void
2968 proto_reg_handoff_rohc(void)
2970 dissector_add_uint("ethertype", ETHERTYPE_ROHC, rohc_handle);
2972 ip_handle = find_dissector("ip");
2973 ipv6_handle = find_dissector("ipv6");
2974 data_handle = find_dissector("data");