/* packet-aastra-aasp.c * Routines for AASP (Aastra Signalling Protocol) packet dissection. * Copyright 2011, Marek Tews * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ /* * AASP over SIP * Content-Type: message/x-aasp-signalling */ #include "config.h" #include /* commands id */ #define BEGIN_BLOCK_DATA 0x80 #define WINDOW 0x81 #define TITLE 0x83 #define ROW 0x84 #define MENU_ITEM 0x85 #define CONTEXT_INFO 0x86 #define BUTTON_PRESSED 0x87 #define COLUMN 0x88 #define SET_TEXT 0x89 #define DATE_TIME_INFO 0xA4 #define INCOMING_CALLER 0xA5 #define DO_COMMAND 0xA9 #define PUSH_BTN_C 0xC8 #define PUSH_BTN_TASK 0xC9 #define PUSH_BTN_PLUS 0xCA #define PUSH_BTN_MINUS 0xCB #define PUSH_BTN_MIC 0xCC #define PUSH_BTN_SPK 0xCD #define PUSH_BTN_TBOOK 0xCE #define PUSH_BTN_DBL_ARROW 0xCF #define PUSH_BTN_ON_HOOK 0xD0 #define PUSH_BTN_OFF_HOOK 0xD1 #define PUSH_BTN_UP 0xD2 #define PUSH_BTN_DOWN 0xD3 #define PUSH_BTN_LEFT 0xD4 #define PUSH_BTN_RIGHT 0xD5 #define END_BLOCK_DATA 0xFE /* Forward declarations */ void proto_register_aasp(void); void proto_reg_handoff_aasp(void); /* Initialize the protocol and registered fields */ static gint proto_aasp = -1; static gint hf_a_data = -1; static gint hf_a_cmd = -1; static gint hf_a_id = -1; static gint hf_a_length = -1; static gint hf_a_text = -1; static gint hf_a_line = -1; static gint hf_a_cdpn = -1; static gint hf_a_button_id = -1; static gint hf_a_attr = -1; static gint hf_a_item = -1; static gint hf_a_hour = -1; static gint hf_a_minute = -1; static gint hf_a_day = -1; static gint hf_a_month = -1; static gint hf_a_weekofyear = -1; static gint hf_a_weekday = -1; static gint hf_a_month_name = -1; static gint hf_a_weekofyear_prefix = -1; /* Initialize the subtree pointers */ static gint ett_aasp = -1; static gint ett_a_cmd = -1; static gint ett_a_item = -1; /* Preferences */ /** * Commands */ static const value_string szCmdID[] = { { BEGIN_BLOCK_DATA, "Begin Block Data" }, { WINDOW, "Window" }, { TITLE, "Title" }, { ROW, "Row" }, { MENU_ITEM, "Menu Item" }, { CONTEXT_INFO, "Context Info" }, { BUTTON_PRESSED, "Button Pressed" }, { COLUMN, "Column" }, { SET_TEXT, "Set Text" }, { DATE_TIME_INFO, "Date Time Info" }, { INCOMING_CALLER, "Incoming Caller" }, { DO_COMMAND, "Do Command" }, { PUSH_BTN_C, "Push Button 'C'" }, { PUSH_BTN_TASK, "Push Button 'Task'" }, { PUSH_BTN_PLUS, "Push Button '+'" }, { PUSH_BTN_MINUS, "Push Button '-'" }, { PUSH_BTN_MIC, "Push Button 'Microphone'" }, { PUSH_BTN_SPK, "Push Button 'Speaker'" }, { PUSH_BTN_TBOOK, "Push Button 'Telephone Book'" }, { PUSH_BTN_DBL_ARROW, "Push Button 'Double-Arrow'" }, { PUSH_BTN_ON_HOOK, "Red Button 'On Hook'" }, { PUSH_BTN_OFF_HOOK, "Green Button 'Off Hook'" }, { PUSH_BTN_UP, "Push Button 'Up'" }, { PUSH_BTN_DOWN, "Push Button 'Down'" }, { PUSH_BTN_LEFT, "Push Button 'Left'" }, { PUSH_BTN_RIGHT, "Push Button 'Right'" }, { END_BLOCK_DATA, "End Block Data" }, { 0, NULL } }; /** * Dissect single command */ static void dissect_a_binary_command(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree) { proto_item *ti; proto_tree *subtree; const guint8* pstr; guint i, len; /* create command subtree */ ti = proto_tree_add_item(tree, hf_a_cmd, tvb, 0, -1, ENC_NA); subtree = proto_item_add_subtree(ti, ett_a_cmd); proto_item_append_text(ti, ", %s", val_to_str(tvb_get_guint8(tvb, 0), szCmdID, "Unk %d")); /* command id */ proto_tree_add_item(subtree, hf_a_id, tvb, 0, 1, ENC_BIG_ENDIAN); /* attributes */ switch(tvb_get_guint8(tvb, 0)) { default: { if(tvb_reported_length(tvb) > 1) proto_tree_add_item(subtree, hf_a_data, tvb, 1, -1, ENC_NA); break; } case CONTEXT_INFO: { for(i = 1; i 3) { proto_tree_add_item(subtree, hf_a_data, tvb, 1, 3, ENC_NA); proto_tree_add_item(subtree, hf_a_length, tvb, 4, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_a_text, tvb, 5, -1, ENC_ASCII|ENC_NA); pstr = tvb_get_string_enc(wmem_packet_scope(), tvb, 5, tvb_get_guint8(tvb, 4), ENC_ASCII|ENC_NA); if(pstr) { proto_item_append_text(ti, ": '%s'", pstr); } } else { proto_tree_add_item(subtree, hf_a_data, tvb, 1, -1, ENC_NA); } break; } case DATE_TIME_INFO: { proto_tree *infotree; for(i=1; i 1) { proto_tree_add_item(subtree, hf_a_line, tvb, 1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_a_length, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_a_cdpn, tvb, 3, -1, ENC_ASCII|ENC_NA); pstr = tvb_get_string_enc(wmem_packet_scope(), tvb, 3, tvb_get_guint8(tvb, 2), ENC_ASCII|ENC_NA); if(pstr) proto_item_append_text(ti, ": '%s'", pstr); } else proto_item_append_text(ti, ": ???"); break; } } } /** * Searching for the next command when the variable or unknown length. */ static guint searchNext(tvbuff_t *tvb, guint begin, guint end) { for(; begin < end; begin++) { if(tvb_get_guint8(tvb, begin) & 0x80) return begin; } return end; } /** * AASP-over-SIP */ static int dissect_aasp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *aasp_tree; guint n; /* Check that there's enough data */ n = tvb_reported_length(tvb); if(n < 3) return 0; col_clear(pinfo->cinfo, COL_INFO); col_append_str(pinfo->cinfo, COL_PROTOCOL, "/AASP"); if(tree) { guint i, prev; /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_aasp, tvb, 0, -1, ENC_NA); aasp_tree = proto_item_add_subtree(ti, ett_aasp); /* separation of command; jump "a=" */ if(tvb_memeql(tvb, 0, "a=", 2) == 0) { prev = 2; for(i=2; i