/src/wireshark/epan/dissectors/packet-evrc.c
Line | Count | Source |
1 | | /* packet-evrc.c |
2 | | * Routines for: |
3 | | * EVRC EVRC-B EVRC-WB EVRC-NW EVRC-NW2K |
4 | | * RTP payload header dissection |
5 | | * |
6 | | * Copyright 2008, Michael Lum <michael.lum [AT] shaw.ca> |
7 | | * In association with Star Solutions |
8 | | * |
9 | | * Title 3GPP2 Other |
10 | | * |
11 | | * Enhanced Variable Rate Codec, Speech Service Options 3, 68, 70, 73 and 77 |
12 | | * for Wideband Spread Spectrum Digital Systems |
13 | | * 3GPP2 C.S0014-E v1.0 TIA-127-? |
14 | | * |
15 | | * RFC 3558 https://tools.ietf.org/html/rfc3558 |
16 | | * RFC 4788 https://tools.ietf.org/html/rfc4788 |
17 | | * RFC 5188 https://tools.ietf.org/html/rfc5188 |
18 | | * draft-agupta-payload-rtp-evrc-nw2k-00 |
19 | | * |
20 | | * Wireshark - Network traffic analyzer |
21 | | * By Gerald Combs <gerald@wireshark.org> |
22 | | * Copyright 1998 Gerald Combs |
23 | | * |
24 | | * SPDX-License-Identifier: GPL-2.0-or-later |
25 | | */ |
26 | | |
27 | | #include "config.h" |
28 | | |
29 | | #include <epan/packet.h> |
30 | | #include <epan/prefs.h> |
31 | | #include <epan/expert.h> |
32 | | #include <epan/tfs.h> |
33 | | |
34 | | #include <wsutil/str_util.h> |
35 | | |
36 | | /* PROTOTYPES/FORWARDS */ |
37 | | |
38 | | void proto_register_evrc(void); |
39 | | void proto_reg_handoff_evrc(void); |
40 | | |
41 | | static dissector_handle_t evrc_handle; |
42 | | static dissector_handle_t evrcb_handle; |
43 | | static dissector_handle_t evrcwb_handle; |
44 | | static dissector_handle_t evrcnw_handle; |
45 | | static dissector_handle_t evrcnw2k_handle; |
46 | | static dissector_handle_t evrc_legacy_handle; |
47 | | |
48 | | static const value_string evrc_frame_type_vals[] = { |
49 | | { 0, "Blank (0 bits)" }, |
50 | | { 1, "1/8 Rate (16 bits)" }, |
51 | | { 2, "Not valid (1/4 Rate : 40 bits)" }, |
52 | | { 3, "1/2 Rate (80 bits)" }, |
53 | | { 4, "Full Rate (171 bits; + 5 bits padding)" }, |
54 | | { 5, "Erasure (0 bits)" }, |
55 | | { 0, NULL } |
56 | | }; |
57 | | |
58 | | static const value_string evrc_b_frame_type_vals[] = { |
59 | | { 0, "Blank (0 bits)" }, |
60 | | { 1, "1/8 Rate (16 bits)" }, |
61 | | { 2, "1/4 Rate (40 bits)" }, |
62 | | { 3, "1/2 Rate (80 bits)" }, |
63 | | { 4, "Full Rate (171 bits; + 5 bits padding)" }, |
64 | | { 5, "Erasure (0 bits)" }, |
65 | | { 0, NULL } |
66 | | }; |
67 | | |
68 | | static const value_string evrc_legacy_frame_type_vals[] = { |
69 | | { 0, "Blank (0 bits)" }, |
70 | | { 1, "1/8 Rate (16 bits)" }, |
71 | | { 3, "1/2 Rate (80 bits)" }, |
72 | | { 4, "Full Rate (171 bits; + 5 bits padding)" }, |
73 | | { 14, "Erasure (0 bits)" }, |
74 | | { 0, NULL } |
75 | | }; |
76 | | |
77 | | static const value_string evrc_mode_request_vals[] = { |
78 | | { 0, "Rate Reduction 0 (Full Rate)" }, |
79 | | { 1, "Rate Reduction 1" }, |
80 | | { 2, "Rate Reduction 2" }, |
81 | | { 3, "Rate Reduction 3" }, |
82 | | { 4, "Rate Reduction 4" }, |
83 | | { 0, NULL } |
84 | | }; |
85 | | |
86 | | static const value_string evrc_b_mode_request_vals[] = { |
87 | | { 0, "Encoder Operating Point 0 (Full Rate)" }, |
88 | | { 1, "Encoder Operating Point 1" }, |
89 | | { 2, "Encoder Operating Point 2" }, |
90 | | { 3, "Encoder Operating Point 3" }, |
91 | | { 4, "Encoder Operating Point 4" }, |
92 | | { 5, "Encoder Operating Point 5" }, |
93 | | { 6, "Encoder Operating Point 6" }, |
94 | | { 7, "Encoder Operating Point 7 (1/2 rate max)" }, |
95 | | { 0, NULL } |
96 | | }; |
97 | | |
98 | | static const value_string evrc_wb_mode_request_vals[] = { |
99 | | { 0, "Encoder Operating Point 0 (Full Rate)" }, |
100 | | { 1, "Reserved" }, |
101 | | { 2, "Reserved" }, |
102 | | { 3, "Reserved" }, |
103 | | { 4, "Encoder Operating Point 4" }, |
104 | | { 5, "Reserved" }, |
105 | | { 6, "Reserved" }, |
106 | | { 7, "Encoder Operating Point 7 (1/2 rate max)" }, |
107 | | { 0, NULL } |
108 | | }; |
109 | | |
110 | | static const value_string evrc_nw_mode_request_vals[] = { |
111 | | { 0, "Encoder Operating Point 0 (EVRC-WB COP0)" }, |
112 | | { 1, "Encoder Operating Point 1 (EVRC-B COP0/EVRC-WB COP4)" }, |
113 | | { 2, "Encoder Operating Point 2 (EVRC-B COP2)" }, |
114 | | { 3, "Encoder Operating Point 3 (EVRC-B COP3)" }, |
115 | | { 4, "Encoder Operating Point 4 (EVRC-B COP4)" }, |
116 | | { 5, "Encoder Operating Point 5 (EVRC-B COP5)" }, |
117 | | { 6, "Encoder Operating Point 6 (EVRC-B COP6)" }, |
118 | | { 7, "Encoder Operating Point 7 (EVRC-B COP7/EVRC-WB COP7)" }, |
119 | | { 0, NULL } |
120 | | }; |
121 | | |
122 | | static const value_string evrc_nw2k_mode_request_vals[] = { |
123 | | { 0, "Encoder Operating Point 0 (EVRC-WB COP0)" }, |
124 | | { 1, "Encoder Operating Point 1 (EVRC-B COP0/EVRC-WB COP4)" }, |
125 | | { 2, "Encoder Operating Point 2 (EVRC-B COP2)" }, |
126 | | { 3, "Encoder Operating Point 3 (EVRC-B COP3/EVRC-NW2k)" }, |
127 | | { 4, "Encoder Operating Point 4 (EVRC-B COP4)" }, |
128 | | { 5, "Encoder Operating Point 5 (EVRC-B COP5)" }, |
129 | | { 6, "Encoder Operating Point 6 (EVRC-B COP6)" }, |
130 | | { 7, "Encoder Operating Point 7 (EVRC-B COP7/EVRC-WB COP7)" }, |
131 | | { 0, NULL } |
132 | | }; |
133 | | |
134 | | static const true_false_string toc_further_entries_bit_vals = { |
135 | | "More ToC entries follow", |
136 | | "End of ToC entries" |
137 | | }; |
138 | | |
139 | | static const true_false_string evrc_nw2k_enc_capability_bit_vals = { |
140 | | "Mode-0 wideband encoding capable", |
141 | | "Mode-0 wideband encoding incapable (i.e. narrowband encoding only)" |
142 | | }; |
143 | | |
144 | | typedef enum |
145 | | { |
146 | | EVRC_VARIANT_EVRC, |
147 | | EVRC_VARIANT_EVRC_B, |
148 | | EVRC_VARIANT_EVRC_WB, |
149 | | EVRC_VARIANT_EVRC_NW, |
150 | | EVRC_VARIANT_EVRC_NW2k, |
151 | | EVRC_VARIANT_EVRC_LEGACY |
152 | | } |
153 | | evrc_variant_t; |
154 | | |
155 | | |
156 | | /* Initialize the protocol and registered fields */ |
157 | | static int proto_evrc; |
158 | | static int proto_evrcb; |
159 | | static int proto_evrcwb; |
160 | | static int proto_evrcnw; |
161 | | static int proto_evrcnw2k; |
162 | | static int proto_evrc_legacy; |
163 | | |
164 | | static int hf_evrc_reserved; |
165 | | static int hf_evrc_reserved_2k; |
166 | | static int hf_evrc_enc_capability_2k; |
167 | | static int hf_evrc_interleave_length; |
168 | | static int hf_evrc_interleave_index; |
169 | | static int hf_evrc_mode_request; |
170 | | static int hf_evrc_b_mode_request; |
171 | | static int hf_evrc_wb_mode_request; |
172 | | static int hf_evrc_nw_mode_request; |
173 | | static int hf_evrc_nw2k_mode_request; |
174 | | static int hf_evrc_frame_count; |
175 | | static int hf_evrc_toc_frame_type_high; |
176 | | static int hf_evrc_toc_frame_type_low; |
177 | | static int hf_evrc_b_toc_frame_type_high; |
178 | | static int hf_evrc_b_toc_frame_type_low; |
179 | | static int hf_evrc_padding; |
180 | | static int hf_evrc_speech_data; |
181 | | static int hf_evrc_legacy_toc_fe_ind; |
182 | | static int hf_evrc_legacy_toc_reduc_rate; |
183 | | static int hf_evrc_legacy_toc_frame_type; |
184 | | |
185 | | /* Initialize the subtree pointers */ |
186 | | static int ett_evrc; |
187 | | static int ett_toc; |
188 | | |
189 | | static expert_field ei_evrc_unknown_variant; |
190 | | |
191 | | /* |
192 | | * Variables to allow for proper deletion of dissector registration when |
193 | | * the user changes values |
194 | | */ |
195 | | static bool legacy_pt_60; |
196 | | |
197 | | |
198 | | static uint8_t |
199 | | evrc_frame_type_to_octs(uint8_t frame_type) |
200 | 0 | { |
201 | 0 | switch (frame_type) |
202 | 0 | { |
203 | 0 | default: |
204 | 0 | break; |
205 | | |
206 | 0 | case 1: /* 1/8 rate */ |
207 | 0 | return 2; |
208 | | |
209 | 0 | case 2: /* 1/4 rate */ |
210 | 0 | return 5; |
211 | | |
212 | 0 | case 3: /* 1/2 rate */ |
213 | 0 | return 10; |
214 | | |
215 | 0 | case 4: /* full rate */ |
216 | 0 | return 22; |
217 | 0 | } |
218 | | |
219 | 0 | return 0; |
220 | 0 | } |
221 | | |
222 | | /* GENERIC EVRC DISSECTOR FUNCTIONS */ |
223 | | |
224 | | static void |
225 | | dissect_evrc_aux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, evrc_variant_t evrc_variant) |
226 | 0 | { |
227 | 0 | uint8_t oct; |
228 | 0 | uint8_t frame_count; |
229 | 0 | uint8_t i; |
230 | 0 | uint32_t offset, saved_offset; |
231 | 0 | bool further_entries; |
232 | 0 | uint32_t len; |
233 | 0 | proto_item *item = NULL; |
234 | 0 | proto_tree *evrc_tree = NULL; |
235 | 0 | proto_tree *toc_tree = NULL; |
236 | 0 | int hf_mode_request; |
237 | 0 | int hf_toc_frame_type_high; |
238 | 0 | int hf_toc_frame_type_low; |
239 | | |
240 | | /* |
241 | | * assumed max number of speech frames based on |
242 | | * frame count being 5 bits + 1 |
243 | | */ |
244 | 0 | uint8_t speech_data_len[0x20]; |
245 | | |
246 | |
|
247 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "EVRC"); |
248 | |
|
249 | 0 | if (!tree) return; |
250 | | |
251 | 0 | offset = 0; |
252 | 0 | memset(speech_data_len, 0, sizeof(speech_data_len)); |
253 | |
|
254 | 0 | len = tvb_reported_length(tvb); |
255 | |
|
256 | 0 | item = proto_tree_add_item(tree, proto_evrc, tvb, 0, len, ENC_NA); |
257 | |
|
258 | 0 | evrc_tree = proto_item_add_subtree(item, ett_evrc); |
259 | |
|
260 | 0 | if (evrc_variant == EVRC_VARIANT_EVRC_LEGACY) |
261 | 0 | { |
262 | | /* legacy 'payload type 60' draft-ietf-avt-evrc-07.txt header format */ |
263 | |
|
264 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); |
265 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_interleave_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
266 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_interleave_index, tvb, offset, 1, ENC_BIG_ENDIAN); |
267 | |
|
268 | 0 | offset++; |
269 | |
|
270 | 0 | frame_count = 0; |
271 | 0 | further_entries = true; |
272 | 0 | while (further_entries && (frame_count < sizeof(speech_data_len)) && |
273 | 0 | ((len - offset) > 0)) |
274 | 0 | { |
275 | 0 | toc_tree = |
276 | 0 | proto_tree_add_subtree_format(evrc_tree, tvb, offset, 1, ett_toc, NULL, "ToC [%u]", frame_count+1); |
277 | |
|
278 | 0 | proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_fe_ind, tvb, offset, 1, ENC_BIG_ENDIAN); |
279 | 0 | proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_reduc_rate, tvb, offset, 1, ENC_BIG_ENDIAN); |
280 | 0 | proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_frame_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
281 | |
|
282 | 0 | oct = tvb_get_uint8(tvb, offset); |
283 | 0 | further_entries = (oct & 0x80) ? true : false; |
284 | |
|
285 | 0 | speech_data_len[frame_count] = evrc_frame_type_to_octs((uint8_t)(oct & 0x7f)); |
286 | |
|
287 | 0 | frame_count++; |
288 | 0 | offset++; |
289 | 0 | } |
290 | 0 | } |
291 | 0 | else |
292 | 0 | { |
293 | | /* RFC 3558 header format */ |
294 | |
|
295 | 0 | switch (evrc_variant) |
296 | 0 | { |
297 | 0 | default: |
298 | 0 | proto_tree_add_expert(evrc_tree, pinfo, &ei_evrc_unknown_variant, tvb, offset, len); |
299 | 0 | return; |
300 | | |
301 | 0 | case EVRC_VARIANT_EVRC: |
302 | 0 | hf_mode_request = hf_evrc_mode_request; |
303 | 0 | hf_toc_frame_type_high = hf_evrc_toc_frame_type_high; |
304 | 0 | hf_toc_frame_type_low = hf_evrc_toc_frame_type_low; |
305 | |
|
306 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); |
307 | 0 | break; |
308 | | |
309 | 0 | case EVRC_VARIANT_EVRC_B: |
310 | 0 | hf_mode_request = hf_evrc_b_mode_request; |
311 | 0 | hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high; |
312 | 0 | hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low; |
313 | |
|
314 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); |
315 | 0 | break; |
316 | | |
317 | 0 | case EVRC_VARIANT_EVRC_WB: |
318 | 0 | hf_mode_request = hf_evrc_wb_mode_request; |
319 | 0 | hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high; |
320 | 0 | hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low; |
321 | |
|
322 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); |
323 | 0 | break; |
324 | | |
325 | 0 | case EVRC_VARIANT_EVRC_NW: |
326 | 0 | hf_mode_request = hf_evrc_nw_mode_request; |
327 | 0 | hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high; |
328 | 0 | hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low; |
329 | |
|
330 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); |
331 | 0 | break; |
332 | | |
333 | 0 | case EVRC_VARIANT_EVRC_NW2k: |
334 | 0 | hf_mode_request = hf_evrc_nw2k_mode_request; |
335 | 0 | hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high; |
336 | 0 | hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low; |
337 | |
|
338 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_reserved_2k, tvb, offset, 1, ENC_BIG_ENDIAN); |
339 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_enc_capability_2k, tvb, offset, 1, ENC_BIG_ENDIAN); |
340 | 0 | break; |
341 | 0 | } |
342 | | |
343 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_interleave_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
344 | 0 | proto_tree_add_item(evrc_tree, hf_evrc_interleave_index, tvb, offset, 1, ENC_BIG_ENDIAN); |
345 | |
|
346 | 0 | offset++; |
347 | |
|
348 | 0 | proto_tree_add_item(evrc_tree, hf_mode_request, tvb, offset, 1, ENC_BIG_ENDIAN); |
349 | 0 | proto_tree_add_item_ret_uint8(evrc_tree, hf_evrc_frame_count, tvb, offset, 1, ENC_BIG_ENDIAN, &frame_count); |
350 | | |
351 | | /* |
352 | | * number of frames in PACKET is frame_count + 1 |
353 | | */ |
354 | 0 | frame_count++; |
355 | |
|
356 | 0 | offset++; |
357 | 0 | saved_offset = offset; |
358 | |
|
359 | 0 | toc_tree = |
360 | 0 | proto_tree_add_subtree_format(evrc_tree, tvb, offset, -1, ett_toc, &item, "ToC - %u frame%s", |
361 | 0 | frame_count, plurality(frame_count, "", "s")); |
362 | |
|
363 | 0 | i = 0; |
364 | 0 | while ((i < frame_count) && |
365 | 0 | ((len - offset) > 0)) |
366 | 0 | { |
367 | 0 | oct = tvb_get_uint8(tvb, offset); |
368 | |
|
369 | 0 | proto_tree_add_item(toc_tree, hf_toc_frame_type_high, tvb, offset, 1, ENC_BIG_ENDIAN); |
370 | |
|
371 | 0 | speech_data_len[i] = evrc_frame_type_to_octs((uint8_t)((oct & 0xf0) >> 4)); |
372 | |
|
373 | 0 | i++; |
374 | |
|
375 | 0 | if (i < frame_count) |
376 | 0 | { |
377 | | /* even number of frames */ |
378 | 0 | proto_tree_add_item(toc_tree, hf_toc_frame_type_low, tvb, offset, 1, ENC_BIG_ENDIAN); |
379 | |
|
380 | 0 | speech_data_len[i] = evrc_frame_type_to_octs((uint8_t)(oct & 0x0f)); |
381 | |
|
382 | 0 | i++; |
383 | 0 | } |
384 | |
|
385 | 0 | offset++; |
386 | 0 | } |
387 | |
|
388 | 0 | if (frame_count & 0x01) |
389 | 0 | { |
390 | | /* odd number of frames */ |
391 | 0 | proto_tree_add_item(toc_tree, hf_evrc_padding, tvb, offset-1, 1, ENC_BIG_ENDIAN); |
392 | 0 | } |
393 | |
|
394 | 0 | proto_item_set_len(item, offset - saved_offset); |
395 | 0 | } |
396 | | |
397 | 0 | i = 0; |
398 | 0 | while ((i < frame_count) && |
399 | 0 | ((len - offset) >= speech_data_len[i])) |
400 | 0 | { |
401 | 0 | proto_tree_add_bytes_format(evrc_tree, hf_evrc_speech_data, tvb, offset, speech_data_len[i], NULL, "Speech Data [%u]", i+1); |
402 | |
|
403 | 0 | offset += speech_data_len[i]; |
404 | 0 | i++; |
405 | 0 | } |
406 | 0 | } |
407 | | |
408 | | static int |
409 | | dissect_evrc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
410 | 0 | { |
411 | 0 | dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC); |
412 | 0 | return tvb_captured_length(tvb); |
413 | 0 | } |
414 | | |
415 | | static int |
416 | | dissect_evrcb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
417 | 0 | { |
418 | 0 | dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_B); |
419 | 0 | return tvb_captured_length(tvb); |
420 | 0 | } |
421 | | |
422 | | static int |
423 | | dissect_evrcwb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
424 | 0 | { |
425 | 0 | dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_WB); |
426 | 0 | return tvb_captured_length(tvb); |
427 | 0 | } |
428 | | |
429 | | static int |
430 | | dissect_evrcnw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
431 | 0 | { |
432 | 0 | dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_NW); |
433 | 0 | return tvb_captured_length(tvb); |
434 | 0 | } |
435 | | |
436 | | static int |
437 | | dissect_evrcnw2k(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
438 | 0 | { |
439 | 0 | dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_NW2k); |
440 | 0 | return tvb_captured_length(tvb); |
441 | 0 | } |
442 | | |
443 | | static int |
444 | | dissect_evrc_legacy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
445 | 0 | { |
446 | 0 | dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_LEGACY); |
447 | 0 | return tvb_captured_length(tvb); |
448 | 0 | } |
449 | | |
450 | | |
451 | | /* Register the protocol with Wireshark */ |
452 | | void |
453 | | proto_register_evrc(void) |
454 | 15 | { |
455 | 15 | module_t *evrc_module; |
456 | | |
457 | | /* Setup list of header fields */ |
458 | | |
459 | 15 | static hf_register_info hf[] = |
460 | 15 | { |
461 | 15 | { &hf_evrc_reserved, |
462 | 15 | { "Reserved", "evrc.reserved", |
463 | 15 | FT_UINT8, BASE_HEX, NULL, 0xc0, |
464 | 15 | "Reserved bits", HFILL } |
465 | 15 | }, |
466 | 15 | { &hf_evrc_reserved_2k, |
467 | 15 | { "Reserved", "evrc.reserved", |
468 | 15 | FT_UINT8, BASE_HEX, NULL, 0x80, |
469 | 15 | "Reserved bits", HFILL } |
470 | 15 | }, |
471 | 15 | { &hf_evrc_enc_capability_2k, |
472 | 15 | { "Encoding Capability", "evrc.enc_capability", |
473 | 15 | FT_BOOLEAN, 8, TFS(&evrc_nw2k_enc_capability_bit_vals), 0x40, |
474 | 15 | "Encoding Capability Identification", HFILL } |
475 | 15 | }, |
476 | 15 | { &hf_evrc_interleave_length, |
477 | 15 | { "Interleave Length", "evrc.interleave_len", |
478 | 15 | FT_UINT8, BASE_DEC, NULL, 0x38, |
479 | 15 | "Interleave length bits", HFILL } |
480 | 15 | }, |
481 | 15 | { &hf_evrc_interleave_index, |
482 | 15 | { "Interleave Index", "evrc.interleave_idx", |
483 | 15 | FT_UINT8, BASE_DEC, NULL, 0x07, |
484 | 15 | "Interleave index bits", HFILL } |
485 | 15 | }, |
486 | 15 | { &hf_evrc_mode_request, |
487 | 15 | { "Mode Request", "evrc.mode_request", |
488 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_mode_request_vals), 0xe0, |
489 | 15 | "Mode Request bits", HFILL } |
490 | 15 | }, |
491 | 15 | { &hf_evrc_b_mode_request, |
492 | 15 | { "Mode Request", "evrc.b.mode_request", |
493 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_b_mode_request_vals), 0xe0, |
494 | 15 | "Mode Request bits", HFILL } |
495 | 15 | }, |
496 | 15 | { &hf_evrc_wb_mode_request, |
497 | 15 | { "Mode Request", "evrc.wb.mode_request", |
498 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_wb_mode_request_vals), 0xe0, |
499 | 15 | "Mode Request bits", HFILL } |
500 | 15 | }, |
501 | 15 | { &hf_evrc_nw_mode_request, |
502 | 15 | { "Mode Request", "evrc.nw.mode_request", |
503 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_nw_mode_request_vals), 0xe0, |
504 | 15 | "Mode Request bits", HFILL } |
505 | 15 | }, |
506 | 15 | { &hf_evrc_nw2k_mode_request, |
507 | 15 | { "Mode Request", "evrc.nw2k.mode_request", |
508 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_nw2k_mode_request_vals), 0xe0, |
509 | 15 | "Mode Request bits", HFILL } |
510 | 15 | }, |
511 | 15 | { &hf_evrc_frame_count, |
512 | 15 | { "Frame Count (0 means 1 frame)", "evrc.frame_count", |
513 | 15 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
514 | 15 | "Frame Count bits, a value of 0 means 1 frame", HFILL } |
515 | 15 | }, |
516 | 15 | { &hf_evrc_toc_frame_type_high, |
517 | 15 | { "ToC Frame Type", "evrc.toc.frame_type_hi", |
518 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_frame_type_vals), 0xf0, |
519 | 15 | "ToC Frame Type bits", HFILL } |
520 | 15 | }, |
521 | 15 | { &hf_evrc_toc_frame_type_low, |
522 | 15 | { "ToC Frame Type", "evrc.toc.frame_type_lo", |
523 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_frame_type_vals), 0x0f, |
524 | 15 | "ToC Frame Type bits", HFILL } |
525 | 15 | }, |
526 | 15 | { &hf_evrc_b_toc_frame_type_high, |
527 | 15 | { "ToC Frame Type", "evrc.b.toc.frame_type_hi", |
528 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_b_frame_type_vals), 0xf0, |
529 | 15 | "ToC Frame Type bits", HFILL } |
530 | 15 | }, |
531 | 15 | { &hf_evrc_b_toc_frame_type_low, |
532 | 15 | { "ToC Frame Type", "evrc.b.toc.frame_type_lo", |
533 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_b_frame_type_vals), 0x0f, |
534 | 15 | "ToC Frame Type bits", HFILL } |
535 | 15 | }, |
536 | 15 | { &hf_evrc_padding, |
537 | 15 | { "Padding", "evrc.padding", |
538 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0f, |
539 | 15 | "Padding bits", HFILL } |
540 | 15 | }, |
541 | 15 | { &hf_evrc_speech_data, |
542 | 15 | { "Speech data", "evrc.speech_data", |
543 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, |
544 | 15 | NULL, HFILL } |
545 | 15 | }, |
546 | 15 | { &hf_evrc_legacy_toc_fe_ind, |
547 | 15 | { "ToC Further Entries Indicator", "evrc.legacy.toc.further_entries_ind", |
548 | 15 | FT_BOOLEAN, 8, TFS(&toc_further_entries_bit_vals), 0x80, |
549 | 15 | "ToC Further Entries Indicator bit", HFILL } |
550 | 15 | }, |
551 | 15 | { &hf_evrc_legacy_toc_reduc_rate, |
552 | 15 | { "ToC Reduced Rate", "evrc.legacy.toc.reduced_rate", |
553 | 15 | FT_UINT8, BASE_DEC, NULL, 0x40, |
554 | 15 | "ToC Reduced Rate bits", HFILL } |
555 | 15 | }, |
556 | 15 | { &hf_evrc_legacy_toc_frame_type, |
557 | 15 | { "ToC Frame Type", "evrc.legacy.toc.frame_type", |
558 | 15 | FT_UINT8, BASE_DEC, VALS(evrc_legacy_frame_type_vals), 0x3f, |
559 | 15 | "ToC Frame Type bits", HFILL } |
560 | 15 | } |
561 | 15 | }; |
562 | | |
563 | 15 | static ei_register_info ei[] = { |
564 | 15 | { &ei_evrc_unknown_variant, |
565 | 15 | { "evrc.unknown_variant", PI_UNDECODED, PI_WARN, |
566 | 15 | "Variant Unknown/Unsupported - dissector bug/later version spec (report to wireshark.org)", |
567 | 15 | EXPFILL } |
568 | 15 | } |
569 | 15 | }; |
570 | | |
571 | 15 | expert_module_t *expert_evrc; |
572 | | |
573 | | /* Setup protocol subtree array */ |
574 | | |
575 | 15 | static int *ett[] = |
576 | 15 | { |
577 | 15 | &ett_evrc, |
578 | 15 | &ett_toc |
579 | 15 | }; |
580 | | |
581 | | /* Register the protocol name and description */ |
582 | | |
583 | 15 | proto_evrc = |
584 | 15 | proto_register_protocol("Enhanced Variable Rate Codec", "EVRC", "evrc"); |
585 | | |
586 | 15 | proto_evrcb = |
587 | 15 | proto_register_protocol_in_name_only("Enhanced Variable Rate Codec B", |
588 | 15 | "EVRC-B", "evrcb", proto_evrc, FT_PROTOCOL); |
589 | 15 | proto_evrcwb = |
590 | 15 | proto_register_protocol_in_name_only("Enhanced Variable Rate Codec - Wideband", |
591 | 15 | "EVRC-WB", "evrcwb", proto_evrc, FT_PROTOCOL); |
592 | 15 | proto_evrcnw = |
593 | 15 | proto_register_protocol_in_name_only("Enhanced Variable Rate Codec - Narrowband-Wideband", |
594 | 15 | "EVRC-NW", "evrcnw", proto_evrc, FT_PROTOCOL); |
595 | 15 | proto_evrcnw2k = |
596 | 15 | proto_register_protocol_in_name_only("Enhanced Variable Rate Codec - Narrowband-Wideband plus 2kpbs", |
597 | 15 | "EVRC-NW2K", "evrcnw2k", proto_evrc, FT_PROTOCOL); |
598 | 15 | proto_evrc_legacy = |
599 | 15 | proto_register_protocol_in_name_only("Enhanced Variable Rate Codec (Legacy Encapsulation)", |
600 | 15 | "EVRC (Legacy)", "evrc_legacy", proto_evrc, FT_PROTOCOL); |
601 | 15 | proto_register_field_array(proto_evrc, hf, array_length(hf)); |
602 | | |
603 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
604 | | |
605 | 15 | evrc_handle = register_dissector("evrc", dissect_evrc, proto_evrc); |
606 | 15 | evrcb_handle = register_dissector("evrcb", dissect_evrcb, proto_evrcb); |
607 | 15 | evrcwb_handle = register_dissector("evrcwb", dissect_evrcwb, proto_evrcwb); |
608 | 15 | evrcnw_handle = register_dissector("evrcnw", dissect_evrcnw, proto_evrcnw); |
609 | 15 | evrcnw2k_handle = register_dissector("evrcnw2k", dissect_evrcnw2k, proto_evrcnw2k); |
610 | 15 | evrc_legacy_handle = register_dissector("evrc_legacy", dissect_evrc_legacy, proto_evrc_legacy); |
611 | | |
612 | 15 | expert_evrc = |
613 | 15 | expert_register_protocol(proto_evrc); |
614 | 15 | expert_register_field_array(expert_evrc, ei, array_length(ei)); |
615 | | |
616 | | /* |
617 | | * setup for preferences |
618 | | */ |
619 | 15 | evrc_module = prefs_register_protocol(proto_evrc, proto_reg_handoff_evrc); |
620 | | |
621 | 15 | prefs_register_bool_preference(evrc_module, |
622 | 15 | "legacy_pt_60", |
623 | 15 | "Add dissector for static payload type 60 as legacy EVRC (non-RFC3558)", |
624 | 15 | "Whether the EVRC dissector should process payload type 60 as legacy EVRC packets", |
625 | 15 | &legacy_pt_60); |
626 | 15 | } |
627 | | |
628 | | |
629 | | void |
630 | | proto_reg_handoff_evrc(void) |
631 | 15 | { |
632 | 15 | static bool evrc_prefs_initialized = false; |
633 | | |
634 | 15 | if (!evrc_prefs_initialized) |
635 | 15 | { |
636 | | /* header-full mime types */ |
637 | 15 | dissector_add_string("rtp_dyn_payload_type", "EVRC", evrc_handle); |
638 | 15 | dissector_add_string("rtp_dyn_payload_type", "EVRCB", evrcb_handle); |
639 | 15 | dissector_add_string("rtp_dyn_payload_type", "EVRCWB", evrcwb_handle); |
640 | 15 | dissector_add_string("rtp_dyn_payload_type", "EVRCNW", evrcnw_handle); |
641 | 15 | dissector_add_string("rtp_dyn_payload_type", "EVRCNW2K", evrcnw2k_handle); |
642 | | |
643 | 15 | dissector_add_for_decode_as("rtp.pt", evrc_handle); |
644 | 15 | dissector_add_for_decode_as("rtp.pt", evrcb_handle); |
645 | 15 | dissector_add_for_decode_as("rtp.pt", evrcwb_handle); |
646 | 15 | dissector_add_for_decode_as("rtp.pt", evrcnw_handle); |
647 | 15 | dissector_add_for_decode_as("rtp.pt", evrcnw2k_handle); |
648 | | /* Since the draft legacy encapsulation only appears on PT 60, not |
649 | | * adding it to decode as */ |
650 | | /* dissector_add_for_decode_as("rtp.pt", evrc_legacy_handle); */ |
651 | 15 | evrc_prefs_initialized = true; |
652 | 15 | } |
653 | 0 | else |
654 | 0 | { |
655 | 0 | dissector_delete_uint("rtp.pt", 60, evrc_legacy_handle); |
656 | 0 | } |
657 | | |
658 | 15 | if (legacy_pt_60) |
659 | 0 | { |
660 | 0 | dissector_add_uint("rtp.pt", 60, evrc_legacy_handle); |
661 | 0 | } |
662 | 15 | } |
663 | | |
664 | | /* |
665 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
666 | | * |
667 | | * Local variables: |
668 | | * c-basic-offset: 4 |
669 | | * tab-width: 8 |
670 | | * indent-tabs-mode: nil |
671 | | * End: |
672 | | * |
673 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
674 | | * :indentSize=4:tabSize=8:noTabs=true: |
675 | | */ |