Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-rohc.c
blob8b232d2e3c70d4132cbd55a49e29daaf1e35b278
1 /* packet-rohc.c
2 * Routines for RObust Header Compression (ROHC) dissection.
4 * Copyright 2011, Anders Broman <anders.broman[at]ericsson.com>
5 * Per Liedberg <per.liedberg [at]ericsson.com>
7 * 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
13 * Ref:
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.
21 #include "config.h"
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>
30 #include <epan/tfs.h>
31 #include <wsutil/array.h>
32 #include "packet-rohc.h"
34 void proto_register_rohc(void);
35 void proto_reg_handoff_rohc(void);
37 static int
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;
186 static int ett_rohc;
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;
223 enum rohc_d_mode
225 NO_CONTEXT = 1,
226 STATIC_CONTEXT = 2,
227 FULL_CONTEXT = 3
230 typedef struct _rohc_cid_context_t
232 uint8_t rohc_ip_version;
233 bool large_cid_present;
234 enum rohc_mode mode;
235 enum rohc_d_mode d_mode; /* Decompressor mode (not used) */
236 bool rnd;
237 bool udp_checksum_present;
238 uint16_t profile;
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*/
262 { 0, NULL },
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[] =
271 { 0, "ACK" },
272 { 1, "NACK" },
273 { 2, "STATIC-NACK" },
274 { 3, "reserved (MUST NOT be used. Otherwise unparsable.)" },
275 { 0, NULL },
278 static const value_string rohc_mode_vals[] =
280 { 0, "Reserved" },
281 { 1, "Unidirectional" },
282 { 2, "Bidirectional Optimistic" },
283 { 3, "Bidirectional Reliable" },
284 { 0, NULL },
287 static const value_string rohc_opt_type_vals[] =
289 { 1, "CRC" },
290 { 2, "REJECT" },
291 { 3, "SN-NOT-VALID" },
292 { 4, "SN" },
293 { 5, "CLOCK" },
294 { 6, "JITTER" },
295 { 7, "LOSS" },
296 { 0, NULL },
301 static const value_string rohc_ip_version_vals[] =
303 { 0, "Unknown" },
304 { 4, "IPv4" },
305 { 6, "IPv6" },
306 { 0, NULL },
309 static const value_string rohc_ip_version_ip_profile_vals[] =
311 { 0x4, "IPv4" },
312 { 0x6, "IPv6" },
313 { 0xc, "IPv4" },
314 { 0xe, "IPv6" },
315 { 0, NULL },
318 static const value_string rohc_var_len_vals[] =
320 { 0, "One octet" },
321 { 2, "Two octets" },
322 { 6, "Three octets" },
323 { 7, "Four octets" },
324 { 0, NULL },
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" },
333 { 0, NULL },
336 static const value_string compressed_list_ps_vals[] =
338 { 0, "4-bit XI fields" },
339 { 1, "8-bit XI fields" },
340 { 0, NULL },
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 */
386 static uint32_t
387 get_self_describing_var_len_val(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, uint8_t *val_len)
389 uint8_t oct;
390 uint32_t val = 0;
391 int num_bits = 0, bit_offset = offset <<3;
393 /* Get first byte */
394 oct = tvb_get_uint8(tvb, offset);
396 if ((oct&0x80)==0) {
397 /* First bit is 0 - 1 octet */
398 *val_len = 1;
399 val = (oct&0x7f);
400 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
401 num_bits = 7;
402 bit_offset++;
403 } else if ((oct&0xc0)==0x80) {
404 /* First bits are 10: 2 octets */
405 *val_len = 2;
406 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 2, ENC_BIG_ENDIAN);
407 bit_offset+=2;
408 num_bits = 14;
409 val = tvb_get_ntohs(tvb, offset)&0x3fff;
410 } else if ((oct&0xe0)==0xc0) {
411 /* First bits are 110: 3 octets */
412 *val_len = 3;
413 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
414 bit_offset+=3;
415 num_bits = 21;
416 val = tvb_get_ntoh24(tvb, offset)&0x1fffff;
417 } else if ((oct&0xe0)==0xe0) {
418 /* First bits are 111: 4 octets */
419 *val_len = 4;
420 proto_tree_add_bits_item(tree, hf_rohc_var_len, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
421 bit_offset+=3;
422 num_bits = 29;
423 val = tvb_get_ntohl(tvb, offset)&0x1fffffff;
426 /* Add the field */
427 proto_tree_add_bits_item(tree, hf_index, tvb, bit_offset, num_bits, ENC_BIG_ENDIAN);
429 return val;
432 /* 5.7.1. Packet type 0: UO-0, R-0, R-0-CRC */
433 static int
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)
436 uint8_t val_len = 0;
437 uint64_t sn;
438 proto_tree *pkt_tree;
440 switch (rohc_cid_context->mode) {
441 case RELIABLE_BIDIRECTIONAL: /* R-mode */
442 if ((pkt_type&0xc0)==0x00) {
443 /* R-0
445 * 0 1 2 3 4 5 6 7
446 * +---+---+---+---+---+---+---+---+
447 * | 0 0 | SN |
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);
454 /* R-0 subtree */
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");
458 /* SN */
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) {
466 /* R-0-CRC
468 * 0 1 2 3 4 5 6 7
469 * +---+---+---+---+---+---+---+---+
470 * | 0 1 | SN |
471 * +===+===+===+===+===+===+===+===+
472 * |SN | CRC |
473 * +---+---+---+---+---+---+---+---+
475 crumb_spec_t rohc_sn_crumbs[] = {
476 { 2, 6},
477 { 8, 1},
478 { 0, 0}
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");
488 /* SN */
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);
493 /* CRC */
494 proto_tree_add_bits_item(pkt_tree, hf_rohc_r_0_crc, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
495 offset++;
497 /* Show SN in info column */
498 col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", (unsigned)sn);
500 break;
501 case UNIDIRECTIONAL: /* U-mode */
502 /* Fall trough */
503 case OPTIMISTIC_BIDIRECTIONAL: /* O-mode */
504 /* UO-0
506 * 0 1 2 3 4 5 6 7
507 * +---+---+---+---+---+---+---+---+
508 * | 0 | SN | CRC |
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);
515 /* UO-0 subtree */
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");
519 /* SN */
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);
523 /* CRC */
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);
529 break;
531 default:
532 col_append_str(pinfo->cinfo, COL_INFO, "Packet type 0");
533 break;
536 return offset;
539 /* 5.7.5. Extension formats */
540 /* UDP profile extension variations as described in 5.11.4 */
541 static int
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,
549 hf_rohc_ext,
550 tvb, offset, 0,
551 "", "Extension");
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;
557 if (ext_type != 3) {
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);
562 if (ext_type == 0) {
563 /* Extension 0:
565 * 0 1 2 3 4 5 6 7
566 * +---+---+---+---+---+---+---+---+
567 * | 0 0 | SN | +T |
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)) {
580 /* IP-ID */
581 proto_tree_add_bits_item(ext_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
582 } else {
583 /* TS */
584 proto_tree_add_bits_item(ext_tree, hf_rohc_ts, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
586 offset++;
588 } else if (ext_type == 1) {
589 /* Extension 1:
592 * +---+---+---+---+---+---+---+---+
593 * | 0 1 | SN | +T |
594 * +---+---+---+---+---+---+---+---+
595 * | -T |
596 * +---+---+---+---+---+---+---+---+
599 * +---+---+---+---+---+---+---+---+
600 * | 0 1 | SN | IP-ID |
601 * +---+---+---+---+---+---+---+---+
602 * | IP-ID |
603 * +---+---+---+---+---+---+---+---+
605 proto_item_append_text(ext_ti, " 1");
607 if (rohc_cid_context->profile == ROHC_PROFILE_UDP) {
608 /* IP-ID */
609 proto_tree_add_bits_item(ext_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
610 offset++;
611 } else {
612 /* RTP profile */
613 if (t == 0) {
614 /* +T is IP-ID */
615 proto_tree_add_bits_item(ext_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
616 offset++;
617 /* -T is TS */
618 proto_tree_add_bits_item(ext_tree, hf_rohc_ts, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
619 } else if (t == 1) {
620 /* +T is TS */
621 proto_tree_add_bits_item(ext_tree, hf_rohc_ts, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
622 offset++;
623 /* -T is IP-ID */
624 proto_tree_add_bits_item(ext_tree, hf_rohc_comp_ip_id, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
626 offset++;
629 } else if (ext_type == 2) {
630 /* Extension 2:
633 * +---+---+---+---+---+---+---+---+
634 * | 1 0 | SN | +T |
635 * +---+---+---+---+---+---+---+---+
636 * | +T |
637 * +---+---+---+---+---+---+---+---+
638 * | -T |
639 * +---+---+---+---+---+---+---+---+
642 * +---+---+---+---+---+---+---+---+
643 * | 1 0 | SN | IP-ID2 |
644 * +---+---+---+---+---+---+---+---+
645 * | IP-ID2 |
646 * +---+---+---+---+---+---+---+---+
647 * | IP-ID |
648 * +---+---+---+---+---+---+---+---+
650 proto_item_append_text(ext_ti, " 2");
652 if (rohc_cid_context->profile == ROHC_PROFILE_UDP) {
653 /* IP-ID2 */
654 proto_tree_add_bits_item(ext_tree, hf_rohc_comp_ip_id2, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
655 offset += 2;
656 /* IP ID */
657 proto_tree_add_bits_item(ext_tree, hf_rohc_comp_ip_id, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
658 offset++;
659 } else {
660 /* RTP Profile */
661 if (t == 0) {
662 /* +T is IP-ID */
663 proto_tree_add_bits_item(ext_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
664 offset += 2;
665 /* -T is TS */
666 proto_tree_add_bits_item(ext_tree, hf_rohc_ts, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
667 } else if (t == 1) {
668 /* +T is TS */
669 proto_tree_add_bits_item(ext_tree, hf_rohc_ts, tvb, (offset<<3)+5, 11, ENC_BIG_ENDIAN);
670 offset += 2;
671 /* -T is IP-ID */
672 proto_tree_add_bits_item(ext_tree, hf_rohc_comp_ip_id, tvb, (offset<<3), 8, ENC_BIG_ENDIAN);
674 offset++;
677 } else {
678 if ((rohc_cid_context->profile == ROHC_PROFILE_RTP) ||
679 (rohc_cid_context->profile == ROHC_PROFILE_UDP)) {
680 /* Extension 3:
682 * 0 1 2 3 4 5 6 7
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 * ..... ..... ..... ..... ..... ..... ..... .....
690 * | SN | if S = 1
691 * ..... ..... ..... ..... ..... ..... ..... .....
692 * / TS (encoded as in section 4.5.6) / 1-4 octets,
693 * ..... ..... ..... ..... ..... ..... ..... ..... if R-TS = 1
694 * | |
695 * / Inner IP header fields / variable,
696 * | | if ip = 1
697 * ..... ..... ..... ..... ..... ..... ..... .....
698 * | IP-ID | 2 octets, if I = 1
699 * ..... ..... ..... ..... ..... ..... ..... .....
700 * | |
701 * / Outer IP header fields / variable,
702 * | | if ip2 = 1
703 * ..... ..... ..... ..... ..... ..... ..... .....
704 * | |
705 * / RTP header flags and fields / variable,
706 * | | if rtp = 1
707 * ..... ..... ..... ..... ..... ..... ..... .....
709 proto_item_append_text(ext_ti, " 3");
711 static int * const ext3_rtp_flags[] = {
712 &hf_rohc_ext3_s,
713 &hf_rohc_ext3_r_ts,
714 &hf_rohc_ext3_tsc,
715 &hf_rohc_ext3_i,
716 &hf_rohc_ext3_ip,
717 &hf_rohc_ext3_rtp,
718 NULL
720 static int * const ext3_udp_flags[] = {
721 &hf_rohc_ext3_s,
722 &hf_rohc_ext3_udp_mode,
723 &hf_rohc_ext3_i,
724 &hf_rohc_ext3_ip,
725 &hf_rohc_ext3_ip2,
726 NULL
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;
733 /* FLAGS */
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);
737 offset++;
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,
749 NULL
751 /* Inner IP header flags
753 * These correspond to the inner IP header if there are two, and the
754 * single IP header otherwise.
756 * 0 1 2 3 4 5 6 7
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);
763 offset++;
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,
775 NULL
777 /* Outer IP header flags
779 * The fields in this part of the Extension 3 header refer to the
780 * outermost IP header:
782 * 0 1 2 3 4 5 6 7
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);
790 offset++;
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);
794 offset++;
796 if (ext3_flags_value & ROHC_RTP_EXT3_R_TS_MASK) {
797 uint8_t val_len = 0;
798 get_self_describing_var_len_val(tvb, ext_tree, offset, hf_rohc_ts, &val_len);
799 offset += 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);
816 offset++;
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);
820 offset++;
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);
824 offset++;
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);
832 offset += 2;
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);
851 offset++;
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);
855 offset++;
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);
859 offset++;
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);
866 offset += 2;
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,
875 &hf_rohc_ext3_r_pt,
876 &hf_rohc_ext3_m,
877 &hf_rohc_ext3_r_x,
878 &hf_rohc_ext3_csrc,
879 &hf_rohc_ext3_tss,
880 &hf_rohc_ext3_tis,
881 NULL
883 /* RTP header flags and fields
885 * 0 1 2 3 4 5 6 7
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);
900 offset++;
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);
905 offset++;
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) {
911 uint8_t val_len = 0;
912 get_self_describing_var_len_val(tvb, ext_tree, offset, hf_rohc_rtp_ts_stride, &val_len);
913 offset += val_len;
915 if (ext3_rtp_flags_value & ROHC_RTP_EXT3_TIS_MASK) {
916 uint8_t val_len = 0;
917 get_self_describing_var_len_val(tvb, ext_tree, offset, hf_rohc_rtp_time_stride, &val_len);
918 offset += val_len;
921 } else {
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);
930 return offset;
933 /* 5.7.2. Packet type 1 (R-mode): R-1, R-1-TS, R-1-ID */
934 static int
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)
937 proto_item *ti;
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)) {
950 /* R-1 (RTP profile)
952 * 0 1 2 3 4 5 6 7
953 * +---+---+---+---+---+---+---+---+
954 * | 1 0 | SN |
955 * +===+===+===+===+===+===+===+===+
956 * | M | X | TS |
957 * +---+---+---+---+---+---+---+---+
959 /* R-1 (UDP profile)
961 * 0 1 2 3 4 5 6 7
962 * +---+---+---+---+---+---+---+---+
963 * | 1 0 | SN |
964 * +===+===+===+===+===+===+===+===+
965 * | X | IP-ID |
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");
973 /* SN */
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) {
981 /* UDP Profile */
983 /* X */
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);
987 /* IP-ID */
988 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
989 } else {
990 /* RTP Profile */
992 /* M */
993 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
995 /* X */
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);
999 /* TS */
1000 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
1002 offset++;
1003 } else {
1004 /* Packet type depends upon value of T bit */
1005 t = tvb_get_bits8(tvb, ((offset+1+val_len)<<3)+2, 1);
1006 if (t == 0) {
1007 /* R-1-ID
1009 * 0 1 2 3 4 5 6 7
1010 * +---+---+---+---+---+---+---+---+
1011 * | 1 0 | SN |
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");
1019 } else {
1020 /* R-1-TS
1022 * 0 1 2 3 4 5 6 7
1023 * +---+---+---+---+---+---+---+---+
1024 * | 1 0 | SN |
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");
1034 /* SN */
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);
1041 /* M */
1042 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
1044 /* X */
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);
1048 /* T */
1049 proto_tree_add_bits_item(pkt_tree, hf_rohc_t, tvb, (offset<<3)+2, 1, ENC_BIG_ENDIAN);
1050 if (t == 0) {
1051 /* IP-ID */
1052 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
1053 } else {
1054 /* TS */
1055 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
1057 offset++;
1060 if (x) {
1061 offset = dissect_rohc_ext_format(tvb, pinfo, pkt_tree, offset, t, rohc_cid_context);
1063 proto_item_set_len(ti, offset-start_offset);
1065 return offset;
1068 /* 5.7.3. Packet type 1 (U/O-mode): UO-1, UO-1-ID, UO-1-TS */
1069 static int
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)
1072 proto_item *ti;
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)
1087 * 0 1 2 3 4 5 6 7
1088 * +---+---+---+---+---+---+---+---+
1089 * | 1 0 | TS |
1090 * +===+===+===+===+===+===+===+===+
1091 * | M | SN | CRC |
1092 * +---+---+---+---+---+---+---+---+
1094 /* UO-1 (UDP profile)
1096 * 0 1 2 3 4 5 6 7
1097 * +---+---+---+---+---+---+---+---+
1098 * | 1 0 | IP-ID |
1099 * +===+===+===+===+===+===+===+===+
1100 * | SN | CRC |
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) {
1108 /* IP-ID */
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;
1112 /* SN */
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);
1115 } else {
1116 /* RTP Profile */
1118 /* TS */
1119 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
1120 offset += 1 + val_len;
1122 /* M */
1123 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
1125 /* SN */
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);
1134 offset++;
1135 } else {
1136 /* Type depends upon t bit */
1137 t = tvb_get_bits8(tvb, ((offset)<<3)+2, 1);
1138 if (t == 0) {
1139 /* UO-1-ID
1141 * 0 1 2 3 4 5 6 7
1142 * +---+---+---+---+---+---+---+---+
1143 * | 1 0 |T=0| IP-ID |
1144 * +===+===+===+===+===+===+===+===+
1145 * | X | SN | CRC |
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");
1153 /* T */
1154 proto_tree_add_bits_item(pkt_tree, hf_rohc_t, tvb, (offset<<3)+2, 1, ENC_BIG_ENDIAN);
1156 /* IP-ID */
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;
1160 /* X */
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);
1163 } else {
1164 /* UO-1-TS
1166 * 0 1 2 3 4 5 6 7
1167 * +---+---+---+---+---+---+---+---+
1168 * | 1 0 |T=1| TS |
1169 * +===+===+===+===+===+===+===+===+
1170 * | M | SN | CRC |
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");
1178 /* T */
1179 proto_tree_add_bits_item(pkt_tree, hf_rohc_t, tvb, (offset<<3)+2, 1, ENC_BIG_ENDIAN);
1181 /* TS */
1182 proto_tree_add_bits_item(pkt_tree, hf_rohc_ts, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
1183 offset += 1 + val_len;
1185 /* M */
1186 proto_tree_add_bits_item(pkt_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
1189 /* SN */
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);
1195 /* CRC */
1196 proto_tree_add_bits_item(pkt_tree, hf_rohc_crc, tvb, (offset<<3)+5, 3, ENC_BIG_ENDIAN);
1197 offset++;
1199 if (x) {
1200 offset = dissect_rohc_ext_format(tvb, pinfo, pkt_tree, offset, t, rohc_cid_context);
1202 proto_item_set_len(ti, offset-start_offset);
1204 return offset;
1207 /* 5.7.4. Packet type 2: UOR-2 */
1208 static int
1209 dissect_rohc_pkt_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, rohc_cid_context_t *rohc_cid_context)
1211 proto_item *ti;
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)
1226 * 0 1 2 3 4 5 6 7
1227 * +---+---+---+---+---+---+---+---+
1228 * | 1 1 0 | TS |
1229 * +===+===+===+===+===+===+===+===+
1230 * |TS | M | SN |
1231 * +---+---+---+---+---+---+---+---+
1232 * | X | CRC |
1233 * +---+---+---+---+---+---+---+---+
1235 /* UOR-2 (UDP profile)
1237 * 0 1 2 3 4 5 6 7
1238 * +---+---+---+---+---+---+---+---+
1239 * | 1 1 0 | SN |
1240 * +===+===+===+===+===+===+===+===+
1241 * | X | CRC |
1242 * +---+---+---+---+---+---+---+---+
1244 col_append_str(pinfo->cinfo, COL_INFO, "UOR-2");
1246 /* UOR-2 subtree */
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) {
1249 /* UDP profile */
1251 /* SN */
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);
1257 } else {
1258 /* RTP profile */
1260 /* TS */
1261 crumb_spec_t rohc_ts_crumbs[] = {
1262 { 2, 6},
1263 { 8, 1},
1264 { 0, 0}
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;
1272 /* M */
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);
1276 /* SN */
1277 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_sn, tvb, (offset<<3)+2, 6, ENC_BIG_ENDIAN);
1278 offset++;
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);
1289 offset++;
1290 } else {
1291 /* Packet type depends upon T bit */
1292 t = tvb_get_bits8(tvb, ((offset+1+val_len)<<3), 1);
1293 if (t == 0) {
1294 /* UOR-2-ID
1296 * 0 1 2 3 4 5 6 7
1297 * +---+---+---+---+---+---+---+---+
1298 * | 1 1 0 | IP-ID |
1299 * +===+===+===+===+===+===+===+===+
1300 * |T=0| M | SN |
1301 * +---+---+---+---+---+---+---+---+
1302 * | X | CRC |
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");
1310 /* IP-ID */
1311 proto_tree_add_bits_item(pkt_tree, hf_rohc_comp_ip_id, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
1312 } else {
1313 /* UOR-2-TS
1315 * 0 1 2 3 4 5 6 7
1316 * +---+---+---+---+---+---+---+---+
1317 * | 1 1 0 | TS |
1318 * +===+===+===+===+===+===+===+===+
1319 * |T=1| M | SN |
1320 * +---+---+---+---+---+---+---+---+
1321 * | X | CRC |
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");
1329 /* TS */
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);
1343 offset++;
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);
1353 offset++;
1355 if (x) {
1356 offset = dissect_rohc_ext_format(tvb, pinfo, pkt_tree, offset, t, rohc_cid_context);
1358 proto_item_set_len(ti, offset-start_offset);
1360 return offset;
1363 static void
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)
1367 proto_item *ti;
1368 proto_tree *rohc_feedback_tree;
1369 uint8_t opt, opt_len, oct;
1370 rohc_cid_context_t *rohc_cid_context = NULL;
1371 int key = cid;
1372 uint32_t sn;
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);
1380 } else{
1381 rohc_cid_context = (rohc_cid_context_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_rohc, 0);
1384 if (!rohc_cid_context) {
1385 if (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;
1397 } else {
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]");
1401 return;
1405 if (feedback_data_len==1) {
1406 /* FEEDBACK-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);
1412 if (oct) {
1413 expert_add_info_format(pinfo, ti, &ei_rohc_profile_spec_octet, "Invalid profile-specific octet value (0x%02X)", oct);
1415 break;
1416 case ROHC_PROFILE_RTP: /* 1 */
1417 case ROHC_PROFILE_UDP: /* 2 */
1419 * 0 1 2 3 4 5 6 7
1420 * +---+---+---+---+---+---+---+---+
1421 * | SN |
1422 * +---+---+---+---+---+---+---+---+
1426 /* SN */
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);
1429 break;
1430 default:
1431 proto_tree_add_expert(tree, pinfo, &ei_rohc_profile_specific, tvb, offset, feedback_data_len);
1432 break;
1434 return;
1436 /* FEEDBACK-2 */
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);
1441 break;
1442 case ROHC_PROFILE_RTP: /* 1 */
1443 case ROHC_PROFILE_UDP: /* 2 */
1444 /* 0 1 2 3 4 5 6 7
1445 * +---+---+---+---+---+---+---+---+
1446 * |Acktype| Mode | SN |
1447 * +---+---+---+---+---+---+---+---+
1448 * | SN |
1449 * +---+---+---+---+---+---+---+---+
1450 * / Feedback options /
1451 * +---+---+---+---+---+---+---+---+
1454 /* Subtree */
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?
1462 /* Acktype */
1463 proto_tree_add_item(rohc_feedback_tree, hf_rohc_acktype, tvb, offset, 1, ENC_BIG_ENDIAN);
1464 /* Mode */
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);
1467 /* SN */
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);
1470 offset+=2;
1471 feedback_data_len-=2;
1473 /* 0 1 2 3 4 5 6 7
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);
1482 opt = opt >> 4;
1483 opt_len = opt_len &0x0f;
1484 /* Opt Type */
1485 ti = proto_tree_add_item(rohc_feedback_tree, hf_rohc_opt_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1486 /* Opt Len */
1487 proto_tree_add_item(rohc_feedback_tree, hf_rohc_opt_len, tvb, offset, 1, ENC_BIG_ENDIAN);
1488 offset++;
1489 feedback_data_len--;
1491 /* optional data */
1492 switch (opt) {
1493 case 1:
1494 /* CRC */
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);
1498 break;
1499 case 2:
1500 /* REJECT */
1501 col_append_str(pinfo->cinfo, COL_INFO, "Reject ");
1502 break;
1503 case 3:
1504 /* SN-Not-Valid */
1505 col_append_str(pinfo->cinfo, COL_INFO, "SN-Not-Valid ");
1506 break;
1507 case 4:
1508 /* SN */
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);
1513 break;
1514 case 5:
1515 /* Clock */
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);
1520 } else {
1521 expert_add_info(pinfo, ti, &ei_rohc_rohc_opt_clock);
1523 break;
1524 case 6:
1525 /* Jitter */
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);
1530 } else {
1531 expert_add_info(pinfo, ti, &ei_rohc_opt_jitter);
1533 break;
1534 case 7:
1535 /* Loss */
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);
1539 break;
1541 default:
1542 proto_tree_add_item(rohc_feedback_tree, hf_rohc_unknown_option_data, tvb, offset, opt_len, ENC_NA);
1543 break;
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);
1550 break;
1552 default:
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);
1556 break;
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 */
1565 static int
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"));
1585 #if 0
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);
1590 return offset+1;
1592 #endif
1593 GP = (first_byte & 0x20) >> 5;
1594 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gp, tvb, offset, 1, ENC_BIG_ENDIAN);
1596 switch (ET) {
1597 case 0:
1598 /* 5.8.6.1 Encoding Type 0 (generic scheme)
1600 * 0 1 2 3 4 5 6 7
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 * +---+---+---+---+---+---+---+---+
1610 * | |
1611 * / item 1, ..., item n / variable
1612 * | |
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);
1627 offset++;
1629 /* GP: Indicates presence of gen_id field. */
1630 if (GP) {
1631 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gen_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1632 offset++;
1634 if (CC!=0) {
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
1638 * follows:
1640 * +---+---+---+---+
1641 * PS = 0: | X | Index |
1642 * +---+---+---+---+
1644 * 0 1 2 3 4 5 6 7
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
1652 * not sent.
1654 if (PS) {
1655 /* PS = 1 indicates 8-bit XI fields. */
1656 } else {
1657 /* PS = 0 indicates 4-bit XI fields; */
1661 break;
1663 case 1:
1665 * 5.8.6.2. Encoding Type 1 (insertion only scheme)
1667 * 0 1 2 3 4 5 6 7
1668 * +---+---+---+---+---+---+---+---+
1669 * | ET=1 |GP |PS | XI 1 |
1670 * +---+---+---+---+---+---+---+---+
1671 * : gen_id : 1 octet, if GP = 1
1672 * +---+---+---+---+---+---+---+---+
1673 * | ref_id |
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 * +---+---+---+---+---+---+---+---+
1681 * | |
1682 * / item 1, ..., item n / variable
1683 * | |
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.
1693 if (PS==0) {
1694 proto_tree_add_item(list_tree, hf_rohc_compressed_list_xi_1, tvb, offset, 1, ENC_BIG_ENDIAN);
1696 offset++;
1697 /* GP: Indicates presence of gen_id field. */
1698 if (GP) {
1699 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gen_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1700 offset++;
1702 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ref_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1703 offset++;
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:
1711 * 0 1 2 3 4 5 6 7
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);
1726 offset+=2;
1727 } else {
1728 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_ins_bit_mask, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
1729 offset++;
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.
1741 /* TODO: */
1742 break;
1743 case 2:
1745 * 5.8.6.3. Encoding Type 2 (removal only scheme)
1747 * 0 1 2 3 4 5 6 7
1748 * +---+---+---+---+---+---+---+---+
1749 * | ET=2 |GP |res| Count |
1750 * +---+---+---+---+---+---+---+---+
1751 * : gen_id : 1 octet, if GP = 1
1752 * +---+---+---+---+---+---+---+---+
1753 * | ref_id |
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);
1762 offset++;
1763 /* GP: Indicates presence of gen_id field. */
1764 if (GP) {
1765 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gen_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1766 offset++;
1768 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ref_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1769 offset++;
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);
1781 offset+=2;
1782 } else {
1783 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_rem_bit_mask, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
1784 offset++;
1786 break;
1787 case 3:
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
1792 * scheme.
1794 * 0 1 2 3 4 5 6 7
1795 * +---+---+---+---+---+---+---+---+
1796 * | ET=3 |GP |PS | XI 1 |
1797 * +---+---+---+---+---+---+---+---+
1798 * : gen_id : 1 octet, if GP = 1
1799 * +---+---+---+---+---+---+---+---+
1800 * | ref_id |
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 * +---+---+---+---+---+---+---+---+
1810 * | |
1811 * / item 1, ..., item n / variable
1812 * | |
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.
1822 if (PS==0) {
1823 proto_tree_add_item(list_tree, hf_rohc_compressed_list_xi_1, tvb, offset, 1, ENC_BIG_ENDIAN);
1825 offset++;
1826 /* GP: Indicates presence of gen_id field. */
1827 if (GP) {
1828 proto_tree_add_item(list_tree, hf_rohc_compressed_list_gen_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1829 offset++;
1831 proto_tree_add_item(list_tree, hf_rohc_compressed_list_ref_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1832 offset++;
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);
1845 offset+=2;
1846 } else {
1847 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_rem_bit_mask, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
1848 offset++;
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:
1858 * 0 1 2 3 4 5 6 7
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);
1873 offset+=2;
1874 } else {
1875 proto_tree_add_bits_item(list_tree, hf_rohc_compressed_list_ins_bit_mask, tvb, (offset<<3)+1, 7, ENC_BIG_ENDIAN);
1876 offset++;
1878 /* TODO: */
1879 offset++;
1880 break;
1883 proto_item_set_len(list_ti, offset-start_offset);
1885 return offset;
1888 static int
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;
1897 uint16_t id;
1898 /*uint8_t contributing_csrcs;*/
1899 uint16_t sequence_number;
1900 uint32_t timestamp;
1901 #if 0
1902 uint8_t tis = 0, tss=0;
1903 uint64_t ts_stride = 0;
1904 #endif
1905 start_offset = offset;
1907 /* Create subtree according to profile */
1908 switch (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");
1911 break;
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");
1915 break;
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");
1919 break;
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");
1923 break;
1925 default:
1926 proto_tree_add_expert(tree, pinfo, &ei_rohc_profile_not_supported, tvb, offset, 0);
1927 return -1;
1930 /* IP dynamic */
1931 /* for all profiles except uncompressed */
1932 if (profile != ROHC_PROFILE_UNCOMPRESSED) {
1933 switch (rohc_cid_context->rohc_ip_version) {
1934 case 4:
1935 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
1936 * Dynamic part:
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);
1946 offset++;
1947 /* Time to Live */
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);
1950 offset++;
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);
1954 offset+=2;
1955 /* +---+---+---+---+---+---+---+---+
1956 * | DF|RND|NBO| 0 |
1957 * +---+---+---+---+---+---+---+---+
1959 rohc_cid_context->rnd = (tvb_get_uint8(tvb, offset) & 0x40) >> 6;
1960 nbo = (tvb_get_uint8(tvb, offset) & 0x20) >> 5;
1961 /* DF */
1962 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_df, tvb, offset, 1, ENC_BIG_ENDIAN);
1963 /* RND */
1964 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_rnd, tvb, offset, 1, ENC_BIG_ENDIAN);
1965 /* NBO */
1966 proto_tree_add_item(dynamic_ipv4_tree, hf_rohc_rtp_nbo, tvb, offset, 1, ENC_BIG_ENDIAN);
1967 /* Spare */
1968 proto_tree_add_bits_item(dynamic_ipv4_tree, hf_rohc_spare_bits, tvb, (offset<<3)+3, 5, ENC_BIG_ENDIAN);
1969 offset++;
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);
1985 break;
1986 case 6:
1988 /* Dynamic part:
1989 * +---+---+---+---+---+---+---+---+
1990 * | Traffic Class | 1 octet
1991 * +---+---+---+---+---+---+---+---+
1992 * | Hop Limit | 1 octet
1993 * +---+---+---+---+---+---+---+---+
1994 * / Generic extension header list / variable length
1995 * +---+---+---+---+---+---+---+---+
1998 /* Traffic Class */
1999 proto_tree_add_item(sub_tree, hf_rohc_ipv6_tc, tvb, offset, 1, ENC_BIG_ENDIAN);
2000 offset++;
2001 /* Hop Limit */
2002 proto_tree_add_item(sub_tree, hf_rohc_ipv6_hop_limit, tvb, offset, 1, ENC_BIG_ENDIAN);
2003 offset++;
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);
2006 return -1;
2007 default:
2008 break;
2012 /* UDP dynamic */
2013 if ( (profile == ROHC_PROFILE_UDP) ||
2014 (profile == ROHC_PROFILE_RTP) ) {
2015 /* 5.7.7.5. Initialization of UDP Header
2016 * Dynamic part:
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;
2027 /* Checksum */
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);
2029 offset += 2;
2030 if (profile == ROHC_PROFILE_UDP) {
2031 /* IP-ID 5.11.1 */
2032 proto_tree_add_item(dynamic_udp_tree, hf_rohc_comp_ip_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2033 offset += 2;
2035 proto_item_set_len(item, offset - start_offset);
2038 /* RTP dynamic*/
2039 if (profile == ROHC_PROFILE_RTP) {
2040 /* 5.7.7.6. Initialization of RTP Header
2041 * Dynamic part:
2042 * Checksum
2043 * P, X, CC, PT, M, sequence number, timestamp, timestamp stride,
2044 * CSRC identifiers.
2046 * 0 1 2 3 4 5 6 7
2047 * +---+---+---+---+---+---+---+---+
2048 * | V=2 | P | RX| CC | (RX is NOT the RTP X bit)
2049 * +---+---+---+---+---+---+---+---+
2050 * | M | PT |
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;
2071 /* V */
2072 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_v, tvb, offset, 1, ENC_BIG_ENDIAN);
2073 /* P */
2074 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_p, tvb, offset, 1, ENC_BIG_ENDIAN);
2075 /* RX */
2076 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_rx, tvb, offset, 1, ENC_BIG_ENDIAN);
2077 /* CC */
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;
2082 offset++;
2084 /* M */
2085 proto_tree_add_bits_item(dynamic_rtp_tree, hf_rohc_rtp_m, tvb, (offset<<3), 1, ENC_BIG_ENDIAN);
2086 /* PT */
2087 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_pt, tvb, offset, 1, ENC_BIG_ENDIAN);
2088 offset++;
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);
2092 offset+=2;
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);
2096 offset+=4;
2097 /* RFC 4815
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
2113 * same value.
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 */
2122 if (rx==0) {
2123 return offset;
2125 /* X */
2126 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_x, tvb, offset, 1, ENC_BIG_ENDIAN);
2127 /* Mode */
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);
2130 /* TIS */
2131 proto_tree_add_item(dynamic_rtp_tree, hf_rohc_rtp_tis, tvb, offset, 1, ENC_BIG_ENDIAN);
2132 /* TSS */
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);
2135 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);
2163 return offset;
2166 static int
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 */
2177 switch (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");
2181 break;
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");
2185 break;
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");
2189 break;
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");
2193 break;
2195 default:
2196 proto_tree_add_expert(tree, pinfo, &ei_rohc_profile_not_supported, tvb, offset, 0);
2197 return -1;
2200 /* IP static*/
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 */
2206 version &= 0x07;
2207 ver_item = proto_tree_add_item(sub_tree, hf_rohc_ip_version_ip_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
2208 } else {
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;
2213 switch (version) {
2214 case 4:
2216 /* 5.7.7.4. Initialization of IPv4 Header [IPv4, section 3.1].
2217 * Static part:
2219 uint32_t source, dest;
2221 offset++;
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);
2226 /* Protocol */
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);
2229 offset++;
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);
2233 offset+=4;
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);
2237 offset+=4;
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));
2246 break;
2248 case 6:
2249 /* 5.7.7.3. Initialization of IPv6 Header [IPv6]*/
2250 /* Static part:
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 * +---+---+---+---+---+---+---+---+
2265 /* Flow Label */
2266 proto_tree_add_item(sub_tree, hf_rohc_ipv6_flow, tvb, offset, 3, ENC_BIG_ENDIAN);
2267 offset+=3;
2269 /* Next Header */
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);
2272 offset++;
2274 /* Source Address */
2275 proto_tree_add_item(sub_tree, hf_rohc_ipv6_src, tvb, offset, 16, ENC_NA);
2276 offset+=16;
2278 /* Destination Address */
2279 proto_tree_add_item(sub_tree, hf_rohc_ipv6_dst, tvb, offset, 16, ENC_NA);
2280 offset+=16;
2281 break;
2283 default:
2284 expert_add_info(pinfo, ver_item, &ei_rohc_ip_version);
2285 return -1;
2287 } else {
2288 protocol = 0; /* Something other than UDP (which is checked for below) */
2291 if (protocol == IP_PROTO_UDP) {
2292 /* UDP static */
2293 if ((profile == ROHC_PROFILE_RTP) ||
2294 (profile == ROHC_PROFILE_UDP)) {
2295 /* 5.7.7.5. Initialization of UDP Header [RFC-768].
2296 * Static part
2298 uint16_t source_port, dest_port;
2299 uint32_t ssrc;
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);
2305 /* Source Port */
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);
2308 offset+=2;
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);
2312 offset+=2;
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);
2320 if (d) {
2321 /* UDP Dynamic */
2322 offset = dissect_rohc_ir_profile_dynamic(tvb, pinfo, tree, offset, profile, rohc_cid_context);
2324 return offset;
2327 /* RTP static */
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);
2333 /* SSRC */
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);
2336 offset += 4;
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. */
2344 if (d==true) {
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);
2350 if (d==true) {
2351 offset = dissect_rohc_ir_profile_dynamic(tvb, pinfo, tree, offset, profile, rohc_cid_context);
2353 return offset;
2354 } else {
2355 proto_tree_add_expert(sub_tree, pinfo, &ei_rohc_not_dissected_yet, tvb, offset, -1);
2357 return offset;
2360 static int
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;
2366 int ir_item_start;
2367 int x_bit_offset;
2368 bool d = false;
2369 uint8_t oct, profile, val_len = 0;
2370 int16_t feedback_data_len = 0;
2371 tvbuff_t *next_tvb;
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
2380 0 1 2 3 4 5 6 7
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 +---+---+---+---+---+---+---+---+
2390 | Profile | 1 octet
2391 +---+---+---+---+---+---+---+---+
2392 | CRC | 1 octet
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;
2417 d = oct & 0x01;
2418 x_bit_offset = offset;
2419 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;
2426 /* Read profile */
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);
2434 /* Profile.
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);
2439 offset++;
2441 /* CRC */
2442 proto_tree_add_item(ir_tree, hf_rohc_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
2443 offset++;
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)) {
2450 int key = cid;
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);
2474 } else {
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);
2492 } else {
2493 /* get the stored data */
2494 rohc_cid_context = (rohc_cid_context_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_rohc, 0);
2497 switch (profile) {
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/");
2514 break;
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);
2519 break;
2521 default:
2522 proto_tree_add_expert(ir_tree, pinfo, &ei_rohc_profile_specific, tvb, offset, feedback_data_len);
2523 offset = -1;
2524 break;
2527 if (offset != -1) {
2528 /* Set length of IR header */
2529 proto_item_set_len(ir_item, offset-ir_item_start);
2532 return offset;
2535 static int
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;
2541 int ir_item_start;
2542 uint8_t profile, val_len = 0;
2543 int16_t feedback_data_len = 0;
2544 rohc_cid_context_t *rohc_cid_context;
2546 /* Add-CID */
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;
2555 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;
2563 /* Profile */
2564 profile = tvb_get_uint8(tvb,offset);
2565 proto_tree_add_item(ir_tree, hf_rohc_profile, tvb, offset, 1, ENC_BIG_ENDIAN);
2566 offset++;
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)) {
2573 int key = cid;
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);
2598 } else {
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);
2615 } else {
2616 /* get the stored data */
2617 rohc_cid_context = (rohc_cid_context_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_rohc, 0);
2620 /* CRC */
2621 proto_tree_add_item(ir_tree, hf_rohc_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
2622 offset++;
2624 /* Profile specific information */
2625 switch (profile ) {
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);
2629 break;
2631 default:
2632 proto_tree_add_expert(ir_tree, pinfo, &ei_rohc_profile_specific, tvb, offset, feedback_data_len);
2633 break;
2636 /* Set length of IR-DYN header */
2637 if (offset != -1) {
2638 proto_item_set_len(ir_item, offset-ir_item_start);
2641 return offset;
2644 /******************************/
2645 /* Main dissection function. */
2646 static int
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;
2660 if (data == 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;
2672 } else {
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);
2685 } else {
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, " ");
2691 /* Add ROHC root */
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);
2719 /* Profile */
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);
2728 /* IR mode */
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);
2732 } else {
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);
2737 } else {
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);
2745 start_over:
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.
2751 cid = 0;
2752 oct = tvb_get_uint8(tvb,offset);
2753 if (oct== 0xe0) {
2754 while (oct == 0xe0) {
2755 offset++;
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) {
2765 is_add_cid = true;
2766 cid = oct & 0x0f;
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);
2769 offset++;
2771 oct = tvb_get_uint8(tvb,offset);
2774 /* feedback ?
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;
2785 if (is_add_cid) {
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);
2790 } else {
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
2798 * compressor;
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);
2805 /* Code */
2806 proto_tree_add_item(sub_tree, hf_rohc_code, tvb, offset, 1, ENC_BIG_ENDIAN);
2807 code = oct&0x7;
2808 offset++;
2809 if (code==0) {
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);
2813 offset++;
2814 } else {
2815 /* Size is in code field itself. */
2816 size = code;
2818 feedback_data_len = size;
2819 /* CID */
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) {
2824 cid = oct & 0x0f;
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);
2827 offset++;
2828 feedback_data_len--;
2829 } else {
2830 item = proto_tree_add_uint(sub_tree, hf_rohc_small_cid, tvb, 0, 0, cid);
2831 proto_item_set_generated(item);
2833 } else {
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;
2838 offset += 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);
2843 offset += size;
2844 if (offset<length) {
2845 goto start_over;
2848 proto_item_set_len(p_rohc_info->last_created_item, offset-feedback_start);
2849 return tvb_captured_length(tvb);
2851 }/*feedback */
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);
2873 if (offset == -1) {
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);
2885 if (offset == -1) {
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)) {
2897 int key = cid;
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);
2915 } else {
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) {
2929 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");
2937 else {
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);
2949 else {
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);
2965 else {
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);
2974 /* IP-ID */
2975 if (rohc_cid_context->rnd) {
2976 proto_tree_add_item(rohc_tree, hf_rohc_ip_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2977 offset += 2;
2980 /* UDP Checksum */
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);
2983 offset += 2;
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.
2995 * XXXX ToDo:
2996 * A better Key than just the CID may have to be devised.
3001 static void
3002 rohc_init_protocol(void)
3004 rohc_cid_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
3007 static void
3008 rohc_cleanup_protocol(void)
3010 g_hash_table_destroy(rohc_cid_hash);
3013 void
3014 proto_register_rohc(void)
3017 static hf_register_info hf[] =
3019 { &hf_rohc_padding,
3020 { "Padding","rohc.padding",
3021 FT_BYTES, BASE_NONE, NULL, 0x0,
3022 NULL , HFILL
3025 { &hf_rohc_add_cid,
3026 { "Add-CID","rohc.add_cid",
3027 FT_UINT8, BASE_HEX, NULL, 0xf0,
3028 NULL , HFILL
3031 { &hf_rohc_feedback,
3032 { "Feedback","rohc.feedback",
3033 FT_UINT8, BASE_HEX, NULL, 0xf8,
3034 NULL , HFILL
3037 { &hf_rohc_code,
3038 { "Code","rohc.code",
3039 FT_UINT8, BASE_DEC, NULL, 0x07,
3040 NULL , HFILL
3043 { &hf_rohc_size,
3044 { "Size","rohc.size",
3045 FT_UINT8, BASE_DEC, NULL, 0x00,
3046 NULL , HFILL
3049 { &hf_rohc_ir_packet,
3050 { "IR packet","rohc.ir_packet",
3051 FT_UINT8, BASE_HEX, NULL, 0xfe,
3052 NULL , HFILL
3055 { &hf_rohc_ir_dyn_packet,
3056 { "IR-DYN packet","rohc.ir_dyn_packet",
3057 FT_UINT8, BASE_HEX, NULL, 0x0,
3058 NULL , HFILL
3061 { &hf_rohc_small_cid,
3062 { "Small CID","rohc.small_cid",
3063 FT_UINT8, BASE_DEC, NULL, 0x0f,
3064 NULL , HFILL
3067 { &hf_rohc_large_cid,
3068 { "Large CID","rohc.large_cid",
3069 FT_UINT16, BASE_DEC, NULL, 0x0,
3070 NULL , HFILL
3073 { &hf_rohc_acktype,
3074 { "Acktype","rohc.acktype",
3075 FT_UINT8, BASE_DEC, VALS(rohc_acktype_vals), 0xc0,
3076 NULL , HFILL
3079 { &hf_rohc_mode,
3080 { "Mode","rohc.mode",
3081 FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x30,
3082 NULL , HFILL
3085 { &hf_rohc_sn,
3086 { "SN LSB","rohc.sn",
3087 FT_UINT16, BASE_HEX_DEC, NULL, 0x0fff,
3088 NULL , HFILL
3091 { &hf_rohc_profile_spec_octet,
3092 { "Profile-specific octet","rohc.profile_spec_octet",
3093 FT_UINT8, BASE_HEX, NULL, 0x0,
3094 NULL , HFILL
3097 { &hf_rohc_fb1_sn,
3098 { "SN LSB","rohc.sn",
3099 FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
3100 NULL , HFILL
3103 { &hf_rohc_opt_type,
3104 { "Option type","rohc.opt_type",
3105 FT_UINT8, BASE_DEC, VALS(rohc_opt_type_vals), 0xf0,
3106 NULL , HFILL
3109 { &hf_rohc_opt_len,
3110 { "Option length","rohc.opt_length",
3111 FT_UINT8, BASE_DEC, NULL, 0x0f,
3112 NULL , HFILL
3115 { &hf_rohc_crc,
3116 { "CRC","rohc.crc",
3117 FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
3118 NULL , HFILL
3121 { &hf_rohc_opt_sn,
3122 { "SN additional bits","rohc.opt.sn_add_bits",
3123 FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
3124 "Feedback Option SN", HFILL
3127 { &hf_rohc_ext,
3128 { "Extension","rohc.ext",
3129 FT_STRING, BASE_NONE, NULL, 0x0,
3130 NULL, HFILL
3133 { &hf_rohc_ext_sn,
3134 { "SN LSB","rohc.sn",
3135 FT_UINT24, BASE_HEX_DEC, NULL, 0x0,
3136 NULL, HFILL
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
3157 { &hf_rohc_profile,
3158 { "Profile","rohc.profile",
3159 FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
3160 NULL , HFILL
3163 { &hf_rohc_d_bit,
3164 { "D - Dynamic chain","rohc.d",
3165 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01,
3166 NULL , HFILL
3169 { &hf_rohc_ip_version,
3170 { "Version","rohc.ip.version",
3171 FT_UINT8, BASE_DEC, VALS(rohc_ip_version_vals), 0xf0,
3172 NULL , HFILL
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,
3178 NULL , HFILL
3181 { &hf_rohc_static_ipv4,
3182 { "Static IPv4 chain",
3183 "rohc.static.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
3184 NULL, HFILL
3187 { &hf_rohc_ip_protocol,
3188 { "Protocol","rohc.ip.protocol",
3189 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ipproto_val_ext, 0x0,
3190 NULL , HFILL
3193 { &hf_rohc_ipv4_src,
3194 { "Source address","rohc.ipv4_src",
3195 FT_IPv4, BASE_NONE, NULL, 0x0,
3196 NULL, HFILL
3199 { &hf_rohc_ipv4_dst,
3200 { "Destination address","rohc.ipv4_dst",
3201 FT_IPv4, BASE_NONE, NULL, 0x0,
3202 NULL, HFILL
3205 { &hf_rohc_ipv6_flow,
3206 { "Flow Label","rohc.ipv6.flow",
3207 FT_UINT24, BASE_DEC, NULL, 0x0fffff,
3208 NULL , HFILL
3211 { &hf_rohc_ipv6_nxt_hdr,
3212 { "Next Header","rohc.ipv6.nxt_hdr",
3213 FT_UINT8, BASE_DEC, NULL, 0x0,
3214 NULL , HFILL
3217 { &hf_rohc_ipv6_src,
3218 { "Source Address","rohc.ipv6.src",
3219 FT_IPv6, BASE_NONE, NULL, 0,
3220 NULL , HFILL
3223 { &hf_rohc_ipv6_dst,
3224 { "Destination Address","rohc.ipv6.dst",
3225 FT_IPv6, BASE_NONE, NULL, 0,
3226 NULL , HFILL
3229 { &hf_rohc_static_udp,
3230 { "Static UDP chain", "rohc.static.udp",
3231 FT_NONE, BASE_NONE, NULL, 0x0,
3232 NULL, HFILL
3235 { &hf_rohc_udp_src_port,
3236 { "Source Port","rohc.udp_src_port",
3237 FT_UINT16, BASE_DEC, NULL, 0x0,
3238 NULL , HFILL
3241 { &hf_rohc_udp_dst_port,
3242 { "Destination Port","rohc.udp_dst_port",
3243 FT_UINT16, BASE_DEC, NULL, 0x0,
3244 NULL , HFILL
3247 { &hf_rohc_static_rtp,
3248 { "Static RTP chain",
3249 "rohc.static.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
3250 NULL, HFILL
3253 { &hf_rohc_rtp_ssrc,
3254 { "SSRC","rohc.rtp.ssrc",
3255 FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
3256 NULL , HFILL
3259 { &hf_rohc_dynamic_ipv4,
3260 { "Dynamic IPv4 chain",
3261 "rohc.dynamic.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
3262 NULL, HFILL
3265 { &hf_rohc_dynamic_udp,
3266 { "Dynamic UDP chain",
3267 "rohc.dynamic.udp", FT_NONE, BASE_NONE, NULL, 0x0,
3268 NULL, HFILL
3271 { &hf_rohc_rtp_tos,
3272 { "Type of Service","rohc.rtp.tos",
3273 FT_UINT8, BASE_HEX, NULL, 0x0,
3274 NULL , HFILL
3277 { &hf_rohc_rtp_ttl,
3278 { "Time to Live","rohc.rtp.ttl",
3279 FT_UINT8, BASE_DEC, NULL, 0x0,
3280 NULL , HFILL
3283 { &hf_rohc_rtp_id,
3284 { "Identification","rohc.rtp.id",
3285 FT_UINT16, BASE_HEX, NULL, 0x0,
3286 NULL , HFILL
3289 { &hf_rohc_rtp_df,
3290 { "Don't Fragment(DF)","rohc.rtp.df",
3291 FT_BOOLEAN, 8, NULL, 0x80,
3292 NULL , HFILL
3295 { &hf_rohc_rtp_rnd,
3296 { "RND(IP-ID behaves randomly)","rohc.rtp.rnd",
3297 FT_BOOLEAN, 8, NULL, 0x40,
3298 NULL , HFILL
3301 { &hf_rohc_rtp_nbo,
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,
3310 NULL, HFILL
3313 { &hf_rohc_dynamic_rtp,
3314 { "Dynamic RTP chain",
3315 "rohc.dynamic.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
3316 NULL, HFILL
3319 { &hf_rohc_rtp_v,
3320 { "Version","rohc.rtp.v",
3321 FT_UINT8, BASE_DEC, NULL, 0xc0,
3322 NULL , HFILL
3325 { &hf_rohc_rtp_p,
3326 { "Padding(P)","rohc.rtp.p",
3327 FT_BOOLEAN, 8, NULL, 0x20,
3328 NULL , HFILL
3331 { &hf_rohc_rtp_rx,
3332 { "RX","rohc.rtp.rx",
3333 FT_BOOLEAN, 8, NULL, 0x10,
3334 NULL , HFILL
3337 { &hf_rohc_rtp_cc,
3338 { "CC","rohc.rtp.cc",
3339 FT_UINT8, BASE_DEC, NULL, 0x0f,
3340 "CSRC counter from original RTP header" , HFILL
3343 { &hf_rohc_rtp_m,
3344 { "Marker Bit (M)","rohc.rtp.m",
3345 FT_BOOLEAN, BASE_NONE, TFS(&tfs_set_notset), 0x00,
3346 NULL , HFILL
3349 { &hf_rohc_rtp_pt,
3350 { "Payload Type(PT)","rohc.rtp.pt",
3351 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &rtp_payload_type_vals_ext, 0x7f,
3352 NULL , HFILL
3355 { &hf_rohc_rtp_sn,
3356 { "Sequence Number(SN)","rohc.rtp.sn",
3357 FT_UINT16, BASE_DEC, NULL, 0x0,
3358 NULL , HFILL
3361 { &hf_rohc_rtp_timestamp,
3362 { "RTP Timestamp","rohc.rtp.timestamp",
3363 FT_UINT32, BASE_DEC, NULL, 0x0,
3364 NULL , HFILL
3367 { &hf_rohc_rtp_x,
3368 { "X","rohc.rtp.x",
3369 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x10,
3370 NULL , HFILL
3373 { &hf_rohc_rtp_mode,
3374 { "Mode","rohc.rtp.mode",
3375 FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0c,
3376 NULL , HFILL
3379 { &hf_rohc_rtp_tis,
3380 { "TIS","rohc.rtp.tis",
3381 FT_BOOLEAN, 8, NULL, 0x02,
3382 NULL , HFILL
3385 { &hf_rohc_rtp_tss,
3386 { "TSS","rohc.rtp.tss",
3387 FT_BOOLEAN, 8, NULL, 0x01,
3388 NULL , HFILL
3391 { &hf_rohc_rtp_ts_stride,
3392 { "TS_Stride","rohc.rtp.ts_stride",
3393 FT_UINT32, BASE_DEC, NULL, 0x0,
3394 NULL , HFILL
3397 { &hf_rohc_rtp_time_stride,
3398 { "Time_Stride","rohc.rtp.time_stride",
3399 FT_UINT32, BASE_DEC, NULL, 0x0,
3400 NULL , HFILL
3403 { &hf_rohc_var_len,
3404 { "Variable length","rohc.var_len",
3405 FT_UINT8, BASE_DEC, VALS(rohc_var_len_vals), 0x0,
3406 NULL , HFILL
3409 { &hf_rohc_ipv6_tc,
3410 { "Traffic class","rohc.tc",
3411 FT_UINT8, BASE_DEC, NULL, 0x0,
3412 NULL , HFILL
3415 { &hf_rohc_ipv6_hop_limit,
3416 { "Hop limit","rohc.hop_limit",
3417 FT_UINT8, BASE_DEC, NULL, 0x0,
3418 NULL , HFILL
3421 { &hf_rohc_ir_previous_frame,
3422 { "Previous IR frame","rohc.ir.prev.frame_num",
3423 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3424 NULL , HFILL,
3427 { &hf_rohc_ir_profile,
3428 { "Profile","rohc.ir_profile",
3429 FT_UINT16, BASE_DEC, VALS(rohc_profile_vals), 0x0,
3430 NULL , HFILL
3434 { &hf_rohc_ir_ip_version,
3435 { "IP Version","rohc.ir_ip_version",
3436 FT_UINT8, BASE_DEC, VALS(rohc_ip_version_vals), 0x0,
3437 NULL , HFILL
3441 { &hf_rohc_ir_mode,
3442 { "Mode","rohc.ir_mode",
3443 FT_UINT32, BASE_DEC, VALS(rohc_mode_vals), 0x0,
3444 NULL , HFILL
3447 { &hf_rohc_ir_pkt_frame,
3448 { "Setup by IR frame","rohc.ir.frame_num",
3449 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3450 NULL , HFILL
3453 { &hf_rohc_comp_sn,
3454 { "Compressed Sequence Number","rohc.comp.sn",
3455 FT_UINT8, BASE_DEC, NULL, 0x0,
3456 NULL , HFILL
3459 { &hf_rohc_r_0_crc,
3460 { "CRC","rohc.r_0_crc",
3461 FT_UINT8, BASE_HEX, NULL, 0x0,
3462 NULL , HFILL
3465 { &hf_rohc_x,
3466 { "Extension","rohc.x",
3467 FT_BOOLEAN, BASE_NONE, TFS(&tfs_present_not_present), 0x0,
3468 NULL , HFILL
3471 { &hf_rohc_ts,
3472 { "Compressed RTP timestamp","rohc.tp",
3473 FT_UINT16, BASE_DEC, NULL, 0x0,
3474 NULL , HFILL
3477 { &hf_rohc_comp_ip_id,
3478 { "Compressed IP-ID","rohc.comp_ip_id",
3479 FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
3480 NULL , HFILL
3483 { &hf_rohc_comp_ip_id2,
3484 { "Compressed IP-ID2","rohc.comp_ip_id2",
3485 FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
3486 NULL , HFILL
3489 { &hf_rohc_t,
3490 { "T bit","rohc.t",
3491 FT_UINT8, BASE_DEC, NULL, 0x0,
3492 NULL , HFILL
3495 { &hf_rohc_compressed_list,
3496 { "Compressed List", "rohc.compressed-list",
3497 FT_NONE, BASE_NONE, NULL, 0x0,
3498 NULL , HFILL
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,
3504 NULL , HFILL
3507 { &hf_rohc_compressed_list_gp,
3508 { "Gen-id Present", "rohc.compressed-list.gp",
3509 FT_UINT8, BASE_DEC, NULL, 0x20,
3510 NULL , HFILL
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,
3522 NULL, HFILL
3525 { &hf_rohc_compressed_list_count,
3526 { "Count", "rohc.compressed-list.count",
3527 FT_UINT8, BASE_DEC, NULL, 0x0f,
3528 NULL, HFILL
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,
3540 NULL, HFILL
3543 { &hf_rohc_compressed_list_gen_id,
3544 { "gen_id", "rohc.compressed-list.gen-id",
3545 FT_UINT8, BASE_DEC, NULL, 0x0,
3546 NULL, HFILL
3549 { &hf_rohc_compressed_list_ref_id,
3550 { "ref_id", "rohc.compressed-list.ref-id",
3551 FT_UINT8, BASE_DEC, NULL, 0x0,
3552 NULL, HFILL
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,
3558 NULL , HFILL
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,
3564 NULL, HFILL
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,
3570 NULL, HFILL
3573 { &hf_rohc_spare_bits,
3574 { "Spare bits(0)", "rohc.spare_bits",
3575 FT_UINT8, BASE_DEC, NULL, 0x0,
3576 NULL, HFILL
3579 { &hf_rohc_ip_id,
3580 { "IP-ID", "rohc.ip-id",
3581 FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
3582 NULL, HFILL
3585 { &hf_rohc_udp_checksum,
3586 { "UDP checksum", "rohc.udp_checksum",
3587 FT_UINT16, BASE_HEX, NULL, 0x0,
3588 NULL, HFILL
3591 { &hf_rohc_ext3_flags,
3592 { "Extension 3 flags","rohc.ext3_flags",
3593 FT_UINT8, BASE_HEX, NULL, ROHC_RTP_EXT3_FLAGS_MASK,
3594 NULL, HFILL
3597 { &hf_rohc_ext3_s,
3598 { "S","rohc.ext3.s",
3599 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_S_MASK,
3600 NULL, HFILL
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,
3606 NULL, HFILL
3609 { &hf_rohc_ext3_tsc,
3610 { "Tsc","rohc.ext3.tsc",
3611 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_TSC_MASK,
3612 NULL, HFILL
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,
3618 NULL, HFILL
3621 { &hf_rohc_ext3_i,
3622 { "I","rohc.ext3.i",
3623 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_I_MASK,
3624 NULL, HFILL
3627 { &hf_rohc_ext3_ip,
3628 { "ip","rohc.ext3.ip",
3629 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_IP_MASK,
3630 NULL, HFILL
3633 { &hf_rohc_ext3_ip2,
3634 { "ip2","rohc.ext3.ip2",
3635 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_UDP_EXT3_IP2_MASK,
3636 NULL, HFILL
3639 { &hf_rohc_ext3_rtp,
3640 { "rtp","rohc.ext3.rtp",
3641 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_RTP_MASK,
3642 NULL, HFILL
3645 { &hf_rohc_ext3_inner_ip_flags,
3646 { "Inner IP header flags","rohc.ext3.inner_ip_flags",
3647 FT_UINT8, BASE_HEX, NULL, 0x0,
3648 NULL, HFILL
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,
3654 NULL, HFILL
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,
3660 NULL, HFILL
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,
3666 NULL, HFILL
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,
3672 NULL, HFILL
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,
3678 NULL, HFILL
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,
3684 NULL, HFILL
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,
3690 NULL, HFILL
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,
3696 NULL, HFILL
3699 { &hf_rohc_ext3_outer_ip_flags,
3700 { "Outer IP header flags","rohc.ext3.outer_ip_flags",
3701 FT_UINT8, BASE_HEX, NULL, 0x0,
3702 NULL, HFILL
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,
3708 NULL, HFILL
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,
3714 NULL, HFILL
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,
3720 NULL, HFILL
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,
3726 NULL, HFILL
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,
3732 NULL, HFILL
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,
3738 NULL, HFILL
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,
3744 NULL, HFILL
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,
3750 NULL, HFILL
3753 { &hf_rohc_ext3_rtp_flags,
3754 { "RTP header flags","rohc.ext3.rtp_flags",
3755 FT_UINT8, BASE_HEX, NULL, 0x0,
3756 NULL, HFILL
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,
3762 NULL, HFILL
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,
3768 NULL, HFILL
3771 { &hf_rohc_ext3_m,
3772 { "M","rohc.ext3.m",
3773 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_M_MASK,
3774 NULL, HFILL
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,
3780 NULL, HFILL
3783 { &hf_rohc_ext3_csrc,
3784 { "CSRC","rohc.ext3.csrc",
3785 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_CSRC_MASK,
3786 NULL, HFILL
3789 { &hf_rohc_ext3_tss,
3790 { "TSS","rohc.ext3.tss",
3791 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_TSS_MASK,
3792 NULL, HFILL
3795 { &hf_rohc_ext3_tis,
3796 { "TIS","rohc.ext3.tis",
3797 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ROHC_RTP_EXT3_TIS_MASK,
3798 NULL, HFILL
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,
3804 NULL, HFILL
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[] = {
3816 &ett_rohc,
3817 &ett_rohc_conf,
3818 &ett_rohc_fb,
3819 &ett_rohc_feedback,
3820 &ett_rohc_ir,
3821 &ett_rohc_ir_dyn,
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,
3831 &ett_rohc_packet,
3832 &ett_rohc_ext,
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));
3868 void
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
3880 * Local variables:
3881 * c-basic-offset: 4
3882 * tab-width: 8
3883 * indent-tabs-mode: nil
3884 * End:
3886 * vi: set shiftwidth=4 tabstop=8 expandtab:
3887 * :indentSize=4:tabSize=8:noTabs=true: