/* packet-dect_aastra.c * * Dissector for the proprietary protocol of the internal ethernet link * between DECT burst processor and ARM processor in Aastra/Mitel DECT * base stations. * * Copyright 2018 by Harald Welte * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include static int proto_dect_aastra = -1; static gint hf_aamide_len = -1; static gint hf_xdlc_prim_type = -1; static gint hf_xdlc_mcei = -1; static gint hf_xdlc_info_string = -1; static gint hf_xdlc_pmid = -1; static gint hf_xdlc_subfield = -1; static gint ett_aamide = -1; static dissector_handle_t data_handle; static dissector_handle_t dlc_handle; #define AAMIDE_ETH_T_XDLC 0xA000 #define AAMIDE_ETH_T_DOWNLOAD 0xA002 #define AAMIDE_ETH_T_VIDEO 0xA003 #define AAMIDE_ETH_T_AUDIOLOG 0xA004 enum aamide_prim_type { AAMIDE_P_MAC_CON_IND = 0x01, AAMIDE_P_MAC_DIS_REQ = 0x02, AAMIDE_P_MAC_DIS_IND = 0x03, AAMIDE_P_LC_DATA_REQ = 0x05, AAMIDE_P_LC_DATA_IND = 0x06, AAMIDE_P_LC_DTR_IND = 0x07, AAMIDE_P_MAC_PAGE_REQ = 0x08, AAMIDE_P_MAC_ENC_KEY_REQ = 0x09, AAMIDE_P_MAC_ENC_EKS_IND = 0x0a, AAMIDE_P_HO_IN_PROGRESS_IND = 0x0b, AAMIDE_P_HO_IN_PROGRESS_RES = 0x0c, AAMIDE_P_HO_FAILED_IND = 0x0d, AAMIDE_P_HO_FAILED_REQ = 0x0e, AAMIDE_P_DLC_RFP_ERROR_IND = 0x14, AAMIDE_P_MAC_CON_EXT_IND = 0x15, AAMIDE_P_HO_IN_PROGRESS_EXT_IND = 0x16, AAMIDE_P_MAC_MOD_REQ = 0x17, AAMIDE_P_MAC_MOD_CNF = 0x18, AAMIDE_P_MAC_MOD_IND = 0x19, AAMIDE_P_MAC_MOD_REJ = 0x1a, AAMIDE_P_MAC_RECORD_AUDIO = 0x1b, AAMIDE_P_MAC_INFO_IND = 0x1c, AAMIDE_P_MAC_GET_DEF_CKEY_IND = 0x1d, AAMIDE_P_MAC_GET_DEF_CKEY_RES = 0x1e, AAMIDE_P_MAC_CLEAR_DEF_CKEY_REQ = 0x1f, AAMIDE_P_MAC_GET_CURR_CKEY_ID_REQ = 0x20, AAMIDE_P_MAC_GET_CURR_CKEY_ID_CNF = 0x21, }; static const value_string xdlc_prim_names[] = { { AAMIDE_P_MAC_CON_IND, "MAC_CON_IND" }, { AAMIDE_P_MAC_DIS_REQ, "MAC_DIS_REQ" }, { AAMIDE_P_MAC_DIS_IND, "MAC_DIS_IND" }, { AAMIDE_P_LC_DATA_REQ, "LC_DATA_REQ" }, { AAMIDE_P_LC_DATA_IND, "LC_DATA_IND" }, { AAMIDE_P_LC_DTR_IND, "LC_DTR_IND" }, { AAMIDE_P_MAC_PAGE_REQ, "MAC_PAGE_REQ" }, { AAMIDE_P_MAC_ENC_KEY_REQ, "MAC_ENC_KEY_REQ" }, { AAMIDE_P_MAC_ENC_EKS_IND, "MAC_ENC_EKS_IND" }, { AAMIDE_P_HO_IN_PROGRESS_IND, "HO_IN_PROGRRESS_IND" }, { AAMIDE_P_HO_IN_PROGRESS_RES, "HO_IN_PROGRERSS_RES" }, { AAMIDE_P_HO_FAILED_IND, "HO_FAILED_IND" }, { AAMIDE_P_HO_FAILED_REQ, "HO_FAILED_REQ" }, { AAMIDE_P_DLC_RFP_ERROR_IND, "RFP_ERROR_IND" }, { AAMIDE_P_MAC_CON_EXT_IND, "MAC_CON_EXT_IND" }, { AAMIDE_P_HO_IN_PROGRESS_EXT_IND, "HO_IN_PROGRESS_EXT_IND" }, { AAMIDE_P_MAC_MOD_REQ, "MAC_MOD_REQ" }, { AAMIDE_P_MAC_MOD_CNF, "MAC_MOD_CNF" }, { AAMIDE_P_MAC_MOD_IND, "MAC_MOD_IND" }, { AAMIDE_P_MAC_MOD_REQ, "MAC_MOD_REQ" }, { AAMIDE_P_MAC_RECORD_AUDIO, "MAC_RECORD_AUDIO" }, { AAMIDE_P_MAC_INFO_IND, "MAC_INFO_IND" }, { AAMIDE_P_MAC_GET_DEF_CKEY_IND, "MAC_GET_DEF_CKEY_IND" }, { AAMIDE_P_MAC_GET_DEF_CKEY_RES, "MAC_GET_DEF_CKEY_RES" }, { AAMIDE_P_MAC_CLEAR_DEF_CKEY_REQ, "MAC_CLEAR_DEF_CKEY_REQ" }, { AAMIDE_P_MAC_GET_CURR_CKEY_ID_REQ, "MAC_GET_CURR_CKEY_ID_REQ"}, { AAMIDE_P_MAC_GET_CURR_CKEY_ID_CNF, "MAC_GET_CURR_CKEY_ID_CNF" }, { 0, NULL } }; static const value_string xdlc_subfield_names[] = { { 0x00, "B0" }, { 0x10, "B1" }, { 0, NULL } }; static int dissect_aamide_xdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { guint16 aamide_len, payload_len; guint8 prim_type, mcei; int offset = 0; tvbuff_t *payload_tvb = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "AA-XDLC"); col_clear(pinfo->cinfo, COL_INFO); aamide_len = tvb_get_guint16(tvb, offset, 2); proto_tree_add_item(tree, hf_aamide_len, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (aamide_len < 3) return tvb_captured_length(tvb); prim_type = tvb_get_guint8(tvb, offset+3); proto_tree_add_item(tree, hf_xdlc_prim_type, tvb, offset+3, 1, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(prim_type, xdlc_prim_names, "Unknown 0x%02x")); switch (prim_type) { case AAMIDE_P_MAC_PAGE_REQ: payload_len = tvb_get_guint8(tvb, offset+4); payload_tvb = tvb_new_subset_length(tvb, offset+5, payload_len); break; case AAMIDE_P_MAC_CON_IND: mcei = tvb_get_guint8(tvb, offset+4); col_append_fstr(pinfo->cinfo, COL_INFO, "MCEI=%02x ", mcei); proto_tree_add_item(tree, hf_xdlc_mcei, tvb, offset+4, 1, ENC_NA); proto_tree_add_item(tree, hf_xdlc_pmid, tvb, offset+6, 2, ENC_BIG_ENDIAN); break; case AAMIDE_P_MAC_INFO_IND: mcei = tvb_get_guint8(tvb, offset+4); col_append_fstr(pinfo->cinfo, COL_INFO, "MCEI=%02x ", mcei); proto_tree_add_item(tree, hf_xdlc_mcei, tvb, offset+4, 1, ENC_NA); /* from offset 9 onwards, there's a null-terminated string */ proto_tree_add_item(tree, hf_xdlc_info_string, tvb, offset+9, tvb_captured_length_remaining(tvb, offset+9), ENC_ASCII|ENC_NA); break; case AAMIDE_P_MAC_DIS_REQ: case AAMIDE_P_MAC_DIS_IND: mcei = tvb_get_guint8(tvb, offset+4); col_append_fstr(pinfo->cinfo, COL_INFO, "MCEI=%02x ", mcei); proto_tree_add_item(tree, hf_xdlc_mcei, tvb, offset+4, 1, ENC_NA); break; case AAMIDE_P_LC_DTR_IND: mcei = tvb_get_guint8(tvb, offset+4); col_append_fstr(pinfo->cinfo, COL_INFO, "MCEI=%02x ", mcei); proto_tree_add_item(tree, hf_xdlc_mcei, tvb, offset+4, 1, ENC_NA); proto_tree_add_item(tree, hf_xdlc_subfield, tvb, offset+5, 1, ENC_NA); break; case AAMIDE_P_LC_DATA_REQ: case AAMIDE_P_LC_DATA_IND: mcei = tvb_get_guint8(tvb, offset+4); col_append_fstr(pinfo->cinfo, COL_INFO, "MCEI=%02x ", mcei); proto_tree_add_item(tree, hf_xdlc_mcei, tvb, offset+4, 1, ENC_NA); proto_tree_add_item(tree, hf_xdlc_subfield, tvb, offset+5, 1, ENC_NA); payload_len = tvb_get_guint8(tvb, offset+6); payload_len = tvb_get_guint8(tvb, offset+6); payload_tvb = tvb_new_subset_length(tvb, offset+7, payload_len); if (payload_tvb) call_dissector(dlc_handle, payload_tvb, pinfo, tree); payload_tvb = NULL; break; default: break; } if (payload_tvb) call_dissector(data_handle, payload_tvb, pinfo, tree); return tvb_captured_length(tvb); } void proto_register_dect_aastra(void) { static hf_register_info hf[] = { { &hf_aamide_len, { "Length", "aamide.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_xdlc_prim_type, { "Primitive Type", "aamide.prim", FT_UINT8, BASE_HEX, VALS(xdlc_prim_names), 0x0, NULL, HFILL } }, { &hf_xdlc_mcei, { "MCEI", "aamide.mcei", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_xdlc_info_string, { "MAC Info String", "aamide.mac_info_str", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_xdlc_pmid, { "PMID", "aamide.pmid", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_xdlc_subfield, { "Subfield", "aamide.subfield", FT_UINT8, BASE_HEX, VALS(xdlc_subfield_names), 0, NULL, HFILL } }, }; static gint *ett[] = { &ett_aamide, }; /* Register protocol */ proto_dect_aastra = proto_register_protocol("Aastra/Mitel DECT-over-Etehernet XDLC", "DECToE-XDLC", "aamide"); proto_register_subtree_array(ett, array_length(ett)); proto_register_field_array(proto_dect_aastra, hf, array_length(hf)); } void proto_reg_handoff_dect_aastra(void) { dissector_handle_t xdlc_handle = create_dissector_handle(dissect_aamide_xdlc, proto_dect_aastra); dissector_add_uint("ethertype", AAMIDE_ETH_T_XDLC, xdlc_handle); data_handle = find_dissector("data"); dlc_handle = find_dissector("dect_dlc"); } /* * 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: */