/* packet-osmux.c * Routines for packet dissection of OSmux voice/signalling multiplex protocol * * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include void proto_register_osmux(void); void proto_reg_handoff_osmux(void); /* * FIXME: Link to OSmux docs here */ static const value_string osmux_ft_vals[] = { {0x00, "Signalling"}, {0x01, "AMR"}, {0x02, "Dummy"}, {0, NULL} }; struct osmux_hdr { int ft; int ctr; int amr_f; int amr_q; int seq; int circuit_id; int amr_cmr; int amr_ft; }; /* Initialize the protocol and registered fields */ static dissector_handle_t osmux_handle; static int proto_osmux = -1; static int osmux_tap = -1; static int hf_osmux_ft_ctr = -1; static int hf_osmux_ft = -1; static int hf_osmux_ctr = -1; static int hf_osmux_amr_f = -1; static int hf_osmux_amr_q = -1; static int hf_osmux_seq = -1; static int hf_osmux_circuit_id = -1; static int hf_osmux_amr_ft_cmr = -1; static int hf_osmux_amr_ft = -1; static int hf_osmux_amr_cmr = -1; /* Initialize the subtree pointers */ static gint ett_osmux = -1; static gint ett_osmux_ft_ctr = -1; static gint ett_osmux_amr_ft_cmr = -1; enum { SUB_RSL, SUB_AMR, SUB_DUMMY, SUB_MAX }; /* Code to actually dissect the packets */ static gint dissect_osmux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { int offset = 0; struct osmux_hdr *osmuxh; proto_item *ti; proto_tree *osmux_tree = NULL; guint8 ft_ctr, amr_ft_cmr; col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSmux"); col_clear(pinfo->cinfo, COL_INFO); osmuxh = wmem_new0(wmem_packet_scope(), struct osmux_hdr); ft_ctr = tvb_get_guint8(tvb, offset); osmuxh->ft = ft_ctr >> 5; osmuxh->ctr = (ft_ctr >> 2) & 0x7; osmuxh->amr_q = !!(ft_ctr & 0x02); osmuxh->amr_f = !!(ft_ctr & 0x01); osmuxh->seq = tvb_get_guint8(tvb, offset+1); osmuxh->circuit_id = tvb_get_guint8(tvb, offset+2); amr_ft_cmr = tvb_get_guint8(tvb, offset+3); osmuxh->amr_ft = (amr_ft_cmr & 0xf0) >> 4; osmuxh->amr_cmr = amr_ft_cmr & 0x0f; col_append_fstr(pinfo->cinfo, COL_INFO, "OSMux "); ti = proto_tree_add_protocol_format(tree, proto_osmux, tvb, offset, -1, "OSmux type %s frame", val_to_str(osmuxh->ft, osmux_ft_vals, "unknown 0x%02x")); osmux_tree = proto_item_add_subtree(ti, ett_osmux); /* Two-byte dummy packets for firewalls */ if (ft_ctr == 0x23 && tvb_reported_length(tvb) == 2) { col_append_fstr(pinfo->cinfo, COL_INFO, "Dummy frame"); proto_tree_add_item(osmux_tree, hf_osmux_circuit_id, tvb, offset+1, 1, ENC_BIG_ENDIAN); return 2; } col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(osmuxh->ft, osmux_ft_vals, "unknown 0x%02x")); { static const gint *ft_ctr_fields[] = { &hf_osmux_ft, &hf_osmux_ctr, &hf_osmux_amr_f, &hf_osmux_amr_q, NULL }; proto_tree_add_bitmask(osmux_tree, tvb, offset, hf_osmux_ft_ctr, ett_osmux_ft_ctr, ft_ctr_fields, ENC_BIG_ENDIAN); offset++; } proto_tree_add_item(osmux_tree, hf_osmux_seq, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(osmux_tree, hf_osmux_circuit_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; { static const gint *amr_ft_cmr_fields[] = { &hf_osmux_amr_ft, &hf_osmux_amr_cmr, NULL }; proto_tree_add_bitmask(osmux_tree, tvb, offset, hf_osmux_amr_ft_cmr, ett_osmux_amr_ft_cmr, amr_ft_cmr_fields, ENC_BIG_ENDIAN); offset++; } tap_queue_packet(osmux_tap, pinfo, osmuxh); return offset; } void proto_register_osmux(void) { static hf_register_info hf[] = { {&hf_osmux_ft_ctr, {"FTCTRByte", "osmux.ft_ctr", FT_UINT8, BASE_DEC, NULL, 0x00, "Byte with Fieldtype, Counter", HFILL} }, {&hf_osmux_ft, {"FieldType", "osmux.ft", FT_UINT8, BASE_DEC, VALS(osmux_ft_vals), 0xe0, "Type of data in packet", HFILL} }, {&hf_osmux_ctr, {"CTR", "osmux.ctr", FT_UINT8, BASE_HEX, NULL, 0x1c, "Number of AMR packets inside", HFILL} }, {&hf_osmux_amr_q, {"AMR f", "osmux.amr_f", FT_UINT8, BASE_HEX, NULL, 0x02, "AMR f parameter", HFILL} }, {&hf_osmux_amr_f, {"AMR q", "osmux.amr_q", FT_UINT8, BASE_HEX, NULL, 0x01, "AMR q parameter", HFILL} }, {&hf_osmux_seq, {"Seq", "osmux.seq", FT_UINT8, BASE_HEX, NULL, 0x0, "Sequence number", HFILL} }, {&hf_osmux_circuit_id, {"Circuit ID", "osmux.circuit_id", FT_UINT8, BASE_HEX, NULL, 0x0, "Circuit ID", HFILL} }, {&hf_osmux_amr_ft_cmr, {"FourthByte", "osmux.amr_ft_cmr", FT_UINT8, BASE_DEC, NULL, 0x00, "Byte with AMR params ft and cmr", HFILL} }, {&hf_osmux_amr_ft, {"AMR ft", "osmux.amr_ft", FT_UINT8, BASE_HEX, NULL, 0xf0, "AMR parameter ft", HFILL} }, {&hf_osmux_amr_cmr, {"AMR cmr", "osmux.amr_cmr", FT_UINT8, BASE_HEX, NULL, 0x0f, "AMR parameter cmr", HFILL} }, }; static gint *ett[] = { &ett_osmux, &ett_osmux_ft_ctr, &ett_osmux_amr_ft_cmr, }; proto_osmux = proto_register_protocol("GSM multiplexing for AMR", "GSM OSmux", "osmux"); proto_register_field_array(proto_osmux, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } void proto_reg_handoff_osmux(void) { static gboolean osmux_initialized = FALSE; if (!osmux_initialized) { osmux_handle = create_dissector_handle(dissect_osmux, proto_osmux); dissector_add_uint("udp.port", 1984, osmux_handle); osmux_initialized = TRUE; } osmux_tap = register_tap("osmux"); } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 8 * tab-width: 8 * indent-tabs-mode: t * End: * * vi: set shiftwidth=8 tabstop=8 noexpandtab: * :indentSize=8:tabSize=8:noTabs=false: */