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>
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.
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
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
;
178 enum rohc_d_mode d_mode
;
180 gboolean udp_checksum_present
;
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
;
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*/
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
[] =
223 { 2, "STATIC-NACK" },
224 { 3, "reserved (MUST NOT be used. Otherwise unparsable)" },
228 static const value_string rohc_mode_vals
[] =
231 { 1, "Unidirectional" },
232 { 2, "Bidirectional Optimistic" },
233 { 3, "Bidirectional Reliable" },
237 static const value_string rohc_opt_type_vals
[] =
241 { 3, "SN-NOT-VALID" },
251 static const value_string rohc_ip_version_vals
[] =
258 static const value_string rohc_var_len_vals
[] =
262 { 6, "Three octets" },
263 { 7, "Four octets" },
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" },
276 static const value_string compressed_list_ps_vals
[] =
278 { 0, "4-bit XI fields" },
279 { 1, "8-bit XI fields" },
283 /* 4.5.6. Self-describing variable-length values */
285 get_self_describing_var_len_val(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int hf_index
, guint8
*val_len
){
288 int num_bits
= 0, bit_offset
= offset
<<3;
290 oct
= tvb_get_guint8(tvb
, offset
);
295 proto_tree_add_bits_item(tree
, hf_rohc_var_len
, tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
298 }else if((oct
&0xc0)==0x80){
301 proto_tree_add_bits_item(tree
, hf_rohc_var_len
, tvb
, bit_offset
, 2, ENC_BIG_ENDIAN
);
304 val
= tvb_get_ntohs(tvb
, offset
)&0x3fff;
305 }else if((oct
&0xe0)==0xc0){
308 proto_tree_add_bits_item(tree
, hf_rohc_var_len
, tvb
, bit_offset
, 3, ENC_BIG_ENDIAN
);
311 val
= tvb_get_ntoh24(tvb
, offset
)&0x1fffff;
312 }else if ((oct
&0xe0)==0xe0){
315 proto_tree_add_bits_item(tree
, hf_rohc_var_len
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
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
);
325 /* 5.7.1. Packet type 0: UO-0, R-0, R-0-CRC */
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
)
332 proto_tree
*pkt_tree
;
334 switch(rohc_cid_context
->mode
){
335 case RELIABLE_BIDIRECTIONAL
: /* R-mode */
336 if((pkt_type
&0xc0)==0x00){
340 * +---+---+---+---+---+---+---+---+
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){
360 * +---+---+---+---+---+---+---+---+
362 * +===+===+===+===+===+===+===+===+
364 * +---+---+---+---+---+---+---+---+
366 crumb_spec_t rohc_sn_crumbs
[] = {
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
);
384 /* Show SN in info column */
385 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", (guint
)sn
);
388 case UNIDIRECTIONAL
: /* U-mode */
390 case OPTIMISTIC_BIDIRECTIONAL
: /* O-mode */
394 * +---+---+---+---+---+---+---+---+
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
);
413 col_set_str(pinfo
->cinfo
, COL_INFO
, "Packet type 0");
421 /* 5.7.5. Extension formats */
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) {
432 * +---+---+---+---+---+---+---+---+
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
);
439 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
442 } else if (ext_type
== 0x40) {
445 * +---+---+---+---+---+---+---+---+
447 * +---+---+---+---+---+---+---+---+
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
);
455 proto_tree_add_bits_item(tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
457 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
459 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
461 proto_tree_add_bits_item(tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
463 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
465 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
468 } else if (ext_type
== 0x80) {
471 * +---+---+---+---+---+---+---+---+
473 * +---+---+---+---+---+---+---+---+
475 * +---+---+---+---+---+---+---+---+
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
);
482 proto_tree_add_bits_item(tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
484 proto_tree_add_bits_item(tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+5, 11, ENC_BIG_ENDIAN
);
486 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
488 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3)+5, 11, ENC_BIG_ENDIAN
);
490 proto_tree_add_bits_item(tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
492 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3)+5, 11, ENC_BIG_ENDIAN
);
494 proto_tree_add_bits_item(tree
, hf_rohc_ts
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
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
);
505 /* 5.7.2. Packet type 1 (R-mode): R-1, R-1-TS, R-1-ID */
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
)
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
)) {
525 * +---+---+---+---+---+---+---+---+
527 * +===+===+===+===+===+===+===+===+
529 * +---+---+---+---+---+---+---+---+
534 * +---+---+---+---+---+---+---+---+
536 * +===+===+===+===+===+===+===+===+
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
);
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
);
560 t
= tvb_get_bits8(tvb
, ((offset
+1+val_len
)<<3)+2, 1);
565 * +---+---+---+---+---+---+---+---+
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
);
578 * +---+---+---+---+---+---+---+---+
580 * +===+===+===+===+===+===+===+===+
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
);
598 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
600 proto_tree_add_bits_item(pkt_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
605 offset
= dissect_rohc_ext_format(tvb
, pkt_tree
, offset
, t
, rohc_cid_context
);
607 proto_item_set_len(ti
, offset
-start_offset
);
612 /* 5.7.3. Packet type 1 (U/O-mode): UO-1, UO-1-ID, UO-1-TS */
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
)
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)
632 * +---+---+---+---+---+---+---+---+
634 * +===+===+===+===+===+===+===+===+
636 * +---+---+---+---+---+---+---+---+
638 /* UO-1 (UDP profile)
641 * +---+---+---+---+---+---+---+---+
643 * +===+===+===+===+===+===+===+===+
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
);
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
);
667 t
= tvb_get_bits8(tvb
, ((offset
)<<3)+2, 1);
672 * +---+---+---+---+---+---+---+---+
673 * | 1 0 |T=0| IP-ID |
674 * +===+===+===+===+===+===+===+===+
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
);
690 * +---+---+---+---+---+---+---+---+
692 * +===+===+===+===+===+===+===+===+
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
);
712 offset
= dissect_rohc_ext_format(tvb
, pkt_tree
, offset
, t
, rohc_cid_context
);
714 proto_item_set_len(ti
, offset
-start_offset
);
719 /* 5.7.4. Packet type 2: UOR-2 */
721 dissect_rohc_pkt_type_2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, rohc_cid_context_t
*rohc_cid_context
)
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)
739 * +---+---+---+---+---+---+---+---+
741 * +===+===+===+===+===+===+===+===+
743 * +---+---+---+---+---+---+---+---+
745 * +---+---+---+---+---+---+---+---+
747 /* UOR-2 (UDP profile)
750 * +---+---+---+---+---+---+---+---+
752 * +===+===+===+===+===+===+===+===+
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
);
766 crumb_spec_t rohc_ts_crumbs
[] = {
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
);
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
);
787 t
= tvb_get_bits8(tvb
, ((offset
+1+val_len
)<<3), 1);
792 * +---+---+---+---+---+---+---+---+
794 * +===+===+===+===+===+===+===+===+
796 * +---+---+---+---+---+---+---+---+
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
);
808 * +---+---+---+---+---+---+---+---+
810 * +===+===+===+===+===+===+===+===+
812 * +---+---+---+---+---+---+---+---+
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
);
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
);
835 offset
= dissect_rohc_ext_format(tvb
, pkt_tree
, offset
, t
, rohc_cid_context
);
837 proto_item_set_len(ti
, offset
-start_offset
);
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
){
847 proto_tree
*rohc_feedback_tree
;
848 guint8 opt
, opt_len
, oct
;
849 rohc_cid_context_t
*rohc_cid_context
= NULL
;
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
);
859 rohc_cid_context
= (rohc_cid_context_t
*)p_get_proto_data(pinfo
->fd
, proto_rohc
, 0);
862 if(!rohc_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;
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]");
883 if(feedback_data_len
==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
);
891 expert_add_info_format(pinfo
, ti
, &ei_rohc_profile_spec_octet
, "Invalid profile-specific octet value (0x%02X)", oct
);
894 case ROHC_PROFILE_RTP
: /* 1 */
895 case ROHC_PROFILE_UDP
: /* 2 */
898 * +---+---+---+---+---+---+---+---+
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
);
908 proto_tree_add_text(tree
, tvb
, offset
, feedback_data_len
, "profile-specific information[Not dissected yet]");
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
);
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
);
933 feedback_data_len
-=2;
935 while(feedback_data_len
>0){
936 opt
= opt_len
= tvb_get_guint8(tvb
,offset
);
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
);
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
);
952 col_append_str(pinfo
->cinfo
, COL_INFO
, "Reject ");
956 col_append_str(pinfo
->cinfo
, COL_INFO
, "SN-Not-Valid ");
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
);
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
);
972 expert_add_info(pinfo
, ti
, &ei_rohc_rohc_opt_clock
);
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
);
982 expert_add_info(pinfo
, ti
, &ei_rohc_opt_jitter
);
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
);
992 proto_tree_add_text(rohc_feedback_tree
, tvb
, offset
, opt_len
, "Unknown Option data");
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
);
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
);
1010 const true_false_string rohc_cmp_lst_mask_size_vals
= { "15-bit mask", "7-bit mask" };
1013 /* 5.8.6. Compressed list formats */
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"));
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
);
1042 GP
= (first_byte
& 0x20) >> 5;
1043 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gp
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1047 /* 5.8.6.1 Encoding Type 0 (generic scheme)
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 * +---+---+---+---+---+---+---+---+
1060 * / item 1, ..., item n / variable
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
);
1078 /* GP: Indicates presence of gen_id field. */
1080 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gen_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
1090 * PS = 0: | X | Index |
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
1104 /* PS = 1 indicates 8-bit XI fields. */
1106 /* PS = 0 indicates 4-bit XI fields; */
1114 * 5.8.6.2. Encoding Type 1 (insertion only scheme)
1117 * +---+---+---+---+---+---+---+---+
1118 * | ET=1 |GP |PS | XI 1 |
1119 * +---+---+---+---+---+---+---+---+
1120 * : gen_id : 1 octet, if GP = 1
1121 * +---+---+---+---+---+---+---+---+
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 * +---+---+---+---+---+---+---+---+
1131 * / item 1, ..., item n / variable
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.
1143 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_xi_1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1146 /* GP: Indicates presence of gen_id field. */
1148 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gen_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1151 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ref_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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:
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
);
1174 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_ins_bit_mask
, tvb
, (offset
<<3)+1, 15, ENC_BIG_ENDIAN
);
1177 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_ins_bit_mask
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
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.
1194 * 5.8.6.3. Encoding Type 2 (removal only scheme)
1197 * +---+---+---+---+---+---+---+---+
1198 * | ET=2 |GP |res| Count |
1199 * +---+---+---+---+---+---+---+---+
1200 * : gen_id : 1 octet, if GP = 1
1201 * +---+---+---+---+---+---+---+---+
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
);
1212 /* GP: Indicates presence of gen_id field. */
1214 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gen_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1217 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ref_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
);
1229 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_rem_bit_mask
, tvb
, (offset
<<3)+1, 15, ENC_BIG_ENDIAN
);
1232 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_rem_bit_mask
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
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
1244 * +---+---+---+---+---+---+---+---+
1245 * | ET=3 |GP |PS | XI 1 |
1246 * +---+---+---+---+---+---+---+---+
1247 * : gen_id : 1 octet, if GP = 1
1248 * +---+---+---+---+---+---+---+---+
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 * +---+---+---+---+---+---+---+---+
1260 * / item 1, ..., item n / variable
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.
1272 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_xi_1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1275 /* GP: Indicates presence of gen_id field. */
1277 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gen_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1280 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ref_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
);
1293 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_rem_bit_mask
, tvb
, (offset
<<3)+1, 15, ENC_BIG_ENDIAN
);
1296 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_rem_bit_mask
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
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:
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
);
1321 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_ins_bit_mask
, tvb
, (offset
<<3)+1, 15, ENC_BIG_ENDIAN
);
1324 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_ins_bit_mask
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
1332 proto_item_set_len(list_ti
, offset
-start_offset
);
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
;
1347 /*guint8 contributing_csrcs;*/
1348 guint16 sequence_number
;
1351 guint8 tis
= 0, tss
=0;
1352 guint64 ts_stride
= 0;
1354 start_offset
= offset
;
1357 case ROHC_PROFILE_UNCOMPRESSED
:
1358 item
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile 0x0000 Uncompressed");
1361 case ROHC_PROFILE_RTP
:
1362 item
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile 0x0001 RTP Dynamic Chain");
1365 case ROHC_PROFILE_UDP
:
1366 item
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile 0x0002 UDP Dynamic Chain");
1369 case ROHC_PROFILE_IP
:
1370 item
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile 0x0004 IP Dynamic Chain");
1374 proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile not supported");
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
){
1384 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
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
);
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
);
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
);
1404 /* +---+---+---+---+---+---+---+---+
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
);
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
);
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
);
1444 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_hop_limit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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");
1455 if ( (profile
== ROHC_PROFILE_UDP
) ||
1456 (profile
== ROHC_PROFILE_RTP
) ) {
1457 /* 5.7.7.5. Initialization of UDP Header
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
);
1471 proto_item_set_len(item
, offset
- start_offset
);
1475 if (profile
== ROHC_PROFILE_RTP
) {
1476 /* 5.7.7.6. Initialization of RTP Header
1479 * P, X, CC, PT, M, sequence number, timestamp, timestamp stride,
1483 * +---+---+---+---+---+---+---+---+
1484 * | V=2 | P | RX| CC | (RX is NOT the RTP X bit)
1485 * +---+---+---+---+---+---+---+---+
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;
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
);
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
);
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
);
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
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 */
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
);
1559 /* TS_Stride : 1-4 octets, if TSS = 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 */
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
);
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
;
1599 case ROHC_PROFILE_UNCOMPRESSED
:
1600 item
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile 0x0000 Uncompressed");
1603 case ROHC_PROFILE_RTP
:
1604 item
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile 0x0001 RTP Static Chain");
1607 case ROHC_PROFILE_UDP
:
1608 item
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile 0x0002 UDP Static Chain");
1611 case ROHC_PROFILE_IP
:
1612 item
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile 0x0004 IP Static Chain");
1616 proto_tree_add_text(tree
, tvb
, offset
, 0, "Profile not supported");
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
;
1631 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
1634 guint32 source
, dest
;
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
);
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
);
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
);
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
);
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
));
1665 /* 5.7.7.3. Initialization of IPv6 Header [IPv6]*/
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 * +---+---+---+---+---+---+---+---+
1682 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_flow
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
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
);
1690 /* Source Address */
1691 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_src
, tvb
, offset
, 16, ENC_NA
);
1694 /* Destination Address */
1695 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_dst
, tvb
, offset
, 16, ENC_NA
);
1701 proto_tree_add_text(sub_tree
, tvb
, offset
, -1, "Error unknown version, only 4 or 6 allowed");
1705 protocol
= 0; /* Something other than UDP (which is checked for below) */
1708 if (protocol
== IP_PROTO_UDP
) {
1710 if ((profile
== ROHC_PROFILE_RTP
) ||
1711 (profile
== ROHC_PROFILE_UDP
)) {
1712 /* 5.7.7.5. Initialization of UDP Header [RFC-768].
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
);
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
);
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
);
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
);
1737 offset
= dissect_rohc_ir_rtp_profile_dynamic(tvb
, pinfo
, tree
, offset
, profile
, rohc_cid_context
);
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
);
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
);
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. */
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
);
1766 offset
= dissect_rohc_ir_rtp_profile_dynamic(tvb
, pinfo
, tree
, offset
, profile
, rohc_cid_context
);
1770 proto_tree_add_text(sub_tree
, tvb
, offset
, -1, "[Not dissected yet]");
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
;
1784 guint8 oct
, profile
, val_len
= 0;
1785 gint16 feedback_data_len
= 0;
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
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 +---+---+---+---+---+---+---+---+
1806 +---+---+---+---+---+---+---+---+
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
;
1833 x_bit_offset
= 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
;
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
);
1850 proto_tree_add_item(ir_tree
, hf_rohc_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
){
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
);
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
);
1901 /* get the stored data */
1902 rohc_cid_context
= (rohc_cid_context_t
*)p_get_proto_data(pinfo
->fd
, proto_rohc
, 0);
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
, ">");
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
);
1929 proto_tree_add_text(ir_tree
, tvb
, offset
, feedback_data_len
, "profile-specific information[Not dissected yet]");
1935 /* Set length of IR header */
1936 proto_item_set_len(ir_item
, offset
-ir_item_start
);
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
;
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
;
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
);
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
){
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
);
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
);
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
);
2030 case ROHC_PROFILE_RTP
:
2031 offset
= dissect_rohc_ir_rtp_profile_dynamic(tvb
, pinfo
, ir_tree
, offset
, profile
, rohc_cid_context
);
2034 proto_tree_add_text(ir_tree
, tvb
, offset
, feedback_data_len
, "profile-specific information[Not dissected yet]");
2038 /* Set length of IR-DYN header */
2039 proto_item_set_len(ir_item
, offset
-ir_item_start
);
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
;
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
;
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
);
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
);
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
);
2120 conf_item
= proto_tree_add_text(conf_tree
, tvb
, offset
, 0, "No configuration info");
2121 PROTO_ITEM_SET_GENERATED(conf_item
);
2127 oct
= tvb_get_guint8(tvb
,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){
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
);
2145 oct
= tvb_get_guint8(tvb
,offset
);
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
;
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
);
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
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
);
2180 size
= tvb_get_guint8(tvb
,offset
);
2181 proto_tree_add_item(sub_tree
, hf_rohc_size
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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){
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
);
2195 feedback_data_len
--;
2197 item
= proto_tree_add_uint(sub_tree
, hf_rohc_small_cid
, tvb
, 0, 0, cid
);
2198 PROTO_ITEM_SET_GENERATED(item
);
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
;
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
;
2214 proto_item_set_len(p_rohc_info
->last_created_item
, offset
-feedback_start
);
2215 return tvb_length(tvb
);
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
);
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
);
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
){
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);*/
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
);
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
;
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
) {
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");
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
);
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
);
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
);
2334 if (rohc_cid_context
->rnd
) {
2335 proto_tree_add_item(rohc_tree
, hf_rohc_ip_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
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.
2354 * A better Key than just the CID may have to be devised.
2359 static gint
cid_hash_equal(gconstpointer v
, gconstpointer v2
)
2364 static guint
cid_hash_func(gconstpointer v
)
2366 return GPOINTER_TO_UINT(v
);
2371 rohc_init_protocol(void)
2373 /* Destroy any existing hashes. */
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
);
2382 proto_register_rohc(void)
2385 static hf_register_info hf
[] =
2388 { "Padding","rohc.pading",
2389 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2394 { "Add-CID","rohc.add_cid",
2395 FT_UINT8
, BASE_HEX
, NULL
, 0xf0,
2399 { &hf_rohc_feedback
,
2400 { "Feedback","rohc.feedback",
2401 FT_UINT8
, BASE_HEX
, NULL
, 0xf8,
2406 { "Code","rohc.code",
2407 FT_UINT8
, BASE_DEC
, NULL
, 0x07,
2412 { "Size","rohc.size",
2413 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
2417 { &hf_rohc_ir_packet
,
2418 { "IR packet","rohc.ir_packet",
2419 FT_UINT8
, BASE_HEX
, NULL
, 0xfe,
2423 { &hf_rohc_ir_dyn_packet
,
2424 { "IR-DYN packet","rohc.ir_dyn_packet",
2425 FT_UINT8
, BASE_HEX
, NULL
, 0xff,
2429 { &hf_rohc_small_cid
,
2430 { "Small CID","rohc.small_cid",
2431 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
2435 { &hf_rohc_large_cid
,
2436 { "Large CID","rohc.large_cid",
2437 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2442 { "Acktype","rohc.acktype",
2443 FT_UINT8
, BASE_DEC
, VALS(rohc_acktype_vals
), 0xc0,
2448 { "Mode","rohc.mode",
2449 FT_UINT8
, BASE_DEC
, VALS(rohc_mode_vals
), 0x30,
2454 { "SN LSB","rohc.sn",
2455 FT_UINT16
, BASE_HEX_DEC
, NULL
, 0x0fff,
2459 { &hf_rohc_profile_spec_octet
,
2460 { "Profile-specific octet","rohc.profile_spec_octet",
2461 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2466 { "SN LSB","rohc.sn",
2467 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
2471 { &hf_rohc_opt_type
,
2472 { "Option type","rohc.opt_type",
2473 FT_UINT8
, BASE_DEC
, VALS(rohc_opt_type_vals
), 0xf0,
2478 { "Option length","rohc.opt_length",
2479 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
2485 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
2490 { "SN additional bits","rohc.opt.sn_add_bits",
2491 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
2492 "Feedback Option SN", HFILL
2496 { "SN LSB","rohc.sn",
2497 FT_UINT24
, BASE_HEX_DEC
, NULL
, 0x0,
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
2520 { "Profile","rohc.profile",
2521 FT_UINT8
, BASE_DEC
, VALS(rohc_profile_vals
), 0x0,
2526 { "D - Dynamic chain","rohc.d",
2527 FT_BOOLEAN
, 8, TFS(&tfs_present_not_present
), 0x01,
2531 { &hf_rohc_ip_version
,
2532 { "Version","rohc.ip.version",
2533 FT_UINT8
, BASE_DEC
, VALS(rohc_ip_version_vals
), 0xf0,
2537 { &hf_rohc_static_ipv4
,
2538 { "Static IPv4 chain",
2539 "rohc.static.ipv4", FT_NONE
, BASE_NONE
, NULL
, 0x0,
2543 { &hf_rohc_ip_protocol
,
2544 { "Protocol","rohc.ip.protocol",
2545 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, (&ipproto_val_ext
), 0x0,
2549 { &hf_rohc_ipv4_src
,
2550 { "Source address","rohc.ipv4_src",
2551 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
2555 { &hf_rohc_ipv4_dst
,
2556 { "Destination address","rohc.ipv4_dst",
2557 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
2561 { &hf_rohc_ipv6_flow
,
2562 { "Flow Label","rohc.ipv6.flow",
2563 FT_UINT24
, BASE_DEC
, NULL
, 0x0fffff,
2567 { &hf_rohc_ipv6_nxt_hdr
,
2568 { "Next Header","rohc.ipv6.nxt_hdr",
2569 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2573 { &hf_rohc_ipv6_src
,
2574 { "Source Address","rohc.ipv6.src",
2575 FT_IPv6
, BASE_NONE
, NULL
, 0,
2579 { &hf_rohc_ipv6_dst
,
2580 { "Destination Address","rohc.ipv6.src",
2581 FT_IPv6
, BASE_NONE
, NULL
, 0,
2585 { &hf_rohc_static_udp
,
2586 { "Static UDP chain", "rohc.static.udp",
2587 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2591 { &hf_rohc_udp_src_port
,
2592 { "Source Port","rohc.udp_src_port",
2593 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2597 { &hf_rohc_udp_dst_port
,
2598 { "Destination Port","rohc.udp_dst_port",
2599 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2603 { &hf_rohc_static_rtp
,
2604 { "Static RTP chain",
2605 "rohc.static.rtp", FT_NONE
, BASE_NONE
, NULL
, 0x0,
2609 { &hf_rohc_rtp_ssrc
,
2610 { "SSRC","rohc.rtp.ssrc",
2611 FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0,
2615 { &hf_rohc_dynamic_ipv4
,
2616 { "Dynamic IPv4 chain",
2617 "rohc.dynamic.ipv4", FT_NONE
, BASE_NONE
, NULL
, 0x0,
2621 { &hf_rohc_dynamic_udp
,
2622 { "Dynamic UDP chain",
2623 "rohc.dynamic.udp", FT_NONE
, BASE_NONE
, NULL
, 0x0,
2628 { "Type of Service","rohc.rtp.tos",
2629 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2634 { "Time to Live","rohc.rtp.ttl",
2635 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2640 { "Identification","rohc.rtp.id",
2641 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2646 { "Don't Fragment(DF)","rohc.rtp.df",
2647 FT_BOOLEAN
, 8, NULL
, 0x80,
2652 { "RND(IP-ID behaves randomly)","rohc.rtp.rnd",
2653 FT_BOOLEAN
, 8, NULL
, 0x40,
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,
2669 { &hf_rohc_dynamic_rtp
,
2670 { "Dynamic RTP chain",
2671 "rohc.dynamic.rtp", FT_NONE
, BASE_NONE
, NULL
, 0x0,
2676 { "Version","rohc.rtp.v",
2677 FT_UINT8
, BASE_DEC
, NULL
, 0xc0,
2682 { "Padding(P)","rohc.rtp.p",
2683 FT_BOOLEAN
, 8, NULL
, 0x20,
2688 { "RX","rohc.rtp.rx",
2689 FT_BOOLEAN
, 8, NULL
, 0x10,
2694 { "CC","rohc.rtp.cc",
2695 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
2696 "CSRC counter from original RTP header" , HFILL
2700 { "Marker Bit (M)","rohc.rtp.m",
2701 FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_set_notset
), 0x00,
2706 { "Payload Type(PT)","rohc.rtp.pt",
2707 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, (&rtp_payload_type_vals_ext
), 0x7f,
2712 { "Sequence Number(SN)","rohc.rtp.sn",
2713 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2717 { &hf_rohc_rtp_timestamp
,
2718 { "RTP Timestamp","rohc.rtp.timestamp",
2719 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2725 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x10,
2729 { &hf_rohc_rtp_mode
,
2730 { "Mode","rohc.rtp.mode",
2731 FT_UINT8
, BASE_DEC
, VALS(rohc_mode_vals
), 0x0c,
2736 { "TIS","rohc.rtp.tis",
2737 FT_BOOLEAN
, 8, NULL
, 0x02,
2742 { "TSS","rohc.rtp.tss",
2743 FT_BOOLEAN
, 8, NULL
, 0x01,
2747 { &hf_rohc_rtp_ts_stride
,
2748 { "TS_Stride","rohc.rtp.ts_stride",
2749 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2753 { &hf_rohc_rtp_time_stride
,
2754 { "Time_Stride","rohc.rtp.time_stride",
2755 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2760 { "Variable length","rohc.var_len",
2761 FT_UINT8
, BASE_DEC
, VALS(rohc_var_len_vals
), 0x0,
2766 { "Traffic class","rohc.tc",
2767 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2771 { &hf_rohc_ipv6_hop_limit
,
2772 { "Hop limit","rohc.hop_limit",
2773 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2777 { &hf_rohc_ir_previous_frame
,
2778 { "Previous IR frame","rohc.ir.prev.frame_num",
2779 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
2783 { &hf_rohc_ir_pkt_frame
,
2784 { "Setup by IR frame","rohc.ir.frame_num",
2785 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
2790 { "Compressed Sequence Number","rohc.comp.sn",
2791 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2796 { "CRC","rohc.r_0_crc",
2797 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2802 { "Extension","rohc.x",
2803 FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_present_not_present
), 0x0,
2808 { "Compressed RTP timestamp","rohc.tp",
2809 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2813 { &hf_rohc_comp_ip_id
,
2814 { "Compressed IP-ID","rohc.comp_ip_id",
2815 FT_UINT16
, BASE_HEX_DEC
, NULL
, 0x0,
2821 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2825 { &hf_rohc_compressed_list
,
2826 { "Compressed List", "rohc.compressed-list",
2827 FT_NONE
, BASE_NONE
, NULL
, 0x0,
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,
2837 { &hf_rohc_compressed_list_gp
,
2838 { "Gen-id Present", "rohc.compressed-list.gp",
2839 FT_UINT8
, BASE_DEC
, NULL
, 0x20,
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,
2855 { &hf_rohc_compressed_list_count
,
2856 { "Count", "rohc.compressed-list.count",
2857 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
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,
2873 { &hf_rohc_compressed_list_gen_id
,
2874 { "gen_id", "rohc.compressed-list.gen-id",
2875 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2879 { &hf_rohc_compressed_list_ref_id
,
2880 { "ref_id", "rohc.compressed-list.ref-id",
2881 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
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,
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,
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,
2903 { &hf_rohc_spare_bits
,
2904 { "Spare bits(0)", "rohc.spare_bits",
2905 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2910 { "IP-ID", "rohc.ip-id",
2911 FT_UINT16
, BASE_HEX_DEC
, NULL
, 0x0,
2915 { &hf_rohc_udp_checksum
,
2916 { "UDP checksum", "rohc.udp_checksum",
2917 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2924 /* Setup protocol subtree array */
2925 static gint
*ett
[] = {
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
,
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
));
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");