PageRenderTime 52ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/epan/dissectors/packet-tpncp.c

https://github.com/labx-technologies-llc/wireshark
C | 806 lines | 619 code | 98 blank | 89 comment | 103 complexity | 2b12dd13a2d58ef973ee6564dd15b6db MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* packet-tpncp.c
  2. * Routines for Audiocodes TrunkPack Network Control Protocol (TPNCP) dissection
  3. *
  4. * Copyright (c) 2007 by Valery Sigalov <valery.sigalov@audiocodes.com>
  5. *
  6. * $Id$
  7. *
  8. * Wireshark - Network traffic analyzer
  9. * By Gerald Combs <gerald@wireshark.com>
  10. * Copyright 1998 Gerald Combs
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License
  14. * as published by the Free Software Foundation; either version 2
  15. * of the License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  25. */
  26. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  27. #include "config.h"
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <glib.h>
  32. #include <wsutil/file_util.h>
  33. #include <epan/exceptions.h>
  34. #include <epan/packet.h>
  35. #include <epan/prefs.h>
  36. #include <epan/emem.h>
  37. #include <epan/filesystem.h>
  38. #include <epan/dissectors/packet-tcp.h>
  39. #include <epan/strutil.h>
  40. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  41. #define BASE_TPNCP_PORT 2424
  42. #define TCP_PORT_TPNCP_TRUNKPACK BASE_TPNCP_PORT
  43. #define UDP_PORT_TPNCP_TRUNKPACK BASE_TPNCP_PORT
  44. #define TCP_PORT_TPNCP_HOST BASE_TPNCP_PORT
  45. #define UDP_PORT_TPNCP_HOST BASE_TPNCP_PORT
  46. #define BASE_TPNCP_DATA_LEN 256
  47. #define MAX_TPNCP_DB_ENTRY_LEN BASE_TPNCP_DATA_LEN
  48. #define MAX_TPNCP_DB_SIZE 3000
  49. #define MAX_ENUMS_NUM 500
  50. #define MAX_ENUM_ENTRIES 500
  51. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  52. /* The linked list for storing information about specific data fields. */
  53. typedef struct tpncp_data_field_info
  54. {
  55. gchar *tpncp_data_field_name;
  56. gint tpncp_data_field_descr;
  57. gint tpncp_data_field_sign;
  58. gint tpncp_data_field_size;
  59. gint tpncp_data_field_array_dim;
  60. gint tpncp_data_field_is_ip_addr;
  61. struct tpncp_data_field_info *p_next;
  62. } tpncp_data_field_info;
  63. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  64. /* Desegmentation of TPNCP over TCP */
  65. static gboolean tpncp_desegment = TRUE;
  66. /* Database for storing information about all TPNCP events. */
  67. /* XXX: ToDo: allocate at runtime as needed */
  68. static tpncp_data_field_info tpncp_events_info_db[MAX_TPNCP_DB_SIZE];
  69. /* Database for storing information about all TPNCP commands. */
  70. /* XXX: ToDo: allocate at runtime as needed */
  71. static tpncp_data_field_info tpncp_commands_info_db[MAX_TPNCP_DB_SIZE];
  72. /* Global variables for bitfields representation. */
  73. static gint bits[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
  74. static gint bitindex = 0;
  75. /* TPNCP packet header fields. */
  76. static gint proto_tpncp = -1;
  77. static gint hf_tpncp_version = -1;
  78. static gint hf_tpncp_length = -1;
  79. static gint hf_tpncp_seq_number = -1;
  80. /* static gint hf_tpncp_old_event_seq_number = -1; */
  81. static gint hf_tpncp_reserved = -1;
  82. static gint hf_tpncp_command_id = -1;
  83. /* static gint hf_tpncp_old_command_id = -1; */
  84. static gint hf_tpncp_event_id = -1;
  85. static gint hf_tpncp_cid = -1;
  86. /* TPNCP fields defining a subtree. */
  87. static gint ett_tpncp = -1;
  88. static gint ett_tpncp_body = -1;
  89. static guint global_tpncp_trunkpack_tcp_port = TCP_PORT_TPNCP_TRUNKPACK;
  90. static guint global_tpncp_trunkpack_udp_port = UDP_PORT_TPNCP_TRUNKPACK;
  91. static guint global_tpncp_host_tcp_port = TCP_PORT_TPNCP_HOST;
  92. static guint global_tpncp_host_udp_port = UDP_PORT_TPNCP_HOST;
  93. static dissector_handle_t tpncp_handle;
  94. static guint trunkpack_tcp_port = 0;
  95. static guint trunkpack_udp_port = 0;
  96. static guint host_tcp_port = 0;
  97. static guint host_udp_port = 0;
  98. /* XXX: ToDo: allocate at runtime as needed */
  99. /* The following allocates something on the order of 2M of static memory ! */
  100. /* Also: Runtime value_string_ext arrays should be used */
  101. static value_string tpncp_commands_id_vals[MAX_TPNCP_DB_SIZE];
  102. static value_string tpncp_events_id_vals[MAX_TPNCP_DB_SIZE];
  103. static value_string tpncp_enums_id_vals[MAX_ENUMS_NUM][MAX_ENUM_ENTRIES];
  104. static gchar *tpncp_enums_name_vals[MAX_ENUMS_NUM];
  105. static gint hf_size = 1;
  106. static gint hf_allocated = 0;
  107. static hf_register_info *hf = NULL;
  108. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  109. static void dissect_tpncp_data(gint data_id, tvbuff_t *tvb, proto_item *item,
  110. gint *offset, tpncp_data_field_info *data_fields_info) {
  111. proto_tree *ltree = NULL;
  112. proto_item *pi = NULL;
  113. gint32 g_int;
  114. gint16 g_short;
  115. guint16 g_ushort;
  116. gint8 g_char;
  117. guint8 g_uchar;
  118. gint g_str_len, counter, bitshift, bitmask;
  119. tpncp_data_field_info *current_tpncp_data_field_info = NULL;
  120. ltree = proto_item_add_subtree(item, ett_tpncp_body);
  121. current_tpncp_data_field_info = &data_fields_info[data_id];
  122. while (current_tpncp_data_field_info) {
  123. switch(current_tpncp_data_field_info->tpncp_data_field_size) {
  124. case 1: case 2: case 3: case 4:
  125. case 5: case 6: case 7: case 8:
  126. if ((g_str_len = current_tpncp_data_field_info->tpncp_data_field_array_dim)) { /* add char array */
  127. g_str_len = MIN(g_str_len, tvb_length_remaining(tvb, *offset));
  128. proto_tree_add_item(ltree, current_tpncp_data_field_info->tpncp_data_field_descr,
  129. tvb, *offset, g_str_len, ENC_NA|ENC_ASCII);
  130. (*offset) += g_str_len;
  131. }
  132. else { /* add single char */
  133. g_uchar = tvb_get_guint8(tvb, *offset);
  134. /* bitfields */
  135. if (current_tpncp_data_field_info->tpncp_data_field_size != 8) {
  136. for (counter = 0, bitmask = 0x0, bitshift = bitindex;
  137. counter < current_tpncp_data_field_info->tpncp_data_field_size;
  138. counter++)
  139. bitmask |= bits[bitindex++]; /* Bitmask of interesting bits. */
  140. g_uchar &= bitmask;
  141. g_uchar >>= bitshift;
  142. }
  143. if (current_tpncp_data_field_info->tpncp_data_field_sign || current_tpncp_data_field_info->tpncp_data_field_size != 8) {
  144. proto_tree_add_uint(ltree, current_tpncp_data_field_info->tpncp_data_field_descr,
  145. tvb, *offset, 1, g_uchar);
  146. }
  147. else {
  148. /* signed*/
  149. g_char = (gint8)g_uchar;
  150. proto_tree_add_int(ltree, current_tpncp_data_field_info->tpncp_data_field_descr,
  151. tvb, *offset, 1, g_char);
  152. }
  153. if ((bitindex == 0) || (bitindex == 8)) {
  154. (*offset)++;
  155. bitindex = 0;
  156. }
  157. }
  158. break;
  159. case 16:
  160. if (current_tpncp_data_field_info->tpncp_data_field_sign) {
  161. g_ushort = tvb_get_ntohs(tvb, *offset);
  162. proto_tree_add_uint(ltree, current_tpncp_data_field_info->tpncp_data_field_descr,
  163. tvb, *offset, 2, g_ushort);
  164. }
  165. else {
  166. g_short = tvb_get_ntohs(tvb, *offset);
  167. proto_tree_add_int(ltree, current_tpncp_data_field_info->tpncp_data_field_descr,
  168. tvb, *offset, 2, g_short);
  169. }
  170. (*offset) += 2;
  171. break;
  172. case 32:
  173. g_int = tvb_get_ntohl(tvb, *offset);
  174. if (current_tpncp_data_field_info->tpncp_data_field_sign) {
  175. pi = proto_tree_add_uint(ltree, current_tpncp_data_field_info->tpncp_data_field_descr,
  176. tvb, *offset, 4, g_int);
  177. }
  178. else {
  179. pi = proto_tree_add_int(ltree, current_tpncp_data_field_info->tpncp_data_field_descr,
  180. tvb, *offset, 4, g_int);
  181. }
  182. /* Add string representation for ip_address's field (if needed). */
  183. if (current_tpncp_data_field_info->tpncp_data_field_is_ip_addr) {
  184. proto_item_append_text(pi, " (%s)", tvb_ip_to_str(tvb, *offset));
  185. }
  186. (*offset) += 4;
  187. break;
  188. default:
  189. break;
  190. }
  191. current_tpncp_data_field_info = current_tpncp_data_field_info->p_next;
  192. if (tvb_length_remaining(tvb, *offset) <= 0) {
  193. break;
  194. }
  195. }
  196. }
  197. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  198. static void dissect_tpncp_event(gint event_id, tvbuff_t *tvb,
  199. proto_item *item, gint *offset) {
  200. switch (event_id) {
  201. /* Place non-standard events here. */
  202. default:
  203. dissect_tpncp_data(event_id, tvb, item, offset, tpncp_events_info_db);
  204. break;
  205. }
  206. }
  207. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  208. static void dissect_tpncp_command(gint command_id, tvbuff_t *tvb,
  209. proto_item *item, gint *offset) {
  210. switch (command_id) {
  211. /* Place non-standard commands here. */
  212. default:
  213. dissect_tpncp_data(command_id, tvb, item, offset, tpncp_commands_info_db);
  214. break;
  215. }
  216. }
  217. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  218. static void dissect_tpncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  219. proto_item *item = NULL, *tpncp_item = NULL;
  220. proto_tree *tpncp_tree = NULL;
  221. gint offset = 0;
  222. guint32 id, cid = 0;
  223. guint16 seq_number, len, ver, reserved;
  224. gchar *tpncp_header;
  225. ver = tvb_get_ntohs(tvb, 0);
  226. len = tvb_get_ntohs(tvb, 2);
  227. seq_number = tvb_get_ntohs(tvb, 4);
  228. reserved = tvb_get_ntohs(tvb, 6);
  229. id = tvb_get_ntohl(tvb, 8);
  230. if (pinfo->srcport == UDP_PORT_TPNCP_TRUNKPACK) /* Event */
  231. cid = tvb_get_ntohl(tvb, 12 );
  232. col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPNCP");
  233. if (pinfo->srcport == UDP_PORT_TPNCP_TRUNKPACK) {
  234. col_add_fstr(pinfo->cinfo, COL_INFO,
  235. "EvID=%s(%d), SeqNo=%d, ChID=%d, Len=%d, Ver=%d",
  236. val_to_str_const(id, tpncp_events_id_vals, "Unknown"),
  237. id, seq_number, cid, len, ver);
  238. } else {
  239. col_add_fstr(pinfo->cinfo, COL_INFO,
  240. "CmdID=%s(%d), SeqNo=%d, Len=%d, Ver=%d",
  241. val_to_str_const(id, tpncp_commands_id_vals, "Unknown"),
  242. id, seq_number, len, ver);
  243. }
  244. if (tree) {
  245. item = proto_tree_add_item(tree, proto_tpncp, tvb, 0, -1, ENC_NA);
  246. tpncp_tree = proto_item_add_subtree(item, ett_tpncp);
  247. proto_tree_add_uint(tpncp_tree, hf_tpncp_version, tvb, 0, 2, ver);
  248. proto_tree_add_uint(tpncp_tree, hf_tpncp_length, tvb, 2, 2, len);
  249. proto_tree_add_uint(tpncp_tree, hf_tpncp_seq_number, tvb, 4, 2, seq_number);
  250. proto_tree_add_uint(tpncp_tree, hf_tpncp_reserved, tvb, 6, 2, reserved);
  251. if (pinfo->srcport == UDP_PORT_TPNCP_TRUNKPACK) {
  252. if (try_val_to_str(id, tpncp_events_id_vals)) {
  253. proto_tree_add_uint(tpncp_tree, hf_tpncp_event_id, tvb, 8, 4, id);
  254. proto_tree_add_int(tpncp_tree, hf_tpncp_cid, tvb, 12, 4, cid);
  255. offset += 16;
  256. if (tpncp_events_info_db[id].tpncp_data_field_size) {
  257. tpncp_header = ep_strdup_printf("TPNCP Event: %s (%d)", val_to_str_const(id, tpncp_events_id_vals, "Unknown"), id);
  258. tpncp_item = proto_tree_add_text(tree, tvb, offset, -1, "%s", tpncp_header);
  259. dissect_tpncp_event(id, tvb, tpncp_item, &offset);
  260. }
  261. }
  262. }
  263. else {
  264. if (try_val_to_str(id, tpncp_commands_id_vals)) {
  265. proto_tree_add_uint(tpncp_tree, hf_tpncp_command_id, tvb, 8, 4, id);
  266. offset += 12;
  267. if (tpncp_commands_info_db[id].tpncp_data_field_size) {
  268. tpncp_header = ep_strdup_printf("TPNCP Command: %s (%d)", val_to_str_const(id, tpncp_commands_id_vals, "Unknown"), id);
  269. tpncp_item = proto_tree_add_text(tree, tvb, offset, -1, "%s", tpncp_header);
  270. dissect_tpncp_command(id, tvb, tpncp_item, &offset);
  271. }
  272. }
  273. }
  274. }
  275. }
  276. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  277. static guint get_tpncp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, gint offset) {
  278. guint16 plen;
  279. /* Get the length of the DNS packet. */
  280. plen = tvb_get_ntohs(tvb, offset + 2);
  281. /* Length does not include the version+length field. */
  282. plen += 4;
  283. return plen;
  284. }
  285. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  286. static void dissect_tpncp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  287. if (pinfo->can_desegment)
  288. /* If desegmentation is enabled (TCP preferences) use the desegmentation API. */
  289. tcp_dissect_pdus(tvb, pinfo, tree, tpncp_desegment, 4, get_tpncp_pdu_len, dissect_tpncp);
  290. else
  291. /* Otherwise use the regular dissector (might not give correct dissection). */
  292. dissect_tpncp(tvb, pinfo, tree);
  293. }
  294. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  295. static gint fill_tpncp_id_vals(value_string string[], FILE *file) {
  296. gint i = 0, tpncp_id = 0;
  297. gchar *tpncp_name = NULL, *line_in_file = NULL;
  298. line_in_file = (gchar *)ep_alloc(MAX_TPNCP_DB_ENTRY_LEN);
  299. line_in_file[0] = 0;
  300. tpncp_name = (gchar *)ep_alloc(MAX_TPNCP_DB_ENTRY_LEN);
  301. tpncp_name[0] = 0;
  302. while (fgets(line_in_file, MAX_TPNCP_DB_ENTRY_LEN, file) != NULL) {
  303. if (!strncmp(line_in_file, "#####", 5)) {
  304. break;
  305. }
  306. if (sscanf(line_in_file, "%255s %d", tpncp_name, &tpncp_id) == 2) {
  307. string[i].strptr = g_strdup(tpncp_name);
  308. string[i].value = tpncp_id;
  309. if (i < (MAX_TPNCP_DB_SIZE-1)) {
  310. i++;
  311. }
  312. else {
  313. break;
  314. }
  315. }
  316. }
  317. return 0;
  318. }
  319. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  320. static gint fill_enums_id_vals(FILE *file) {
  321. gint i = 0, enum_id = 0, enum_val = 0;
  322. gboolean first_entry = TRUE;
  323. gchar *line_in_file = NULL, *enum_name = NULL,
  324. *enum_type = NULL, *enum_str = NULL;
  325. line_in_file = (gchar *)ep_alloc(MAX_TPNCP_DB_ENTRY_LEN);
  326. line_in_file[0] = 0;
  327. enum_name = (gchar *)ep_alloc(MAX_TPNCP_DB_ENTRY_LEN);
  328. enum_name[0] = 0;
  329. enum_type = (gchar *)ep_alloc(MAX_TPNCP_DB_ENTRY_LEN);
  330. enum_type[0] = 0;
  331. enum_str = (gchar *)ep_alloc(MAX_TPNCP_DB_ENTRY_LEN);
  332. enum_str[0] = 0;
  333. while (fgets(line_in_file, MAX_TPNCP_DB_ENTRY_LEN, file) != NULL) {
  334. if (!strncmp(line_in_file, "#####", 5)) {
  335. break;
  336. }
  337. if (sscanf(line_in_file, "%255s %255s %d", enum_name, enum_str, &enum_id) == 3) {
  338. if (strcmp(enum_type, enum_name)) {
  339. if (!first_entry) {
  340. tpncp_enums_id_vals[enum_val][i].strptr = NULL;
  341. tpncp_enums_id_vals[enum_val][i].value = 0;
  342. if (enum_val < (MAX_ENUMS_NUM-1)) {
  343. enum_val++; i = 0;
  344. }
  345. else {
  346. break;
  347. }
  348. }
  349. else
  350. first_entry = FALSE;
  351. tpncp_enums_name_vals[enum_val] = g_strdup(enum_name);
  352. g_strlcpy(enum_type, enum_name, MAX_TPNCP_DB_ENTRY_LEN);
  353. }
  354. tpncp_enums_id_vals[enum_val][i].strptr = g_strdup(enum_str);
  355. tpncp_enums_id_vals[enum_val][i].value = enum_id;
  356. if (i < (MAX_ENUM_ENTRIES-1)) {
  357. i++;
  358. }
  359. else {
  360. break;
  361. }
  362. }
  363. }
  364. /* make sure the last entry in the array is null but
  365. * don't overflow if we've filled the entire thing (in which case
  366. * we have to drop an entry) */
  367. if (enum_val + 1 >= MAX_ENUMS_NUM) {
  368. g_free(tpncp_enums_name_vals[enum_val]);
  369. tpncp_enums_name_vals[enum_val] = NULL;
  370. }
  371. else {
  372. tpncp_enums_name_vals[enum_val+1] = NULL;
  373. }
  374. return 0;
  375. }
  376. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  377. static gint get_enum_name_val(gchar *enum_name) {
  378. gint enum_val = 0;
  379. while (tpncp_enums_name_vals[enum_val]) {
  380. if (!strcmp(enum_name, tpncp_enums_name_vals[enum_val]))
  381. return enum_val;
  382. enum_val++;
  383. }
  384. return -1;
  385. }
  386. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  387. static gint init_tpncp_data_fields_info(tpncp_data_field_info *data_fields_info, FILE *file) {
  388. static gboolean was_registered = FALSE;
  389. gchar *tpncp_db_entry = NULL, *tpncp_data_field_name = NULL, *tmp = NULL;
  390. gint enum_val, data_id, current_data_id = -1,
  391. tpncp_data_field_sign, tpncp_data_field_size,
  392. tpncp_data_field_array_dim, tpncp_data_field_is_ip_addr;
  393. guint idx;
  394. tpncp_data_field_info *current_tpncp_data_field_info = NULL;
  395. hf_register_info hf_entr;
  396. static hf_register_info hf_tpncp[] = {
  397. {
  398. &hf_tpncp_version,
  399. {
  400. "Version",
  401. "tpncp.version",
  402. FT_UINT16,
  403. BASE_DEC,
  404. NULL,
  405. 0x0,
  406. NULL, HFILL
  407. }
  408. },
  409. {
  410. &hf_tpncp_length,
  411. {
  412. "Length",
  413. "tpncp.length",
  414. FT_UINT16,
  415. BASE_DEC,
  416. NULL,
  417. 0x0,
  418. NULL, HFILL
  419. }
  420. },
  421. {
  422. &hf_tpncp_seq_number,
  423. {
  424. "Sequence number",
  425. "tpncp.seq_number",
  426. FT_UINT16,
  427. BASE_DEC,
  428. NULL,
  429. 0x0,
  430. NULL, HFILL
  431. }
  432. },
  433. #if 0
  434. {
  435. &hf_tpncp_old_event_seq_number,
  436. {
  437. "Sequence number",
  438. "tpncp.old_event_seq_number",
  439. FT_UINT32,
  440. BASE_DEC,
  441. NULL,
  442. 0x0,
  443. NULL, HFILL
  444. }
  445. },
  446. #endif
  447. {
  448. &hf_tpncp_reserved,
  449. {
  450. "Reserved",
  451. "tpncp.reserved",
  452. FT_UINT16,
  453. BASE_DEC,
  454. NULL,
  455. 0x0,
  456. NULL, HFILL
  457. }
  458. },
  459. {
  460. &hf_tpncp_command_id,
  461. {
  462. "Command ID",
  463. "tpncp.command_id",
  464. FT_UINT32,
  465. BASE_DEC,
  466. VALS(tpncp_commands_id_vals),
  467. 0x0,
  468. NULL, HFILL
  469. }
  470. },
  471. #if 0
  472. {
  473. &hf_tpncp_old_command_id,
  474. {
  475. "Command ID",
  476. "tpncp.old_command_id",
  477. FT_UINT16,
  478. BASE_DEC,
  479. VALS(tpncp_commands_id_vals),
  480. 0x0,
  481. NULL, HFILL
  482. }
  483. },
  484. #endif
  485. {
  486. &hf_tpncp_event_id,
  487. {
  488. "Event ID",
  489. "tpncp.event_id",
  490. FT_UINT32,
  491. BASE_DEC,
  492. VALS(tpncp_events_id_vals),
  493. 0x0,
  494. NULL, HFILL
  495. }
  496. },
  497. {
  498. &hf_tpncp_cid,
  499. {
  500. "Channel ID",
  501. "tpncp.channel_id",
  502. FT_INT32,
  503. BASE_DEC,
  504. NULL,
  505. 0x0,
  506. NULL, HFILL
  507. }
  508. }
  509. };
  510. tpncp_db_entry = (gchar *)ep_alloc(MAX_TPNCP_DB_ENTRY_LEN);
  511. tpncp_db_entry[0] = 0;
  512. /* Register common fields of hf_register_info struture. */
  513. hf_entr.hfinfo.type = FT_NONE;
  514. hf_entr.hfinfo.strings = NULL;
  515. hf_entr.hfinfo.bitmask = 0x0;
  516. hf_entr.hfinfo.blurb = NULL;
  517. hf_entr.hfinfo.id = 0;
  518. hf_entr.hfinfo.parent = 0;
  519. hf_entr.hfinfo.ref_type = HF_REF_TYPE_NONE;
  520. hf_entr.hfinfo.same_name_next = NULL;
  521. hf_entr.hfinfo.same_name_prev_id = -1;
  522. if (!was_registered) {
  523. /* Register non-standard data should be done only once. */
  524. hf_allocated = hf_size+(int)array_length(hf_tpncp)-1;
  525. if ((hf = (hf_register_info *)g_realloc(hf, hf_allocated * sizeof(hf_register_info))) == NULL)
  526. return (-1);
  527. for (idx = 0; idx < array_length(hf_tpncp); idx++) {
  528. memcpy(hf + (hf_size - 1), hf_tpncp + idx, sizeof(hf_register_info));
  529. hf_size++;
  530. }
  531. was_registered = TRUE;
  532. }
  533. else
  534. hf_size++;
  535. /* Register standard data. */
  536. while (fgets(tpncp_db_entry, MAX_TPNCP_DB_ENTRY_LEN, file) != NULL) {
  537. if (!strncmp(tpncp_db_entry, "#####", 5)) {
  538. hf_size--;
  539. break;
  540. }
  541. /* Default to decimal display type */
  542. hf_entr.hfinfo.display = BASE_DEC;
  543. if ((tmp = strtok(tpncp_db_entry, " ")) == NULL)
  544. continue; /* Badly formed data base entry - skip corresponding field's registration. */
  545. data_id = atoi(tmp);
  546. if ((tpncp_data_field_name = strtok(NULL, " ")) == NULL)
  547. continue; /* Badly formed data base entry - skip corresponding field's registration. */
  548. if ((tmp = strtok(NULL, " ")) == NULL)
  549. continue; /* Badly formed data base entry - skip corresponding field's registration. */
  550. tpncp_data_field_sign = atoi(tmp);
  551. if ((tmp = strtok(NULL, " ")) == NULL)
  552. continue; /* Badly formed data base entry - skip corresponding field's registration. */
  553. tpncp_data_field_size = atoi(tmp);
  554. if ((tmp = strtok(NULL, " ")) == NULL)
  555. continue; /* Badly formed data base entry - skip corresponding field's registration. */
  556. tpncp_data_field_array_dim = atoi(tmp);
  557. if ((tmp = strtok(NULL, " ")) == NULL)
  558. continue; /* Badly formed data base entry - skip corresponding field's registration. */
  559. tpncp_data_field_is_ip_addr = atoi(tmp);
  560. if ((tmp = strtok(NULL, "\n")) == NULL)
  561. continue; /* Badly formed data base entry - skip corresponding field's registration. */
  562. if (current_data_id != data_id) { /* new data */
  563. current_tpncp_data_field_info = &data_fields_info[data_id];
  564. current_data_id = data_id;
  565. }
  566. else {
  567. if ((current_tpncp_data_field_info->p_next =
  568. (tpncp_data_field_info *)g_malloc0(sizeof(tpncp_data_field_info)))
  569. == NULL)
  570. return (-1);
  571. current_tpncp_data_field_info = current_tpncp_data_field_info->p_next;
  572. }
  573. /* Register specific fields of hf_register_info struture. */
  574. if (strcmp(tmp, "primitive")) {
  575. enum_val = get_enum_name_val(tmp);
  576. if (enum_val == -1) {
  577. hf_entr.hfinfo.strings = NULL;
  578. }
  579. else {
  580. hf_entr.hfinfo.strings = VALS(tpncp_enums_id_vals[enum_val]);
  581. }
  582. }
  583. else {
  584. hf_entr.hfinfo.strings = NULL;
  585. }
  586. current_tpncp_data_field_info->tpncp_data_field_descr = -1;
  587. hf_entr.p_id = &current_tpncp_data_field_info->tpncp_data_field_descr;
  588. current_tpncp_data_field_info->tpncp_data_field_name = g_strdup_printf("tpncp.%s", tpncp_data_field_name);
  589. hf_entr.hfinfo.name = current_tpncp_data_field_info->tpncp_data_field_name;
  590. hf_entr.hfinfo.abbrev = current_tpncp_data_field_info->tpncp_data_field_name;
  591. switch (tpncp_data_field_size) {
  592. case 1: case 2: case 3: case 4:
  593. case 5: case 6: case 7: case 8:
  594. if (tpncp_data_field_array_dim) {
  595. hf_entr.hfinfo.type = FT_STRING;
  596. hf_entr.hfinfo.display = BASE_NONE;
  597. }
  598. else
  599. hf_entr.hfinfo.type = (tpncp_data_field_sign)?FT_UINT8:FT_INT8;
  600. break;
  601. case 16:
  602. hf_entr.hfinfo.type = (tpncp_data_field_sign)?FT_UINT16:FT_INT16;
  603. break;
  604. case 32:
  605. hf_entr.hfinfo.type = (tpncp_data_field_sign)?FT_UINT32:FT_INT32;
  606. break;
  607. default:
  608. break;
  609. }
  610. /* Register initialized hf_register_info in global database. */
  611. if (hf_size > hf_allocated) {
  612. hf_allocated += 1024;
  613. if ((hf = (hf_register_info *)g_realloc(hf, hf_allocated * sizeof(hf_register_info))) == NULL)
  614. return (-1);
  615. }
  616. memcpy(hf + hf_size - 1, &hf_entr, sizeof(hf_register_info));
  617. hf_size++;
  618. current_tpncp_data_field_info->tpncp_data_field_sign = tpncp_data_field_sign;
  619. current_tpncp_data_field_info->tpncp_data_field_size = tpncp_data_field_size;
  620. current_tpncp_data_field_info->tpncp_data_field_array_dim = tpncp_data_field_array_dim;
  621. current_tpncp_data_field_info->tpncp_data_field_is_ip_addr = tpncp_data_field_is_ip_addr;
  622. }
  623. return 0;
  624. }
  625. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  626. static gint init_tpncp_db(void) {
  627. gchar *tpncp_dat_file_path;
  628. FILE *file;
  629. tpncp_dat_file_path = ep_strdup_printf("%s" G_DIR_SEPARATOR_S"tpncp" G_DIR_SEPARATOR_S "tpncp.dat", get_datafile_dir());
  630. /* Open file with TPNCP data. */
  631. if ((file = ws_fopen(tpncp_dat_file_path, "r")) == NULL)
  632. return (-1);
  633. fill_tpncp_id_vals(tpncp_events_id_vals, file);
  634. fill_tpncp_id_vals(tpncp_commands_id_vals, file);
  635. fill_enums_id_vals(file);
  636. init_tpncp_data_fields_info(tpncp_events_info_db, file);
  637. init_tpncp_data_fields_info(tpncp_commands_info_db, file);
  638. fclose(file);
  639. return 0;
  640. }
  641. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  642. void proto_reg_handoff_tpncp(void) {
  643. static gint tpncp_prefs_initialized = FALSE;
  644. static dissector_handle_t tpncp_tcp_handle;
  645. /* If we weren't able to load the database (and thus the hf_ entries)
  646. * do not attach to any ports (if we did then we'd get a "dissector bug"
  647. * assertions every time a packet is handed to us and we tried to use the
  648. * hf_ entry).
  649. */
  650. if (proto_tpncp == -1)
  651. return;
  652. if (!tpncp_prefs_initialized) {
  653. tpncp_tcp_handle = create_dissector_handle(dissect_tpncp_tcp, proto_tpncp);
  654. tpncp_prefs_initialized = TRUE;
  655. }
  656. else {
  657. dissector_delete_uint("tcp.port", trunkpack_tcp_port, tpncp_tcp_handle);
  658. dissector_delete_uint("udp.port", trunkpack_udp_port, tpncp_handle);
  659. dissector_delete_uint("tcp.port", host_tcp_port, tpncp_tcp_handle);
  660. dissector_delete_uint("udp.port", host_udp_port, tpncp_handle);
  661. }
  662. trunkpack_tcp_port = global_tpncp_trunkpack_tcp_port;
  663. trunkpack_udp_port = global_tpncp_trunkpack_udp_port;
  664. host_tcp_port = global_tpncp_host_tcp_port;
  665. host_udp_port = global_tpncp_host_udp_port;
  666. dissector_add_uint("tcp.port", global_tpncp_trunkpack_tcp_port, tpncp_tcp_handle);
  667. dissector_add_uint("udp.port", global_tpncp_trunkpack_udp_port, tpncp_handle);
  668. }
  669. /*-------------------------------------------------------------------------------------------------------------------------------------------*/
  670. void proto_register_tpncp(void) {
  671. gint idx;
  672. module_t *tpncp_module;
  673. static gint *ett[] = {
  674. &ett_tpncp,
  675. &ett_tpncp_body
  676. };
  677. if (init_tpncp_db() == -1)
  678. return;
  679. proto_tpncp = proto_register_protocol("AudioCodes TPNCP (TrunkPack Network Control Protocol)",
  680. "TPNCP", "tpncp");
  681. /* Rather than duplicating large quantities of code from
  682. * proto_register_field_array() and friends to sanitize the tpncp.dat file
  683. * when we read it, just catch any exceptions we get while registering and
  684. * take them as a hint that the file is corrupt. Then move on, so that at
  685. * least the rest of the protocol dissectors will still work.
  686. */
  687. TRY {
  688. /* The function proto_register_field_array does not work with dynamic
  689. * arrays, so pass dynamic array elements one-by-one in the loop.
  690. */
  691. for(idx = 0; idx < hf_size; idx++) {
  692. proto_register_field_array(proto_tpncp, &hf[idx], 1);
  693. }
  694. }
  695. CATCH_ALL {
  696. g_warning("Corrupt tpncp.dat file, tpncp dissector will not work.");
  697. }
  698. ENDTRY;
  699. proto_register_subtree_array(ett, array_length(ett));
  700. tpncp_handle = register_dissector("tpncp", dissect_tpncp, proto_tpncp);
  701. tpncp_module = prefs_register_protocol(proto_tpncp, proto_reg_handoff_tpncp);
  702. prefs_register_uint_preference(tpncp_module, "tcp.trunkpack_port",
  703. "TPNCP \"well-known\" TrunkPack TCP Port",
  704. "", 10, &global_tpncp_trunkpack_tcp_port);
  705. prefs_register_uint_preference(tpncp_module, "udp.trunkpack_port",
  706. "TPNCP \"well-known\" TrunkPack UDP Port",
  707. "", 10, &global_tpncp_trunkpack_udp_port);
  708. }