summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-evrc.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-evrc.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-evrc.c')
-rw-r--r--epan/dissectors/packet-evrc.c674
1 files changed, 674 insertions, 0 deletions
diff --git a/epan/dissectors/packet-evrc.c b/epan/dissectors/packet-evrc.c
new file mode 100644
index 00000000..982d7c9f
--- /dev/null
+++ b/epan/dissectors/packet-evrc.c
@@ -0,0 +1,674 @@
+/* packet-evrc.c
+ * Routines for:
+ * EVRC EVRC-B EVRC-WB EVRC-NW EVRC-NW2K
+ * RTP payload header dissection
+ *
+ * Copyright 2008, Michael Lum <michael.lum [AT] shaw.ca>
+ * In association with Star Solutions
+ *
+ * Title 3GPP2 Other
+ *
+ * Enhanced Variable Rate Codec, Speech Service Options 3, 68, 70, 73 and 77
+ * for Wideband Spread Spectrum Digital Systems
+ * 3GPP2 C.S0014-E v1.0 TIA-127-?
+ *
+ * RFC 3558 https://tools.ietf.org/html/rfc3558
+ * RFC 4788 https://tools.ietf.org/html/rfc4788
+ * RFC 5188 https://tools.ietf.org/html/rfc5188
+ * draft-agupta-payload-rtp-evrc-nw2k-00
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/expert.h>
+
+#include <wsutil/str_util.h>
+
+/* PROTOTYPES/FORWARDS */
+
+void proto_register_evrc(void);
+void proto_reg_handoff_evrc(void);
+
+static dissector_handle_t evrc_handle;
+static dissector_handle_t evrcb_handle;
+static dissector_handle_t evrcwb_handle;
+static dissector_handle_t evrcnw_handle;
+static dissector_handle_t evrcnw2k_handle;
+static dissector_handle_t evrc_legacy_handle;
+
+static const value_string evrc_frame_type_vals[] = {
+ { 0, "Blank (0 bits)" },
+ { 1, "1/8 Rate (16 bits)" },
+ { 2, "Not valid (1/4 Rate : 40 bits)" },
+ { 3, "1/2 Rate (80 bits)" },
+ { 4, "Full Rate (171 bits; + 5 bits padding)" },
+ { 5, "Erasure (0 bits)" },
+ { 0, NULL }
+};
+
+static const value_string evrc_b_frame_type_vals[] = {
+ { 0, "Blank (0 bits)" },
+ { 1, "1/8 Rate (16 bits)" },
+ { 2, "1/4 Rate (40 bits)" },
+ { 3, "1/2 Rate (80 bits)" },
+ { 4, "Full Rate (171 bits; + 5 bits padding)" },
+ { 5, "Erasure (0 bits)" },
+ { 0, NULL }
+};
+
+static const value_string evrc_legacy_frame_type_vals[] = {
+ { 0, "Blank (0 bits)" },
+ { 1, "1/8 Rate (16 bits)" },
+ { 3, "1/2 Rate (80 bits)" },
+ { 4, "Full Rate (171 bits; + 5 bits padding)" },
+ { 14, "Erasure (0 bits)" },
+ { 0, NULL }
+};
+
+static const value_string evrc_mode_request_vals[] = {
+ { 0, "Rate Reduction 0 (Full Rate)" },
+ { 1, "Rate Reduction 1" },
+ { 2, "Rate Reduction 2" },
+ { 3, "Rate Reduction 3" },
+ { 4, "Rate Reduction 4" },
+ { 0, NULL }
+};
+
+static const value_string evrc_b_mode_request_vals[] = {
+ { 0, "Encoder Operating Point 0 (Full Rate)" },
+ { 1, "Encoder Operating Point 1" },
+ { 2, "Encoder Operating Point 2" },
+ { 3, "Encoder Operating Point 3" },
+ { 4, "Encoder Operating Point 4" },
+ { 5, "Encoder Operating Point 5" },
+ { 6, "Encoder Operating Point 6" },
+ { 7, "Encoder Operating Point 7 (1/2 rate max)" },
+ { 0, NULL }
+};
+
+static const value_string evrc_wb_mode_request_vals[] = {
+ { 0, "Encoder Operating Point 0 (Full Rate)" },
+ { 1, "Reserved" },
+ { 2, "Reserved" },
+ { 3, "Reserved" },
+ { 4, "Encoder Operating Point 4" },
+ { 5, "Reserved" },
+ { 6, "Reserved" },
+ { 7, "Encoder Operating Point 7 (1/2 rate max)" },
+ { 0, NULL }
+};
+
+static const value_string evrc_nw_mode_request_vals[] = {
+ { 0, "Encoder Operating Point 0 (EVRC-WB COP0)" },
+ { 1, "Encoder Operating Point 1 (EVRC-B COP0/EVRC-WB COP4)" },
+ { 2, "Encoder Operating Point 2 (EVRC-B COP2)" },
+ { 3, "Encoder Operating Point 3 (EVRC-B COP3)" },
+ { 4, "Encoder Operating Point 4 (EVRC-B COP4)" },
+ { 5, "Encoder Operating Point 5 (EVRC-B COP5)" },
+ { 6, "Encoder Operating Point 6 (EVRC-B COP6)" },
+ { 7, "Encoder Operating Point 7 (EVRC-B COP7/EVRC-WB COP7)" },
+ { 0, NULL }
+};
+
+static const value_string evrc_nw2k_mode_request_vals[] = {
+ { 0, "Encoder Operating Point 0 (EVRC-WB COP0)" },
+ { 1, "Encoder Operating Point 1 (EVRC-B COP0/EVRC-WB COP4)" },
+ { 2, "Encoder Operating Point 2 (EVRC-B COP2)" },
+ { 3, "Encoder Operating Point 3 (EVRC-B COP3/EVRC-NW2k)" },
+ { 4, "Encoder Operating Point 4 (EVRC-B COP4)" },
+ { 5, "Encoder Operating Point 5 (EVRC-B COP5)" },
+ { 6, "Encoder Operating Point 6 (EVRC-B COP6)" },
+ { 7, "Encoder Operating Point 7 (EVRC-B COP7/EVRC-WB COP7)" },
+ { 0, NULL }
+};
+
+static const true_false_string toc_further_entries_bit_vals = {
+ "More ToC entries follow",
+ "End of ToC entries"
+};
+
+static const true_false_string evrc_nw2k_enc_capability_bit_vals = {
+ "Mode-0 wideband encoding capable",
+ "Mode-0 wideband encoding incapable (i.e. narrowband encoding only)"
+};
+
+typedef enum
+{
+ EVRC_VARIANT_EVRC,
+ EVRC_VARIANT_EVRC_B,
+ EVRC_VARIANT_EVRC_WB,
+ EVRC_VARIANT_EVRC_NW,
+ EVRC_VARIANT_EVRC_NW2k,
+ EVRC_VARIANT_EVRC_LEGACY
+}
+evrc_variant_t;
+
+
+/* Initialize the protocol and registered fields */
+static int proto_evrc = -1;
+static int proto_evrcb = -1;
+static int proto_evrcwb = -1;
+static int proto_evrcnw = -1;
+static int proto_evrcnw2k = -1;
+static int proto_evrc_legacy = -1;
+
+static int hf_evrc_reserved = -1;
+static int hf_evrc_reserved_2k = -1;
+static int hf_evrc_enc_capability_2k = -1;
+static int hf_evrc_interleave_length = -1;
+static int hf_evrc_interleave_index = -1;
+static int hf_evrc_mode_request = -1;
+static int hf_evrc_b_mode_request = -1;
+static int hf_evrc_wb_mode_request = -1;
+static int hf_evrc_nw_mode_request = -1;
+static int hf_evrc_nw2k_mode_request = -1;
+static int hf_evrc_frame_count = -1;
+static int hf_evrc_toc_frame_type_high = -1;
+static int hf_evrc_toc_frame_type_low = -1;
+static int hf_evrc_b_toc_frame_type_high = -1;
+static int hf_evrc_b_toc_frame_type_low = -1;
+static int hf_evrc_padding = -1;
+static int hf_evrc_speech_data = -1;
+static int hf_evrc_legacy_toc_fe_ind = -1;
+static int hf_evrc_legacy_toc_reduc_rate = -1;
+static int hf_evrc_legacy_toc_frame_type = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_evrc = -1;
+static gint ett_toc = -1;
+
+static expert_field ei_evrc_unknown_variant = EI_INIT;
+
+/*
+ * Variables to allow for proper deletion of dissector registration when
+ * the user changes values
+ */
+static gboolean legacy_pt_60 = FALSE;
+
+
+static guint8
+evrc_frame_type_to_octs(guint8 frame_type)
+{
+ switch (frame_type)
+ {
+ default:
+ break;
+
+ case 1: /* 1/8 rate */
+ return(2);
+
+ case 2: /* 1/4 rate */
+ return(5);
+
+ case 3: /* 1/2 rate */
+ return(10);
+
+ case 4: /* full rate */
+ return(22);
+ }
+
+ return(0);
+}
+
+/* GENERIC EVRC DISSECTOR FUNCTIONS */
+
+static void
+dissect_evrc_aux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, evrc_variant_t evrc_variant)
+{
+ guint8 oct;
+ guint8 frame_count;
+ guint8 i;
+ guint32 offset, saved_offset;
+ gboolean further_entries;
+ guint32 len;
+ proto_item *item = NULL;
+ proto_tree *evrc_tree = NULL;
+ proto_tree *toc_tree = NULL;
+ int hf_mode_request;
+ int hf_toc_frame_type_high;
+ int hf_toc_frame_type_low;
+
+ /*
+ * assumed max number of speech frames based on
+ * frame count being 5 bits + 1
+ */
+ guint8 speech_data_len[0x20];
+
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "EVRC");
+
+ if (!tree) return;
+
+ offset = 0;
+ memset(speech_data_len, 0, sizeof(speech_data_len));
+
+ len = tvb_reported_length(tvb);
+
+ item = proto_tree_add_item(tree, proto_evrc, tvb, 0, len, ENC_NA);
+
+ evrc_tree = proto_item_add_subtree(item, ett_evrc);
+
+ if (evrc_variant == EVRC_VARIANT_EVRC_LEGACY)
+ {
+ /* legacy 'payload type 60' draft-ietf-avt-evrc-07.txt header format */
+
+ proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(evrc_tree, hf_evrc_interleave_length, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(evrc_tree, hf_evrc_interleave_index, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ offset++;
+
+ frame_count = 0;
+ further_entries = TRUE;
+ while (further_entries && (frame_count < sizeof(speech_data_len)) &&
+ ((len - offset) > 0))
+ {
+ toc_tree =
+ proto_tree_add_subtree_format(evrc_tree, tvb, offset, 1, ett_toc, NULL, "ToC [%u]", frame_count+1);
+
+ proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_fe_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_reduc_rate, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_frame_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ oct = tvb_get_guint8(tvb, offset);
+ further_entries = (oct & 0x80) ? TRUE : FALSE;
+
+ speech_data_len[frame_count] = evrc_frame_type_to_octs((guint8)(oct & 0x7f));
+
+ frame_count++;
+ offset++;
+ }
+ }
+ else
+ {
+ /* RFC 3558 header format */
+
+ switch (evrc_variant)
+ {
+ default:
+ proto_tree_add_expert(evrc_tree, pinfo, &ei_evrc_unknown_variant, tvb, offset, len);
+ return;
+
+ case EVRC_VARIANT_EVRC:
+ hf_mode_request = hf_evrc_mode_request;
+ hf_toc_frame_type_high = hf_evrc_toc_frame_type_high;
+ hf_toc_frame_type_low = hf_evrc_toc_frame_type_low;
+
+ proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+
+ case EVRC_VARIANT_EVRC_B:
+ hf_mode_request = hf_evrc_b_mode_request;
+ hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high;
+ hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low;
+
+ proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+
+ case EVRC_VARIANT_EVRC_WB:
+ hf_mode_request = hf_evrc_wb_mode_request;
+ hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high;
+ hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low;
+
+ proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+
+ case EVRC_VARIANT_EVRC_NW:
+ hf_mode_request = hf_evrc_nw_mode_request;
+ hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high;
+ hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low;
+
+ proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+
+ case EVRC_VARIANT_EVRC_NW2k:
+ hf_mode_request = hf_evrc_nw2k_mode_request;
+ hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high;
+ hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low;
+
+ proto_tree_add_item(evrc_tree, hf_evrc_reserved_2k, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(evrc_tree, hf_evrc_enc_capability_2k, tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+ }
+
+ proto_tree_add_item(evrc_tree, hf_evrc_interleave_length, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(evrc_tree, hf_evrc_interleave_index, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ offset++;
+
+ proto_tree_add_item(evrc_tree, hf_mode_request, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(evrc_tree, hf_evrc_frame_count, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ /*
+ * number of frames in PACKET is frame_count + 1
+ */
+ frame_count = (tvb_get_guint8(tvb, offset) & 0x1f) + 1;
+
+ offset++;
+ saved_offset = offset;
+
+ toc_tree =
+ proto_tree_add_subtree_format(evrc_tree, tvb, offset, -1, ett_toc, &item, "ToC - %u frame%s",
+ frame_count, plurality(frame_count, "", "s"));
+
+ i = 0;
+ while ((i < frame_count) &&
+ ((len - offset) > 0))
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_item(toc_tree, hf_toc_frame_type_high, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ speech_data_len[i] = evrc_frame_type_to_octs((guint8)((oct & 0xf0) >> 4));
+
+ i++;
+
+ if (i < frame_count)
+ {
+ /* even number of frames */
+ proto_tree_add_item(toc_tree, hf_toc_frame_type_low, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ speech_data_len[i] = evrc_frame_type_to_octs((guint8)(oct & 0x0f));
+
+ i++;
+ }
+
+ offset++;
+ }
+
+ if (frame_count & 0x01)
+ {
+ /* odd number of frames */
+ proto_tree_add_item(toc_tree, hf_evrc_padding, tvb, offset-1, 1, ENC_BIG_ENDIAN);
+ }
+
+ proto_item_set_len(item, offset - saved_offset);
+ }
+
+ i = 0;
+ while ((i < frame_count) &&
+ ((len - offset) >= speech_data_len[i]))
+ {
+ proto_tree_add_bytes_format(evrc_tree, hf_evrc_speech_data, tvb, offset, speech_data_len[i], NULL, "Speech Data [%u]", i+1);
+
+ offset += speech_data_len[i];
+ i++;
+ }
+}
+
+static int
+dissect_evrc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_evrcb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_B);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_evrcwb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_WB);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_evrcnw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_NW);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_evrcnw2k(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_NW2k);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_evrc_legacy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_evrc_aux(tvb, pinfo, tree, EVRC_VARIANT_EVRC_LEGACY);
+ return tvb_captured_length(tvb);
+}
+
+
+/* Register the protocol with Wireshark */
+void
+proto_register_evrc(void)
+{
+ module_t *evrc_module;
+
+ /* Setup list of header fields */
+
+ static hf_register_info hf[] =
+ {
+ { &hf_evrc_reserved,
+ { "Reserved", "evrc.reserved",
+ FT_UINT8, BASE_HEX, NULL, 0xc0,
+ "Reserved bits", HFILL }
+ },
+ { &hf_evrc_reserved_2k,
+ { "Reserved", "evrc.reserved",
+ FT_UINT8, BASE_HEX, NULL, 0x80,
+ "Reserved bits", HFILL }
+ },
+ { &hf_evrc_enc_capability_2k,
+ { "Encoding Capability", "evrc.enc_capability",
+ FT_BOOLEAN, 8, TFS(&evrc_nw2k_enc_capability_bit_vals), 0x40,
+ "Encoding Capability Identification", HFILL }
+ },
+ { &hf_evrc_interleave_length,
+ { "Interleave Length", "evrc.interleave_len",
+ FT_UINT8, BASE_DEC, NULL, 0x38,
+ "Interleave length bits", HFILL }
+ },
+ { &hf_evrc_interleave_index,
+ { "Interleave Index", "evrc.interleave_idx",
+ FT_UINT8, BASE_DEC, NULL, 0x07,
+ "Interleave index bits", HFILL }
+ },
+ { &hf_evrc_mode_request,
+ { "Mode Request", "evrc.mode_request",
+ FT_UINT8, BASE_DEC, VALS(evrc_mode_request_vals), 0xe0,
+ "Mode Request bits", HFILL }
+ },
+ { &hf_evrc_b_mode_request,
+ { "Mode Request", "evrc.b.mode_request",
+ FT_UINT8, BASE_DEC, VALS(evrc_b_mode_request_vals), 0xe0,
+ "Mode Request bits", HFILL }
+ },
+ { &hf_evrc_wb_mode_request,
+ { "Mode Request", "evrc.wb.mode_request",
+ FT_UINT8, BASE_DEC, VALS(evrc_wb_mode_request_vals), 0xe0,
+ "Mode Request bits", HFILL }
+ },
+ { &hf_evrc_nw_mode_request,
+ { "Mode Request", "evrc.nw.mode_request",
+ FT_UINT8, BASE_DEC, VALS(evrc_nw_mode_request_vals), 0xe0,
+ "Mode Request bits", HFILL }
+ },
+ { &hf_evrc_nw2k_mode_request,
+ { "Mode Request", "evrc.nw2k.mode_request",
+ FT_UINT8, BASE_DEC, VALS(evrc_nw2k_mode_request_vals), 0xe0,
+ "Mode Request bits", HFILL }
+ },
+ { &hf_evrc_frame_count,
+ { "Frame Count (0 means 1 frame)", "evrc.frame_count",
+ FT_UINT8, BASE_DEC, NULL, 0x1f,
+ "Frame Count bits, a value of 0 means 1 frame", HFILL }
+ },
+ { &hf_evrc_toc_frame_type_high,
+ { "ToC Frame Type", "evrc.toc.frame_type_hi",
+ FT_UINT8, BASE_DEC, VALS(evrc_frame_type_vals), 0xf0,
+ "ToC Frame Type bits", HFILL }
+ },
+ { &hf_evrc_toc_frame_type_low,
+ { "ToC Frame Type", "evrc.toc.frame_type_lo",
+ FT_UINT8, BASE_DEC, VALS(evrc_frame_type_vals), 0x0f,
+ "ToC Frame Type bits", HFILL }
+ },
+ { &hf_evrc_b_toc_frame_type_high,
+ { "ToC Frame Type", "evrc.b.toc.frame_type_hi",
+ FT_UINT8, BASE_DEC, VALS(evrc_b_frame_type_vals), 0xf0,
+ "ToC Frame Type bits", HFILL }
+ },
+ { &hf_evrc_b_toc_frame_type_low,
+ { "ToC Frame Type", "evrc.b.toc.frame_type_lo",
+ FT_UINT8, BASE_DEC, VALS(evrc_b_frame_type_vals), 0x0f,
+ "ToC Frame Type bits", HFILL }
+ },
+ { &hf_evrc_padding,
+ { "Padding", "evrc.padding",
+ FT_UINT8, BASE_DEC, NULL, 0x0f,
+ "Padding bits", HFILL }
+ },
+ { &hf_evrc_speech_data,
+ { "Speech data", "evrc.speech_data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_evrc_legacy_toc_fe_ind,
+ { "ToC Further Entries Indicator", "evrc.legacy.toc.further_entries_ind",
+ FT_BOOLEAN, 8, TFS(&toc_further_entries_bit_vals), 0x80,
+ "ToC Further Entries Indicator bit", HFILL }
+ },
+ { &hf_evrc_legacy_toc_reduc_rate,
+ { "ToC Reduced Rate", "evrc.legacy.toc.reduced_rate",
+ FT_UINT8, BASE_DEC, NULL, 0x40,
+ "ToC Reduced Rate bits", HFILL }
+ },
+ { &hf_evrc_legacy_toc_frame_type,
+ { "ToC Frame Type", "evrc.legacy.toc.frame_type",
+ FT_UINT8, BASE_DEC, VALS(evrc_legacy_frame_type_vals), 0x3f,
+ "ToC Frame Type bits", HFILL }
+ }
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_evrc_unknown_variant,
+ { "evrc.unknown_variant", PI_UNDECODED, PI_WARN,
+ "Variant Unknown/Unsupported - dissector bug/later version spec (report to wireshark.org)",
+ EXPFILL }
+ }
+ };
+
+ expert_module_t *expert_evrc;
+
+ /* Setup protocol subtree array */
+
+ static gint *ett[] =
+ {
+ &ett_evrc,
+ &ett_toc
+ };
+
+ /* Register the protocol name and description */
+
+ proto_evrc =
+ proto_register_protocol("Enhanced Variable Rate Codec", "EVRC", "evrc");
+
+ proto_evrcb =
+ proto_register_protocol_in_name_only("Enhanced Variable Rate Codec B",
+ "EVRC-B", "evrcb", proto_evrc, FT_PROTOCOL);
+ proto_evrcwb =
+ proto_register_protocol_in_name_only("Enhanced Variable Rate Codec - Wideband",
+ "EVRC-WB", "evrcwb", proto_evrc, FT_PROTOCOL);
+ proto_evrcnw =
+ proto_register_protocol_in_name_only("Enhanced Variable Rate Codec - Narrowband-Wideband",
+ "EVRC-NW", "evrcnw", proto_evrc, FT_PROTOCOL);
+ proto_evrcnw2k =
+ proto_register_protocol_in_name_only("Enhanced Variable Rate Codec - Narrowband-Wideband plus 2kpbs",
+ "EVRC-NW2K", "evrcnw2k", proto_evrc, FT_PROTOCOL);
+ proto_evrc_legacy =
+ proto_register_protocol_in_name_only("Enhanced Variable Rate Codec (Legacy Encapsulation)",
+ "EVRC (Legacy)", "evrc_legacy", proto_evrc, FT_PROTOCOL);
+ proto_register_field_array(proto_evrc, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ evrc_handle = register_dissector("evrc", dissect_evrc, proto_evrc);
+ evrcb_handle = register_dissector("evrcb", dissect_evrcb, proto_evrcb);
+ evrcwb_handle = register_dissector("evrcwb", dissect_evrcwb, proto_evrcwb);
+ evrcnw_handle = register_dissector("evrcnw", dissect_evrcnw, proto_evrcnw);
+ evrcnw2k_handle = register_dissector("evrcnw2k", dissect_evrcnw2k, proto_evrcnw2k);
+ evrc_legacy_handle = register_dissector("evrc_legacy", dissect_evrc_legacy, proto_evrc_legacy);
+
+ expert_evrc =
+ expert_register_protocol(proto_evrc);
+ expert_register_field_array(expert_evrc, ei, array_length(ei));
+
+ /*
+ * setup for preferences
+ */
+ evrc_module = prefs_register_protocol(proto_evrc, proto_reg_handoff_evrc);
+
+ prefs_register_bool_preference(evrc_module,
+ "legacy_pt_60",
+ "Add dissector for static payload type 60 as legacy EVRC (non-RFC3558)",
+ "Whether the EVRC dissector should process payload type 60 as legacy EVRC packets",
+ &legacy_pt_60);
+}
+
+
+void
+proto_reg_handoff_evrc(void)
+{
+ static gboolean evrc_prefs_initialized = FALSE;
+
+ if (!evrc_prefs_initialized)
+ {
+ /* header-full mime types */
+ dissector_add_string("rtp_dyn_payload_type", "EVRC", evrc_handle);
+ dissector_add_string("rtp_dyn_payload_type", "EVRCB", evrcb_handle);
+ dissector_add_string("rtp_dyn_payload_type", "EVRCWB", evrcwb_handle);
+ dissector_add_string("rtp_dyn_payload_type", "EVRCNW", evrcnw_handle);
+ dissector_add_string("rtp_dyn_payload_type", "EVRCNW2K", evrcnw2k_handle);
+
+ dissector_add_for_decode_as("rtp.pt", evrc_handle);
+ dissector_add_for_decode_as("rtp.pt", evrcb_handle);
+ dissector_add_for_decode_as("rtp.pt", evrcwb_handle);
+ dissector_add_for_decode_as("rtp.pt", evrcnw_handle);
+ dissector_add_for_decode_as("rtp.pt", evrcnw2k_handle);
+ /* Since the draft legacy encapsulation only appears on PT 60, not
+ * adding it to decode as */
+ /* dissector_add_for_decode_as("rtp.pt", evrc_legacy_handle); */
+ evrc_prefs_initialized = TRUE;
+ }
+ else
+ {
+ dissector_delete_uint("rtp.pt", 60, evrc_legacy_handle);
+ }
+
+ if (legacy_pt_60)
+ {
+ dissector_add_uint("rtp.pt", 60, evrc_legacy_handle);
+ }
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */