PageRenderTime 53ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/epan/dissectors/packet-aastra-aasp.c

https://github.com/labx-technologies-llc/wireshark
C | 529 lines | 413 code | 43 blank | 73 comment | 18 complexity | a77c6d53d0493cfa66d1e537d6acb918 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* packet-aastra-aasp.c
  2. * Routines for AASP (Aastra Signalling Protocol) packet dissection.
  3. * Copyright 2011, Marek Tews <marek.tews@gmail.com>
  4. *
  5. * $Id$
  6. *
  7. * Wireshark - Network traffic analyzer
  8. * By Gerald Combs <gerald@wireshark.org>
  9. * Copyright 1998 Gerald Combs
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version 2
  14. * of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  24. */
  25. /*
  26. * AASP over SIP
  27. * Content-Type: message/x-aasp-signalling
  28. */
  29. #include "config.h"
  30. #include <glib.h>
  31. #include <epan/packet.h>
  32. #include <epan/prefs.h>
  33. /* commands id */
  34. #define BEGIN_BLOCK_DATA 0x80
  35. #define WINDOW 0x81
  36. #define TITLE 0x83
  37. #define ROW 0x84
  38. #define MENU_ITEM 0x85
  39. #define CONTEXT_INFO 0x86
  40. #define BUTTON_PRESSED 0x87
  41. #define COLUMN 0x88
  42. #define SET_TEXT 0x89
  43. #define DATE_TIME_INFO 0xA4
  44. #define INCOMING_CALLER 0xA5
  45. #define DO_COMMAND 0xA9
  46. #define PUSH_BTN_C 0xC8
  47. #define PUSH_BTN_TASK 0xC9
  48. #define PUSH_BTN_PLUS 0xCA
  49. #define PUSH_BTN_MINUS 0xCB
  50. #define PUSH_BTN_MIC 0xCC
  51. #define PUSH_BTN_SPK 0xCD
  52. #define PUSH_BTN_TBOOK 0xCE
  53. #define PUSH_BTN_DBL_ARROW 0xCF
  54. #define PUSH_BTN_ON_HOOK 0xD0
  55. #define PUSH_BTN_OFF_HOOK 0xD1
  56. #define PUSH_BTN_UP 0xD2
  57. #define PUSH_BTN_DOWN 0xD3
  58. #define PUSH_BTN_LEFT 0xD4
  59. #define PUSH_BTN_RIGHT 0xD5
  60. #define END_BLOCK_DATA 0xFE
  61. /* Forward declarations */
  62. void proto_register_aasp(void);
  63. void proto_reg_handoff_aasp(void);
  64. /* Initialize the protocol and registered fields */
  65. static gint proto_aasp = -1;
  66. static gint hf_a_data = -1;
  67. static gint hf_a_cmd = -1;
  68. static gint hf_a_id = -1;
  69. static gint hf_a_length = -1;
  70. static gint hf_a_text = -1;
  71. static gint hf_a_line = -1;
  72. static gint hf_a_cdpn = -1;
  73. static gint hf_a_button_id = -1;
  74. static gint hf_a_attr = -1;
  75. static gint hf_a_item = -1;
  76. static gint hf_a_hour = -1;
  77. static gint hf_a_minute = -1;
  78. static gint hf_a_day = -1;
  79. static gint hf_a_month = -1;
  80. static gint hf_a_weekofyear = -1;
  81. static gint hf_a_weekday = -1;
  82. static gint hf_a_month_name = -1;
  83. static gint hf_a_weekofyear_prefix = -1;
  84. /* Initialize the subtree pointers */
  85. static gint ett_aasp = -1;
  86. static gint ett_a_cmd = -1;
  87. static gint ett_a_item = -1;
  88. /* Preferences */
  89. /**
  90. * Commands
  91. */
  92. static const value_string szCmdID[] =
  93. {
  94. { BEGIN_BLOCK_DATA, "Begin Block Data" },
  95. { WINDOW, "Window" },
  96. { TITLE, "Title" },
  97. { ROW, "Row" },
  98. { MENU_ITEM, "Menu Item" },
  99. { CONTEXT_INFO, "Context Info" },
  100. { BUTTON_PRESSED, "Button Pressed" },
  101. { COLUMN, "Column" },
  102. { SET_TEXT, "Set Text" },
  103. { DATE_TIME_INFO, "Date Time Info" },
  104. { INCOMING_CALLER, "Incoming Caller" },
  105. { DO_COMMAND, "Do Command" },
  106. { PUSH_BTN_C, "Push Button 'C'" },
  107. { PUSH_BTN_TASK, "Push Button 'Task'" },
  108. { PUSH_BTN_PLUS, "Push Button '+'" },
  109. { PUSH_BTN_MINUS, "Push Button '-'" },
  110. { PUSH_BTN_MIC, "Push Button 'Microphone'" },
  111. { PUSH_BTN_SPK, "Push Button 'Speaker'" },
  112. { PUSH_BTN_TBOOK, "Push Button 'Telephone Book'" },
  113. { PUSH_BTN_DBL_ARROW, "Push Button 'Double-Arrow'" },
  114. { PUSH_BTN_ON_HOOK, "Red Button 'On Hook'" },
  115. { PUSH_BTN_OFF_HOOK, "Green Button 'Off Hook'" },
  116. { PUSH_BTN_UP, "Push Button 'Up'" },
  117. { PUSH_BTN_DOWN, "Push Button 'Down'" },
  118. { PUSH_BTN_LEFT, "Push Button 'Left'" },
  119. { PUSH_BTN_RIGHT, "Push Button 'Right'" },
  120. { END_BLOCK_DATA, "End Block Data" },
  121. { 0, NULL }
  122. };
  123. /**
  124. * Dissect single command
  125. */
  126. static void
  127. dissect_a_binary_command(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
  128. {
  129. proto_item *ti;
  130. proto_tree *subtree;
  131. guint8* pstr;
  132. guint i, len;
  133. /* create command subtree */
  134. ti = proto_tree_add_item(tree, hf_a_cmd, tvb, 0, -1, ENC_NA);
  135. subtree = proto_item_add_subtree(ti, ett_a_cmd);
  136. proto_item_append_text(ti, ", %s", val_to_str(tvb_get_guint8(tvb, 0), szCmdID, "Unk %d"));
  137. /* command id */
  138. proto_tree_add_item(subtree, hf_a_id, tvb, 0, 1, ENC_NA);
  139. /* attributes */
  140. switch(tvb_get_guint8(tvb, 0))
  141. {
  142. default:
  143. {
  144. if(tvb_length(tvb) > 1)
  145. proto_tree_add_item(subtree, hf_a_data, tvb, 1, -1, ENC_NA);
  146. break;
  147. }
  148. case CONTEXT_INFO:
  149. {
  150. for(i = 1; i<tvb_length(tvb); )
  151. {
  152. switch(tvb_get_guint8(tvb, i))
  153. {
  154. default: i = tvb_length(tvb); continue;
  155. case 1:
  156. case 3:
  157. case 7:
  158. {
  159. ti = proto_tree_add_item(subtree, hf_a_attr, tvb, i, 2, ENC_NA);
  160. proto_item_append_text(ti, " %d", tvb_get_guint8(tvb, i));
  161. i+=2; break;
  162. }
  163. case 0:
  164. case 4:
  165. {
  166. ti = proto_tree_add_item(subtree, hf_a_attr, tvb, i, 3, ENC_NA);
  167. proto_item_append_text(ti, " %d", tvb_get_guint8(tvb, i));
  168. i+=3; break;
  169. }
  170. case 2:
  171. {
  172. ti = proto_tree_add_item(subtree, hf_a_attr, tvb, i, 5, ENC_NA);
  173. proto_item_append_text(ti, " %d", tvb_get_guint8(tvb, i));
  174. i+=5; break;
  175. }
  176. }
  177. }
  178. break;
  179. }
  180. case BUTTON_PRESSED:
  181. {
  182. guint8 c = tvb_get_guint8(tvb, 5);
  183. proto_item_append_text(ti, ": %d '%c'", c, c);
  184. proto_tree_add_item(subtree, hf_a_data, tvb, 1, 4, ENC_NA);
  185. ti = proto_tree_add_item(subtree, hf_a_button_id, tvb, 5, 1, ENC_NA);
  186. if(ti)
  187. proto_item_append_text(ti, " '%c'", c);
  188. break;
  189. }
  190. case SET_TEXT:
  191. {
  192. if(tvb_length(tvb) > 3)
  193. {
  194. proto_tree_add_item(subtree, hf_a_data, tvb, 1, 3, ENC_NA);
  195. proto_tree_add_item(subtree, hf_a_length, tvb, 4, 1, ENC_NA);
  196. proto_tree_add_item(subtree, hf_a_text, tvb, 5, -1, ENC_ASCII|ENC_NA);
  197. pstr = tvb_get_ephemeral_string(tvb, 5, tvb_get_guint8(tvb, 4));
  198. if(pstr)
  199. {
  200. proto_item_append_text(ti, ": '%s'", pstr);
  201. }
  202. }
  203. else
  204. {
  205. proto_tree_add_item(subtree, hf_a_data, tvb, 1, -1, ENC_NA);
  206. }
  207. break;
  208. }
  209. case DATE_TIME_INFO:
  210. {
  211. proto_tree *infotree;
  212. for(i=1; i<tvb_length(tvb); )
  213. {
  214. switch(tvb_get_guint8(tvb, i))
  215. {
  216. default: i++; break;
  217. case 1:
  218. {
  219. len = 2;
  220. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len, ENC_NA);
  221. infotree = proto_item_add_subtree(ti, ett_a_item);
  222. proto_tree_add_item(infotree, hf_a_day, tvb, i+1, 1, ENC_NA);
  223. proto_item_append_text(ti, ", Day: '%d'", tvb_get_guint8(tvb, i+1));
  224. i += len;
  225. break;
  226. }
  227. case 2:
  228. {
  229. len = 2;
  230. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len, ENC_NA);
  231. infotree = proto_item_add_subtree(ti, ett_a_item);
  232. proto_tree_add_item(infotree, hf_a_month, tvb, i+1, 1, ENC_NA);
  233. proto_item_append_text(ti, ", Month: '%d'", tvb_get_guint8(tvb, i+1));
  234. i += len;
  235. break;
  236. }
  237. case 3:
  238. {
  239. len = 2;
  240. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len, ENC_NA);
  241. infotree = proto_item_add_subtree(ti, ett_a_item);
  242. proto_tree_add_item(infotree, hf_a_weekofyear, tvb, i+1, 1, ENC_NA);
  243. proto_item_append_text(ti, ", Week of the year: '%d'", tvb_get_guint8(tvb, i+1));
  244. i += len;
  245. break;
  246. }
  247. case 4:
  248. {
  249. len = tvb_get_guint8(tvb, i+1);
  250. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len+2, ENC_NA);
  251. infotree = proto_item_add_subtree(ti, ett_a_item);
  252. proto_tree_add_item(infotree, hf_a_data, tvb, i+2, len, ENC_NA);
  253. i += len +2;
  254. break;
  255. }
  256. case 5:
  257. {
  258. len = tvb_get_guint8(tvb, i+1);
  259. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len+2, ENC_NA);
  260. infotree = proto_item_add_subtree(ti, ett_a_item);
  261. proto_tree_add_item(infotree, hf_a_weekday, tvb, i+2, len, ENC_ASCII|ENC_NA);
  262. pstr = tvb_get_ephemeral_string(tvb, i+2, len);
  263. if(pstr)
  264. proto_item_append_text(ti, ", Weekday: '%s'", pstr);
  265. i += len +2;
  266. break;
  267. }
  268. case 6:
  269. {
  270. len = tvb_get_guint8(tvb, i+1);
  271. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len+2, ENC_NA);
  272. infotree = proto_item_add_subtree(ti, ett_a_item);
  273. proto_tree_add_item(infotree, hf_a_month_name, tvb, i+2, len, ENC_ASCII|ENC_NA);
  274. pstr = tvb_get_ephemeral_string(tvb, i+2, len);
  275. if(pstr)
  276. proto_item_append_text(ti, ", Month name: '%s'", pstr);
  277. i += len +2;
  278. break;
  279. }
  280. case 7:
  281. {
  282. len = tvb_get_guint8(tvb, i+1);
  283. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len+2, ENC_NA);
  284. infotree = proto_item_add_subtree(ti, ett_a_item);
  285. proto_tree_add_item(infotree, hf_a_weekofyear_prefix, tvb, i+2, len, ENC_ASCII|ENC_NA);
  286. pstr = tvb_get_ephemeral_string(tvb, i+2, len);
  287. if(pstr)
  288. proto_item_append_text(ti, ", Week of the year prefix: '%s'", pstr);
  289. i += len +2;
  290. break;
  291. }
  292. case 8:
  293. {
  294. len = 2;
  295. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len, ENC_NA);
  296. infotree = proto_item_add_subtree(ti, ett_a_item);
  297. proto_tree_add_item(infotree, hf_a_hour, tvb, i+1, 1, ENC_NA);
  298. proto_item_append_text(ti, ", Hour: '%d'", tvb_get_guint8(tvb, i+1));
  299. i += len;
  300. break;
  301. }
  302. case 9:
  303. {
  304. len = 2;
  305. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len, ENC_NA);
  306. infotree = proto_item_add_subtree(ti, ett_a_item);
  307. proto_tree_add_item(infotree, hf_a_minute, tvb, i+1, 1, ENC_NA);
  308. proto_item_append_text(ti, ", Minute: '%d'", tvb_get_guint8(tvb, i+1));
  309. i += len;
  310. break;
  311. }
  312. case 10:
  313. {
  314. len = 2;
  315. ti = proto_tree_add_item(subtree, hf_a_item, tvb, i, len, ENC_NA);
  316. infotree = proto_item_add_subtree(ti, ett_a_item);
  317. proto_tree_add_item(infotree, hf_a_data, tvb, i+1, 1, ENC_NA);
  318. i += len;
  319. break;
  320. }
  321. }
  322. }
  323. break;
  324. }
  325. case DO_COMMAND:
  326. {
  327. if(tvb_length(tvb) > 1)
  328. {
  329. proto_tree_add_item(subtree, hf_a_line, tvb, 1, 1, ENC_NA);
  330. proto_tree_add_item(subtree, hf_a_length, tvb, 2, 1, ENC_NA);
  331. proto_tree_add_item(subtree, hf_a_cdpn, tvb, 3, -1, ENC_ASCII|ENC_NA);
  332. pstr = tvb_get_ephemeral_string(tvb, 3, tvb_get_guint8(tvb, 2));
  333. if(pstr)
  334. proto_item_append_text(ti, ": '%s'", pstr);
  335. }
  336. else
  337. proto_item_append_text(ti, ": ???");
  338. break;
  339. }
  340. }
  341. }
  342. /**
  343. * Searching for the next command when the variable or unknown length.
  344. */
  345. static guint searchNext(tvbuff_t *tvb, guint begin, guint end)
  346. {
  347. for(; begin < end; begin++)
  348. {
  349. if(tvb_get_guint8(tvb, begin) & 0x80)
  350. return begin;
  351. }
  352. return end;
  353. }
  354. /**
  355. * AASP-over-SIP
  356. */
  357. static int
  358. dissect_aasp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
  359. {
  360. /* Set up structures needed to add the protocol subtree and manage it */
  361. proto_item *ti; proto_tree *aasp_tree; guint n;
  362. /* Check that there's enough data */
  363. n = tvb_length(tvb);
  364. if(n < 3) return 0;
  365. col_clear(pinfo->cinfo, COL_INFO);
  366. col_append_str(pinfo->cinfo, COL_PROTOCOL, "/AASP");
  367. if(tree)
  368. {
  369. guint i, prev;
  370. /* create display subtree for the protocol */
  371. ti = proto_tree_add_item(tree, proto_aasp, tvb, 0, -1, ENC_NA);
  372. aasp_tree = proto_item_add_subtree(ti, ett_aasp);
  373. /* separation of command; jump "a=" */
  374. if(tvb_memeql(tvb, 0, "a=", 2) == 0)
  375. {
  376. prev = 2;
  377. for(i=2; i<n;)
  378. {
  379. switch(tvb_get_guint8(tvb, i))
  380. {
  381. #if 0
  382. case CONTEXT_INFO:
  383. {
  384. /* 86:02:00:02:00:23:04:00 */
  385. /* 86:02:00:12:00:23:04:00 */
  386. /* 86:02:00:3a:02:77 */
  387. /* 86:02:00:45:02:77 */
  388. /* 86:02:00:62:02:77 */
  389. /* 86:02:00:61:02:77 */
  390. /* 86:02:00:1e:02:77 */
  391. /* 86:02:00:00:12:77 */
  392. /* 86:02:00:07:12:77 */
  393. /* 86:02:00:00:00:01:03:02 */
  394. /* 86:02:00:00:01:03:02 */
  395. switch(tvb_get_guint8(tvb, i+2))
  396. {
  397. case 0x00: i += 11; break;
  398. case 0x02: i += 8; break;
  399. }
  400. break;
  401. }
  402. #endif
  403. default: i = searchNext(tvb, i+1, n); break;
  404. }
  405. dissect_a_binary_command(tvb_new_subset(tvb, prev, i-prev, i-prev), pinfo, aasp_tree);
  406. prev = i;
  407. }
  408. }
  409. else
  410. {
  411. proto_tree_add_item(aasp_tree, hf_a_text, tvb, 0, -1, ENC_ASCII|ENC_NA);
  412. }
  413. }
  414. /* Return the amount of data this dissector was able to dissect */
  415. return n;
  416. }
  417. /* Register the protocol with Wireshark */
  418. void
  419. proto_register_aasp(void)
  420. {
  421. /*module_t *aasp_module;*/
  422. /* Setup list of header fields See Section 1.6.1 for details*/
  423. static hf_register_info hf[] = {
  424. { &hf_a_data,
  425. { "Data", "aasp.bin.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
  426. { &hf_a_cmd,
  427. { "Bin Cmd", "aasp.a", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
  428. { &hf_a_id,
  429. { "ID", "aasp.a.id", FT_UINT8, BASE_DEC, VALS(szCmdID), 0, NULL, HFILL }},
  430. { &hf_a_length,
  431. { "Length", "aasp.bin.length", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
  432. { &hf_a_text,
  433. { "Text", "aasp.bin.text", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
  434. { &hf_a_line,
  435. { "Line", "aasp.bin.line", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
  436. { &hf_a_cdpn,
  437. { "CDPN", "aasp.bin.cdpn", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
  438. { &hf_a_button_id,
  439. { "Button ID", "aasp.bin.btnid", FT_UINT8, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
  440. { &hf_a_attr,
  441. { "Attribute", "aasp.a.attr", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
  442. { &hf_a_item,
  443. { "Info item", "aasp.bin.infoitem", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
  444. { &hf_a_hour,
  445. { "Hour", "aasp.bin.hour", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
  446. { &hf_a_minute,
  447. { "Minute", "aasp.bin.minute", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
  448. { &hf_a_day,
  449. { "Day", "aasp.bin.day", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
  450. { &hf_a_month,
  451. { "Month", "aasp.bin.month", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
  452. { &hf_a_weekofyear,
  453. { "Week of the year", "aasp.bin.weekofyear", FT_UINT8, BASE_DEC, NULL, 0,
  454. "Week number in the year", HFILL }},
  455. { &hf_a_weekday,
  456. { "Weekday", "aasp.bin.weekday", FT_STRING, BASE_NONE, NULL, 0,
  457. "Short weekday name in the PBX current language", HFILL }},
  458. { &hf_a_month_name,
  459. { "Month name", "aasp.bin.monthname", FT_STRING, BASE_NONE, NULL, 0,
  460. "Short month name in the PBX current language", HFILL }},
  461. { &hf_a_weekofyear_prefix,
  462. { "Week of the year prefix", "aasp.bin.weekofyearprefix", FT_STRING, BASE_NONE, NULL, 0,
  463. "Precedes the number on the screen which is the week number in year", HFILL }},
  464. };
  465. /* Setup protocol subtree array */
  466. static gint *ett[] = {
  467. &ett_aasp,
  468. &ett_a_cmd,
  469. &ett_a_item,
  470. };
  471. /* Register the protocol name and description */
  472. proto_aasp = proto_register_protocol("Aastra Signalling Protocol", "AASP", "aasp");
  473. /* Required function calls to register the header fields and subtrees used */
  474. proto_register_field_array(proto_aasp, hf, array_length(hf));
  475. proto_register_subtree_array(ett, array_length(ett));
  476. /* Register our configuration options */
  477. /* aasp_module = prefs_register_protocol(proto_aasp, proto_reg_handoff_aasp); */
  478. }
  479. /* */
  480. void
  481. proto_reg_handoff_aasp(void)
  482. {
  483. dissector_handle_t aasp_handle;
  484. aasp_handle = new_create_dissector_handle(dissect_aasp, proto_aasp);
  485. dissector_add_string("media_type", "message/x-aasp-signalling", aasp_handle);
  486. }