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 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 * https://www.ietf.org/rfc/rfc3095 RObust Header Compression (ROHC): Framework and four profiles: RTP, UDP, ESP, and uncompressed
15 * https://datatracker.ietf.org/doc/rfc4815/ RObust Header Compression (ROHC): Corrections and Clarifications to RFC 3095
16 * https://datatracker.ietf.org/doc/rfc5225/ RObust Header Compression Version 2 (ROHCv2): Profiles for RTP, UDP, IP, ESP and UDP-Lite
18 * Only RTP (1) and UDP (2) are currently implemented.
23 #include <epan/packet.h>
24 #include <epan/etypes.h>
25 #include <epan/ipproto.h>
26 #include <epan/addr_resolv.h>
27 #include <epan/rtp_pt.h>
28 #include <epan/expert.h>
29 #include <epan/proto_data.h>
31 #include <wsutil/array.h>
32 #include "packet-rohc.h"
34 void proto_register_rohc(void);
35 void proto_reg_handoff_rohc(void);
38 dissect_compressed_list(int expected_encoding_type _U_
, packet_info
*pinfo _U_
,
39 proto_tree
*tree
, tvbuff_t
*tvb
, int offset
);
41 /* cid -> rohc_cid_context_t* */
42 static GHashTable
*rohc_cid_hash
;
44 /* Initialize the protocol and registered fields */
45 static int proto_rohc
;
48 static int hf_rohc_padding
;
49 static int hf_rohc_add_cid
;
50 static int hf_rohc_feedback
;
51 static int hf_rohc_code
;
52 static int hf_rohc_size
;
53 static int hf_rohc_ir_packet
;
54 static int hf_rohc_ir_dyn_packet
;
55 static int hf_rohc_small_cid
;
56 static int hf_rohc_large_cid
;
57 static int hf_rohc_acktype
;
58 static int hf_rohc_mode
;
59 static int hf_rohc_sn
;
60 static int hf_rohc_profile_spec_octet
;
61 static int hf_rohc_fb1_sn
;
62 static int hf_rohc_opt_type
;
63 static int hf_rohc_opt_len
;
64 static int hf_rohc_crc
;
65 static int hf_rohc_opt_sn
;
66 static int hf_rohc_ext
;
67 static int hf_rohc_ext_sn
;
68 static int hf_rohc_opt_clock
;
69 static int hf_rohc_opt_jitter
;
70 static int hf_rohc_opt_loss
;
71 static int hf_rohc_profile
;
72 static int hf_rohc_d_bit
;
73 static int hf_rohc_ip_version
;
74 static int hf_rohc_ip_version_ip_profile
;
75 static int hf_rohc_ip_protocol
;
76 static int hf_rohc_static_ipv4
;
77 static int hf_rohc_ipv4_src
;
78 static int hf_rohc_ipv4_dst
;
79 static int hf_rohc_ipv6_flow
;
80 static int hf_rohc_ipv6_nxt_hdr
;
81 static int hf_rohc_ipv6_src
;
82 static int hf_rohc_ipv6_dst
;
83 static int hf_rohc_static_udp
;
84 static int hf_rohc_udp_src_port
;
85 static int hf_rohc_udp_dst_port
;
86 static int hf_rohc_static_rtp
;
87 static int hf_rohc_rtp_ssrc
;
88 static int hf_rohc_dynamic_ipv4
;
89 static int hf_rohc_dynamic_udp
;
90 static int hf_rohc_rtp_tos
;
91 static int hf_rohc_rtp_ttl
;
92 static int hf_rohc_rtp_id
;
93 static int hf_rohc_rtp_df
;
94 static int hf_rohc_rtp_rnd
;
95 static int hf_rohc_rtp_nbo
;
96 static int hf_rohc_dynamic_udp_checksum
;
97 static int hf_rohc_dynamic_rtp
;
98 static int hf_rohc_rtp_v
;
99 static int hf_rohc_rtp_p
;
100 static int hf_rohc_rtp_rx
;
101 static int hf_rohc_rtp_cc
;
102 static int hf_rohc_rtp_m
;
103 static int hf_rohc_rtp_pt
;
104 static int hf_rohc_rtp_sn
;
105 static int hf_rohc_rtp_timestamp
;
106 static int hf_rohc_rtp_x
;
107 static int hf_rohc_rtp_mode
;
108 static int hf_rohc_rtp_tis
;
109 static int hf_rohc_rtp_tss
;
110 static int hf_rohc_rtp_ts_stride
;
111 static int hf_rohc_rtp_time_stride
;
112 static int hf_rohc_var_len
;
113 static int hf_rohc_ipv6_tc
;
114 static int hf_rohc_ipv6_hop_limit
;
115 static int hf_rohc_ir_pkt_frame
;
116 static int hf_rohc_ir_previous_frame
;
117 static int hf_rohc_ir_profile
;
118 static int hf_rohc_ir_ip_version
;
119 static int hf_rohc_ir_mode
;
120 static int hf_rohc_comp_sn
;
121 static int hf_rohc_r_0_crc
;
122 static int hf_rohc_x
;
123 static int hf_rohc_ts
;
124 static int hf_rohc_comp_ip_id
;
125 static int hf_rohc_comp_ip_id2
;
126 static int hf_rohc_t
;
127 static int hf_rohc_ext3_flags
;
128 static int hf_rohc_ext3_s
;
129 static int hf_rohc_ext3_r_ts
;
130 static int hf_rohc_ext3_tsc
;
131 static int hf_rohc_ext3_udp_mode
;
132 static int hf_rohc_ext3_i
;
133 static int hf_rohc_ext3_ip
;
134 static int hf_rohc_ext3_ip2
;
135 static int hf_rohc_ext3_rtp
;
136 static int hf_rohc_ext3_inner_ip_flags
;
137 static int hf_rohc_ext3_inner_tos
;
138 static int hf_rohc_ext3_inner_ttl
;
139 static int hf_rohc_ext3_inner_df
;
140 static int hf_rohc_ext3_inner_pr
;
141 static int hf_rohc_ext3_inner_ipx
;
142 static int hf_rohc_ext3_inner_nbo
;
143 static int hf_rohc_ext3_inner_rnd
;
144 static int hf_rohc_ext3_inner_ip2
;
145 static int hf_rohc_ext3_outer_ip_flags
;
146 static int hf_rohc_ext3_outer_tos
;
147 static int hf_rohc_ext3_outer_ttl
;
148 static int hf_rohc_ext3_outer_df
;
149 static int hf_rohc_ext3_outer_pr
;
150 static int hf_rohc_ext3_outer_ipx
;
151 static int hf_rohc_ext3_outer_nbo
;
152 static int hf_rohc_ext3_outer_rnd
;
153 static int hf_rohc_ext3_outer_i2
;
154 static int hf_rohc_ext3_rtp_flags
;
155 static int hf_rohc_ext3_rtp_mode
;
156 static int hf_rohc_ext3_r_pt
;
157 static int hf_rohc_ext3_m
;
158 static int hf_rohc_ext3_r_x
;
159 static int hf_rohc_ext3_csrc
;
160 static int hf_rohc_ext3_tss
;
161 static int hf_rohc_ext3_tis
;
162 static int hf_rohc_ext3_r_p
;
164 static int hf_rohc_compressed_list
;
165 static int hf_rohc_compressed_list_et
;
166 static int hf_rohc_compressed_list_gp
;
167 static int hf_rohc_compressed_list_ps
;
168 static int hf_rohc_compressed_list_res
;
169 static int hf_rohc_compressed_list_count
;
170 static int hf_rohc_compressed_list_cc
;
171 static int hf_rohc_compressed_list_xi_1
;
172 static int hf_rohc_compressed_list_gen_id
;
173 static int hf_rohc_compressed_list_ref_id
;
174 static int hf_rohc_compressed_list_mask_size
;
175 static int hf_rohc_compressed_list_ins_bit_mask
;
176 static int hf_rohc_compressed_list_rem_bit_mask
;
177 static int hf_rohc_spare_bits
;
178 static int hf_rohc_ip_id
;
179 static int hf_rohc_udp_checksum
;
180 /* Generated from convert_proto_tree_add_text.pl */
181 static int hf_rohc_no_configuration_info
;
182 static int hf_rohc_unknown_option_data
;
183 static int hf_rohc_error_packet
;
184 static int hf_rohc_configured_by_ir_packet
;
187 static int ett_rohc_conf
;
188 static int ett_rohc_fb
;
189 static int ett_rohc_feedback
;
190 static int ett_rohc_ir
;
191 static int ett_rohc_ir_dyn
;
192 static int ett_rohc_static_ipv4
;
193 static int ett_rohc_static_udp
;
194 static int ett_rohc_static_rtp
;
195 static int ett_rohc_rtp_static
;
196 static int ett_rohc_rtp_dynamic
;
197 static int ett_rohc_dynamic_ipv4
;
198 static int ett_rohc_dynamic_udp
;
199 static int ett_rohc_dynamic_rtp
;
200 static int ett_rohc_compressed_list
;
201 static int ett_rohc_packet
;
202 static int ett_rohc_ext
;
203 static int ett_rohc_ext3_flags
;
204 static int ett_rohc_ext3_inner_ip_flags
;
205 static int ett_rohc_ext3_outer_ip_flags
;
206 static int ett_rohc_ext3_rtp_flags
;
208 static expert_field ei_rohc_profile_spec_octet
;
209 static expert_field ei_rohc_rohc_opt_clock
;
210 static expert_field ei_rohc_opt_jitter
;
211 static expert_field ei_rohc_feedback_type_2_is_not_applicable_for_uncompressed_profile
;
212 static expert_field ei_rohc_not_dissected_yet
;
213 static expert_field ei_rohc_profile_specific
;
214 static expert_field ei_rohc_profile_not_supported
;
215 static expert_field ei_rohc_ip_version
;
216 static expert_field ei_rohc_desegmentation_not_implemented
;
218 static dissector_handle_t rohc_handle
;
220 static dissector_handle_t ip_handle
;
221 static dissector_handle_t ipv6_handle
;
230 typedef struct _rohc_cid_context_t
232 uint8_t rohc_ip_version
;
233 bool large_cid_present
;
235 enum rohc_d_mode d_mode
; /* Decompressor mode (not used) */
237 bool udp_checksum_present
;
239 int prev_ir_frame_number
; /* The frame number of the previous IR packet seen. -1 if not set */
240 int ir_frame_number
; /* The frame number of the latest IR packet seen. -1 if not set */
242 } rohc_cid_context_t
;
244 static const value_string rohc_profile_vals
[] =
246 { 0x0000, "Uncompressed" }, /*RFC 5795*/
247 { 0x0001, "RTP" }, /*RFC 3095*/
248 { 0x0002, "UDP" }, /*RFC 3095*/
249 { 0x0003, "ESP" }, /*RFC 3095*/
250 { 0x0004, "IP" }, /*RFC 3843*/
251 { 0x0005, "LLA" }, /*RFC 3242*/
252 { 0x0105, "LLA with R-mode" }, /*RFC 3408*/
253 { 0x0006, "TCP" }, /*RFC 4996*/
254 { 0x0007, "RTP/UDP-Lite" }, /*RFC 4019*/
255 { 0x0008, "UDP-Lite" }, /*RFC 4019*/
256 { 0x0101, "v2 RTP" }, /*RFC 5225*/
257 { 0x0102, "v2 UDP" }, /*RFC 5225*/
258 { 0x0103, "v2 ESP" }, /*RFC 5225*/
259 { 0x0104, "v2 IP" }, /*RFC 5225*/
260 { 0x0107, "v2 RTP/UDP-Lite" }, /*RFC 5225*/
261 { 0x0108, "v2 UDP-Lite" }, /*RFC 5225*/
265 /* Defaults if not supplied */
266 static uint16_t g_profile
= ROHC_PROFILE_UNKNOWN
;
267 static uint8_t g_version
= 4;
269 static const value_string rohc_acktype_vals
[] =
273 { 2, "STATIC-NACK" },
274 { 3, "reserved (MUST NOT be used. Otherwise unparsable.)" },
278 static const value_string rohc_mode_vals
[] =
281 { 1, "Unidirectional" },
282 { 2, "Bidirectional Optimistic" },
283 { 3, "Bidirectional Reliable" },
287 static const value_string rohc_opt_type_vals
[] =
291 { 3, "SN-NOT-VALID" },
301 static const value_string rohc_ip_version_vals
[] =
309 static const value_string rohc_ip_version_ip_profile_vals
[] =
318 static const value_string rohc_var_len_vals
[] =
322 { 6, "Three octets" },
323 { 7, "Four octets" },
327 static const value_string compressed_list_encoding_type_vals
[] =
329 { 0, "Generic scheme" },
330 { 1, "Insertion only scheme" },
331 { 2, "Removal only scheme" },
332 { 3, "Remove then insert scheme" },
336 static const value_string compressed_list_ps_vals
[] =
338 { 0, "4-bit XI fields" },
339 { 1, "8-bit XI fields" },
343 /* RTP extension 3 flags masks */
344 #define ROHC_RTP_EXT3_FLAGS_MASK 0x7f
345 #define ROHC_RTP_EXT3_S_MASK 0x20
346 #define ROHC_RTP_EXT3_R_TS_MASK 0x10
347 #define ROHC_RTP_EXT3_TSC_MASK 0x08
348 #define ROHC_RTP_EXT3_I_MASK 0x04
349 #define ROHC_RTP_EXT3_IP_MASK 0x02
350 #define ROHC_RTP_EXT3_RTP_MASK 0x01
351 /* RTP Inner IP header flags masks */
352 #define ROHC_RTP_EXT3_INNER_TOS_MASK 0x80
353 #define ROHC_RTP_EXT3_INNER_TTL_MASK 0x40
354 #define ROHC_RTP_EXT3_INNER_DF_MASK 0x20
355 #define ROHC_RTP_EXT3_INNER_PR_MASK 0x10
356 #define ROHC_RTP_EXT3_INNER_IPX_MASK 0x08
357 #define ROHC_RTP_EXT3_INNER_NBO_MASK 0x04
358 #define ROHC_RTP_EXT3_INNER_RND_MASK 0x02
359 #define ROHC_RTP_EXT3_INNER_IP2_MASK 0x01
360 /* RTP Outer IP header flags masks */
361 #define ROHC_RTP_EXT3_OUTER_TOS_MASK 0x80
362 #define ROHC_RTP_EXT3_OUTER_TTL_MASK 0x40
363 #define ROHC_RTP_EXT3_OUTER_DF_MASK 0x20
364 #define ROHC_RTP_EXT3_OUTER_PR_MASK 0x10
365 #define ROHC_RTP_EXT3_OUTER_IPX_MASK 0x08
366 #define ROHC_RTP_EXT3_OUTER_NBO_MASK 0x04
367 #define ROHC_RTP_EXT3_OUTER_RND_MASK 0x02
368 #define ROHC_RTP_EXT3_OUTER_I2_MASK 0x01
369 /* RTP header flags masks */
370 #define ROHC_RTP_EXT3_RTP_MODE_MASK 0xc0
371 #define ROHC_RTP_EXT3_R_PT_MASK 0x20
372 #define ROHC_RTP_EXT3_M_MASK 0x10
373 #define ROHC_RTP_EXT3_R_X_MASK 0x08
374 #define ROHC_RTP_EXT3_CSRC_MASK 0x04
375 #define ROHC_RTP_EXT3_TSS_MASK 0x02
376 #define ROHC_RTP_EXT3_TIS_MASK 0x01
377 /* RTP header fields masks */
378 #define ROHC_RTP_EXT3_R_P_MASK 0x80
380 /* UDP extension 3 flag masks */
381 #define ROHC_UDP_EXT3_UDP_MODE_MASK 0x18
382 #define ROHC_UDP_EXT3_IP2_MASK 0x01
385 /* 4.5.6. Self-describing variable-length values */
387 get_self_describing_var_len_val(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int hf_index
, uint8_t *val_len
)
391 int num_bits
= 0, bit_offset
= offset
<<3;
394 oct
= tvb_get_uint8(tvb
, offset
);
397 /* First bit is 0 - 1 octet */
400 proto_tree_add_bits_item(tree
, hf_rohc_var_len
, tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
403 } else if ((oct
&0xc0)==0x80) {
404 /* First bits are 10: 2 octets */
406 proto_tree_add_bits_item(tree
, hf_rohc_var_len
, tvb
, bit_offset
, 2, ENC_BIG_ENDIAN
);
409 val
= tvb_get_ntohs(tvb
, offset
)&0x3fff;
410 } else if ((oct
&0xe0)==0xc0) {
411 /* First bits are 110: 3 octets */
413 proto_tree_add_bits_item(tree
, hf_rohc_var_len
, tvb
, bit_offset
, 3, ENC_BIG_ENDIAN
);
416 val
= tvb_get_ntoh24(tvb
, offset
)&0x1fffff;
417 } else if ((oct
&0xe0)==0xe0) {
418 /* First bits are 111: 4 octets */
420 proto_tree_add_bits_item(tree
, hf_rohc_var_len
, tvb
, bit_offset
, 3, ENC_BIG_ENDIAN
);
423 val
= tvb_get_ntohl(tvb
, offset
)&0x1fffffff;
427 proto_tree_add_bits_item(tree
, hf_index
, tvb
, bit_offset
, num_bits
, ENC_BIG_ENDIAN
);
432 /* 5.7.1. Packet type 0: UO-0, R-0, R-0-CRC */
434 dissect_rohc_pkt_type_0(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint8_t pkt_type
, rohc_cid_context_t
*rohc_cid_context
)
438 proto_tree
*pkt_tree
;
440 switch (rohc_cid_context
->mode
) {
441 case RELIABLE_BIDIRECTIONAL
: /* R-mode */
442 if ((pkt_type
&0xc0)==0x00) {
446 * +---+---+---+---+---+---+---+---+
448 * +===+===+===+===+===+===+===+===+
450 if (rohc_cid_context
->large_cid_present
== true) {
451 /* Handle Large CID:s here */
452 get_self_describing_var_len_val(tvb
, tree
, offset
+1, hf_rohc_large_cid
, &val_len
);
455 col_append_str(pinfo
->cinfo
, COL_INFO
, "R-0");
456 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 1+val_len
, ett_rohc_packet
, NULL
, "R-0 packet");
459 sn
= tvb_get_bits8(tvb
,(offset
<<3)+2, 6);
460 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+2, 6, ENC_BIG_ENDIAN
);
461 offset
+= 1 + val_len
;
463 /* Show SN in info column */
464 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", (unsigned)sn
);
465 } else if ((pkt_type
&0xc0)==0x40) {
469 * +---+---+---+---+---+---+---+---+
471 * +===+===+===+===+===+===+===+===+
473 * +---+---+---+---+---+---+---+---+
475 crumb_spec_t rohc_sn_crumbs
[] = {
480 if (rohc_cid_context
->large_cid_present
) {
481 /* Handle Large CID:s here */
482 get_self_describing_var_len_val(tvb
, tree
, offset
+1, hf_rohc_large_cid
, &val_len
);
483 rohc_sn_crumbs
[1].crumb_bit_offset
+= val_len
*8;
485 /* R-0-CRC subtree */
486 col_append_str(pinfo
->cinfo
, COL_INFO
, "R-0-CRC");
487 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 2+val_len
, ett_rohc_packet
, NULL
, "R-0-CRC packet");
489 proto_tree_add_split_bits_item_ret_val(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3),
490 rohc_sn_crumbs
, &sn
);
491 offset
+= (1 + val_len
);
494 proto_tree_add_bits_item(pkt_tree
, hf_rohc_r_0_crc
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
497 /* Show SN in info column */
498 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", (unsigned)sn
);
501 case UNIDIRECTIONAL
: /* U-mode */
503 case OPTIMISTIC_BIDIRECTIONAL
: /* O-mode */
507 * +---+---+---+---+---+---+---+---+
509 * +===+===+===+===+===+===+===+===+
511 if (rohc_cid_context
->large_cid_present
== true) {
512 /* Handle Large CID:s here */
513 get_self_describing_var_len_val(tvb
, tree
, offset
+1, hf_rohc_large_cid
, &val_len
);
516 col_append_str(pinfo
->cinfo
, COL_INFO
, "UO-0");
517 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 1+val_len
, ett_rohc_packet
, NULL
, "UO-0 packet");
520 sn
= tvb_get_bits8(tvb
,(offset
<<3)+1, 4);
521 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+1, 4, ENC_BIG_ENDIAN
);
524 proto_tree_add_bits_item(pkt_tree
, hf_rohc_r_0_crc
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
525 offset
+= 1 + val_len
;
527 /* Show SN in info column */
528 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", (unsigned)sn
);
532 col_append_str(pinfo
->cinfo
, COL_INFO
, "Packet type 0");
539 /* 5.7.5. Extension formats */
540 /* UDP profile extension variations as described in 5.11.4 */
542 dissect_rohc_ext_format(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
,
543 uint8_t t
, /* T-bit from base compressed header */
544 rohc_cid_context_t
*rohc_cid_context
)
546 /* Extension subtree */
547 int start_offset
= offset
;
548 proto_item
*ext_ti
= proto_tree_add_string_format(tree
,
552 proto_tree
*ext_tree
= proto_item_add_subtree(ext_ti
, ett_rohc_ext
);
555 uint8_t ext_type
= (tvb_get_uint8(tvb
, offset
) & 0xc0) >> 6;
558 /* SN (common to extensions 0,1,2) */
559 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+2, 3, ENC_BIG_ENDIAN
);
566 * +---+---+---+---+---+---+---+---+
568 * +---+---+---+---+---+---+---+---+
572 * +---+---+---+---+---+---+---+---+
573 * | 0 0 | SN | IP-ID |
574 * +---+---+---+---+---+---+---+---+
577 proto_item_append_text(ext_ti
, " 0");
579 if ((t
== 0) || (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
)) {
581 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
584 proto_tree_add_bits_item(ext_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
588 } else if (ext_type
== 1) {
592 * +---+---+---+---+---+---+---+---+
594 * +---+---+---+---+---+---+---+---+
596 * +---+---+---+---+---+---+---+---+
599 * +---+---+---+---+---+---+---+---+
600 * | 0 1 | SN | IP-ID |
601 * +---+---+---+---+---+---+---+---+
603 * +---+---+---+---+---+---+---+---+
605 proto_item_append_text(ext_ti
, " 1");
607 if (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
) {
609 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+5, 11, ENC_BIG_ENDIAN
);
615 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
618 proto_tree_add_bits_item(ext_tree
, hf_rohc_ts
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
621 proto_tree_add_bits_item(ext_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
624 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
629 } else if (ext_type
== 2) {
633 * +---+---+---+---+---+---+---+---+
635 * +---+---+---+---+---+---+---+---+
637 * +---+---+---+---+---+---+---+---+
639 * +---+---+---+---+---+---+---+---+
642 * +---+---+---+---+---+---+---+---+
643 * | 1 0 | SN | IP-ID2 |
644 * +---+---+---+---+---+---+---+---+
646 * +---+---+---+---+---+---+---+---+
648 * +---+---+---+---+---+---+---+---+
650 proto_item_append_text(ext_ti
, " 2");
652 if (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
) {
654 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_ip_id2
, tvb
, (offset
<<3)+5, 11, ENC_BIG_ENDIAN
);
657 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
663 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+5, 11, ENC_BIG_ENDIAN
);
666 proto_tree_add_bits_item(ext_tree
, hf_rohc_ts
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
669 proto_tree_add_bits_item(ext_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+5, 11, ENC_BIG_ENDIAN
);
672 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
678 if ((rohc_cid_context
->profile
== ROHC_PROFILE_RTP
) ||
679 (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
)) {
683 * +-----+-----+-----+-----+-----+-----+-----+-----+
684 * | 1 1 | S |R-TS | Tsc | I | ip | rtp | (FLAGS)
685 * +-----+-----+-----+-----+-----+-----+-----+-----+
686 * | Inner IP header flags | ip2 | if ip = 1
687 * ..... ..... ..... ..... ..... ..... ..... .....
688 * | Outer IP header flags | if ip2 = 1
689 * ..... ..... ..... ..... ..... ..... ..... .....
691 * ..... ..... ..... ..... ..... ..... ..... .....
692 * / TS (encoded as in section 4.5.6) / 1-4 octets,
693 * ..... ..... ..... ..... ..... ..... ..... ..... if R-TS = 1
695 * / Inner IP header fields / variable,
697 * ..... ..... ..... ..... ..... ..... ..... .....
698 * | IP-ID | 2 octets, if I = 1
699 * ..... ..... ..... ..... ..... ..... ..... .....
701 * / Outer IP header fields / variable,
703 * ..... ..... ..... ..... ..... ..... ..... .....
705 * / RTP header flags and fields / variable,
707 * ..... ..... ..... ..... ..... ..... ..... .....
709 proto_item_append_text(ext_ti
, " 3");
711 static int * const ext3_rtp_flags
[] = {
720 static int * const ext3_udp_flags
[] = {
722 &hf_rohc_ext3_udp_mode
,
729 uint64_t ext3_flags_value
= 0;
730 uint64_t ext3_inner_ip_flags_value
= 0;
731 uint64_t ext3_outer_ip_flags_value
= 0;
734 proto_tree_add_bitmask_ret_uint64(ext_tree
, tvb
, offset
, hf_rohc_ext3_flags
, ett_rohc_ext3_flags
,
735 (rohc_cid_context
->profile
== ROHC_PROFILE_RTP
) ? ext3_rtp_flags
: ext3_udp_flags
,
736 ENC_BIG_ENDIAN
, &ext3_flags_value
);
739 if (ext3_flags_value
& ROHC_RTP_EXT3_IP_MASK
) {
740 static int * const inner_ip_flags
[] = {
741 &hf_rohc_ext3_inner_tos
,
742 &hf_rohc_ext3_inner_ttl
,
743 &hf_rohc_ext3_inner_df
,
744 &hf_rohc_ext3_inner_pr
,
745 &hf_rohc_ext3_inner_ipx
,
746 &hf_rohc_ext3_inner_nbo
,
747 &hf_rohc_ext3_inner_rnd
,
748 &hf_rohc_ext3_inner_ip2
,
751 /* Inner IP header flags
753 * These correspond to the inner IP header if there are two, and the
754 * single IP header otherwise.
757 * ..... ..... ..... ..... ..... ..... ..... .....
758 * | TOS | TTL | DF | PR | IPX | NBO | RND | ip2 | if ip = 1
759 * ..... ..... ..... ..... ..... ..... ..... .....
761 proto_tree_add_bitmask_ret_uint64(ext_tree
, tvb
, offset
, hf_rohc_ext3_inner_ip_flags
, ett_rohc_ext3_inner_ip_flags
, inner_ip_flags
, ENC_BIG_ENDIAN
, &ext3_inner_ip_flags_value
);
762 rohc_cid_context
->rnd
= ((ext3_inner_ip_flags_value
& ROHC_RTP_EXT3_INNER_RND_MASK
) != 0);
765 if (ext3_inner_ip_flags_value
& ROHC_RTP_EXT3_INNER_IP2_MASK
) {
766 static int * const outer_ip_flags
[] = {
767 &hf_rohc_ext3_outer_tos
,
768 &hf_rohc_ext3_outer_ttl
,
769 &hf_rohc_ext3_outer_df
,
770 &hf_rohc_ext3_outer_pr
,
771 &hf_rohc_ext3_outer_ipx
,
772 &hf_rohc_ext3_outer_nbo
,
773 &hf_rohc_ext3_outer_rnd
,
774 &hf_rohc_ext3_outer_i2
,
777 /* Outer IP header flags
779 * The fields in this part of the Extension 3 header refer to the
780 * outermost IP header:
783 * ..... ..... ..... ..... ..... ..... ..... .....
784 * | TOS2| TTL2| DF2 | PR2 |IPX2 |NBO2 |RND2 | I2 | if ip2 = 1
785 * ..... ..... ..... ..... ..... ..... ..... .....
787 proto_tree_add_bitmask_ret_uint64(ext_tree
, tvb
, offset
, hf_rohc_ext3_outer_ip_flags
, ett_rohc_ext3_outer_ip_flags
, outer_ip_flags
, ENC_BIG_ENDIAN
, &ext3_outer_ip_flags_value
);
788 /* TODO Update rnd when adding support for inner/outer behavior */
789 rohc_cid_context
->rnd
= ((ext3_outer_ip_flags_value
& ROHC_RTP_EXT3_OUTER_RND_MASK
) != 0);
792 if (ext3_flags_value
& ROHC_RTP_EXT3_S_MASK
) {
793 proto_tree_add_bits_item(ext_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3), 8, ENC_BIG_ENDIAN
);
796 if (ext3_flags_value
& ROHC_RTP_EXT3_R_TS_MASK
) {
798 get_self_describing_var_len_val(tvb
, ext_tree
, offset
, hf_rohc_ts
, &val_len
);
801 if (ext3_flags_value
& ROHC_RTP_EXT3_IP_MASK
) {
802 /* Inner IP header fields
804 * ..... ..... ..... ..... ..... ..... ..... .....
805 * | Type of Service/Traffic Class | if TOS = 1
806 * ..... ..... ..... ..... ..... ..... ..... .....
807 * | Time to Live/Hop Limit | if TTL = 1
808 * ..... ..... ..... ..... ..... ..... ..... .....
809 * | Protocol/Next Header | if PR = 1
810 * ..... ..... ..... ..... ..... ..... ..... .....
811 * / IP extension headers / variable,
812 * ..... ..... ..... ..... ..... ..... ..... ..... if IPX = 1
814 if (ext3_inner_ip_flags_value
& ROHC_RTP_EXT3_INNER_TOS_MASK
) {
815 proto_tree_add_item(ext_tree
, hf_rohc_rtp_tos
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
818 if (ext3_inner_ip_flags_value
& ROHC_RTP_EXT3_INNER_TTL_MASK
) {
819 proto_tree_add_item(ext_tree
, hf_rohc_rtp_ttl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
822 if (ext3_inner_ip_flags_value
& ROHC_RTP_EXT3_INNER_PR_MASK
) {
823 proto_tree_add_item(ext_tree
, hf_rohc_ip_protocol
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
826 if (ext3_inner_ip_flags_value
& ROHC_RTP_EXT3_INNER_IPX_MASK
) {
827 offset
= dissect_compressed_list(0, pinfo
, ext_tree
, tvb
, offset
);
830 if (ext3_flags_value
& ROHC_RTP_EXT3_I_MASK
) {
831 proto_tree_add_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
834 if (ext3_inner_ip_flags_value
& ROHC_RTP_EXT3_INNER_IP2_MASK
) {
835 /* Outer IP header fields
837 * ..... ..... ..... ..... ..... ..... ..... .....
838 * | Type of Service/Traffic Class | if TOS2 = 1
839 * ..... ..... ..... ..... ..... ..... ..... .....
840 * | Time to Live/Hop Limit | if TTL2 = 1
841 * ..... ..... ..... ..... ..... ..... ..... .....
842 * | Protocol/Next Header | if PR2 = 1
843 * ..... ..... ..... ..... ..... ..... ..... .....
844 * / IP extension header(s) / variable,
845 * ..... ..... ..... ..... ..... ..... ..... ..... if IPX2 = 1
846 * | IP-ID | 2 octets,
847 * ..... ..... ..... ..... ..... ..... ..... ..... if I2 = 1
849 if (ext3_outer_ip_flags_value
& ROHC_RTP_EXT3_OUTER_TOS_MASK
) {
850 proto_tree_add_item(ext_tree
, hf_rohc_rtp_tos
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
853 if (ext3_outer_ip_flags_value
& ROHC_RTP_EXT3_OUTER_TTL_MASK
) {
854 proto_tree_add_item(ext_tree
, hf_rohc_rtp_ttl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
857 if (ext3_outer_ip_flags_value
& ROHC_RTP_EXT3_OUTER_PR_MASK
) {
858 proto_tree_add_item(ext_tree
, hf_rohc_ip_protocol
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
861 if (ext3_outer_ip_flags_value
& ROHC_RTP_EXT3_OUTER_IPX_MASK
) {
862 offset
= dissect_compressed_list(0, pinfo
, ext_tree
, tvb
, offset
);
864 if (ext3_outer_ip_flags_value
& ROHC_RTP_EXT3_OUTER_I2_MASK
) {
865 proto_tree_add_item(ext_tree
, hf_rohc_comp_ip_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
869 if ((rohc_cid_context
->profile
== ROHC_PROFILE_RTP
) &&
870 (ext3_flags_value
& ROHC_RTP_EXT3_RTP_MASK
)) {
872 uint64_t ext3_rtp_flags_value
= 0;
873 static int * const rtp_flags
[] = {
874 &hf_rohc_ext3_rtp_mode
,
883 /* RTP header flags and fields
886 * ..... ..... ..... ..... ..... ..... ..... .....
887 * | Mode |R-PT | M | R-X |CSRC | TSS | TIS | if rtp = 1
888 * ..... ..... ..... ..... ..... ..... ..... .....
889 * | R-P | RTP PT | if R-PT = 1
890 * ..... ..... ..... ..... ..... ..... ..... .....
891 * / Compressed CSRC list / if CSRC = 1
892 * ..... ..... ..... ..... ..... ..... ..... .....
893 * / TS_STRIDE / 1-4 oct if TSS = 1
894 * ..... ..... ..... ..... ..... ..... ..... ....
895 * / TIME_STRIDE (milliseconds) / 1-4 oct if TIS = 1
896 * ..... ..... ..... ..... ..... ..... ..... .....
898 proto_tree_add_bitmask_ret_uint64(ext_tree
, tvb
, offset
, hf_rohc_ext3_rtp_flags
, ett_rohc_ext3_rtp_flags
, rtp_flags
, ENC_BIG_ENDIAN
, &ext3_rtp_flags_value
);
899 rohc_cid_context
->mode
= (enum rohc_mode
)((ext3_rtp_flags_value
& ROHC_RTP_EXT3_RTP_MODE_MASK
)>>6);
902 if (ext3_rtp_flags_value
& ROHC_RTP_EXT3_R_PT_MASK
) {
903 proto_tree_add_item(ext_tree
, hf_rohc_ext3_r_p
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
904 proto_tree_add_item(ext_tree
, hf_rohc_rtp_pt
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
907 if (ext3_rtp_flags_value
& ROHC_RTP_EXT3_CSRC_MASK
) {
908 offset
= dissect_compressed_list(0, pinfo
, ext_tree
, tvb
, offset
);
910 if (ext3_rtp_flags_value
& ROHC_RTP_EXT3_TSS_MASK
) {
912 get_self_describing_var_len_val(tvb
, ext_tree
, offset
, hf_rohc_rtp_ts_stride
, &val_len
);
915 if (ext3_rtp_flags_value
& ROHC_RTP_EXT3_TIS_MASK
) {
917 get_self_describing_var_len_val(tvb
, ext_tree
, offset
, hf_rohc_rtp_time_stride
, &val_len
);
922 proto_tree_add_expert_format(ext_tree
, pinfo
, &ei_rohc_not_dissected_yet
, tvb
, offset
, -1,
923 "extension 3 [Not dissected yet for profile %u]", rohc_cid_context
->profile
);
924 if (tvb_captured_length_remaining(tvb
, offset
) > 0)
925 offset
+= tvb_captured_length_remaining(tvb
, offset
);
929 proto_item_set_len(ext_ti
, offset
-start_offset
);
933 /* 5.7.2. Packet type 1 (R-mode): R-1, R-1-TS, R-1-ID */
935 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
)
938 proto_tree
*pkt_tree
;
939 uint8_t val_len
= 0, x
, sn
, t
= 0xff;
940 int start_offset
= offset
;
942 if (rohc_cid_context
->large_cid_present
== true) {
943 /* Handle Large CID:s here */
944 get_self_describing_var_len_val(tvb
, tree
, offset
+1, hf_rohc_large_cid
, &val_len
);
947 if ((rohc_cid_context
->rohc_ip_version
!= 4) ||
948 (rohc_cid_context
->rnd
) ||
949 (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
)) {
953 * +---+---+---+---+---+---+---+---+
955 * +===+===+===+===+===+===+===+===+
957 * +---+---+---+---+---+---+---+---+
962 * +---+---+---+---+---+---+---+---+
964 * +===+===+===+===+===+===+===+===+
966 * +---+---+---+---+---+---+---+---+
968 col_append_str(pinfo
->cinfo
, COL_INFO
, "R-1");
970 /* Create R-1 subtree */
971 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "R-1 packet");
974 sn
= tvb_get_bits8(tvb
, (offset
<<3)+2, 6);
975 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+2, 6, ENC_BIG_ENDIAN
);
976 offset
+= 1 + val_len
;
978 /* Show SN in info column */
979 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", sn
);
980 if (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
) {
984 x
= tvb_get_bits8(tvb
, (offset
<<3), 1);
985 proto_tree_add_bits_item(pkt_tree
, hf_rohc_x
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
988 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
993 proto_tree_add_bits_item(pkt_tree
, hf_rohc_rtp_m
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
996 x
= tvb_get_bits8(tvb
, (offset
<<3)+1, 1);
997 proto_tree_add_bits_item(pkt_tree
, hf_rohc_x
, tvb
, (offset
<<3)+1, 1, ENC_BIG_ENDIAN
);
1000 proto_tree_add_bits_item(pkt_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+2, 6, ENC_BIG_ENDIAN
);
1004 /* Packet type depends upon value of T bit */
1005 t
= tvb_get_bits8(tvb
, ((offset
+1+val_len
)<<3)+2, 1);
1010 * +---+---+---+---+---+---+---+---+
1012 * +===+===+===+===+===+===+===+===+
1013 * | M | X |T=0| IP-ID |
1014 * +---+---+---+---+---+---+---+---+
1016 col_append_str(pinfo
->cinfo
, COL_INFO
, "R-1-ID");
1017 /* Create R-1-ID subtree */
1018 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "R-1-ID packet");
1023 * +---+---+---+---+---+---+---+---+
1025 * +===+===+===+===+===+===+===+===+
1026 * | M | X |T=1| TS |
1027 * +---+---+---+---+---+---+---+---+
1029 col_append_str(pinfo
->cinfo
, COL_INFO
, "R-1-TS");
1030 /* Create R-1-TS subtree */
1031 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "R-1-TS packet");
1035 sn
= tvb_get_bits8(tvb
, (offset
<<3)+2, 6);
1036 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+2, 6, ENC_BIG_ENDIAN
);
1037 offset
+= 1 + val_len
;
1038 /* Show SN in info column */
1039 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", sn
);
1042 proto_tree_add_bits_item(pkt_tree
, hf_rohc_rtp_m
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
1045 x
= tvb_get_bits8(tvb
, (offset
<<3)+1, 1);
1046 proto_tree_add_bits_item(pkt_tree
, hf_rohc_x
, tvb
, (offset
<<3)+1, 1, ENC_BIG_ENDIAN
);
1049 proto_tree_add_bits_item(pkt_tree
, hf_rohc_t
, tvb
, (offset
<<3)+2, 1, ENC_BIG_ENDIAN
);
1052 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
1055 proto_tree_add_bits_item(pkt_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
1061 offset
= dissect_rohc_ext_format(tvb
, pinfo
, pkt_tree
, offset
, t
, rohc_cid_context
);
1063 proto_item_set_len(ti
, offset
-start_offset
);
1068 /* 5.7.3. Packet type 1 (U/O-mode): UO-1, UO-1-ID, UO-1-TS */
1070 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
)
1073 proto_tree
*pkt_tree
;
1074 uint8_t val_len
= 0, x
= 0, sn
, t
= 0xff;
1075 int start_offset
= offset
;
1077 if (rohc_cid_context
->large_cid_present
== true) {
1078 /* Handle Large CID:s here */
1079 get_self_describing_var_len_val(tvb
, tree
, offset
+1, hf_rohc_large_cid
, &val_len
);
1082 if ((rohc_cid_context
->rohc_ip_version
!= 4) ||
1083 (rohc_cid_context
->rnd
) ||
1084 (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
)) {
1085 /* UO-1 (RTP profile)
1088 * +---+---+---+---+---+---+---+---+
1090 * +===+===+===+===+===+===+===+===+
1092 * +---+---+---+---+---+---+---+---+
1094 /* UO-1 (UDP profile)
1097 * +---+---+---+---+---+---+---+---+
1099 * +===+===+===+===+===+===+===+===+
1101 * +---+---+---+---+---+---+---+---+
1103 col_append_str(pinfo
->cinfo
, COL_INFO
, "UO-1");
1105 /* Create subtree */
1106 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "UO-1 packet");
1107 if (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
) {
1109 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+2, 6, ENC_BIG_ENDIAN
);
1110 offset
+= 1 + val_len
;
1113 sn
= tvb_get_bits8(tvb
, (offset
<<3), 5);
1114 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3), 5, ENC_BIG_ENDIAN
);
1119 proto_tree_add_bits_item(pkt_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+2, 6, ENC_BIG_ENDIAN
);
1120 offset
+= 1 + val_len
;
1123 proto_tree_add_bits_item(pkt_tree
, hf_rohc_rtp_m
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
1126 sn
= tvb_get_bits8(tvb
, (offset
<<3)+1, 4);
1127 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+1, 4, ENC_BIG_ENDIAN
);
1129 /* Show SN in info column */
1130 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", sn
);
1132 /* CRC (common to both) */
1133 proto_tree_add_bits_item(pkt_tree
, hf_rohc_crc
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
1136 /* Type depends upon t bit */
1137 t
= tvb_get_bits8(tvb
, ((offset
)<<3)+2, 1);
1142 * +---+---+---+---+---+---+---+---+
1143 * | 1 0 |T=0| IP-ID |
1144 * +===+===+===+===+===+===+===+===+
1146 * +---+---+---+---+---+---+---+---+
1148 col_append_str(pinfo
->cinfo
, COL_INFO
, "UO-1-ID");
1150 /* UO-1-ID subtree */
1151 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "UO-1-ID packet");
1154 proto_tree_add_bits_item(pkt_tree
, hf_rohc_t
, tvb
, (offset
<<3)+2, 1, ENC_BIG_ENDIAN
);
1157 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
1158 offset
+= 1 + val_len
;
1161 x
= tvb_get_bits8(tvb
, (offset
<<3), 1);
1162 proto_tree_add_bits_item(pkt_tree
, hf_rohc_x
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
1167 * +---+---+---+---+---+---+---+---+
1169 * +===+===+===+===+===+===+===+===+
1171 * +---+---+---+---+---+---+---+---+
1173 col_append_str(pinfo
->cinfo
, COL_INFO
, "UO-1-TS");
1175 /* UO-1-TS subtree */
1176 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "UO-1-TS packet");
1179 proto_tree_add_bits_item(pkt_tree
, hf_rohc_t
, tvb
, (offset
<<3)+2, 1, ENC_BIG_ENDIAN
);
1182 proto_tree_add_bits_item(pkt_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
1183 offset
+= 1 + val_len
;
1186 proto_tree_add_bits_item(pkt_tree
, hf_rohc_rtp_m
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
1190 sn
= tvb_get_bits8(tvb
, (offset
<<3)+1, 4);
1191 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+1, 4, ENC_BIG_ENDIAN
);
1192 /* Show SN in info column */
1193 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", sn
);
1196 proto_tree_add_bits_item(pkt_tree
, hf_rohc_crc
, tvb
, (offset
<<3)+5, 3, ENC_BIG_ENDIAN
);
1200 offset
= dissect_rohc_ext_format(tvb
, pinfo
, pkt_tree
, offset
, t
, rohc_cid_context
);
1202 proto_item_set_len(ti
, offset
-start_offset
);
1207 /* 5.7.4. Packet type 2: UOR-2 */
1209 dissect_rohc_pkt_type_2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, rohc_cid_context_t
*rohc_cid_context
)
1212 proto_tree
*pkt_tree
;
1213 uint8_t val_len
= 0, x
, sn
, t
= 0xff;
1214 int start_offset
= offset
;
1216 if (rohc_cid_context
->large_cid_present
== true) {
1217 /* Handle Large CID:s here */
1218 get_self_describing_var_len_val(tvb
, tree
, offset
+1, hf_rohc_large_cid
, &val_len
);
1221 if ((rohc_cid_context
->rohc_ip_version
!= 4) ||
1222 (rohc_cid_context
->rnd
) ||
1223 (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
)) {
1224 /* UOR-2 (RTP profile)
1227 * +---+---+---+---+---+---+---+---+
1229 * +===+===+===+===+===+===+===+===+
1231 * +---+---+---+---+---+---+---+---+
1233 * +---+---+---+---+---+---+---+---+
1235 /* UOR-2 (UDP profile)
1238 * +---+---+---+---+---+---+---+---+
1240 * +===+===+===+===+===+===+===+===+
1242 * +---+---+---+---+---+---+---+---+
1244 col_append_str(pinfo
->cinfo
, COL_INFO
, "UOR-2");
1247 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "UOR-2 packet");
1248 if (rohc_cid_context
->profile
== ROHC_PROFILE_UDP
) {
1252 sn
= tvb_get_bits8(tvb
, (offset
<<3)+3, 5);
1253 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
1254 offset
+= 1 + val_len
;
1255 /* Show SN in info column */
1256 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", sn
);
1261 crumb_spec_t rohc_ts_crumbs
[] = {
1266 rohc_ts_crumbs
[1].crumb_bit_offset
+= val_len
*8;
1268 proto_tree_add_split_bits_item_ret_val(pkt_tree
, hf_rohc_ts
, tvb
, (offset
<<3),
1269 rohc_ts_crumbs
, NULL
);
1270 offset
+= 1 + val_len
;
1273 proto_tree_add_bits_item(pkt_tree
, hf_rohc_rtp_m
, tvb
, (offset
<<3)+1, 1, ENC_BIG_ENDIAN
);
1274 sn
= tvb_get_bits8(tvb
, (offset
<<3)+2, 6);
1277 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+2, 6, ENC_BIG_ENDIAN
);
1279 /* Show SN in info column */
1280 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", sn
);
1283 /* X - common to both */
1284 x
= tvb_get_bits8(tvb
, (offset
<<3), 1);
1285 proto_tree_add_bits_item(pkt_tree
, hf_rohc_x
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
1287 /* CRC - common to both */
1288 proto_tree_add_bits_item(pkt_tree
, hf_rohc_crc
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
1291 /* Packet type depends upon T bit */
1292 t
= tvb_get_bits8(tvb
, ((offset
+1+val_len
)<<3), 1);
1297 * +---+---+---+---+---+---+---+---+
1299 * +===+===+===+===+===+===+===+===+
1301 * +---+---+---+---+---+---+---+---+
1303 * +---+---+---+---+---+---+---+---+
1305 col_append_str(pinfo
->cinfo
, COL_INFO
, "UOR-2-ID");
1307 /* UOR-2-ID subtree */
1308 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "UOR-2-ID packet");
1311 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_ip_id
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
1316 * +---+---+---+---+---+---+---+---+
1318 * +===+===+===+===+===+===+===+===+
1320 * +---+---+---+---+---+---+---+---+
1322 * +---+---+---+---+---+---+---+---+
1324 col_append_str(pinfo
->cinfo
, COL_INFO
, "UOR-2-TS");
1326 /* UOR-2-TS subtree */
1327 pkt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_rohc_packet
, &ti
, "UOR-2-TS packet");
1330 proto_tree_add_bits_item(pkt_tree
, hf_rohc_ts
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
1332 offset
+= 1 + val_len
;
1334 /* T - commonto both */
1335 proto_tree_add_bits_item(pkt_tree
, hf_rohc_t
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
1337 /* M - common to both */
1338 proto_tree_add_bits_item(pkt_tree
, hf_rohc_rtp_m
, tvb
, (offset
<<3)+1, 1, ENC_BIG_ENDIAN
);
1340 /* SN - common to both */
1341 sn
= tvb_get_bits8(tvb
, (offset
<<3)+2, 6);
1342 proto_tree_add_bits_item(pkt_tree
, hf_rohc_comp_sn
, tvb
, (offset
<<3)+2, 6, ENC_BIG_ENDIAN
);
1344 /* Show SN in info column */
1345 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", sn
);
1347 /* X - common to both */
1348 x
= tvb_get_bits8(tvb
, (offset
<<3), 1);
1349 proto_tree_add_bits_item(pkt_tree
, hf_rohc_x
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
1351 /* CRC - common to both */
1352 proto_tree_add_bits_item(pkt_tree
, hf_rohc_crc
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
1356 offset
= dissect_rohc_ext_format(tvb
, pinfo
, pkt_tree
, offset
, t
, rohc_cid_context
);
1358 proto_item_set_len(ti
, offset
-start_offset
);
1364 dissect_rohc_feedback_data(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int offset
, int16_t feedback_data_len
,
1365 rohc_info
*p_rohc_info
, uint16_t cid
, bool cid_context
)
1368 proto_tree
*rohc_feedback_tree
;
1369 uint8_t opt
, opt_len
, oct
;
1370 rohc_cid_context_t
*rohc_cid_context
= NULL
;
1374 /* Look up context using cid */
1375 if (!PINFO_FD_VISITED(pinfo
)) {
1376 rohc_cid_context
= (rohc_cid_context_t
*)g_hash_table_lookup(rohc_cid_hash
, GUINT_TO_POINTER(key
));
1377 if (rohc_cid_context
) {
1378 p_add_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0, rohc_cid_context
);
1381 rohc_cid_context
= (rohc_cid_context_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0);
1384 if (!rohc_cid_context
) {
1386 /* Reuse info coming from private data */
1387 rohc_cid_context
= wmem_new(pinfo
->pool
, rohc_cid_context_t
);
1388 /*rohc_cid_context->d_mode;*/
1389 rohc_cid_context
->rnd
= p_rohc_info
->rnd
;
1390 rohc_cid_context
->udp_checksum_present
= p_rohc_info
->udp_checksum_present
;
1391 rohc_cid_context
->profile
= p_rohc_info
->profile
;
1392 rohc_cid_context
->mode
= p_rohc_info
->mode
;
1393 rohc_cid_context
->rohc_ip_version
= p_rohc_info
->rohc_ip_version
;
1394 rohc_cid_context
->large_cid_present
= p_rohc_info
->large_cid_present
;
1395 rohc_cid_context
->prev_ir_frame_number
= -1;
1396 rohc_cid_context
->ir_frame_number
= -1;
1398 /* No context info, not much we can do */
1399 proto_item_append_text(p_rohc_info
->last_created_item
, " (type %d)", (feedback_data_len
==1) ? 1 : 2);
1400 proto_tree_add_expert_format(tree
, pinfo
, &ei_rohc_profile_not_supported
, tvb
, offset
, feedback_data_len
, "profile-specific information [Profile not known]");
1405 if (feedback_data_len
==1) {
1407 proto_item_append_text(p_rohc_info
->last_created_item
, " (type 1)");
1408 oct
= tvb_get_uint8(tvb
, offset
);
1409 switch (rohc_cid_context
->profile
) {
1410 case ROHC_PROFILE_UNCOMPRESSED
: /* 0 */
1411 ti
= proto_tree_add_item(tree
, hf_rohc_profile_spec_octet
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1413 expert_add_info_format(pinfo
, ti
, &ei_rohc_profile_spec_octet
, "Invalid profile-specific octet value (0x%02X)", oct
);
1416 case ROHC_PROFILE_RTP
: /* 1 */
1417 case ROHC_PROFILE_UDP
: /* 2 */
1420 * +---+---+---+---+---+---+---+---+
1422 * +---+---+---+---+---+---+---+---+
1427 proto_tree_add_item(tree
, hf_rohc_fb1_sn
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1428 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", oct
);
1431 proto_tree_add_expert(tree
, pinfo
, &ei_rohc_profile_specific
, tvb
, offset
, feedback_data_len
);
1437 proto_item_append_text(p_rohc_info
->last_created_item
, " (type 2)");
1438 switch (rohc_cid_context
->profile
) {
1439 case ROHC_PROFILE_UNCOMPRESSED
: /* 0 */
1440 expert_add_info(pinfo
, p_rohc_info
->last_created_item
, &ei_rohc_feedback_type_2_is_not_applicable_for_uncompressed_profile
);
1442 case ROHC_PROFILE_RTP
: /* 1 */
1443 case ROHC_PROFILE_UDP
: /* 2 */
1445 * +---+---+---+---+---+---+---+---+
1446 * |Acktype| Mode | SN |
1447 * +---+---+---+---+---+---+---+---+
1449 * +---+---+---+---+---+---+---+---+
1450 * / Feedback options /
1451 * +---+---+---+---+---+---+---+---+
1455 rohc_feedback_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, feedback_data_len
, ett_rohc_feedback
, NULL
,
1456 "%s profile-specific information",
1457 (rohc_cid_context
->profile
== ROHC_PROFILE_RTP
) ? "RTP" : "UDP");
1458 /* Set mode at first pass? Do we need a new context for the following frames?
1463 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_acktype
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1465 rohc_cid_context
->mode
= (enum rohc_mode
)((tvb_get_uint8(tvb
,offset
) & 0x30)>>4);
1466 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_mode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1468 sn
= tvb_get_ntohs(tvb
, offset
) & 0x0fff;
1469 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_sn
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1471 feedback_data_len
-=2;
1474 * +---+---+---+---+---+---+---+---+
1475 * | Opt Type | Opt Len |
1476 * +---+---+---+---+---+---+---+---+
1477 * / option data / Opt Len octets
1478 * +---+---+---+---+---+---+---+---+
1480 while (feedback_data_len
>0) {
1481 opt
= opt_len
= tvb_get_uint8(tvb
,offset
);
1483 opt_len
= opt_len
&0x0f;
1485 ti
= proto_tree_add_item(rohc_feedback_tree
, hf_rohc_opt_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1487 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_opt_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1489 feedback_data_len
--;
1495 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1496 oct
= tvb_get_uint8(tvb
, offset
);
1497 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "CRC=%u ", oct
);
1501 col_append_str(pinfo
->cinfo
, COL_INFO
, "Reject ");
1505 col_append_str(pinfo
->cinfo
, COL_INFO
, "SN-Not-Valid ");
1509 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_opt_sn
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1510 sn
= (sn
<< 8) | tvb_get_uint8(tvb
, offset
);
1511 ti
= proto_tree_add_uint(rohc_feedback_tree
, hf_rohc_ext_sn
, tvb
, 0, 0, sn
);
1512 proto_item_set_generated(ti
);
1516 if (rohc_cid_context
->profile
== ROHC_PROFILE_RTP
) {
1517 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_opt_clock
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1518 oct
= tvb_get_uint8(tvb
, offset
);
1519 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Clock=%u ", oct
);
1521 expert_add_info(pinfo
, ti
, &ei_rohc_rohc_opt_clock
);
1526 if (rohc_cid_context
->profile
== ROHC_PROFILE_RTP
) {
1527 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_opt_jitter
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1528 oct
= tvb_get_uint8(tvb
, offset
);
1529 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Jitter=%u ", oct
);
1531 expert_add_info(pinfo
, ti
, &ei_rohc_opt_jitter
);
1536 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_opt_loss
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1537 oct
= tvb_get_uint8(tvb
, offset
);
1538 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Loss=%u ", oct
);
1542 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_unknown_option_data
, tvb
, offset
, opt_len
, ENC_NA
);
1545 feedback_data_len
= feedback_data_len
- opt_len
;
1546 offset
= offset
+ opt_len
;
1549 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (sn=%u)", sn
);
1553 rohc_feedback_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, feedback_data_len
,
1554 ett_rohc_feedback
, NULL
, "profile-specific information[Not dissected yet]");
1555 proto_tree_add_item(rohc_feedback_tree
, hf_rohc_acktype
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1561 static const true_false_string rohc_cmp_lst_mask_size_vals
= { "15-bit mask", "7-bit mask" };
1564 /* 5.8.6. Compressed list formats */
1566 dissect_compressed_list(int expected_encoding_type _U_
, packet_info
*pinfo _U_
,
1567 proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
1569 proto_item
*list_ti
/* , *et_ti */;
1570 proto_item
*list_tree
;
1571 uint8_t first_byte
= tvb_get_uint8(tvb
, offset
);
1572 uint8_t ET
, GP
, PS
, CC
, bit_mask_size
;
1573 int start_offset
= offset
;
1575 /* Compressed list root */
1576 list_ti
= proto_tree_add_item(tree
, hf_rohc_compressed_list
, tvb
, offset
, -1, ENC_NA
);
1577 list_tree
= proto_item_add_subtree(list_ti
, ett_rohc_compressed_list
);
1579 /* Fixed fields from first byte */
1580 ET
= (first_byte
& 0xc0) >> 6;
1581 /* et_ti = proto_tree_add_item(list_tree, hf_rohc_compressed_list_et, tvb, offset, 1, ENC_BIG_ENDIAN); */
1582 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_et
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1583 proto_item_append_text(list_ti
, " (type=%d - %s)",
1584 ET
, val_to_str_const(ET
, compressed_list_encoding_type_vals
, "Unknown"));
1586 if (ET
!= expected_encoding_type
) {
1587 expert_add_info_format(pinfo
, et_ti
, PI_MALFORMED
, PI_ERROR
,
1588 "Wrong compressed list encoding type (expected %d, got %d)",
1589 expected_encoding_type
, ET
);
1593 GP
= (first_byte
& 0x20) >> 5;
1594 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gp
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1598 /* 5.8.6.1 Encoding Type 0 (generic scheme)
1601 * +---+---+---+---+---+---+---+---+
1602 * | ET=0 |GP |PS | CC = m |
1603 * +---+---+---+---+---+---+---+---+
1604 * : gen_id : 1 octet, if GP = 1
1605 * +---+---+---+---+---+---+---+---+
1606 * | XI 1, ..., XI m | m octets, or m * 4 bits
1607 * / --- --- --- ---/
1608 * | : Padding : if PS = 0 and m is odd
1609 * +---+---+---+---+---+---+---+---+
1611 * / item 1, ..., item n / variable
1613 * +---+---+---+---+---+---+---+---+
1616 /* PS = (first_byte & 0x10) >> 4;
1617 * PS: Indicates size of XI fields:
1618 * PS = 0 indicates 4-bit XI fields;
1619 * PS = 1 indicates 8-bit XI fields.
1621 PS
= (first_byte
& 0x10) >> 4;
1622 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ps
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1624 /* CC: CSRC counter from original RTP header. */
1625 CC
= first_byte
& 0x0f;
1626 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_cc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1629 /* GP: Indicates presence of gen_id field. */
1631 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gen_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1635 /* TODO: calculate how many bytes to skip for items */
1637 * XI 1, ..., XI m: m XI items. The format of an XI item is as
1641 * PS = 0: | X | Index |
1645 * +---+---+---+---+---+---+---+---+
1646 * PS = 1: | X | Index |
1647 * +---+---+---+---+---+---+---+---+
1649 * X = 1 indicates that the item corresponding to the Index
1650 * is sent in the item 0, ..., item n list.
1651 * X = 0 indicates that the item corresponding to the Index is
1655 /* PS = 1 indicates 8-bit XI fields. */
1657 /* PS = 0 indicates 4-bit XI fields; */
1665 * 5.8.6.2. Encoding Type 1 (insertion only scheme)
1668 * +---+---+---+---+---+---+---+---+
1669 * | ET=1 |GP |PS | XI 1 |
1670 * +---+---+---+---+---+---+---+---+
1671 * : gen_id : 1 octet, if GP = 1
1672 * +---+---+---+---+---+---+---+---+
1674 * +---+---+---+---+---+---+---+---+
1675 * / insertion bit mask / 1-2 octets
1676 * +---+---+---+---+---+---+---+---+
1677 * | XI list | k octets, or (k - 1) * 4 bits
1678 * / --- --- --- ---/
1679 * | : Padding : if PS = 0 and k is even
1680 * +---+---+---+---+---+---+---+---+
1682 * / item 1, ..., item n / variable
1684 * +---+---+---+---+---+---+---+---+
1687 PS
= (first_byte
& 0x10) >> 4;
1688 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ps
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1689 /* XI 1: When PS = 0, the first 4-bit XI item is placed here.
1690 * When PS = 1, the field is set to zero when sending, and
1691 * ignored when receiving.
1694 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_xi_1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1697 /* GP: Indicates presence of gen_id field. */
1699 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gen_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1702 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ref_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1705 * insertion bit mask: Bit mask indicating the positions where new
1706 * items are to be inserted. See Insertion Only scheme in
1707 * section 5.8.3. The bit mask can have either of the
1708 * following two formats:
1712 * +---+---+---+---+---+---+---+---+
1713 * | 0 | 7-bit mask | bit 1 is the first bit
1714 * +---+---+---+---+---+---+---+---+
1716 * +---+---+---+---+---+---+---+---+
1717 * | 1 | | bit 1 is the first bit
1718 * +---+ 15-bit mask +
1719 * | | bit 7 is the last bit
1720 * +---+---+---+---+---+---+---+---+
1722 bit_mask_size
= (tvb_get_uint8(tvb
,offset
)&0x80)>>7;
1723 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_mask_size
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1724 if (bit_mask_size
) {
1725 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_ins_bit_mask
, tvb
, (offset
<<3)+1, 15, ENC_BIG_ENDIAN
);
1728 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_ins_bit_mask
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
1733 * XI list: XI fields for items to be inserted. When the insertion
1734 * bit mask has k ones, the total number of XI fields is k. When
1735 * PS = 1, all XI fields are in the XI list. When PS = 0, the
1736 * first XI field is in the XI 1 field, and the remaining k - 1
1737 * XI fields are in the XI list.
1739 * Padding: Present when PS = 0 and k is even.
1745 * 5.8.6.3. Encoding Type 2 (removal only scheme)
1748 * +---+---+---+---+---+---+---+---+
1749 * | ET=2 |GP |res| Count |
1750 * +---+---+---+---+---+---+---+---+
1751 * : gen_id : 1 octet, if GP = 1
1752 * +---+---+---+---+---+---+---+---+
1754 * +---+---+---+---+---+---+---+---+
1755 * / removal bit mask / 1-2 octets
1756 * +---+---+---+---+---+---+---+---+
1759 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_res
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1760 /* Count: Number of elements in ref_list. */
1761 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_count
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1763 /* GP: Indicates presence of gen_id field. */
1765 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gen_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1768 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ref_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1771 * removal bit mask: Indicates the elements in ref_list to be
1772 * removed in order to obtain the current list. See section
1773 * 5.8.3. The removal bit mask has the same format as the
1774 * insertion bit mask of section 5.8.6.3.
1777 bit_mask_size
= (tvb_get_uint8(tvb
,offset
)&0x80)>>7;
1778 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_mask_size
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1779 if (bit_mask_size
) {
1780 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_rem_bit_mask
, tvb
, (offset
<<3)+1, 15, ENC_BIG_ENDIAN
);
1783 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_rem_bit_mask
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
1789 * 5.8.6.4. Encoding Type 3 (remove then insert scheme)
1791 * See section 5.8.3 for a description of the Remove then insert
1795 * +---+---+---+---+---+---+---+---+
1796 * | ET=3 |GP |PS | XI 1 |
1797 * +---+---+---+---+---+---+---+---+
1798 * : gen_id : 1 octet, if GP = 1
1799 * +---+---+---+---+---+---+---+---+
1801 * +---+---+---+---+---+---+---+---+
1802 * / removal bit mask / 1-2 octets
1803 * +---+---+---+---+---+---+---+---+
1804 * / insertion bit mask / 1-2 octets
1805 * +---+---+---+---+---+---+---+---+
1806 * | XI list | k octets, or (k - 1) * 4 bits
1807 * / --- --- --- ---/
1808 * | : Padding : if PS = 0 and k is even
1809 * +---+---+---+---+---+---+---+---+
1811 * / item 1, ..., item n / variable
1813 * +---+---+---+---+---+---+---+---+
1816 PS
= (first_byte
& 0x10) >> 4;
1817 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ps
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1818 /* XI 1: When PS = 0, the first 4-bit XI item is placed here.
1819 * When PS = 1, the field is set to zero when sending, and
1820 * ignored when receiving.
1823 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_xi_1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1826 /* GP: Indicates presence of gen_id field. */
1828 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_gen_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1831 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_ref_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1835 * removal bit mask: Indicates the elements in ref_list to be
1836 * removed in order to obtain the current list. See section
1837 * 5.8.3. The removal bit mask has the same format as the
1838 * insertion bit mask of section 5.8.6.3.
1841 bit_mask_size
= (tvb_get_uint8(tvb
,offset
)&0x80)>>7;
1842 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_mask_size
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1843 if (bit_mask_size
) {
1844 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_rem_bit_mask
, tvb
, (offset
<<3)+1, 15, ENC_BIG_ENDIAN
);
1847 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_rem_bit_mask
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
1852 * insertion bit mask: Bit mask indicating the positions where new
1853 * items are to be inserted. See Insertion Only scheme in
1854 * section 5.8.3. The bit mask can have either of the
1855 * following two formats:
1859 * +---+---+---+---+---+---+---+---+
1860 * | 0 | 7-bit mask | bit 1 is the first bit
1861 * +---+---+---+---+---+---+---+---+
1863 * +---+---+---+---+---+---+---+---+
1864 * | 1 | | bit 1 is the first bit
1865 * +---+ 15-bit mask +
1866 * | | bit 7 is the last bit
1867 * +---+---+---+---+---+---+---+---+
1869 bit_mask_size
= (tvb_get_uint8(tvb
,offset
)&0x80)>>7;
1870 proto_tree_add_item(list_tree
, hf_rohc_compressed_list_mask_size
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1871 if (bit_mask_size
) {
1872 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_ins_bit_mask
, tvb
, (offset
<<3)+1, 15, ENC_BIG_ENDIAN
);
1875 proto_tree_add_bits_item(list_tree
, hf_rohc_compressed_list_ins_bit_mask
, tvb
, (offset
<<3)+1, 7, ENC_BIG_ENDIAN
);
1883 proto_item_set_len(list_ti
, offset
-start_offset
);
1889 dissect_rohc_ir_profile_dynamic(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1890 int offset
, uint8_t profile
, rohc_cid_context_t
*rohc_cid_context
)
1892 proto_item
*item
, *root_ti
;
1893 proto_tree
*sub_tree
= NULL
, *dynamic_ipv4_tree
, *dynamic_udp_tree
, *dynamic_rtp_tree
;
1894 uint8_t oct
, rx
, /* cc, */ val_len
= 0;
1895 int start_offset
, tree_start_offset
;
1896 uint8_t tos
, ttl
, nbo
;
1898 /*uint8_t contributing_csrcs;*/
1899 uint16_t sequence_number
;
1902 uint8_t tis
= 0, tss
=0;
1903 uint64_t ts_stride
= 0;
1905 start_offset
= offset
;
1907 /* Create subtree according to profile */
1909 case ROHC_PROFILE_UNCOMPRESSED
:
1910 sub_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_rohc_rtp_dynamic
, &item
, "Profile 0x0000 Uncompressed");
1913 case ROHC_PROFILE_RTP
:
1914 sub_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_rohc_rtp_dynamic
, &item
, "Profile 0x0001 RTP Dynamic Chain");
1917 case ROHC_PROFILE_UDP
:
1918 sub_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_rohc_rtp_dynamic
, &item
, "Profile 0x0002 UDP Dynamic Chain");
1921 case ROHC_PROFILE_IP
:
1922 sub_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_rohc_rtp_dynamic
, &item
, "Profile 0x0004 IP Dynamic Chain");
1926 proto_tree_add_expert(tree
, pinfo
, &ei_rohc_profile_not_supported
, tvb
, offset
, 0);
1931 /* for all profiles except uncompressed */
1932 if (profile
!= ROHC_PROFILE_UNCOMPRESSED
) {
1933 switch (rohc_cid_context
->rohc_ip_version
) {
1935 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
1938 /* Create dynamic IPv4 subtree */
1939 tree_start_offset
= offset
;
1940 root_ti
= proto_tree_add_item(sub_tree
, hf_rohc_dynamic_ipv4
, tvb
, offset
, -1, ENC_NA
);
1941 dynamic_ipv4_tree
= proto_item_add_subtree(root_ti
, ett_rohc_dynamic_ipv4
);
1943 /* Type of Service */
1944 tos
= tvb_get_uint8(tvb
, offset
);
1945 proto_tree_add_item(dynamic_ipv4_tree
, hf_rohc_rtp_tos
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1948 ttl
= tvb_get_uint8(tvb
, offset
);
1949 proto_tree_add_item(dynamic_ipv4_tree
, hf_rohc_rtp_ttl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1951 /* Identification */
1952 id
= tvb_get_ntohs(tvb
, offset
);
1953 proto_tree_add_item(dynamic_ipv4_tree
, hf_rohc_rtp_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1955 /* +---+---+---+---+---+---+---+---+
1957 * +---+---+---+---+---+---+---+---+
1959 rohc_cid_context
->rnd
= (tvb_get_uint8(tvb
, offset
) & 0x40) >> 6;
1960 nbo
= (tvb_get_uint8(tvb
, offset
) & 0x20) >> 5;
1962 proto_tree_add_item(dynamic_ipv4_tree
, hf_rohc_rtp_df
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1964 proto_tree_add_item(dynamic_ipv4_tree
, hf_rohc_rtp_rnd
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1966 proto_tree_add_item(dynamic_ipv4_tree
, hf_rohc_rtp_nbo
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1968 proto_tree_add_bits_item(dynamic_ipv4_tree
, hf_rohc_spare_bits
, tvb
, (offset
<<3)+3, 5, ENC_BIG_ENDIAN
);
1971 /* +---+---+---+---+---+---+---+---+
1972 * / Generic extension header list / variable length
1973 * +---+---+---+---+---+---+---+---+
1974 * Generic extension header list: Encoded according to section
1975 * 5.8.6.1, with all header items present in uncompressed form.
1977 offset
= dissect_compressed_list(0, pinfo
, dynamic_ipv4_tree
, tvb
, offset
);
1979 /* Set proper length for subtree */
1980 proto_item_set_len(root_ti
, offset
-tree_start_offset
);
1982 /* Add summary to ipv4 root item */
1983 proto_item_append_text(root_ti
, " (ToS=%u, TTL=%u, ID=%u, RND=%u, NBO=%u)",
1984 tos
, ttl
, id
, rohc_cid_context
->rnd
, nbo
);
1989 * +---+---+---+---+---+---+---+---+
1990 * | Traffic Class | 1 octet
1991 * +---+---+---+---+---+---+---+---+
1992 * | Hop Limit | 1 octet
1993 * +---+---+---+---+---+---+---+---+
1994 * / Generic extension header list / variable length
1995 * +---+---+---+---+---+---+---+---+
1999 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_tc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2002 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_hop_limit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2004 /* XXX TODO: use the IPv6 dissector to dissect Generic extension header list ?*/
2005 proto_tree_add_expert(sub_tree
, pinfo
, &ei_rohc_not_dissected_yet
, tvb
, offset
, -1);
2013 if ( (profile
== ROHC_PROFILE_UDP
) ||
2014 (profile
== ROHC_PROFILE_RTP
) ) {
2015 /* 5.7.7.5. Initialization of UDP Header
2018 * +---+---+---+---+---+---+---+---+
2019 * / Checksum / 2 octets
2020 * +---+---+---+---+---+---+---+---+
2022 /* Create dynamic UDP subtree */
2023 root_ti
= proto_tree_add_item(sub_tree
, hf_rohc_dynamic_udp
, tvb
, offset
, 2, ENC_NA
);
2024 dynamic_udp_tree
= proto_item_add_subtree(root_ti
, ett_rohc_dynamic_udp
);
2025 id
= tvb_get_ntohs(tvb
, offset
);
2026 rohc_cid_context
->udp_checksum_present
= (id
) ? true : false;
2028 proto_tree_add_checksum(dynamic_udp_tree
, tvb
, offset
, hf_rohc_dynamic_udp_checksum
, -1, NULL
, pinfo
, 0, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
2030 if (profile
== ROHC_PROFILE_UDP
) {
2032 proto_tree_add_item(dynamic_udp_tree
, hf_rohc_comp_ip_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2035 proto_item_set_len(item
, offset
- start_offset
);
2039 if (profile
== ROHC_PROFILE_RTP
) {
2040 /* 5.7.7.6. Initialization of RTP Header
2043 * P, X, CC, PT, M, sequence number, timestamp, timestamp stride,
2047 * +---+---+---+---+---+---+---+---+
2048 * | V=2 | P | RX| CC | (RX is NOT the RTP X bit)
2049 * +---+---+---+---+---+---+---+---+
2051 * +---+---+---+---+---+---+---+---+
2052 * / RTP Sequence Number / 2 octets
2053 * +---+---+---+---+---+---+---+---+
2054 * / RTP Timestamp (absolute) / 4 octets
2055 * +---+---+---+---+---+---+---+---+
2056 * / Generic CSRC list / variable length
2057 * +---+---+---+---+---+---+---+---+
2058 * : Reserved | X | Mode |TIS|TSS: if RX = 1
2059 * +---+---+---+---+---+---+---+---+
2060 * : TS_Stride : 1-4 octets, if TSS = 1
2061 * +---+---+---+---+---+---+---+---+
2062 * : Time_Stride : 1-4 octets, if TIS = 1
2063 * +---+---+---+---+---+---+---+---+
2066 /* Create dynamic RTP subtree */
2067 root_ti
= proto_tree_add_item(sub_tree
, hf_rohc_dynamic_rtp
, tvb
, offset
, -1, ENC_NA
);
2068 dynamic_rtp_tree
= proto_item_add_subtree(root_ti
, ett_rohc_dynamic_rtp
);
2070 tree_start_offset
= offset
;
2072 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_v
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2074 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_p
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2076 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_rx
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2078 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_cc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2079 oct
= tvb_get_uint8(tvb
,offset
);
2080 /* cc = oct & 0x0f; */
2081 rx
= (oct
>> 4)& 0x01;
2085 proto_tree_add_bits_item(dynamic_rtp_tree
, hf_rohc_rtp_m
, tvb
, (offset
<<3), 1, ENC_BIG_ENDIAN
);
2087 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_pt
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2089 /* RTP Sequence Number */
2090 sequence_number
= tvb_get_ntohs(tvb
, offset
);
2091 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_sn
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2093 /* RTP Timestamp (absolute) */
2094 timestamp
= tvb_get_ntohl(tvb
, offset
);
2095 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_timestamp
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2098 * This field is always at least one octet in size, even if the
2099 * list is empty (as opposed to the CSRC list in the uncompressed RTP
2100 * header, which is not present when the RTP CC field is set to 0).
2102 * Generic CSRC list: CSRC list encoded according to section
2103 * 5.8.6.1, with all CSRC items present.
2104 * FORMAL ADDITION TO RFC 3095:
2106 * "The first octet in the dynamic part of the RTP header contains a
2107 * CC field, as defined in Section 5.7.7.6. A second occurrence
2108 * appears in the 'Generic CSRC list', which is also in the dynamic
2109 * part of the RTP header, where Encoding Type 0 is used according
2110 * to the format defined in RFC 3095-5.8.6.1.
2112 * The compressor MUST set both occurrences of the CC field to the
2115 * The decompressor MUST use the value of the CC field from the
2116 * Encoding Type 0 within the Generic CRSC list, and it MUST thus
2117 * ignore the first occurrence of the CC field."
2120 offset
= dissect_compressed_list(0, pinfo
, dynamic_rtp_tree
, tvb
, offset
);
2121 /* : Reserved | X | Mode |TIS|TSS: if RX = 1 */
2126 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_x
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2128 rohc_cid_context
->mode
= (enum rohc_mode
)((tvb_get_uint8(tvb
,offset
) & 0x0c)>>2);
2129 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_mode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2131 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_tis
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2133 proto_tree_add_item(dynamic_rtp_tree
, hf_rohc_rtp_tss
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2134 oct
= tvb_get_uint8(tvb
,offset
);
2137 /* TS_Stride : 1-4 octets, if TSS = 1 */
2138 if ((oct
&0x01)== 1) {
2139 /* TS_Stride encoded as
2140 * 4.5.6. Self-describing variable-length values
2142 get_self_describing_var_len_val(tvb
, dynamic_rtp_tree
, offset
, hf_rohc_rtp_ts_stride
, &val_len
);
2143 offset
= offset
+ val_len
;
2146 /* Time_Stride : 1-4 octets, if TIS = 1 */
2147 if ((oct
&0x02)==2) {
2148 /* Time_Stride encoded as
2149 * 4.5.6. Self-describing variable-length values
2151 get_self_describing_var_len_val(tvb
, dynamic_rtp_tree
, offset
, hf_rohc_rtp_time_stride
, &val_len
);
2152 offset
= offset
+ val_len
;
2154 /* Set proper length for subtree */
2155 proto_item_set_len(root_ti
, offset
-tree_start_offset
);
2157 /* Add summary to root item */
2158 proto_item_append_text(root_ti
, " (seqnum = %u, timestamp = %u)",
2159 sequence_number
, timestamp
);
2161 proto_item_set_len(item
, offset
- start_offset
);
2167 dissect_rohc_ir_rtp_udp_ip_profile_static(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo _U_
, int offset
, bool d
, uint8_t profile
, rohc_cid_context_t
*rohc_cid_context
)
2169 proto_item
*item
, *ipv4_item
, *udp_item
, *rtp_item
, *ver_item
;
2170 proto_tree
*sub_tree
= NULL
, *static_ipv4_tree
, *static_udp_tree
, *static_rtp_tree
;
2171 uint8_t version
, protocol
;
2172 int start_offset
, tree_start_offset
;
2174 start_offset
= offset
;
2176 /* Create subtree root according to profile */
2179 case ROHC_PROFILE_UNCOMPRESSED
:
2180 sub_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_rohc_rtp_static
, &item
, "Profile 0x0000 Uncompressed");
2183 case ROHC_PROFILE_RTP
:
2184 sub_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_rohc_rtp_static
, &item
, "Profile 0x0001 RTP Static Chain");
2187 case ROHC_PROFILE_UDP
:
2188 sub_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_rohc_rtp_static
, &item
, "Profile 0x0002 UDP Static Chain");
2191 case ROHC_PROFILE_IP
:
2192 sub_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_rohc_rtp_static
, &item
, "Profile 0x0004 IP Static Chain");
2196 proto_tree_add_expert(tree
, pinfo
, &ei_rohc_profile_not_supported
, tvb
, offset
, 0);
2201 /* for all profiles except uncompressed */
2202 if (profile
!= ROHC_PROFILE_UNCOMPRESSED
) {
2203 version
= tvb_get_uint8(tvb
,offset
)>>4;
2204 if (profile
== ROHC_PROFILE_IP
) {
2205 /* RFC 3843 chapter 3.1; alternate encoding can set IP version field MSB to 1 */
2207 ver_item
= proto_tree_add_item(sub_tree
, hf_rohc_ip_version_ip_profile
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2209 ver_item
= proto_tree_add_item(sub_tree
, hf_rohc_ip_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2211 rohc_cid_context
->rohc_ip_version
= version
;
2216 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
2219 uint32_t source
, dest
;
2222 tree_start_offset
= offset
;
2223 /* Create static IPv4 subtree */
2224 ipv4_item
= proto_tree_add_item(sub_tree
, hf_rohc_static_ipv4
, tvb
, offset
, -1, ENC_NA
);
2225 static_ipv4_tree
= proto_item_add_subtree(ipv4_item
, ett_rohc_static_ipv4
);
2227 protocol
= tvb_get_uint8(tvb
, offset
);
2228 proto_tree_add_item(static_ipv4_tree
, hf_rohc_ip_protocol
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2230 /* Source Address */
2231 source
= tvb_get_ipv4(tvb
, offset
);
2232 proto_tree_add_item(static_ipv4_tree
, hf_rohc_ipv4_src
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2234 /* Destination Address */
2235 dest
= tvb_get_ipv4(tvb
, offset
);
2236 proto_tree_add_item(static_ipv4_tree
, hf_rohc_ipv4_dst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2238 /* Set proper length for subtree */
2239 proto_item_set_len(ipv4_item
, offset
-tree_start_offset
);
2241 /* Add summary to root item */
2242 proto_item_append_text(ipv4_item
, " (prot=%s: %s -> %s)",
2243 val_to_str_ext_const(protocol
, &ipproto_val_ext
, "Unknown"),
2244 get_hostname(source
),
2245 get_hostname(dest
));
2249 /* 5.7.7.3. Initialization of IPv6 Header [IPv6]*/
2252 * +---+---+---+---+---+---+---+---+
2253 * | Version = 6 |Flow Label(msb)| 1 octet
2254 * +---+---+---+---+---+---+---+---+
2255 * / Flow Label (lsb) / 2 octets
2256 * +---+---+---+---+---+---+---+---+
2257 * | Next Header | 1 octet
2258 * +---+---+---+---+---+---+---+---+
2259 * / Source Address / 16 octets
2260 * +---+---+---+---+---+---+---+---+
2261 * / Destination Address / 16 octets
2262 * +---+---+---+---+---+---+---+---+
2266 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_flow
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
2270 protocol
= tvb_get_uint8(tvb
, offset
);
2271 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_nxt_hdr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2274 /* Source Address */
2275 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_src
, tvb
, offset
, 16, ENC_NA
);
2278 /* Destination Address */
2279 proto_tree_add_item(sub_tree
, hf_rohc_ipv6_dst
, tvb
, offset
, 16, ENC_NA
);
2284 expert_add_info(pinfo
, ver_item
, &ei_rohc_ip_version
);
2288 protocol
= 0; /* Something other than UDP (which is checked for below) */
2291 if (protocol
== IP_PROTO_UDP
) {
2293 if ((profile
== ROHC_PROFILE_RTP
) ||
2294 (profile
== ROHC_PROFILE_UDP
)) {
2295 /* 5.7.7.5. Initialization of UDP Header [RFC-768].
2298 uint16_t source_port
, dest_port
;
2301 /* Create static UDP subtree */
2302 tree_start_offset
= offset
;
2303 udp_item
= proto_tree_add_item(sub_tree
, hf_rohc_static_udp
, tvb
, offset
, -1, ENC_NA
);
2304 static_udp_tree
= proto_item_add_subtree(udp_item
, ett_rohc_static_udp
);
2306 source_port
= tvb_get_ntohs(tvb
, offset
);
2307 proto_tree_add_item(static_udp_tree
, hf_rohc_udp_src_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2309 /* Destination Port */
2310 dest_port
= tvb_get_ntohs(tvb
, offset
);
2311 proto_tree_add_item(static_udp_tree
, hf_rohc_udp_dst_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2313 /* Set proper length for subtree */
2314 proto_item_set_len(udp_item
, offset
-tree_start_offset
);
2315 /* Add summary to root item */
2316 proto_item_append_text(udp_item
, " (%u -> %u)", source_port
, dest_port
);
2318 if (profile
== ROHC_PROFILE_UDP
) {
2319 proto_item_set_len(item
, offset
- start_offset
);
2322 offset
= dissect_rohc_ir_profile_dynamic(tvb
, pinfo
, tree
, offset
, profile
, rohc_cid_context
);
2328 /* 5.7.7.6. Initialization of RTP Header [RTP]. */
2329 /* Create static RTP subtree */
2330 rtp_item
= proto_tree_add_item(sub_tree
, hf_rohc_static_rtp
, tvb
, offset
, 4, ENC_NA
);
2331 static_rtp_tree
= proto_item_add_subtree(rtp_item
, ett_rohc_static_rtp
);
2334 ssrc
= tvb_get_ntohl(tvb
, offset
);
2335 proto_tree_add_item(static_rtp_tree
, hf_rohc_rtp_ssrc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2338 /* Add summary to root item */
2339 proto_item_append_text(rtp_item
, " (SSRC=0x%08x)", ssrc
);
2341 proto_item_set_len(item
, offset
- start_offset
);
2343 /* D: D = 1 indicates that the dynamic chain is present. */
2345 offset
= dissect_rohc_ir_profile_dynamic(tvb
, pinfo
, tree
, offset
, profile
, rohc_cid_context
);
2348 } else if (profile
== ROHC_PROFILE_IP
) {
2349 proto_item_set_len(item
, offset
- start_offset
);
2351 offset
= dissect_rohc_ir_profile_dynamic(tvb
, pinfo
, tree
, offset
, profile
, rohc_cid_context
);
2355 proto_tree_add_expert(sub_tree
, pinfo
, &ei_rohc_not_dissected_yet
, tvb
, offset
, -1);
2361 dissect_rohc_ir_packet(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
,
2362 int offset
, uint16_t cid
, bool is_add_cid
, rohc_info
*p_rohc_info
)
2364 proto_item
*ir_item
, *item
;
2365 proto_tree
*ir_tree
;
2369 uint8_t oct
, profile
, val_len
= 0;
2370 int16_t feedback_data_len
= 0;
2372 rohc_cid_context_t
*rohc_cid_context
= NULL
;
2374 /* The cid value must have been dissected and valid
2375 * offset must point to the IR octet see below ( | 1 1 1 1 1 1 0 | D | )
2376 * TODO: CRC validation
2381 --- --- --- --- --- --- --- ---
2382 | Add-CID octet | if for small CIDs and CID != 0
2383 +---+---+---+---+---+---+---+---+
2384 | 1 1 1 1 1 1 0 | D |
2385 +---+---+---+---+---+---+---+---+
2387 / 0-2 octets of CID info / 1-2 octets if for large CIDs
2389 +---+---+---+---+---+---+---+---+
2391 +---+---+---+---+---+---+---+---+
2393 +---+---+---+---+---+---+---+---+
2395 | Static chain | variable length
2397 +---+---+---+---+---+---+---+---+
2399 | Dynamic chain | present if D = 1, variable length
2401 - - - - - - - - - - - - - - - -
2403 | Payload | variable length
2405 - - - - - - - - - - - - - - - -
2408 oct
= tvb_get_uint8(tvb
,offset
);
2410 if (!p_rohc_info
->large_cid_present
&& !is_add_cid
) {
2411 item
= proto_tree_add_uint(tree
, hf_rohc_small_cid
, tvb
, 0, 0, cid
);
2412 proto_item_set_generated(item
);
2414 ir_item
= proto_tree_add_item(tree
, hf_rohc_ir_packet
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2415 ir_tree
= proto_item_add_subtree(ir_item
, ett_rohc_ir
);
2416 ir_item_start
= offset
;
2418 x_bit_offset
= offset
;
2420 if (p_rohc_info
->large_cid_present
) {
2421 /* Handle Large CID:s here */
2422 get_self_describing_var_len_val(tvb
, ir_tree
, offset
, hf_rohc_large_cid
, &val_len
);
2423 offset
= offset
+ val_len
;
2427 profile
= tvb_get_uint8(tvb
,offset
);
2429 /* D (all profiles?) */
2430 if ((profile
==ROHC_PROFILE_RTP
) || (profile
==ROHC_PROFILE_UDP
)) {
2431 proto_tree_add_item(ir_tree
, hf_rohc_d_bit
, tvb
, x_bit_offset
, 1, ENC_BIG_ENDIAN
);
2435 * In the IR packet, the profile identifier is abbreviated to the 8 least
2436 * significant bits. It selects the highest-number profile in the
2437 * channel state parameter PROFILES that matches the 8 LSBs given. */
2438 proto_tree_add_item(ir_tree
, hf_rohc_profile
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2442 proto_tree_add_item(ir_tree
, hf_rohc_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2445 /* See if we have an entry for this CID
2446 * Update it if we do otherwise create it
2447 * and fill in the info.
2449 if (!PINFO_FD_VISITED(pinfo
)) {
2451 rohc_cid_context
= (rohc_cid_context_t
*)g_hash_table_lookup(rohc_cid_hash
, GUINT_TO_POINTER(key
));
2452 if (rohc_cid_context
!= NULL
) {
2453 /* This is not the first IR packet seen*/
2454 int tmp_prev_ir_frame_number
= rohc_cid_context
->ir_frame_number
;
2455 int tmp_prev_rohc_ip_version
= rohc_cid_context
->rohc_ip_version
;
2456 int tmp_prev_mode
= rohc_cid_context
->mode
;
2457 bool tmp_prev_rnd
= rohc_cid_context
->rnd
;
2458 bool tmp_prev_udp_checksum_present
= rohc_cid_context
->udp_checksum_present
;
2460 /*ws_warning("IR pkt found CID %u",cid);*/
2462 rohc_cid_context
= wmem_new(wmem_file_scope(), rohc_cid_context_t
);
2463 rohc_cid_context
->profile
= profile
;
2464 rohc_cid_context
->prev_ir_frame_number
= tmp_prev_ir_frame_number
;
2465 rohc_cid_context
->ir_frame_number
= pinfo
->num
;
2466 rohc_cid_context
->rohc_ip_version
= tmp_prev_rohc_ip_version
;
2467 rohc_cid_context
->mode
= (enum rohc_mode
)tmp_prev_mode
;
2468 rohc_cid_context
->rnd
= tmp_prev_rnd
;
2469 rohc_cid_context
->udp_checksum_present
= tmp_prev_udp_checksum_present
;
2470 rohc_cid_context
->large_cid_present
= p_rohc_info
->large_cid_present
;
2472 g_hash_table_replace(rohc_cid_hash
, GUINT_TO_POINTER(key
), rohc_cid_context
);
2473 p_add_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0, rohc_cid_context
);
2475 rohc_cid_context
= wmem_new(wmem_file_scope(), rohc_cid_context_t
);
2476 rohc_cid_context
->large_cid_present
= p_rohc_info
->large_cid_present
;
2477 rohc_cid_context
->mode
= 0;
2478 /*rohc_cid_context->d_mode;*/
2479 rohc_cid_context
->rnd
= false;
2480 rohc_cid_context
->udp_checksum_present
= false;
2481 rohc_cid_context
->profile
= profile
;
2482 rohc_cid_context
->prev_ir_frame_number
= -1;
2483 rohc_cid_context
->ir_frame_number
= pinfo
->num
;
2484 rohc_cid_context
->rohc_ip_version
= p_rohc_info
->rohc_ip_version
;
2485 rohc_cid_context
->mode
= p_rohc_info
->mode
;
2487 /*ws_warning("IR pkt New CID %u",cid);*/
2489 g_hash_table_insert(rohc_cid_hash
, GUINT_TO_POINTER(key
), rohc_cid_context
);
2490 p_add_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0, rohc_cid_context
);
2493 /* get the stored data */
2494 rohc_cid_context
= (rohc_cid_context_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0);
2498 case ROHC_PROFILE_UNCOMPRESSED
:
2499 /* Just an ip frame */
2500 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
2501 oct
= tvb_get_uint8(tvb
, offset
);
2502 if ((oct
&0xf0) == 0x60) {
2503 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2504 call_dissector(ipv6_handle
, next_tvb
, pinfo
, tree
);
2505 offset
+= tvb_captured_length_remaining(tvb
, offset
);
2507 else if ((oct
&0xf0) == 0x40) {
2508 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2509 call_dissector(ip_handle
, next_tvb
, pinfo
, tree
);
2510 offset
+= tvb_captured_length_remaining(tvb
, offset
);
2512 col_prepend_fstr(pinfo
->cinfo
, COL_PROTOCOL
, "ROHC/");
2515 case ROHC_PROFILE_RTP
:
2516 case ROHC_PROFILE_UDP
:
2517 case ROHC_PROFILE_IP
:
2518 offset
= dissect_rohc_ir_rtp_udp_ip_profile_static(tvb
, ir_tree
, pinfo
, offset
, d
, profile
, rohc_cid_context
);
2522 proto_tree_add_expert(ir_tree
, pinfo
, &ei_rohc_profile_specific
, tvb
, offset
, feedback_data_len
);
2528 /* Set length of IR header */
2529 proto_item_set_len(ir_item
, offset
-ir_item_start
);
2536 dissect_rohc_ir_dyn_packet(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
,
2537 int offset
, uint16_t cid
, bool is_add_cid
, rohc_info
*p_rohc_info
)
2539 proto_item
*ir_item
, *item
;
2540 proto_tree
*ir_tree
;
2542 uint8_t profile
, val_len
= 0;
2543 int16_t feedback_data_len
= 0;
2544 rohc_cid_context_t
*rohc_cid_context
;
2547 if (!p_rohc_info
->large_cid_present
&& !is_add_cid
) {
2548 item
= proto_tree_add_uint(tree
, hf_rohc_small_cid
, tvb
, 0, 0, cid
);
2549 proto_item_set_generated(item
);
2552 ir_item
= proto_tree_add_item(tree
, hf_rohc_ir_dyn_packet
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2553 ir_tree
= proto_item_add_subtree(ir_item
, ett_rohc_ir_dyn
);
2554 ir_item_start
= offset
;
2557 if (p_rohc_info
->large_cid_present
) {
2558 /* Handle Large CID:s here */
2559 get_self_describing_var_len_val(tvb
, ir_tree
, offset
, hf_rohc_large_cid
, &val_len
);
2560 offset
= offset
+ val_len
;
2564 profile
= tvb_get_uint8(tvb
,offset
);
2565 proto_tree_add_item(ir_tree
, hf_rohc_profile
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2568 /* See if we have an entry for this CID
2569 * Update it if we do otherwise create it
2570 * and fill in the info.
2572 if (!PINFO_FD_VISITED(pinfo
)) {
2574 rohc_cid_context
= (rohc_cid_context_t
*)g_hash_table_lookup(rohc_cid_hash
, GUINT_TO_POINTER(key
));
2576 if (rohc_cid_context
) {
2577 /* This is not the first IR packet seen*/
2578 int tmp_prev_ir_frame_number
= rohc_cid_context
->ir_frame_number
;
2579 int tmp_prev_rohc_ip_version
= rohc_cid_context
->rohc_ip_version
;
2580 int tmp_prev_mode
= rohc_cid_context
->mode
;
2581 bool tmp_prev_rnd
= rohc_cid_context
->rnd
;
2582 bool tmp_prev_udp_checksum_present
= rohc_cid_context
->udp_checksum_present
;
2584 /*ws_warning("IR pkt found CID %u",cid);*/
2586 rohc_cid_context
= wmem_new(wmem_file_scope(), rohc_cid_context_t
);
2587 rohc_cid_context
->profile
= profile
;
2588 rohc_cid_context
->prev_ir_frame_number
= tmp_prev_ir_frame_number
;
2589 rohc_cid_context
->ir_frame_number
= pinfo
->num
;
2590 rohc_cid_context
->rohc_ip_version
= tmp_prev_rohc_ip_version
;
2591 rohc_cid_context
->mode
= (enum rohc_mode
)tmp_prev_mode
;
2592 rohc_cid_context
->rnd
= tmp_prev_rnd
;
2593 rohc_cid_context
->udp_checksum_present
= tmp_prev_udp_checksum_present
;
2594 rohc_cid_context
->large_cid_present
= p_rohc_info
->large_cid_present
;
2596 g_hash_table_replace(rohc_cid_hash
, GUINT_TO_POINTER(key
), rohc_cid_context
);
2597 p_add_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0, rohc_cid_context
);
2599 rohc_cid_context
= wmem_new(wmem_file_scope(), rohc_cid_context_t
);
2600 rohc_cid_context
->rohc_ip_version
= 0;
2601 rohc_cid_context
->large_cid_present
= p_rohc_info
->large_cid_present
;
2602 /*rohc_cid_context->d_mode;*/
2603 rohc_cid_context
->rnd
= false;
2604 rohc_cid_context
->udp_checksum_present
= false;
2605 rohc_cid_context
->profile
= profile
;
2606 rohc_cid_context
->prev_ir_frame_number
= -1;
2607 rohc_cid_context
->ir_frame_number
= pinfo
->num
;
2608 rohc_cid_context
->mode
= p_rohc_info
->mode
;
2610 /*ws_warning("IR pkt New CID %u",cid);*/
2612 g_hash_table_insert(rohc_cid_hash
, GUINT_TO_POINTER(key
), rohc_cid_context
);
2613 p_add_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0, rohc_cid_context
);
2616 /* get the stored data */
2617 rohc_cid_context
= (rohc_cid_context_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0);
2621 proto_tree_add_item(ir_tree
, hf_rohc_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2624 /* Profile specific information */
2626 case ROHC_PROFILE_RTP
:
2627 case ROHC_PROFILE_UDP
:
2628 offset
= dissect_rohc_ir_profile_dynamic(tvb
, pinfo
, ir_tree
, offset
, profile
, rohc_cid_context
);
2632 proto_tree_add_expert(ir_tree
, pinfo
, &ei_rohc_profile_specific
, tvb
, offset
, feedback_data_len
);
2636 /* Set length of IR-DYN header */
2638 proto_item_set_len(ir_item
, offset
-ir_item_start
);
2644 /******************************/
2645 /* Main dissection function. */
2647 dissect_rohc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
/* rohc_info* */)
2649 proto_item
*ti
, *item
, *conf_item
;
2650 proto_tree
*rohc_tree
, *sub_tree
= NULL
, *conf_tree
;
2651 int offset
= 0, length
;
2652 uint8_t oct
, code
, size
, val_len
= 0;
2653 int16_t feedback_data_len
, cid
= 0;
2654 bool is_add_cid
= false;
2655 rohc_info
*p_rohc_info
= NULL
;
2656 rohc_info g_rohc_info
;
2657 tvbuff_t
*next_tvb
=NULL
, *payload_tvb
;
2658 rohc_cid_context_t
*rohc_cid_context
= NULL
;
2661 /* No rohc_info passed in, set some defaults */
2662 g_rohc_info
.rohc_compression
= false;
2663 g_rohc_info
.rohc_ip_version
= g_version
;
2664 g_rohc_info
.cid_inclusion_info
= false;
2665 g_rohc_info
.large_cid_present
= false;
2666 g_rohc_info
.mode
= RELIABLE_BIDIRECTIONAL
;
2667 g_rohc_info
.rnd
= false;
2668 g_rohc_info
.udp_checksum_present
= false;
2669 g_rohc_info
.profile
= g_profile
;
2670 g_rohc_info
.last_created_item
= NULL
;
2671 p_rohc_info
= &g_rohc_info
;
2673 /* Use info passed in */
2674 p_rohc_info
= (rohc_info
*)data
;
2675 /* TODO: contents not referenced again, so why do this? */
2676 memset(&g_rohc_info
, 0, sizeof(rohc_info
));
2679 length
= tvb_reported_length(tvb
);
2681 /* If this is ROHC ethertype clear col */
2682 if (pinfo
->src
.type
== AT_ETHER
) {
2683 col_set_str(pinfo
->cinfo
, COL_INFO
, "ROHC");
2684 col_clear(pinfo
->cinfo
, COL_INFO
);
2686 col_append_str(pinfo
->cinfo
, COL_PROTOCOL
, "|ROHC");
2687 /* Append a space if we add stuff to existing col info */
2688 col_append_str(pinfo
->cinfo
, COL_INFO
, " ");
2692 ti
= proto_tree_add_item(tree
, proto_rohc
, tvb
, 0, -1, ENC_NA
);
2693 rohc_tree
= proto_item_add_subtree(ti
, ett_rohc
);
2695 /* Put configuration data into the tree */
2696 conf_tree
= proto_tree_add_subtree_format(rohc_tree
, tvb
, offset
, 0, ett_rohc_conf
, &item
,
2697 "Global Configuration: (%s)",
2698 p_rohc_info
->large_cid_present
? "Large CID" : "Small CID");
2699 proto_item_set_generated(item
);
2701 /* Look for cid context info attached to frame */
2702 rohc_cid_context
= (rohc_cid_context_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0 /* key */);
2703 if (rohc_cid_context
) {
2704 /* Do we have info from an IR frame? */
2705 if (rohc_cid_context
->ir_frame_number
>0) {
2706 /* Show was configured by IR Packet */
2707 conf_item
= proto_tree_add_item(conf_tree
, hf_rohc_configured_by_ir_packet
, tvb
, offset
, 0, ENC_NA
);
2708 proto_item_set_generated(conf_item
);
2709 /* No. of IR setup frame */
2710 conf_item
= proto_tree_add_uint(conf_tree
, hf_rohc_ir_pkt_frame
, tvb
, 0, 0, rohc_cid_context
->ir_frame_number
);
2711 proto_item_set_generated(conf_item
);
2713 /* Any previous IR frame number */
2714 if (rohc_cid_context
->prev_ir_frame_number
>0) {
2715 conf_item
= proto_tree_add_uint(conf_tree
, hf_rohc_ir_previous_frame
, tvb
, 0, 0, rohc_cid_context
->prev_ir_frame_number
);
2716 proto_item_set_generated(conf_item
);
2720 conf_item
= proto_tree_add_uint(conf_tree
, hf_rohc_ir_profile
, tvb
, offset
, 0, rohc_cid_context
->profile
);
2721 proto_item_set_generated(conf_item
);
2722 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s: ", val_to_str_const(rohc_cid_context
->profile
, rohc_profile_vals
, "Unknown"));
2724 /* IP Version number */
2725 conf_item
= proto_tree_add_uint(conf_tree
, hf_rohc_ir_ip_version
, tvb
, offset
, 0, rohc_cid_context
->rohc_ip_version
);
2726 proto_item_set_generated(conf_item
);
2729 if (rohc_cid_context
->mode
== 0) {
2730 conf_item
= proto_tree_add_uint_format_value(conf_tree
, hf_rohc_ir_mode
, tvb
, offset
, 0, 0, "not known");
2731 proto_item_set_generated(conf_item
);
2733 conf_item
= proto_tree_add_uint(conf_tree
, hf_rohc_ir_mode
, tvb
, offset
, 0, rohc_cid_context
->mode
);
2734 proto_item_set_generated(conf_item
);
2738 /* No IR frame number stored in context */
2739 conf_item
= proto_tree_add_item(conf_tree
, hf_rohc_no_configuration_info
, tvb
, offset
, 0, ENC_NA
);
2740 proto_item_set_generated(conf_item
);
2746 /* N.B. These steps are the procedure described in 5.2.6. ROHC initial decompressor processing */
2748 /* 1) If the first octet is a Padding Octet (11100000),
2749 * strip away all initial Padding Octets and goto next step.
2752 oct
= tvb_get_uint8(tvb
,offset
);
2754 while (oct
== 0xe0) {
2756 oct
= tvb_get_uint8(tvb
,offset
);
2758 proto_tree_add_item(rohc_tree
, hf_rohc_padding
, tvb
, 0, offset
, ENC_NA
);
2761 /* 2) If the first remaining octet starts with 1110, it is an Add-CID octet:
2762 * remember the Add-CID octet; remove the octet.
2764 if ((oct
&0xf0) == 0xe0) {
2767 proto_tree_add_item(rohc_tree
, hf_rohc_add_cid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2768 proto_tree_add_uint(rohc_tree
, hf_rohc_small_cid
, tvb
, offset
, 1, cid
);
2771 oct
= tvb_get_uint8(tvb
,offset
);
2775 * Feedback (begins with 11110)
2777 if ((oct
&0xf8) == 0xf0) {
2778 /* 3) If the first remaining octet starts with 11110, and an Add-CID
2779 * octet was found in step 2), an error has occurred;
2780 * the header MUST be discarded without further action.
2783 int feedback_start
= offset
;
2786 p_rohc_info
->last_created_item
= proto_tree_add_item(rohc_tree
, hf_rohc_feedback
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2787 col_append_str(pinfo
->cinfo
, COL_INFO
, "Error packet");
2788 proto_tree_add_item(rohc_tree
, hf_rohc_error_packet
, tvb
, offset
, -1, ENC_NA
);
2789 return tvb_captured_length(tvb
);
2791 col_append_str(pinfo
->cinfo
, COL_INFO
, "Feedback ");
2792 /* 4) If the first remaining octet starts with 11110, and an Add-CID
2793 * octet was not found in step 2), this is feedback:
2794 * find the size of the feedback data, call it s;
2795 * remove the feedback type octet;
2796 * remove the Size octet if Code is 0;
2797 * send feedback data of length s to the same-side associated
2799 * if packet exhausted, stop; otherwise goto 2).
2802 /* Feedback subtree */
2803 p_rohc_info
->last_created_item
= proto_tree_add_item(rohc_tree
, hf_rohc_feedback
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2804 sub_tree
= proto_item_add_subtree(p_rohc_info
->last_created_item
, ett_rohc_fb
);
2806 proto_tree_add_item(sub_tree
, hf_rohc_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2810 /* Separate size field */
2811 size
= tvb_get_uint8(tvb
,offset
);
2812 proto_tree_add_item(sub_tree
, hf_rohc_size
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2815 /* Size is in code field itself. */
2818 feedback_data_len
= size
;
2820 if (!p_rohc_info
->large_cid_present
) {
2821 /* Check for Add-CID octet */
2822 oct
= tvb_get_uint8(tvb
,offset
);
2823 if ((oct
&0xf0) == 0xe0) {
2825 proto_tree_add_item(sub_tree
, hf_rohc_add_cid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2826 proto_tree_add_uint(sub_tree
, hf_rohc_small_cid
, tvb
, offset
, 1, cid
);
2828 feedback_data_len
--;
2830 item
= proto_tree_add_uint(sub_tree
, hf_rohc_small_cid
, tvb
, 0, 0, cid
);
2831 proto_item_set_generated(item
);
2834 /* Read Large CID here */
2835 get_self_describing_var_len_val(tvb
, sub_tree
, offset
, hf_rohc_large_cid
, &val_len
);
2836 /* feedback_data_len - "length of large CID" */
2837 feedback_data_len
= feedback_data_len
- val_len
;
2841 /* Dissect feedback */
2842 dissect_rohc_feedback_data(tvb
, sub_tree
, pinfo
, offset
, feedback_data_len
, p_rohc_info
, cid
, p_rohc_info
!= &g_rohc_info
);
2844 if (offset
<length
) {
2848 proto_item_set_len(p_rohc_info
->last_created_item
, offset
-feedback_start
);
2849 return tvb_captured_length(tvb
);
2853 /* 5) If the first remaining octet starts with 1111111, this is a segment:
2856 if ((oct
&0xfe) == 0xfe) {
2857 col_append_str(pinfo
->cinfo
, COL_INFO
, "Segment");
2858 if (!p_rohc_info
->large_cid_present
&& !is_add_cid
) {
2859 item
= proto_tree_add_uint(rohc_tree
, hf_rohc_small_cid
, tvb
, 0, 0, cid
);
2860 proto_item_set_generated(item
);
2862 /* Segmentation not supported! */
2863 proto_tree_add_expert(rohc_tree
, pinfo
, &ei_rohc_desegmentation_not_implemented
, tvb
, offset
, -1);
2864 return tvb_captured_length(tvb
);
2867 /* 6) Here, it is known that the rest is forward information (unless the
2868 * header is damaged).
2870 if ((oct
&0xfe) == 0xfc) {
2871 col_append_str(pinfo
->cinfo
, COL_INFO
, "IR");
2872 offset
= dissect_rohc_ir_packet(tvb
, rohc_tree
, pinfo
, offset
, cid
, is_add_cid
, p_rohc_info
);
2874 /* Could not parse header */
2875 return tvb_captured_length(tvb
);
2878 payload_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2879 call_data_dissector(payload_tvb
, pinfo
, rohc_tree
);
2880 return tvb_captured_length(tvb
);
2882 if ((oct
&0xff) == 0xf8) {
2883 col_append_str(pinfo
->cinfo
, COL_INFO
, "IR-DYN packet");
2884 offset
= dissect_rohc_ir_dyn_packet(tvb
, rohc_tree
, pinfo
, offset
, cid
, is_add_cid
, p_rohc_info
);
2886 /* Could not parse header */
2887 return tvb_captured_length(tvb
);
2890 payload_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2891 call_data_dissector(payload_tvb
, pinfo
, rohc_tree
);
2892 return tvb_captured_length(tvb
);
2895 /* First pass - look up or create CID context */
2896 if (!PINFO_FD_VISITED(pinfo
)) {
2898 rohc_cid_context
= (rohc_cid_context_t
*)g_hash_table_lookup(rohc_cid_hash
, GUINT_TO_POINTER(key
));
2899 if (!rohc_cid_context
) {
2900 /* Not found, so initialize new context based upon p_rohc_info */
2901 rohc_cid_context
= wmem_new(wmem_file_scope(), rohc_cid_context_t
);
2902 /*rohc_cid_context->d_mode;*/
2903 rohc_cid_context
->rnd
= p_rohc_info
->rnd
;
2904 rohc_cid_context
->udp_checksum_present
= p_rohc_info
->udp_checksum_present
;
2905 rohc_cid_context
->profile
= p_rohc_info
->profile
;
2906 rohc_cid_context
->mode
= p_rohc_info
->mode
;
2907 rohc_cid_context
->rohc_ip_version
= p_rohc_info
->rohc_ip_version
;
2908 rohc_cid_context
->large_cid_present
= p_rohc_info
->large_cid_present
;
2909 rohc_cid_context
->prev_ir_frame_number
= -1;
2910 rohc_cid_context
->ir_frame_number
= -1;
2911 /*ws_warning("Store dummy data %u",cid);*/
2913 /* Store in pinfo */
2914 p_add_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0, rohc_cid_context
);
2916 /* Later passes - get from pinfo */
2917 rohc_cid_context
= (rohc_cid_context_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_rohc
, 0);
2919 DISSECTOR_ASSERT(rohc_cid_context
);
2921 /* Call IP for uncompressed profile */
2922 if (rohc_cid_context
->profile
==ROHC_PROFILE_UNCOMPRESSED
) {
2923 if (rohc_cid_context
->large_cid_present
) {
2924 /* How long does packet say it is? */
2925 get_self_describing_var_len_val(tvb
, rohc_tree
, offset
+1, hf_rohc_large_cid
, &val_len
);
2926 /* How many bytes do we actually have? */
2927 int len
= tvb_captured_length_remaining(tvb
, offset
);
2928 if (len
>= val_len
) {
2930 uint8_t *payload_data
= (uint8_t *)wmem_alloc(pinfo
->pool
, len
);
2931 tvb_memcpy(tvb
, payload_data
, offset
, 1);
2932 tvb_memcpy(tvb
, &payload_data
[1], offset
+1+val_len
, len
-1);
2933 next_tvb
= tvb_new_child_real_data(tvb
, payload_data
, len
, len
);
2934 add_new_data_source(pinfo
, next_tvb
, "Payload");
2938 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2941 /* Call appropriate IP dissector.
2942 TODO: could just call "ip" dissector instead? */
2943 if ((oct
&0xf0)==0x40) {
2944 call_dissector(ip_handle
, next_tvb
, pinfo
, tree
);
2946 else if ((oct
&0xf0)==0x60) {
2947 call_dissector(ipv6_handle
, next_tvb
, pinfo
, tree
);
2950 call_data_dissector(next_tvb
, pinfo
, tree
);
2953 col_prepend_fstr(pinfo
->cinfo
, COL_PROTOCOL
, "ROHC/");
2954 return tvb_captured_length(tvb
);
2956 else if (((oct
&0x80)==0x00) &&
2957 ((rohc_cid_context
->profile
==ROHC_PROFILE_RTP
) || (rohc_cid_context
->profile
==ROHC_PROFILE_UDP
))) {
2958 /* 5.7.1. Packet type 0: UO-0, R-0, R-0-CRC */
2959 offset
= dissect_rohc_pkt_type_0(tvb
, pinfo
, rohc_tree
, offset
, oct
, rohc_cid_context
);
2960 } else if ((oct
&0xc0)==0x80) {
2961 if (rohc_cid_context
->mode
== RELIABLE_BIDIRECTIONAL
) {
2962 /* 5.7.2. Packet type 1 (R-mode): R-1, R-1-TS, R-1-ID */
2963 offset
= dissect_rohc_pkt_type_1_r_mode(tvb
, pinfo
, rohc_tree
, offset
, rohc_cid_context
);
2966 /* 5.7.3. Packet type 1 (U/O-mode): UO-1, UO-1-ID, UO-1-TS */
2967 offset
= dissect_rohc_pkt_type_1_u_o_mode(tvb
, pinfo
, rohc_tree
, offset
, rohc_cid_context
);
2969 } else if ((oct
&0xe0)==0xc0) {
2970 /* 5.7.4. Packet type 2: UOR-2 */
2971 offset
= dissect_rohc_pkt_type_2(tvb
, pinfo
, rohc_tree
, offset
, rohc_cid_context
);
2975 if (rohc_cid_context
->rnd
) {
2976 proto_tree_add_item(rohc_tree
, hf_rohc_ip_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2981 if (rohc_cid_context
->udp_checksum_present
) {
2982 proto_tree_add_checksum(rohc_tree
, tvb
, offset
, hf_rohc_udp_checksum
, -1, NULL
, pinfo
, 0, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
2986 /* Any remainder is undissected data / payload */
2987 payload_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2988 call_data_dissector(payload_tvb
, pinfo
, tree
);
2990 return tvb_captured_length(tvb
);
2993 /* Set up rohc_cid_hash which holds data for a CID
2994 * needed to dissect subsequent packages.
2996 * A better Key than just the CID may have to be devised.
3002 rohc_init_protocol(void)
3004 rohc_cid_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
3008 rohc_cleanup_protocol(void)
3010 g_hash_table_destroy(rohc_cid_hash
);
3014 proto_register_rohc(void)
3017 static hf_register_info hf
[] =
3020 { "Padding","rohc.padding",
3021 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3026 { "Add-CID","rohc.add_cid",
3027 FT_UINT8
, BASE_HEX
, NULL
, 0xf0,
3031 { &hf_rohc_feedback
,
3032 { "Feedback","rohc.feedback",
3033 FT_UINT8
, BASE_HEX
, NULL
, 0xf8,
3038 { "Code","rohc.code",
3039 FT_UINT8
, BASE_DEC
, NULL
, 0x07,
3044 { "Size","rohc.size",
3045 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3049 { &hf_rohc_ir_packet
,
3050 { "IR packet","rohc.ir_packet",
3051 FT_UINT8
, BASE_HEX
, NULL
, 0xfe,
3055 { &hf_rohc_ir_dyn_packet
,
3056 { "IR-DYN packet","rohc.ir_dyn_packet",
3057 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3061 { &hf_rohc_small_cid
,
3062 { "Small CID","rohc.small_cid",
3063 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
3067 { &hf_rohc_large_cid
,
3068 { "Large CID","rohc.large_cid",
3069 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3074 { "Acktype","rohc.acktype",
3075 FT_UINT8
, BASE_DEC
, VALS(rohc_acktype_vals
), 0xc0,
3080 { "Mode","rohc.mode",
3081 FT_UINT8
, BASE_DEC
, VALS(rohc_mode_vals
), 0x30,
3086 { "SN LSB","rohc.sn",
3087 FT_UINT16
, BASE_HEX_DEC
, NULL
, 0x0fff,
3091 { &hf_rohc_profile_spec_octet
,
3092 { "Profile-specific octet","rohc.profile_spec_octet",
3093 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3098 { "SN LSB","rohc.sn",
3099 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
3103 { &hf_rohc_opt_type
,
3104 { "Option type","rohc.opt_type",
3105 FT_UINT8
, BASE_DEC
, VALS(rohc_opt_type_vals
), 0xf0,
3110 { "Option length","rohc.opt_length",
3111 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
3117 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
3122 { "SN additional bits","rohc.opt.sn_add_bits",
3123 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
3124 "Feedback Option SN", HFILL
3128 { "Extension","rohc.ext",
3129 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3134 { "SN LSB","rohc.sn",
3135 FT_UINT24
, BASE_HEX_DEC
, NULL
, 0x0,
3139 { &hf_rohc_opt_clock
,
3140 { "Clock", "rohc.opt.clock",
3141 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3142 "Feedback Option Clock", HFILL
3145 { &hf_rohc_opt_jitter
,
3146 { "Max Jitter", "rohc.opt.jitter",
3147 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3148 "Feedback Option Jitter", HFILL
3151 { &hf_rohc_opt_loss
,
3152 { "Longest loss event (packets)", "rohc.opt.loss",
3153 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3154 "Feedback Option Loss", HFILL
3158 { "Profile","rohc.profile",
3159 FT_UINT8
, BASE_DEC
, VALS(rohc_profile_vals
), 0x0,
3164 { "D - Dynamic chain","rohc.d",
3165 FT_BOOLEAN
, 8, TFS(&tfs_present_not_present
), 0x01,
3169 { &hf_rohc_ip_version
,
3170 { "Version","rohc.ip.version",
3171 FT_UINT8
, BASE_DEC
, VALS(rohc_ip_version_vals
), 0xf0,
3175 { &hf_rohc_ip_version_ip_profile
,
3176 { "Version","rohc.ip.version",
3177 FT_UINT8
, BASE_DEC
, VALS(rohc_ip_version_ip_profile_vals
), 0xf0,
3181 { &hf_rohc_static_ipv4
,
3182 { "Static IPv4 chain",
3183 "rohc.static.ipv4", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3187 { &hf_rohc_ip_protocol
,
3188 { "Protocol","rohc.ip.protocol",
3189 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &ipproto_val_ext
, 0x0,
3193 { &hf_rohc_ipv4_src
,
3194 { "Source address","rohc.ipv4_src",
3195 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
3199 { &hf_rohc_ipv4_dst
,
3200 { "Destination address","rohc.ipv4_dst",
3201 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
3205 { &hf_rohc_ipv6_flow
,
3206 { "Flow Label","rohc.ipv6.flow",
3207 FT_UINT24
, BASE_DEC
, NULL
, 0x0fffff,
3211 { &hf_rohc_ipv6_nxt_hdr
,
3212 { "Next Header","rohc.ipv6.nxt_hdr",
3213 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3217 { &hf_rohc_ipv6_src
,
3218 { "Source Address","rohc.ipv6.src",
3219 FT_IPv6
, BASE_NONE
, NULL
, 0,
3223 { &hf_rohc_ipv6_dst
,
3224 { "Destination Address","rohc.ipv6.dst",
3225 FT_IPv6
, BASE_NONE
, NULL
, 0,
3229 { &hf_rohc_static_udp
,
3230 { "Static UDP chain", "rohc.static.udp",
3231 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3235 { &hf_rohc_udp_src_port
,
3236 { "Source Port","rohc.udp_src_port",
3237 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3241 { &hf_rohc_udp_dst_port
,
3242 { "Destination Port","rohc.udp_dst_port",
3243 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3247 { &hf_rohc_static_rtp
,
3248 { "Static RTP chain",
3249 "rohc.static.rtp", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3253 { &hf_rohc_rtp_ssrc
,
3254 { "SSRC","rohc.rtp.ssrc",
3255 FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0,
3259 { &hf_rohc_dynamic_ipv4
,
3260 { "Dynamic IPv4 chain",
3261 "rohc.dynamic.ipv4", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3265 { &hf_rohc_dynamic_udp
,
3266 { "Dynamic UDP chain",
3267 "rohc.dynamic.udp", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3272 { "Type of Service","rohc.rtp.tos",
3273 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3278 { "Time to Live","rohc.rtp.ttl",
3279 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3284 { "Identification","rohc.rtp.id",
3285 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
3290 { "Don't Fragment(DF)","rohc.rtp.df",
3291 FT_BOOLEAN
, 8, NULL
, 0x80,
3296 { "RND(IP-ID behaves randomly)","rohc.rtp.rnd",
3297 FT_BOOLEAN
, 8, NULL
, 0x40,
3302 { "Network Byte Order (NBO)","rohc.rtp.nbo",
3303 FT_BOOLEAN
, 8, NULL
, 0x20,
3304 "Whether the IP-ID is in Network Byte Order" , HFILL
3307 { &hf_rohc_dynamic_udp_checksum
,
3308 { "UDP Checksum", "rohc.dynamic.udp.checksum",
3309 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
3313 { &hf_rohc_dynamic_rtp
,
3314 { "Dynamic RTP chain",
3315 "rohc.dynamic.rtp", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3320 { "Version","rohc.rtp.v",
3321 FT_UINT8
, BASE_DEC
, NULL
, 0xc0,
3326 { "Padding(P)","rohc.rtp.p",
3327 FT_BOOLEAN
, 8, NULL
, 0x20,
3332 { "RX","rohc.rtp.rx",
3333 FT_BOOLEAN
, 8, NULL
, 0x10,
3338 { "CC","rohc.rtp.cc",
3339 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
3340 "CSRC counter from original RTP header" , HFILL
3344 { "Marker Bit (M)","rohc.rtp.m",
3345 FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_set_notset
), 0x00,
3350 { "Payload Type(PT)","rohc.rtp.pt",
3351 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &rtp_payload_type_vals_ext
, 0x7f,
3356 { "Sequence Number(SN)","rohc.rtp.sn",
3357 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3361 { &hf_rohc_rtp_timestamp
,
3362 { "RTP Timestamp","rohc.rtp.timestamp",
3363 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3369 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x10,
3373 { &hf_rohc_rtp_mode
,
3374 { "Mode","rohc.rtp.mode",
3375 FT_UINT8
, BASE_DEC
, VALS(rohc_mode_vals
), 0x0c,
3380 { "TIS","rohc.rtp.tis",
3381 FT_BOOLEAN
, 8, NULL
, 0x02,
3386 { "TSS","rohc.rtp.tss",
3387 FT_BOOLEAN
, 8, NULL
, 0x01,
3391 { &hf_rohc_rtp_ts_stride
,
3392 { "TS_Stride","rohc.rtp.ts_stride",
3393 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3397 { &hf_rohc_rtp_time_stride
,
3398 { "Time_Stride","rohc.rtp.time_stride",
3399 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3404 { "Variable length","rohc.var_len",
3405 FT_UINT8
, BASE_DEC
, VALS(rohc_var_len_vals
), 0x0,
3410 { "Traffic class","rohc.tc",
3411 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3415 { &hf_rohc_ipv6_hop_limit
,
3416 { "Hop limit","rohc.hop_limit",
3417 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3421 { &hf_rohc_ir_previous_frame
,
3422 { "Previous IR frame","rohc.ir.prev.frame_num",
3423 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
3427 { &hf_rohc_ir_profile
,
3428 { "Profile","rohc.ir_profile",
3429 FT_UINT16
, BASE_DEC
, VALS(rohc_profile_vals
), 0x0,
3434 { &hf_rohc_ir_ip_version
,
3435 { "IP Version","rohc.ir_ip_version",
3436 FT_UINT8
, BASE_DEC
, VALS(rohc_ip_version_vals
), 0x0,
3442 { "Mode","rohc.ir_mode",
3443 FT_UINT32
, BASE_DEC
, VALS(rohc_mode_vals
), 0x0,
3447 { &hf_rohc_ir_pkt_frame
,
3448 { "Setup by IR frame","rohc.ir.frame_num",
3449 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
3454 { "Compressed Sequence Number","rohc.comp.sn",
3455 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3460 { "CRC","rohc.r_0_crc",
3461 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3466 { "Extension","rohc.x",
3467 FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_present_not_present
), 0x0,
3472 { "Compressed RTP timestamp","rohc.tp",
3473 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3477 { &hf_rohc_comp_ip_id
,
3478 { "Compressed IP-ID","rohc.comp_ip_id",
3479 FT_UINT16
, BASE_HEX_DEC
, NULL
, 0x0,
3483 { &hf_rohc_comp_ip_id2
,
3484 { "Compressed IP-ID2","rohc.comp_ip_id2",
3485 FT_UINT16
, BASE_HEX_DEC
, NULL
, 0x0,
3491 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3495 { &hf_rohc_compressed_list
,
3496 { "Compressed List", "rohc.compressed-list",
3497 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3501 { &hf_rohc_compressed_list_et
,
3502 { "Encoding Type", "rohc.compressed-list.et",
3503 FT_UINT8
, BASE_DEC
, VALS(compressed_list_encoding_type_vals
), 0xc0,
3507 { &hf_rohc_compressed_list_gp
,
3508 { "Gen-id Present", "rohc.compressed-list.gp",
3509 FT_UINT8
, BASE_DEC
, NULL
, 0x20,
3513 { &hf_rohc_compressed_list_ps
,
3514 { "PS", "rohc.compressed-list.ps",
3515 FT_UINT8
, BASE_DEC
, VALS(compressed_list_ps_vals
), 0x10,
3516 "Size of xi fields", HFILL
3519 { &hf_rohc_compressed_list_res
,
3520 { "Reserved", "rohc.compressed-list.res",
3521 FT_UINT8
, BASE_DEC
, NULL
, 0x10,
3525 { &hf_rohc_compressed_list_count
,
3526 { "Count", "rohc.compressed-list.count",
3527 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
3531 { &hf_rohc_compressed_list_cc
,
3532 { "CSRC Counter", "rohc.compressed-list.cc",
3533 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
3534 "CSRC Counter from original RTP header", HFILL
3537 { &hf_rohc_compressed_list_xi_1
,
3538 { "XI 1", "rohc.compressed-list.xi_1",
3539 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
3543 { &hf_rohc_compressed_list_gen_id
,
3544 { "gen_id", "rohc.compressed-list.gen-id",
3545 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3549 { &hf_rohc_compressed_list_ref_id
,
3550 { "ref_id", "rohc.compressed-list.ref-id",
3551 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3555 { &hf_rohc_compressed_list_mask_size
,
3556 { "Mask size","rohc.compressed-list.mask_size",
3557 FT_BOOLEAN
, 8, TFS(&rohc_cmp_lst_mask_size_vals
), 0x80,
3561 { &hf_rohc_compressed_list_ins_bit_mask
,
3562 { "Insertion bit mask","rohc.compressed-list.ins_bit_mask",
3563 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
3567 { &hf_rohc_compressed_list_rem_bit_mask
,
3568 { "Removal bit mask","rohc.compressed-list.rem_bit_mask",
3569 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
3573 { &hf_rohc_spare_bits
,
3574 { "Spare bits(0)", "rohc.spare_bits",
3575 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3580 { "IP-ID", "rohc.ip-id",
3581 FT_UINT16
, BASE_HEX_DEC
, NULL
, 0x0,
3585 { &hf_rohc_udp_checksum
,
3586 { "UDP checksum", "rohc.udp_checksum",
3587 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
3591 { &hf_rohc_ext3_flags
,
3592 { "Extension 3 flags","rohc.ext3_flags",
3593 FT_UINT8
, BASE_HEX
, NULL
, ROHC_RTP_EXT3_FLAGS_MASK
,
3598 { "S","rohc.ext3.s",
3599 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_S_MASK
,
3603 { &hf_rohc_ext3_r_ts
,
3604 { "R-TS","rohc.ext3.r-ts",
3605 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_R_TS_MASK
,
3609 { &hf_rohc_ext3_tsc
,
3610 { "Tsc","rohc.ext3.tsc",
3611 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_TSC_MASK
,
3615 { &hf_rohc_ext3_udp_mode
,
3616 { "Mode","rohc.ext3.mode",
3617 FT_UINT8
, BASE_DEC
, VALS(rohc_mode_vals
), ROHC_UDP_EXT3_UDP_MODE_MASK
,
3622 { "I","rohc.ext3.i",
3623 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_I_MASK
,
3628 { "ip","rohc.ext3.ip",
3629 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_IP_MASK
,
3633 { &hf_rohc_ext3_ip2
,
3634 { "ip2","rohc.ext3.ip2",
3635 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_UDP_EXT3_IP2_MASK
,
3639 { &hf_rohc_ext3_rtp
,
3640 { "rtp","rohc.ext3.rtp",
3641 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_RTP_MASK
,
3645 { &hf_rohc_ext3_inner_ip_flags
,
3646 { "Inner IP header flags","rohc.ext3.inner_ip_flags",
3647 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3651 { &hf_rohc_ext3_inner_tos
,
3652 { "TOS","rohc.ext3.tos",
3653 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_INNER_TOS_MASK
,
3657 { &hf_rohc_ext3_inner_ttl
,
3658 { "TTL","rohc.ext3.ttl",
3659 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_INNER_TTL_MASK
,
3663 { &hf_rohc_ext3_inner_df
,
3664 { "DF","rohc.ext3.df",
3665 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_INNER_DF_MASK
,
3669 { &hf_rohc_ext3_inner_pr
,
3670 { "PR","rohc.ext3.pr",
3671 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_INNER_PR_MASK
,
3675 { &hf_rohc_ext3_inner_ipx
,
3676 { "IPX","rohc.ext3.ipx",
3677 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_INNER_IPX_MASK
,
3681 { &hf_rohc_ext3_inner_nbo
,
3682 { "NBO","rohc.ext3.nbo",
3683 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_INNER_NBO_MASK
,
3687 { &hf_rohc_ext3_inner_rnd
,
3688 { "RND","rohc.ext3.rnd",
3689 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_INNER_RND_MASK
,
3693 { &hf_rohc_ext3_inner_ip2
,
3694 { "ip2","rohc.ext3.ip2",
3695 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_INNER_IP2_MASK
,
3699 { &hf_rohc_ext3_outer_ip_flags
,
3700 { "Outer IP header flags","rohc.ext3.outer_ip_flags",
3701 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3705 { &hf_rohc_ext3_outer_tos
,
3706 { "TOS2","rohc.ext3.tos2",
3707 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_OUTER_TOS_MASK
,
3711 { &hf_rohc_ext3_outer_ttl
,
3712 { "TTL2","rohc.ext3.ttl2",
3713 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_OUTER_TTL_MASK
,
3717 { &hf_rohc_ext3_outer_df
,
3718 { "DF2","rohc.ext3.df2",
3719 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_OUTER_DF_MASK
,
3723 { &hf_rohc_ext3_outer_pr
,
3724 { "PR2","rohc.ext3.pr2",
3725 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_OUTER_PR_MASK
,
3729 { &hf_rohc_ext3_outer_ipx
,
3730 { "IPX2","rohc.ext3.ipx2",
3731 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_OUTER_IPX_MASK
,
3735 { &hf_rohc_ext3_outer_nbo
,
3736 { "NBO2","rohc.ext3.nbo2",
3737 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_OUTER_NBO_MASK
,
3741 { &hf_rohc_ext3_outer_rnd
,
3742 { "RND2","rohc.ext3.rnd2",
3743 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_OUTER_RND_MASK
,
3747 { &hf_rohc_ext3_outer_i2
,
3748 { "I2","rohc.ext3.i2",
3749 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_OUTER_I2_MASK
,
3753 { &hf_rohc_ext3_rtp_flags
,
3754 { "RTP header flags","rohc.ext3.rtp_flags",
3755 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3759 { &hf_rohc_ext3_rtp_mode
,
3760 { "Mode","rohc.ext3.mode",
3761 FT_UINT8
, BASE_DEC
, VALS(rohc_mode_vals
), ROHC_RTP_EXT3_RTP_MODE_MASK
,
3765 { &hf_rohc_ext3_r_pt
,
3766 { "R-PT","rohc.ext3.r_pt",
3767 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_R_PT_MASK
,
3772 { "M","rohc.ext3.m",
3773 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_M_MASK
,
3777 { &hf_rohc_ext3_r_x
,
3778 { "R-X","rohc.ext3.r_x",
3779 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_R_X_MASK
,
3783 { &hf_rohc_ext3_csrc
,
3784 { "CSRC","rohc.ext3.csrc",
3785 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_CSRC_MASK
,
3789 { &hf_rohc_ext3_tss
,
3790 { "TSS","rohc.ext3.tss",
3791 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_TSS_MASK
,
3795 { &hf_rohc_ext3_tis
,
3796 { "TIS","rohc.ext3.tis",
3797 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_TIS_MASK
,
3801 { &hf_rohc_ext3_r_p
,
3802 { "R-P","rohc.ext3.r_p",
3803 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), ROHC_RTP_EXT3_R_P_MASK
,
3807 /* Generated from convert_proto_tree_add_text.pl */
3808 { &hf_rohc_unknown_option_data
, { "Unknown Option data", "rohc.unknown_option_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3809 { &hf_rohc_configured_by_ir_packet
, { "Configured by IR packet", "rohc.configured_by_ir_packet", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3810 { &hf_rohc_no_configuration_info
, { "No configuration info", "rohc.no_configuration_info", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3811 { &hf_rohc_error_packet
, { "Error packet", "rohc.error_packet", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3814 /* Setup protocol subtree array */
3815 static int *ett
[] = {
3822 &ett_rohc_static_ipv4
,
3823 &ett_rohc_static_udp
,
3824 &ett_rohc_static_rtp
,
3825 &ett_rohc_rtp_static
,
3826 &ett_rohc_rtp_dynamic
,
3827 &ett_rohc_dynamic_ipv4
,
3828 &ett_rohc_dynamic_udp
,
3829 &ett_rohc_dynamic_rtp
,
3830 &ett_rohc_compressed_list
,
3833 &ett_rohc_ext3_flags
,
3834 &ett_rohc_ext3_inner_ip_flags
,
3835 &ett_rohc_ext3_outer_ip_flags
,
3836 &ett_rohc_ext3_rtp_flags
3839 static ei_register_info ei
[] = {
3840 { &ei_rohc_profile_spec_octet
, { "rohc.profile_spec_octet.bad", PI_PROTOCOL
, PI_WARN
, "Invalid profile-specific octet value", EXPFILL
}},
3841 { &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
}},
3842 { &ei_rohc_rohc_opt_clock
, { "rohc.opt.clock.udp", PI_MALFORMED
, PI_ERROR
, "CLOCK option should not be used for UDP", EXPFILL
}},
3843 { &ei_rohc_opt_jitter
, { "rohc.opt.jitter.udp", PI_MALFORMED
, PI_ERROR
, "JITTER option should not be used for UDP", EXPFILL
}},
3844 { &ei_rohc_not_dissected_yet
, { "rohc.not_dissected_yet", PI_UNDECODED
, PI_WARN
, "Not dissected yet", EXPFILL
}},
3845 { &ei_rohc_profile_specific
, { "rohc.profile_specific", PI_UNDECODED
, PI_WARN
, "profile-specific information [Not dissected yet]", EXPFILL
}},
3846 { &ei_rohc_profile_not_supported
, { "rohc.profile_not_supported", PI_PROTOCOL
, PI_WARN
, "Profile not supported", EXPFILL
}},
3847 { &ei_rohc_ip_version
, { "rohc.ip.version.unknown", PI_PROTOCOL
, PI_WARN
, "Error unknown version, only 4 or 6 allowed", EXPFILL
}},
3848 { &ei_rohc_desegmentation_not_implemented
, { "rohc.desegmentation_not_implemented", PI_UNDECODED
, PI_WARN
, "Segment [Desegmentation not implemented yet]", EXPFILL
}},
3851 expert_module_t
* expert_rohc
;
3853 /* Register the protocol name and description */
3854 proto_rohc
= proto_register_protocol("RObust Header Compression (ROHC)", "ROHC", "rohc");
3856 rohc_handle
= register_dissector("rohc", dissect_rohc
, proto_rohc
);
3858 register_init_routine(&rohc_init_protocol
);
3859 register_cleanup_routine(&rohc_cleanup_protocol
);
3861 /* Required function calls to register the header fields and subtrees used */
3862 proto_register_field_array(proto_rohc
, hf
, array_length(hf
));
3863 proto_register_subtree_array(ett
, array_length(ett
));
3864 expert_rohc
= expert_register_protocol(proto_rohc
);
3865 expert_register_field_array(expert_rohc
, ei
, array_length(ei
));
3869 proto_reg_handoff_rohc(void)
3871 dissector_add_uint("ethertype", ETHERTYPE_ROHC
, rohc_handle
);
3873 ip_handle
= find_dissector_add_dependency("ip", proto_rohc
);
3874 ipv6_handle
= find_dissector_add_dependency("ipv6", proto_rohc
);
3878 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3883 * indent-tabs-mode: nil
3886 * vi: set shiftwidth=4 tabstop=8 expandtab:
3887 * :indentSize=4:tabSize=8:noTabs=true: