PageRenderTime 65ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/epan/dissectors/packet-megaco.c

https://github.com/labx-technologies-llc/wireshark
C | 3664 lines | 2589 code | 639 blank | 436 comment | 452 complexity | d1120d55ed35d3d68e137e2bcfb78ea8 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* packet-megaco.c
  2. * Routines for megaco packet disassembly
  3. * RFC 3015
  4. *
  5. * $Id$
  6. *
  7. * Christian Falckenberg, 2002/10/17
  8. * Copyright (c) 2002 by Christian Falckenberg
  9. * <christian.falckenberg@nortelnetworks.com>
  10. *
  11. * Christoph Wiest, 2003/06/28
  12. * Modified 2003 by Christoph Wiest
  13. * <ch.wiest@tesionmail.de>
  14. * Modified 2004 by Anders Broman
  15. * <anders.broman@ericsson.com>
  16. * To handle TPKT headers if over TCP
  17. * Modified 2005 by Karl Knoebl
  18. * <karl.knoebl@siemens.com>
  19. * provide info to COL_INFO and some "prettification"
  20. *
  21. * Copyright (c) 2006 Anders Broman <anders.broman@ericsson.com>
  22. *
  23. * Wireshark - Network traffic analyzer
  24. * By Gerald Combs <gerald@wireshark.org>
  25. * Copyright 1999 Gerald Combs
  26. *
  27. * This program is free software; you can redistribute it and/or
  28. * modify it under the terms of the GNU General Public License
  29. * as published by the Free Software Foundation; either version 2
  30. * of the License, or (at your option) any later version.
  31. *
  32. * This program is distributed in the hope that it will be useful,
  33. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  34. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  35. * GNU General Public License for more details.
  36. *
  37. * You should have received a copy of the GNU General Public License
  38. * along with this program; if not, write to the Free Software
  39. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  40. */
  41. #include "config.h"
  42. #include <stdlib.h>
  43. #include <ctype.h>
  44. #include <glib.h>
  45. #include <epan/packet.h>
  46. #include <epan/wmem/wmem.h>
  47. #include <epan/addr_resolv.h>
  48. #include <epan/prefs.h>
  49. #include <epan/strutil.h>
  50. #include <epan/sctpppids.h>
  51. #include <epan/dissectors/packet-tpkt.h>
  52. #include <epan/asn1.h>
  53. #include <epan/dissectors/packet-per.h>
  54. #include <epan/dissectors/packet-h245.h>
  55. #include <epan/dissectors/packet-ip.h>
  56. #include <epan/dissectors/packet-ber.h>
  57. #include <epan/gcp.h>
  58. #include <epan/tap.h>
  59. #define PORT_MEGACO_TXT 2944
  60. #define PORT_MEGACO_BIN 2945
  61. /* Define the megaco proto */
  62. static int proto_megaco = -1;
  63. /* Define headers for megaco */
  64. static int hf_megaco_version = -1;
  65. static int hf_megaco_transaction = -1;
  66. static int hf_megaco_transid = -1;
  67. static int hf_megaco_Context = -1;
  68. /* static int hf_megaco_command_line = -1; */
  69. static int hf_megaco_command = -1;
  70. static int hf_megaco_termid = -1;
  71. /* Define headers in subtree for megaco */
  72. static int hf_megaco_modem_descriptor = -1;
  73. static int hf_megaco_multiplex_descriptor = -1;
  74. /* static int hf_megaco_media_descriptor = -1; */
  75. /* static int hf_megaco_events_descriptor = -1; */
  76. /* static int hf_megaco_signal_descriptor = -1; */
  77. static int hf_megaco_audit_descriptor = -1;
  78. /* static int hf_megaco_servicechange_descriptor = -1; */
  79. static int hf_megaco_digitmap_descriptor = -1;
  80. static int hf_megaco_statistics_descriptor = -1;
  81. /* static int hf_megaco_observedevents_descriptor = -1; */
  82. static int hf_megaco_topology_descriptor = -1;
  83. static int hf_megaco_error_descriptor = -1;
  84. /* static int hf_megaco_TerminationState_descriptor= -1; */
  85. /* static int hf_megaco_Remote_descriptor = -1; */
  86. /* static int hf_megaco_Local_descriptor = -1; */
  87. /* static int hf_megaco_LocalControl_descriptor = -1; */
  88. static int hf_megaco_packages_descriptor = -1;
  89. static int hf_megaco_error_Frame = -1;
  90. static int hf_megaco_Service_State = -1;
  91. static int hf_megaco_Event_Buffer_Control = -1;
  92. static int hf_megaco_mode = -1;
  93. static int hf_megaco_reserve_group = -1;
  94. static int hf_megaco_h324_muxtbl_in = -1;
  95. static int hf_megaco_h324_muxtbl_out = -1;
  96. static int hf_megaco_ds_dscp = -1;
  97. static int hf_megaco_h324_h223capr = -1;
  98. static int hf_megaco_reserve_value = -1;
  99. static int hf_megaco_streamid = -1;
  100. static int hf_megaco_requestid = -1;
  101. static int hf_megaco_pkgdname = -1;
  102. static int hf_megaco_mId = -1;
  103. /* static int hf_megaco_h245 = -1; */
  104. static int hf_megaco_h223Capability = -1;
  105. static int hf_megaco_audititem = -1;
  106. /* Define the trees for megaco */
  107. static int ett_megaco = -1;
  108. static int ett_megaco_message = -1;
  109. static int ett_megaco_message_body = -1;
  110. static int ett_megaco_context = -1;
  111. static int ett_megaco_command_line = -1;
  112. static int ett_megaco_mediadescriptor = -1;
  113. static int ett_megaco_descriptors = -1;
  114. static int ett_megaco_TerminationState = -1;
  115. static int ett_megaco_Localdescriptor = -1;
  116. static int ett_megaco_Remotedescriptor = -1;
  117. static int ett_megaco_LocalControldescriptor = -1;
  118. static int ett_megaco_auditdescriptor = -1;
  119. static int ett_megaco_eventsdescriptor = -1;
  120. static int ett_megaco_observedeventsdescriptor = -1;
  121. static int ett_megaco_observedevent = -1;
  122. static int ett_megaco_packagesdescriptor = -1;
  123. static int ett_megaco_requestedevent = -1;
  124. static int ett_megaco_signalsdescriptor = -1;
  125. static int ett_megaco_requestedsignal = -1;
  126. static int ett_megaco_h245 = -1;
  127. static gcp_hf_ett_t megaco_ctx_ids = {{-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1}};
  128. static expert_field ei_megaco_errored_command = EI_INIT;
  129. static dissector_handle_t megaco_text_handle;
  130. static int megaco_tap = -1;
  131. /*
  132. * Here are the global variables associated with
  133. * the various user definable characteristics of the dissection
  134. *
  135. * MEGACO has two kinds of message formats: text and binary
  136. *
  137. * global_megaco_raw_text determines whether we are going to display
  138. * the raw text of the megaco message, much like the HTTP dissector does.
  139. *
  140. * global_megaco_dissect_tree determines whether we are going to display
  141. * a detailed tree that expresses a somewhat more semantically meaningful
  142. * decode.
  143. */
  144. static guint global_megaco_txt_sctp_port = PORT_MEGACO_TXT;
  145. static guint global_megaco_txt_tcp_port = PORT_MEGACO_TXT;
  146. static guint global_megaco_txt_udp_port = PORT_MEGACO_TXT;
  147. #if 0
  148. static guint global_megaco_bin_sctp_port = PORT_MEGACO_BIN;
  149. static guint global_megaco_bin_tcp_port = PORT_MEGACO_BIN;
  150. static guint global_megaco_bin_udp_port = PORT_MEGACO_BIN;
  151. #endif
  152. static gboolean global_megaco_raw_text = TRUE;
  153. static gboolean global_megaco_dissect_tree = TRUE;
  154. /* Some basic utility functions that are specific to this dissector */
  155. static gint megaco_tvb_skip_wsp(tvbuff_t* tvb, gint offset);
  156. static gint megaco_tvb_skip_wsp_return(tvbuff_t* tvb, gint offset);
  157. /*
  158. * The various functions that either dissect some
  159. * subpart of MEGACO. These aren't really proto dissectors but they
  160. * are written in the same style.
  161. *
  162. */
  163. static void
  164. dissect_megaco_descriptors(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_descriptors_start_offset, gint tvb_descriptors_end_offset);
  165. static void
  166. dissect_megaco_modemdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  167. static void
  168. dissect_megaco_multiplexdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  169. static void
  170. dissect_megaco_mediadescriptor(tvbuff_t *tvb, proto_tree *tree,packet_info *pinfo, gint tvb_RBRKT, gint tvb_previous_offset);
  171. static void
  172. dissect_megaco_eventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  173. static void
  174. dissect_megaco_signaldescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  175. static void
  176. dissect_megaco_auditdescriptor(tvbuff_t *tvb, proto_tree *tree,packet_info *pinfo, gint tvb_RBRKT, gint tvb_previous_offset);
  177. static void
  178. dissect_megaco_servicechangedescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  179. static void
  180. dissect_megaco_digitmapdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  181. static void
  182. dissect_megaco_statisticsdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  183. static void
  184. dissect_megaco_observedeventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  185. static void
  186. dissect_megaco_topologydescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  187. static void
  188. dissect_megaco_errordescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
  189. static void
  190. dissect_megaco_TerminationStatedescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_next_offset, gint tvb_current_offset);
  191. static void
  192. dissect_megaco_Localdescriptor(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset);
  193. static void
  194. dissect_megaco_LocalControldescriptor(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset);
  195. static void
  196. dissect_megaco_Packagesdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_next_offset, gint tvb_current_offset);
  197. static void
  198. tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
  199. static void
  200. dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
  201. static gint
  202. megaco_tvb_find_token(tvbuff_t* tvb, gint offset, gint maxlenght);
  203. static dissector_handle_t data_handle;
  204. static dissector_handle_t sdp_handle;
  205. static dissector_handle_t h245_handle;
  206. static dissector_handle_t h248_handle;
  207. static dissector_handle_t h248_otp_handle;
  208. static gboolean keep_persistent_data = FALSE;
  209. static proto_tree *top_tree;
  210. /*
  211. * dissect_megaco_text over TCP, there will be a TPKT header there
  212. *
  213. */
  214. static void dissect_megaco_text_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  215. {
  216. int lv_tpkt_len;
  217. /* This code is copied from the Q.931 dissector, some parts skipped.
  218. * Check whether this looks like a TPKT-encapsulated
  219. * MEGACO packet.
  220. *
  221. * The minimum length of a MEGACO message is 6?:
  222. * Re-assembly ?
  223. */
  224. lv_tpkt_len = is_tpkt(tvb, 6);
  225. if (lv_tpkt_len == -1) {
  226. /*
  227. * It's not a TPKT packet;
  228. * Is in MEGACO ?
  229. */
  230. dissect_megaco_text(tvb, pinfo, tree);
  231. }
  232. dissect_tpkt_encap(tvb, pinfo, tree, TRUE,
  233. megaco_text_handle);
  234. }
  235. #define ERRORTOKEN 1
  236. #define TRANSTOKEN 2
  237. #define REPLYTOKEN 3
  238. #define PENDINGTOKEN 4
  239. #define RESPONSEACKTOKEN 5
  240. typedef struct {
  241. const char *name;
  242. const char *compact_name;
  243. } megaco_tokens_t;
  244. static const megaco_tokens_t megaco_messageBody_names[] = {
  245. { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
  246. { "Error", "ER" }, /* 1 */
  247. { "Transaction", "T" }, /* 2 */
  248. { "Reply", "P" }, /* 3 */
  249. { "Pending", "PN" }, /* 4 */
  250. { "TransactionResponseAck", "K" }, /* 5 */
  251. };
  252. /* Returns index of megaco_tokens_t */
  253. static gint find_megaco_messageBody_names(tvbuff_t *tvb, int offset, guint header_len)
  254. {
  255. guint i;
  256. for (i = 1; i < array_length(megaco_messageBody_names); i++) {
  257. if (header_len == strlen(megaco_messageBody_names[i].name) &&
  258. tvb_strncaseeql(tvb, offset, megaco_messageBody_names[i].name, header_len) == 0)
  259. return i;
  260. if (megaco_messageBody_names[i].compact_name != NULL &&
  261. header_len == strlen(megaco_messageBody_names[i].compact_name) &&
  262. tvb_strncaseeql(tvb, offset, megaco_messageBody_names[i].compact_name, header_len) == 0)
  263. return i;
  264. }
  265. return -1;
  266. }
  267. static proto_item *
  268. my_proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
  269. gint start, gint length, const char *value)
  270. {
  271. proto_item *pi;
  272. pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
  273. if (!global_megaco_dissect_tree) {
  274. PROTO_ITEM_SET_HIDDEN(pi);
  275. }
  276. return(pi);
  277. }
  278. /*
  279. * dissect_megaco_text - The dissector for the MEGACO Protocol, using
  280. * text encoding.
  281. */
  282. static void
  283. dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  284. {
  285. gint tvb_len, len;
  286. gint tvb_offset,tvb_current_offset,tvb_previous_offset,tvb_next_offset,tokenlen;
  287. gint line_start_offset, ver_offset, ver_length, mId_offset, mId_length;
  288. gint tvb_command_start_offset, tvb_command_end_offset;
  289. gint tvb_descriptors_start_offset, tvb_descriptors_end_offset;
  290. gint tvb_transaction_end_offset;
  291. proto_tree *megaco_tree, *message_tree, *message_body_tree, *megaco_context_tree, *megaco_tree_command_line, *ti, *sub_ti;
  292. guint8 word[7];
  293. guint8 TermID[30];
  294. guint8 tempchar;
  295. gint tvb_RBRKT, tvb_LBRKT, RBRKT_counter, LBRKT_counter;
  296. guint token_index=0;
  297. guint32 dword;
  298. guchar needle;
  299. guint8 first;
  300. gcp_msg_t* msg = NULL;
  301. gcp_trx_t* trx = NULL;
  302. gcp_ctx_t* ctx = NULL;
  303. gcp_cmd_t* cmd = NULL;
  304. gcp_term_t* term = NULL;
  305. gcp_trx_type_t trx_type = GCP_TRX_NONE;
  306. guint32 trx_id = 0;
  307. guint32 ctx_id = 0;
  308. gcp_cmd_type_t cmd_type = GCP_CMD_NONE;
  309. gcp_wildcard_t wild_term = GCP_WILDCARD_NONE;
  310. proto_item *hidden_item;
  311. top_tree=tree;
  312. /* Initialize variables */
  313. tvb_len = tvb_length(tvb);
  314. megaco_tree = NULL;
  315. ti = NULL;
  316. tvb_offset = 0;
  317. tvb_next_offset = 0;
  318. RBRKT_counter = 0;
  319. LBRKT_counter = 0;
  320. /* Check if H.248 in otp(Erlang) internal format
  321. * XXX Needs improvement?
  322. * Ref:
  323. * http://www.erlang.org/doc/apps/megaco/part_frame.html
  324. * 4.1 Internal form of messages
  325. * 4.2 The different encodings
  326. */
  327. dword = tvb_get_ntoh24(tvb,0);
  328. if ((dword == 0x836803)&&(h248_otp_handle)){
  329. call_dissector(h248_otp_handle, tvb, pinfo, tree);
  330. return;
  331. }
  332. msg = gcp_msg(pinfo, tvb_raw_offset(tvb), keep_persistent_data);
  333. /*
  334. * Check to see whether we're really dealing with MEGACO by looking
  335. * for the "MEGACO" string or a "!".This needs to be improved when supporting
  336. * binary encodings. Bugfix add skipping of leading spaces.
  337. */
  338. tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
  339. line_start_offset = tvb_offset;
  340. /* Quick fix for MEGACO not following the RFC, hopefully not breaking any thing
  341. * Turned out to be TPKT in case of TCP, added some code to handle that.
  342. *
  343. * tvb_offset = tvb_find_guint8(tvb, tvb_offset, 5, 'M');
  344. */
  345. if(!tvb_get_nstringz0(tvb,tvb_offset,sizeof(word),word)) return;
  346. if (g_ascii_strncasecmp(word, "MEGACO", 6) != 0 && tvb_get_guint8(tvb, tvb_offset ) != '!'){
  347. gint8 ber_class;
  348. gboolean pc;
  349. gint32 tag;
  350. dissector_handle_t handle = data_handle;
  351. get_ber_identifier(tvb, 0, &ber_class, &pc, &tag);
  352. if (ber_class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE ) {
  353. handle = h248_handle;
  354. }
  355. call_dissector(handle,tvb,pinfo,tree);
  356. return;
  357. }
  358. /* Display MEGACO in protocol column */
  359. col_set_str(pinfo->cinfo, COL_PROTOCOL, "MEGACO");
  360. /* Build the info tree if we've been given a root */
  361. /* Create megaco subtree */
  362. ti = proto_tree_add_item(tree,proto_megaco,tvb, 0, -1, ENC_NA);
  363. megaco_tree = proto_item_add_subtree(ti, ett_megaco);
  364. /* Format of 'message' is = MegacopToken SLASH Version SEP mId SEP messageBody */
  365. /* MegacopToken = "MEGACO" or "!" */
  366. /* According to H248.1-200205 Annex B Text encoding ( protocol version 2 ) */
  367. /* Find version */
  368. tvb_previous_offset = tvb_find_guint8(tvb, 0,
  369. tvb_len, '/');
  370. if (tvb_previous_offset == -1) {
  371. expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
  372. "Sorry, no \"/\" in the MEGACO header, I can't parse this packet");
  373. return;
  374. }
  375. /* skip / */
  376. tvb_previous_offset++;
  377. /* assume at least one digit in version */
  378. tvb_current_offset = tvb_previous_offset + 1;
  379. if (isdigit(tvb_get_guint8(tvb, tvb_current_offset))) {
  380. /* 2-digit version */
  381. tvb_current_offset++;
  382. }
  383. tokenlen = tvb_current_offset - tvb_previous_offset;
  384. ver_offset = tvb_previous_offset;
  385. ver_length = tokenlen;
  386. tvb_previous_offset = tvb_current_offset;
  387. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
  388. if (tvb_previous_offset == tvb_current_offset) {
  389. expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
  390. "[ Parse error: missing SEP in MEGACO header ]");
  391. return;
  392. }
  393. tvb_previous_offset = tvb_current_offset;
  394. /* mId should follow here,
  395. * mId = (( domainAddress / domainName ) [":" portNumber]) / mtpAddress / deviceName
  396. * domainAddress = "[" (IPv4address / IPv6address) "]"
  397. * domainName = "<" (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" /".") ">"
  398. * mtpAddress = MTPToken LBRKT 4*8 (HEXDIG) RBRKT
  399. * MTPToken = ("MTP")
  400. * deviceName = pathNAME
  401. * pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )["@" pathDomainName ]
  402. */
  403. tvb_current_offset = tvb_pbrk_guint8(tvb, tvb_current_offset, -1, " \t\r\n", &needle);
  404. if (tvb_current_offset == -1) {
  405. expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
  406. "[ Parse error: no body in MEGACO message (missing SEP after mId) ]");
  407. return;
  408. }
  409. tokenlen = tvb_current_offset - tvb_previous_offset;
  410. tvb_next_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset);
  411. /* At this point we should point to the "\n" ending the mId element
  412. * or to the next character after white space SEP
  413. */
  414. mId_offset = tvb_previous_offset;
  415. mId_length = tokenlen;
  416. /* Add the first line to the tree */
  417. tokenlen = tvb_next_offset - line_start_offset - 1;
  418. ti = proto_tree_add_text(megaco_tree, tvb, line_start_offset, tokenlen,
  419. "%s",tvb_format_text(tvb,line_start_offset,tokenlen));
  420. message_tree = proto_item_add_subtree(ti, ett_megaco_message);
  421. if (tree){
  422. if(global_megaco_dissect_tree){
  423. proto_tree_add_item(message_tree, hf_megaco_version,tvb, ver_offset, ver_length, ENC_ASCII|ENC_NA);
  424. proto_tree_add_item(message_tree, hf_megaco_mId,tvb, mId_offset, mId_length, ENC_ASCII|ENC_NA);
  425. }else{
  426. hidden_item = proto_tree_add_item(message_tree, hf_megaco_version,tvb, ver_offset, ver_length, ENC_ASCII|ENC_NA);
  427. PROTO_ITEM_SET_HIDDEN(hidden_item);
  428. hidden_item = proto_tree_add_item(message_tree, hf_megaco_mId,tvb, mId_offset, mId_length, ENC_ASCII|ENC_NA);
  429. PROTO_ITEM_SET_HIDDEN(hidden_item);
  430. }
  431. }
  432. col_clear(pinfo->cinfo, COL_INFO);
  433. first = 1;
  434. do{
  435. tvb_previous_offset = tvb_next_offset;
  436. /* Next part is
  437. * : messageBody = ( errorDescriptor / transactionList )
  438. * errorDescriptor = ErrorToken EQUAL ErrorCode LBRKT [quotedString] RBRKT
  439. * ErrorToken = ("Error" / "ER")
  440. *
  441. * transactionList = 1*( transactionRequest / transactionReply /
  442. * transactionPending / transactionResponseAck )
  443. *
  444. * transactionResponseAck = ResponseAckToken LBRKT
  445. * transactionAck*(COMMA transactionAck) RBRKT
  446. * ResponseAckToken = ("TransactionResponseAck"/ "K")
  447. *
  448. * transactionPending = PendingToken EQUAL TransactionID LBRKT RBRKT
  449. * PendingToken = ("Pending" / "PN")
  450. *
  451. * transactionReply = ReplyToken EQUAL TransactionID LBRKT
  452. * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
  453. * ReplyToken = ("Reply" / "P")
  454. *
  455. * transactionRequest = TransToken EQUAL TransactionID LBRKT
  456. * actionRequest *(COMMA actionRequest) RBRKT
  457. * TransToken = ("Transaction" / "T")
  458. */
  459. /* Find token length */
  460. for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_len-1; tvb_offset++){
  461. if (!isalpha(tvb_get_guint8(tvb, tvb_offset ))){
  462. break;
  463. }
  464. }
  465. tokenlen = tvb_offset - tvb_previous_offset;
  466. token_index = find_megaco_messageBody_names(tvb, tvb_previous_offset, tokenlen);
  467. /* Debug code
  468. g_warning("token_index %u",token_index);
  469. */
  470. tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_len, '{');
  471. tvb_current_offset = tvb_LBRKT;
  472. tvb_transaction_end_offset = megaco_tvb_find_token(tvb, tvb_LBRKT - 1, tvb_len);
  473. switch ( token_index ){
  474. /* errorDescriptor */
  475. case ERRORTOKEN:
  476. col_set_str(pinfo->cinfo, COL_INFO, "Error ");
  477. tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_len); /*tvb_find_guint8(tvb, tvb_offset+1, tvb_len, '}');*/
  478. ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset,
  479. "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset));
  480. message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
  481. if (tree) {
  482. my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
  483. tvb_previous_offset, tokenlen,
  484. "Error" );
  485. tvb_command_start_offset = tvb_previous_offset;
  486. dissect_megaco_errordescriptor(tvb, megaco_tree, tvb_len-1, tvb_command_start_offset);
  487. }
  488. return;
  489. /* transactionResponseAck
  490. * transactionResponseAck = ResponseAckToken LBRKT transactionAck
  491. * *(COMMA transactionAck) RBRKT
  492. * transactionAck = transactionID / (transactionID "-" transactionID)
  493. */
  494. case RESPONSEACKTOKEN:
  495. tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
  496. tvb_offset = tvb_LBRKT;
  497. ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_offset-tvb_previous_offset,
  498. "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_offset-tvb_previous_offset+1));
  499. message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
  500. my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
  501. tvb_previous_offset, tokenlen,
  502. "TransactionResponseAck" );
  503. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1);
  504. tvb_current_offset = tvb_find_guint8(tvb, tvb_offset+1, tvb_len, '}');
  505. /*tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_transaction_end_offset);*/
  506. tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset)-1; /* cut last RBRKT */
  507. len = tvb_current_offset - tvb_previous_offset;
  508. if (!first) {
  509. col_append_str(pinfo->cinfo, COL_INFO, " ");
  510. }
  511. col_append_fstr(pinfo->cinfo, COL_INFO, "%s TransactionResponseAck",
  512. tvb_format_text(tvb,tvb_previous_offset,len));
  513. if(tree)
  514. my_proto_tree_add_string(message_body_tree, hf_megaco_transid, tvb,
  515. tvb_previous_offset, len,
  516. tvb_format_text(tvb,tvb_previous_offset,len));
  517. if(global_megaco_raw_text){
  518. tvb_raw_text_add(tvb, megaco_tree);
  519. }
  520. return;
  521. /* Pe and PN is transactionPending, P+"any char" is transactionReply */
  522. case PENDINGTOKEN:
  523. tvb_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '=')+1;
  524. tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
  525. tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
  526. tvb_current_offset = tvb_LBRKT;
  527. ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset,
  528. "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset+1));
  529. message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
  530. tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1);
  531. len = tvb_current_offset - tvb_offset;
  532. if (tree)
  533. my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
  534. tvb_previous_offset, tokenlen,
  535. "Pending" );
  536. if (!first) {
  537. col_append_str(pinfo->cinfo, COL_INFO, " ");
  538. }
  539. col_append_fstr(pinfo->cinfo, COL_INFO, "%s Pending",
  540. tvb_format_text(tvb,tvb_offset,len));
  541. if(tree)
  542. my_proto_tree_add_string(message_body_tree, hf_megaco_transid, tvb,
  543. tvb_offset, len,
  544. tvb_format_text(tvb,tvb_offset,len));
  545. return;
  546. /* transactionReply */
  547. case REPLYTOKEN:
  548. trx_type = GCP_TRX_REPLY;
  549. tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
  550. ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_LBRKT-tvb_previous_offset,
  551. "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_LBRKT-tvb_previous_offset+1));
  552. message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
  553. if (tree)
  554. my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
  555. tvb_previous_offset, tokenlen,
  556. "Reply" );
  557. tvb_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '=')+1;
  558. tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
  559. tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_LBRKT-1);
  560. len = tvb_current_offset - tvb_offset;
  561. col_add_fstr(pinfo->cinfo, COL_INFO, "%s Reply ",
  562. tvb_format_text(tvb,tvb_offset,len));
  563. trx_id = (guint)strtoul(tvb_format_text(tvb,tvb_offset,len),NULL,10);
  564. if(tree)
  565. my_proto_tree_add_string(message_body_tree, hf_megaco_transid, tvb,
  566. tvb_offset, len, tvb_format_text(tvb,tvb_offset,len));
  567. /* Find if we have a errorDescriptor or actionReplyList */
  568. tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
  569. tempchar = tvb_get_guint8(tvb,tvb_offset);
  570. if ((tempchar == 'E')||(tempchar == 'e')){
  571. dissect_megaco_errordescriptor(tvb, megaco_tree, tvb_transaction_end_offset-1, tvb_offset);
  572. return;
  573. }
  574. /* Offset should be at first printable char after { */
  575. tvb_previous_offset = tvb_offset;
  576. break;
  577. case TRANSTOKEN:
  578. /* TransactionRequest */
  579. trx_type = GCP_TRX_REQUEST;
  580. ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset,
  581. "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset+1));
  582. message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
  583. if(tree)
  584. my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
  585. tvb_previous_offset, tokenlen,
  586. "Request" );
  587. tvb_offset = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '=')+1;
  588. tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
  589. tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1);
  590. len = tvb_current_offset - tvb_offset;
  591. if (!first) {
  592. col_append_str(pinfo->cinfo, COL_INFO, " ");
  593. }
  594. col_append_fstr(pinfo->cinfo, COL_INFO, "%s Request",
  595. tvb_format_text(tvb,tvb_offset,len));
  596. trx_id = (guint)strtoul(tvb_format_text(tvb,tvb_offset,len),NULL,10);
  597. if(tree)
  598. my_proto_tree_add_string(message_body_tree, hf_megaco_transid, tvb, tvb_offset,len,
  599. tvb_format_text(tvb,tvb_offset,len));
  600. /* Offset should be at first printable char after { */
  601. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
  602. break;
  603. default :
  604. ti = proto_tree_add_item(tree,proto_megaco,tvb, 0, -1, ENC_NA);
  605. expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
  606. "Sorry, can't understand errorDescriptor / transactionList = %s, can't parse it pos %u",
  607. tvb_format_text(tvb,tvb_previous_offset,2),tvb_previous_offset);
  608. return;
  609. } /* end switch */
  610. /* Only these remains now
  611. * transactionReply = ReplyToken EQUAL TransactionID LBRKT
  612. * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
  613. * ReplyToken = ("Reply" / "P")
  614. *
  615. * errorDescriptor = ErrorToken EQUAL ErrorCode
  616. * LBRKT [quotedString] RBRKT
  617. *
  618. * transactionRequest = TransToken EQUAL TransactionID LBRKT
  619. * actionRequest *(COMMA actionRequest) RBRKT
  620. * TransToken = ("Transaction" / "T")
  621. */
  622. trx = gcp_trx(msg , trx_id , trx_type, keep_persistent_data);
  623. /* Find Context */
  624. nextcontext:
  625. tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '{');
  626. ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_next_offset-tvb_previous_offset+1,
  627. "%s", tvb_format_text(tvb, tvb_previous_offset, tvb_next_offset-tvb_previous_offset+1));
  628. megaco_context_tree = proto_item_add_subtree(ti, ett_megaco_context);
  629. tvb_previous_offset = tvb_find_guint8(tvb, tvb_current_offset,
  630. tvb_transaction_end_offset, '=')+1;
  631. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
  632. if (tvb_current_offset >= tvb_next_offset) {
  633. expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "[ Parse error: Invalid offset ]");
  634. return;
  635. }
  636. tvb_current_offset = tvb_next_offset;
  637. tokenlen = tvb_current_offset - tvb_previous_offset;
  638. tempchar = tvb_get_guint8(tvb, tvb_previous_offset );
  639. if (tvb_get_guint8(tvb, tvb_current_offset-1 ) == ' '){
  640. tokenlen--;
  641. }
  642. switch ( tempchar ){
  643. case '$':
  644. ctx_id = CHOOSE_CONTEXT;
  645. my_proto_tree_add_string(megaco_context_tree, hf_megaco_Context, tvb,
  646. tvb_previous_offset, 1,
  647. "Choose one");
  648. col_append_str(pinfo->cinfo, COL_INFO, " |=Choose one");
  649. break;
  650. case '*':
  651. ctx_id = ALL_CONTEXTS;
  652. my_proto_tree_add_string(megaco_context_tree, hf_megaco_Context, tvb,
  653. tvb_previous_offset, 1,
  654. "All");
  655. col_append_str(pinfo->cinfo, COL_INFO, " |=All");
  656. break;
  657. case '-':
  658. ctx_id = NULL_CONTEXT;
  659. proto_tree_add_text(megaco_context_tree, tvb, tvb_previous_offset, tokenlen, "Context: NULL" );
  660. col_append_str(pinfo->cinfo, COL_INFO, " |=NULL");
  661. break;
  662. default:
  663. my_proto_tree_add_string(megaco_context_tree, hf_megaco_Context, tvb,
  664. tvb_previous_offset, tokenlen,
  665. tvb_format_text(tvb, tvb_previous_offset,
  666. tokenlen));
  667. ctx_id = (guint)strtoul(tvb_format_text(tvb, tvb_previous_offset, tokenlen),NULL,10);
  668. col_append_fstr(pinfo->cinfo, COL_INFO, " |=%s",tvb_format_text(tvb, tvb_previous_offset,tokenlen));
  669. }
  670. ctx = gcp_ctx(msg,trx,ctx_id,keep_persistent_data);
  671. /* Find Commands */
  672. /* If Transaction is is Request, Reply or Pending */
  673. tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
  674. tvb_command_end_offset = tvb_command_start_offset;
  675. tvb_LBRKT = tvb_command_start_offset;
  676. tvb_RBRKT = tvb_command_start_offset;
  677. /* The following loop find the individual contexts, commands and call the for every Descriptor a subroutine */
  678. do {
  679. tvb_command_end_offset = tvb_find_guint8(tvb, tvb_command_end_offset +1,
  680. tvb_transaction_end_offset, ',');
  681. if ( tvb_command_end_offset == -1 || tvb_command_end_offset > tvb_transaction_end_offset){
  682. tvb_command_end_offset = tvb_transaction_end_offset ;
  683. }
  684. /* checking how many left brackets are before the next comma */
  685. while ( tvb_find_guint8(tvb, tvb_LBRKT+1,tvb_transaction_end_offset, '{') != -1
  686. && (tvb_find_guint8(tvb, tvb_LBRKT+1,tvb_transaction_end_offset, '{') < tvb_command_end_offset)){
  687. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
  688. tvb_transaction_end_offset, '{');
  689. LBRKT_counter++;
  690. }
  691. /* checking how many right brackets are before the next comma */
  692. while ( (tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_transaction_end_offset, '}') != -1 )
  693. && (tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_transaction_end_offset, '}') <= tvb_command_end_offset)
  694. && LBRKT_counter != 0){
  695. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  696. tvb_transaction_end_offset, '}');
  697. RBRKT_counter++;
  698. }
  699. /* If equal or more right brackets before the comma, one command is complete */
  700. if ( LBRKT_counter <= RBRKT_counter ){
  701. tvb_current_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
  702. tvb_transaction_end_offset, '{');
  703. /* includes no descriptors */
  704. if ( LBRKT_counter == 0 ){
  705. tvb_current_offset = tvb_command_end_offset;
  706. /* the last command in a context */
  707. if ( tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}') < tvb_current_offset
  708. && tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}') != -1){
  709. tvb_previous_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
  710. tvb_transaction_end_offset, '}');
  711. len = tvb_previous_offset - tvb_command_start_offset;
  712. tvb_previous_offset = megaco_tvb_skip_wsp_return(tvb, tvb_previous_offset -1);
  713. tokenlen = tvb_previous_offset - tvb_command_start_offset;
  714. }
  715. /* not the last command in a context*/
  716. else{
  717. len = tvb_current_offset - tvb_command_start_offset;
  718. tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset -1);
  719. tokenlen = tvb_current_offset - tvb_command_start_offset;
  720. }
  721. }
  722. /* command includes descriptors */
  723. else{
  724. len = tvb_current_offset - tvb_command_start_offset;
  725. tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset -1);
  726. tokenlen = tvb_current_offset - tvb_command_start_offset;
  727. }
  728. /* if a next context is specified */
  729. if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'C'){
  730. tvb_current_offset = tvb_command_start_offset;
  731. tvb_previous_offset = tvb_command_start_offset;
  732. LBRKT_counter = 0;
  733. RBRKT_counter = 0;
  734. goto nextcontext;
  735. }
  736. sub_ti = proto_tree_add_text(megaco_tree, tvb, tvb_command_start_offset, len+1,
  737. "%s", tvb_format_text(tvb, tvb_command_start_offset, len+1));
  738. megaco_tree_command_line = proto_item_add_subtree(sub_ti, ett_megaco_command_line);
  739. /* creation of the megaco_tree_command_line additionally Command and Transaction ID will be printed in this line */
  740. /* Changed to use the lines above. this code is saved if there is complaints
  741. sub_ti = proto_tree_add_item(megaco_tree,hf_megaco_command_line,tvb,tvb_command_start_offset,tokenlen, ENC_ASCII|ENC_NA);
  742. megaco_tree_command_line = proto_item_add_subtree(sub_ti, ett_megaco_command_line);
  743. */
  744. tvb_next_offset = tvb_command_start_offset + tokenlen;
  745. /* Try to dissect Topology Descriptor before the command */
  746. tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
  747. if ( (tempchar >= 'a')&& (tempchar <= 'z')){
  748. tempchar = tempchar - 0x20;
  749. }
  750. if ( tempchar == 'T') {
  751. tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
  752. if ( (tempchar >= 'a')&& (tempchar <= 'z'))
  753. tempchar = tempchar - 0x20;
  754. if ( tempchar == 'P' || tempchar == 'O'){
  755. gint tvb_topology_end_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}');
  756. if ( tvb_topology_end_offset == -1 ){
  757. expert_add_info_format(pinfo, sub_ti, PI_MALFORMED, PI_ERROR, "[ Parse error: Missing \"}\" ]");
  758. return;
  759. }
  760. tvb_command_start_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{');
  761. if ( tvb_command_start_offset == -1 ){
  762. expert_add_info_format(pinfo, sub_ti, PI_MALFORMED, PI_ERROR, "[ Parse error: Missing \"{\" ]");
  763. return;
  764. }
  765. dissect_megaco_topologydescriptor(tvb, megaco_tree_command_line, tvb_topology_end_offset-1, tvb_command_start_offset+1);
  766. /* Command after Topology Descriptor */
  767. tvb_command_start_offset = tvb_find_guint8(tvb, tvb_topology_end_offset + 1,
  768. tvb_transaction_end_offset, ',');
  769. if ( tvb_command_start_offset == -1 ){
  770. /* No Command present after Topology Descriptor */
  771. break;
  772. } else {
  773. /* Try to find the first char of the command */
  774. tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_command_start_offset + 1);
  775. tvb_next_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{');
  776. continue;
  777. }
  778. }
  779. }
  780. /* Additional value */
  781. if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'O'){
  782. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_command_start_offset, 2, "O- indicates an optional command" );
  783. tvb_command_start_offset = tvb_command_start_offset+2;
  784. }
  785. /* Additional value */
  786. if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'W'){
  787. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_command_start_offset, 2, "W- indicates a wildcarded response to a command" );
  788. tvb_command_start_offset = tvb_command_start_offset+2;
  789. }
  790. tvb_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
  791. tvb_transaction_end_offset, '=');
  792. if (tvb_offset == -1 ) {
  793. expert_add_info_format(pinfo, sub_ti, PI_MALFORMED, PI_ERROR, "[ Parse error: Missing \"=\" ]");
  794. return;
  795. }
  796. tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_offset -1);
  797. tokenlen = tvb_offset - tvb_command_start_offset;
  798. tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
  799. if ( (tempchar >= 'a')&& (tempchar <= 'z'))
  800. tempchar = tempchar - 0x20;
  801. if ( tempchar != 'E' ){
  802. /* Short form used */
  803. if ( tvb_get_guint8(tvb, 0 ) == '!'){
  804. switch ( tempchar ){
  805. case 'A':
  806. tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
  807. if ( (tempchar >= 'a')&& (tempchar <= 'z'))
  808. tempchar = tempchar - 0x20;
  809. switch ( tempchar ){
  810. case 'V':
  811. switch(trx_type) {
  812. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITVAL_REPLY; break;
  813. case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITVAL_REQ; break;
  814. default: cmd_type = GCP_CMD_NONE; break;
  815. }
  816. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  817. tvb_command_start_offset, tokenlen,
  818. "AuditValue");
  819. col_append_str(pinfo->cinfo, COL_INFO, " AuditValue");
  820. break;
  821. case 'C':
  822. switch(trx_type) {
  823. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITCAP_REQ; break;
  824. case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITCAP_REPLY; break;
  825. default: cmd_type = GCP_CMD_NONE; break;
  826. }
  827. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  828. tvb_command_start_offset, tokenlen,
  829. "AuditCapability");
  830. col_append_str(pinfo->cinfo, COL_INFO, " AuditCapability");
  831. break;
  832. default:
  833. switch(trx_type) {
  834. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_ADD_REQ; break;
  835. case GCP_TRX_REPLY: cmd_type = GCP_CMD_ADD_REPLY; break;
  836. default: cmd_type = GCP_CMD_NONE; break;
  837. }
  838. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  839. tvb_command_start_offset, tokenlen,
  840. "Add");
  841. col_append_str(pinfo->cinfo, COL_INFO, " Add");
  842. break;
  843. }
  844. break;
  845. case 'N':
  846. switch(trx_type) {
  847. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_NOTIFY_REQ; break;
  848. case GCP_TRX_REPLY: cmd_type = GCP_CMD_NOTIFY_REPLY; break;
  849. default: cmd_type = GCP_CMD_NONE; break;
  850. }
  851. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  852. tvb_command_start_offset, tokenlen,
  853. "Notify");
  854. col_append_str(pinfo->cinfo, COL_INFO, " Notify");
  855. break;
  856. case 'M':
  857. tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
  858. if ( (tempchar >= 'a')&& (tempchar <= 'z'))
  859. tempchar = tempchar - 0x20;
  860. switch ( tempchar ){
  861. case 'F':
  862. switch(trx_type) {
  863. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOD_REQ; break;
  864. case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOD_REPLY; break;
  865. default: cmd_type = GCP_CMD_NONE; break;
  866. }
  867. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  868. tvb_command_start_offset, tokenlen,
  869. "Modify");
  870. col_append_str(pinfo->cinfo, COL_INFO, " Modify");
  871. break;
  872. case 'V':
  873. switch(trx_type) {
  874. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOVE_REQ; break;
  875. case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOVE_REPLY; break;
  876. default: cmd_type = GCP_CMD_NONE; break;
  877. }
  878. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  879. tvb_command_start_offset, tokenlen,
  880. "Move");
  881. col_append_str(pinfo->cinfo, COL_INFO, " Move");
  882. break;
  883. }
  884. break;
  885. case 'P':
  886. cmd_type = GCP_CMD_NONE;
  887. /*
  888. PackagesToken = ("Packages" / "PG")
  889. PendingToken = ("Pending" / "PN")
  890. PriorityToken = ("Priority" / "PR")
  891. ProfileToken = ("Profile" / "PF")
  892. */
  893. tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
  894. if ( (tempchar >= 'a')&& (tempchar <= 'z'))
  895. tempchar = tempchar - 0x20;
  896. switch ( tempchar ){
  897. case 'G':
  898. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  899. tvb_command_start_offset, tokenlen,
  900. "Packages");
  901. break;
  902. case 'N':
  903. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  904. tvb_command_start_offset, tokenlen,
  905. "Pending");
  906. break;
  907. case 'R':
  908. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  909. tvb_command_start_offset, tokenlen,
  910. "Priority");
  911. break;
  912. case 'F':
  913. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  914. tvb_command_start_offset, tokenlen,
  915. "Profile");
  916. break;
  917. }
  918. break;
  919. case 'S':
  920. tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
  921. if ( (tempchar >= 'a')&& (tempchar <= 'z'))
  922. tempchar = tempchar - 0x20;
  923. switch ( tempchar ){
  924. case 'C':
  925. switch(trx_type) {
  926. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SVCCHG_REQ; break;
  927. case GCP_TRX_REPLY: cmd_type = GCP_CMD_SVCCHG_REPLY; break;
  928. default: cmd_type = GCP_CMD_NONE; break;
  929. }
  930. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  931. tvb_command_start_offset, tokenlen,
  932. "ServiceChange");
  933. break;
  934. default:
  935. switch(trx_type) {
  936. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
  937. case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
  938. default: cmd_type = GCP_CMD_NONE; break;
  939. }
  940. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  941. tvb_command_start_offset, tokenlen,
  942. "Subtract");
  943. col_append_str(pinfo->cinfo, COL_INFO, " Subtract");
  944. break;
  945. }
  946. break;
  947. default:
  948. {
  949. proto_item *item;
  950. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  951. tvb_ensure_bytes_exist(tvb, tvb_previous_offset, tokenlen);
  952. item = proto_tree_add_string(megaco_tree, hf_megaco_error_Frame, tvb,
  953. tvb_previous_offset, tokenlen,
  954. "No Command detectable !");
  955. proto_item_append_text(item,"[ tempchar 0x%x ]", tempchar);
  956. return;
  957. }
  958. }
  959. }
  960. else{
  961. gchar* command = tvb_format_text(tvb, tvb_command_start_offset, tokenlen);
  962. if ( g_str_equal(command,"Subtract") ) {
  963. switch(trx_type) {
  964. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
  965. case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
  966. default: cmd_type = GCP_CMD_NONE; break;
  967. }
  968. } else if ( g_str_equal(command,"AuditValue") ) {
  969. switch(trx_type) {
  970. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITVAL_REPLY; break;
  971. case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITVAL_REQ; break;
  972. default: cmd_type = GCP_CMD_NONE; break;
  973. }
  974. } else if ( g_str_equal(command,"AuditCapability") ) {
  975. switch(trx_type) {
  976. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITCAP_REQ; break;
  977. case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITCAP_REPLY; break;
  978. default: cmd_type = GCP_CMD_NONE; break;
  979. }
  980. } else if ( g_str_equal(command,"Add") ) {
  981. switch(trx_type) {
  982. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_ADD_REQ; break;
  983. case GCP_TRX_REPLY: cmd_type = GCP_CMD_ADD_REPLY; break;
  984. default: cmd_type = GCP_CMD_NONE; break;
  985. }
  986. } else if ( g_str_equal(command,"Notify") ) {
  987. switch(trx_type) {
  988. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_NOTIFY_REQ; break;
  989. case GCP_TRX_REPLY: cmd_type = GCP_CMD_NOTIFY_REPLY; break;
  990. default: cmd_type = GCP_CMD_NONE; break;
  991. }
  992. } else if ( g_str_equal(command,"Modify") ) {
  993. switch(trx_type) {
  994. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOD_REQ; break;
  995. case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOD_REPLY; break;
  996. default: cmd_type = GCP_CMD_NONE; break;
  997. }
  998. } else if ( g_str_equal(command,"Move") ) {
  999. switch(trx_type) {
  1000. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOVE_REQ; break;
  1001. case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOVE_REPLY; break;
  1002. default: cmd_type = GCP_CMD_NONE; break;
  1003. }
  1004. } else if ( g_str_equal(command,"ServiceChange") ) {
  1005. switch(trx_type) {
  1006. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SVCCHG_REQ; break;
  1007. case GCP_TRX_REPLY: cmd_type = GCP_CMD_SVCCHG_REPLY; break;
  1008. default: cmd_type = GCP_CMD_NONE; break;
  1009. }
  1010. } else if ( g_str_equal(command,"Subtract") ) {
  1011. switch(trx_type) {
  1012. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
  1013. case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
  1014. default: cmd_type = GCP_CMD_NONE; break;
  1015. }
  1016. } else {
  1017. switch(trx_type) {
  1018. case GCP_TRX_REQUEST: cmd_type = GCP_CMD_OTHER_REQ; break;
  1019. case GCP_TRX_REPLY: cmd_type = GCP_CMD_REPLY; break;
  1020. default: cmd_type = GCP_CMD_NONE; break;
  1021. }
  1022. }
  1023. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
  1024. tvb_command_start_offset, tokenlen,
  1025. tvb_format_text(tvb, tvb_command_start_offset,
  1026. tokenlen));
  1027. col_append_fstr(pinfo->cinfo, COL_INFO, " %s",command);
  1028. }
  1029. if (cmd_type == GCP_CMD_NONE && trx_type == GCP_TRX_REPLY) {
  1030. cmd_type = GCP_CMD_REPLY;
  1031. }
  1032. if (cmd_type != GCP_CMD_NONE) {
  1033. cmd = gcp_cmd(msg, trx, ctx, cmd_type, tvb_command_start_offset, keep_persistent_data);
  1034. tap_queue_packet(megaco_tap, pinfo, cmd);
  1035. }
  1036. tvb_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
  1037. tvb_transaction_end_offset, '=');
  1038. if (tvb_offset == -1 ) {
  1039. expert_add_info_format(pinfo, sub_ti, PI_MALFORMED, PI_ERROR, "[ Parse error: Missing \"=\" ]");
  1040. return;
  1041. }
  1042. tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1);
  1043. tokenlen = tvb_next_offset - tvb_offset;
  1044. if (tokenlen+1 <= 0) {
  1045. expert_add_info_format(pinfo, sub_ti, PI_MALFORMED, PI_ERROR, "[ Parse error: Invalid token length (%d) ]", tokenlen+1);
  1046. return;
  1047. }
  1048. tempchar = tvb_get_guint8(tvb, tvb_offset);
  1049. if ( (tempchar >= 'a')&& (tempchar <= 'z'))
  1050. tempchar = tempchar - 0x20;
  1051. term = wmem_new0(wmem_packet_scope(), gcp_term_t);
  1052. wild_term = GCP_WILDCARD_NONE;
  1053. term->type = GCP_TERM_TYPE_UNKNOWN;
  1054. switch ( tempchar ){
  1055. case 'E':
  1056. if ((tokenlen+1 > (int) sizeof(TermID))) {
  1057. expert_add_info_format(pinfo, sub_ti, PI_MALFORMED, PI_ERROR, "[ Parse error: Invalid TermID length (%d) ]", tokenlen+1);
  1058. return;
  1059. }
  1060. tvb_get_nstringz0(tvb,tvb_offset,tokenlen+1,TermID);
  1061. TermID[0] = 'e';
  1062. term->len = tokenlen;
  1063. term->str = (const gchar*)(term->buffer = TermID);
  1064. gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
  1065. /*** TERM ***/
  1066. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
  1067. tvb_offset, tokenlen,
  1068. TermID);
  1069. break;
  1070. case '*':
  1071. wild_term = GCP_WILDCARD_ALL;
  1072. term->len = 1;
  1073. term->buffer = (const guint8*)(term->str = "*");
  1074. gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
  1075. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
  1076. tvb_offset, tokenlen,
  1077. "WildCard all");
  1078. col_append_str(pinfo->cinfo, COL_INFO, "=*");
  1079. break;
  1080. case '$':
  1081. wild_term = GCP_WILDCARD_CHOOSE;
  1082. term->len = 1;
  1083. term->buffer = (term->str = "$");
  1084. gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
  1085. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
  1086. tvb_offset, tokenlen,
  1087. "WildCard any");
  1088. col_append_str(pinfo->cinfo, COL_INFO, "=$");
  1089. break;
  1090. default:
  1091. /*** TERM ***/
  1092. my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
  1093. tvb_offset, tokenlen,
  1094. tvb_format_text(tvb, tvb_offset,
  1095. tokenlen));
  1096. term->len = tokenlen;
  1097. term->buffer = (const guint8*)(term->str = tvb_format_text(tvb, tvb_offset, tokenlen));
  1098. gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
  1099. col_append_fstr(pinfo->cinfo, COL_INFO, "=%s",tvb_format_text(tvb, tvb_offset,tokenlen));
  1100. break;
  1101. }
  1102. }
  1103. /* Dissect the Descriptors */
  1104. if ( LBRKT_counter != 0 && tvb_current_offset != tvb_command_end_offset){
  1105. tvb_descriptors_start_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
  1106. tvb_transaction_end_offset, '{');
  1107. tvb_descriptors_end_offset = tvb_descriptors_start_offset;
  1108. if ( tvb_descriptors_end_offset > tvb_transaction_end_offset )
  1109. tvb_descriptors_end_offset = tvb_transaction_end_offset;
  1110. while ( LBRKT_counter > 0 ){
  1111. tvb_descriptors_end_offset = tvb_find_guint8(tvb, tvb_descriptors_end_offset+1,
  1112. tvb_transaction_end_offset, '}');
  1113. LBRKT_counter--;
  1114. }
  1115. tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
  1116. if ( tempchar == 'E'|| tempchar == 'e'){
  1117. dissect_megaco_descriptors(tvb, megaco_tree, pinfo, tvb_command_start_offset-1,tvb_descriptors_end_offset);
  1118. }
  1119. else {
  1120. dissect_megaco_descriptors(tvb, megaco_tree, pinfo, tvb_descriptors_start_offset,tvb_descriptors_end_offset);
  1121. }
  1122. }
  1123. RBRKT_counter = 0;
  1124. LBRKT_counter = 0;
  1125. tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_command_end_offset +1);
  1126. tvb_LBRKT = tvb_command_start_offset;
  1127. tvb_RBRKT = tvb_command_start_offset;
  1128. }
  1129. } while ( tvb_command_end_offset < tvb_transaction_end_offset );
  1130. if (keep_persistent_data) {
  1131. gcp_msg_to_str(msg,keep_persistent_data);
  1132. gcp_analyze_msg(megaco_tree, pinfo, tvb, msg, &megaco_ctx_ids, &ei_megaco_errored_command);
  1133. }
  1134. tvb_next_offset = tvb_transaction_end_offset;
  1135. first = 0;
  1136. }
  1137. while( tvb_transaction_end_offset < tvb_len - 2);
  1138. if(global_megaco_raw_text){
  1139. tvb_raw_text_add(tvb, megaco_tree);
  1140. }
  1141. }
  1142. #define MEGACO_MODEM_TOKEN 1
  1143. #define MEGACO_MUX_TOKEN 2
  1144. #define MEGACO_MEDIA_TOKEN 3
  1145. #define MEGACO_SIGNALS_TOKEN 4
  1146. #define MEGACO_SERVICES_TOKEN 5
  1147. #define MEGACO_STATS_TOKEN 6
  1148. #define MEGACO_ERROR_TOKEN 7
  1149. #define MEGACO_EVENTS_TOKEN 8
  1150. #define MEGACO_AUDIT_TOKEN 9
  1151. #define MEGACO_DIGITMAP_TOKEN 10
  1152. #define MEGACO_OE_TOKEN 11
  1153. #define MEGACO_TOPOLOGY_TOKEN 12
  1154. #define MEGACO_PACKAGES_TOKEN 13
  1155. static const megaco_tokens_t megaco_descriptors_names[] = {
  1156. { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
  1157. { "Modem", "MD" }, /* 1 */
  1158. { "Mux", "MX" }, /* 2 */
  1159. { "Media", "M" }, /* 3 */
  1160. { "Signals", "SG" }, /* 4 */
  1161. { "Services", "SV" }, /* 5 */
  1162. { "Statistics", "SA" }, /* 6 */
  1163. { "Error", "ER" }, /* 7 */
  1164. { "Events", "E" }, /* 8 */
  1165. { "Audit", "AT" }, /* 9 */
  1166. { "DigitMap", "DM" }, /* 10 */
  1167. { "ObservedEvents", "OE" }, /* 11 */
  1168. { "Topology", "TP" }, /* 12 */
  1169. { "Packages", "PG" }, /* 13 */
  1170. };
  1171. /* Returns index of megaco_tokens_t */
  1172. /* note - also called by dissect_megaco_auditdescriptor */
  1173. static gint find_megaco_descriptors_names(tvbuff_t *tvb, int offset, guint header_len)
  1174. {
  1175. guint i;
  1176. for (i = 1; i < array_length(megaco_descriptors_names); i++) {
  1177. if (header_len == strlen(megaco_descriptors_names[i].name) &&
  1178. tvb_strncaseeql(tvb, offset, megaco_descriptors_names[i].name, header_len) == 0)
  1179. return i;
  1180. if (megaco_descriptors_names[i].compact_name != NULL &&
  1181. header_len == strlen(megaco_descriptors_names[i].compact_name) &&
  1182. tvb_strncaseeql(tvb, offset, megaco_descriptors_names[i].compact_name, header_len) == 0)
  1183. return i;
  1184. }
  1185. return -1;
  1186. }
  1187. static void
  1188. dissect_megaco_descriptors(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, packet_info *pinfo, gint tvb_descriptors_start_offset, gint tvb_descriptors_end_offset)
  1189. {
  1190. gint tvb_len, token_index, tvb_offset, temp_offset;
  1191. gint tvb_current_offset,tvb_previous_offset,tokenlen;
  1192. gint tvb_RBRKT, tvb_LBRKT;
  1193. tvb_len = tvb_length(tvb);
  1194. tvb_LBRKT = megaco_tvb_skip_wsp(tvb, tvb_descriptors_start_offset +1);
  1195. tvb_previous_offset = tvb_LBRKT;
  1196. tvb_RBRKT = tvb_descriptors_start_offset;
  1197. do {
  1198. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  1199. tvb_len, '}');
  1200. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
  1201. tvb_len, '{');
  1202. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
  1203. tvb_len, ',');
  1204. if (tvb_current_offset == -1 || tvb_current_offset > tvb_descriptors_end_offset){
  1205. tvb_current_offset = tvb_descriptors_end_offset;
  1206. }
  1207. if (tvb_current_offset <= tvb_previous_offset) {
  1208. expert_add_info_format(pinfo, megaco_tree_command_line, PI_MALFORMED, PI_ERROR, "[ Parse error: Invalid offset ]");
  1209. return;
  1210. }
  1211. /* Descriptor includes no parameters */
  1212. if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
  1213. if ( tvb_current_offset > tvb_RBRKT ){
  1214. tvb_current_offset = tvb_RBRKT;
  1215. }
  1216. tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
  1217. }
  1218. /* Descriptor includes Parameters */
  1219. if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
  1220. while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
  1221. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
  1222. tvb_len, '{');
  1223. if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
  1224. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_len, '}');
  1225. }
  1226. }
  1227. /* Find token length */
  1228. for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_descriptors_end_offset -1; tvb_offset++){
  1229. if (!isalpha(tvb_get_guint8(tvb, tvb_offset ))){
  1230. break;
  1231. }
  1232. }
  1233. tokenlen = tvb_offset - tvb_previous_offset;
  1234. token_index = find_megaco_descriptors_names(tvb, tvb_previous_offset, tokenlen);
  1235. if (tvb_RBRKT > tvb_descriptors_end_offset) tvb_RBRKT = tvb_descriptors_end_offset;
  1236. switch ( token_index ){
  1237. case MEGACO_MODEM_TOKEN:
  1238. dissect_megaco_modemdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1239. break;
  1240. case MEGACO_MUX_TOKEN:
  1241. dissect_megaco_multiplexdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1242. break;
  1243. case MEGACO_MEDIA_TOKEN:
  1244. /*TODO: Move this to the top when all branches fixed !!!*/
  1245. temp_offset = tvb_find_guint8(tvb, tvb_previous_offset,tvb_descriptors_end_offset, '{');
  1246. tokenlen = temp_offset - tvb_previous_offset+1;
  1247. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
  1248. "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
  1249. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, temp_offset +1);
  1250. dissect_megaco_mediadescriptor(tvb, megaco_tree_command_line, pinfo, tvb_RBRKT, tvb_previous_offset);
  1251. break;
  1252. case MEGACO_SIGNALS_TOKEN:
  1253. dissect_megaco_signaldescriptor(tvb, pinfo, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1254. break;
  1255. case MEGACO_SERVICES_TOKEN:
  1256. dissect_megaco_servicechangedescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1257. break;
  1258. case MEGACO_STATS_TOKEN:
  1259. dissect_megaco_statisticsdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1260. break;
  1261. case MEGACO_ERROR_TOKEN:
  1262. dissect_megaco_errordescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1263. break;
  1264. case MEGACO_EVENTS_TOKEN:
  1265. dissect_megaco_eventsdescriptor(tvb, pinfo, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1266. break;
  1267. case MEGACO_AUDIT_TOKEN:
  1268. dissect_megaco_auditdescriptor(tvb, megaco_tree_command_line, pinfo, tvb_RBRKT, tvb_previous_offset);
  1269. break;
  1270. case MEGACO_DIGITMAP_TOKEN:
  1271. dissect_megaco_digitmapdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1272. break;
  1273. case MEGACO_OE_TOKEN:
  1274. /* ObservedEventsToken */
  1275. dissect_megaco_observedeventsdescriptor(tvb, pinfo, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1276. break;
  1277. case MEGACO_TOPOLOGY_TOKEN:
  1278. dissect_megaco_topologydescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1279. break;
  1280. case MEGACO_PACKAGES_TOKEN:
  1281. dissect_megaco_Packagesdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
  1282. break;
  1283. default:
  1284. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  1285. proto_tree_add_string(megaco_tree_command_line, hf_megaco_error_Frame, tvb,
  1286. tvb_previous_offset, tokenlen,
  1287. "No Descriptor detectable !");
  1288. break;
  1289. }
  1290. tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT, tvb_len, ',');
  1291. if (tvb_current_offset == -1 || tvb_descriptors_end_offset < tvb_current_offset){
  1292. tvb_current_offset = tvb_descriptors_end_offset;
  1293. }
  1294. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
  1295. tvb_LBRKT = tvb_previous_offset;
  1296. tvb_RBRKT = tvb_previous_offset;
  1297. } while ( tvb_current_offset < tvb_descriptors_end_offset );
  1298. }
  1299. static void
  1300. dissect_megaco_modemdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  1301. {
  1302. gint tokenlen;
  1303. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  1304. proto_tree_add_string(megaco_tree_command_line, hf_megaco_modem_descriptor, tvb,
  1305. tvb_previous_offset, tokenlen,
  1306. tvb_format_text(tvb, tvb_previous_offset,
  1307. tokenlen));
  1308. }
  1309. static void
  1310. dissect_megaco_multiplexdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  1311. {
  1312. gint tokenlen;
  1313. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  1314. proto_tree_add_string(megaco_tree_command_line, hf_megaco_multiplex_descriptor, tvb,
  1315. tvb_previous_offset, tokenlen,
  1316. tvb_format_text(tvb, tvb_previous_offset,
  1317. tokenlen));
  1318. }
  1319. /* mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
  1320. * MediaToken = ("Media" / "M")
  1321. *
  1322. * mediaParm = (streamParm / streamDescriptor /terminationStateDescriptor)
  1323. *
  1324. * ; at-most one terminationStateDescriptor
  1325. * ; and either streamParm(s) or streamDescriptor(s) but not both
  1326. * streamParm = ( localDescriptor / remoteDescriptor /localControlDescriptor )
  1327. * localDescriptor = LocalToken LBRKT octetString RBRKT
  1328. * LocalToken = ("Local" / "L")
  1329. * octetString = *(nonEscapeChar)
  1330. * nonEscapeChar = ( "\}" / %x01-7C / %x7E-FF )
  1331. * remoteDescriptor = RemoteToken LBRKT octetString RBRKT
  1332. * RemoteToken = ("Remote" / "R")
  1333. * localControlDescriptor = LocalControlToken LBRKT localParm*(COMMA localParm) RBRKT
  1334. * LocalControlToken = ("LocalControl" / "O")
  1335. * localParm = ( streamMode / propertyParm / reservedValueMode
  1336. * streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm*(COMMA streamParm) RBRKT
  1337. * StreamToken = ("Stream" / "ST")
  1338. * terminationStateDescriptor = TerminationStateToken LBRKTterminationStateParm
  1339. * *( COMMA terminationStateParm ) RBRKT
  1340. * TerminationStateToken = ("TerminationState" / "TS")
  1341. * terminationStateParm =(propertyParm / serviceStates / eventBufferControl )
  1342. */
  1343. #define MEGACO_LOCAL_TOKEN 1
  1344. #define MEGACO_REMOTE_TOKEN 2
  1345. #define MEGACO_LOCAL_CONTROL_TOKEN 3
  1346. #define MEGACO_STREAM_TOKEN 4
  1347. #define MEGACO_TERMINATION_STATE_DESC 5
  1348. static const megaco_tokens_t megaco_mediaParm_names[] = {
  1349. { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
  1350. { "Local", "L" }, /* 1 */
  1351. { "Remote", "R" }, /* 2 */
  1352. { "LocalControl", "O" }, /* 3 */
  1353. { "Stream", "ST" }, /* 4 */
  1354. { "TerminationState", "TS" }, /* 5 */
  1355. };
  1356. /* Returns index of megaco_tokens_t */
  1357. static gint find_megaco_mediaParm_names(tvbuff_t *tvb, int offset, guint header_len)
  1358. {
  1359. guint i;
  1360. for (i = 1; i < array_length(megaco_mediaParm_names); i++) {
  1361. if (header_len == strlen(megaco_mediaParm_names[i].name) &&
  1362. tvb_strncaseeql(tvb, offset, megaco_mediaParm_names[i].name, header_len) == 0)
  1363. return i;
  1364. if (megaco_mediaParm_names[i].compact_name != NULL &&
  1365. header_len == strlen(megaco_mediaParm_names[i].compact_name) &&
  1366. tvb_strncaseeql(tvb, offset, megaco_mediaParm_names[i].compact_name, header_len) == 0)
  1367. return i;
  1368. }
  1369. return -1;
  1370. }
  1371. static void
  1372. dissect_megaco_mediadescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line,packet_info *pinfo, gint tvb_last_RBRKT, gint tvb_previous_offset)
  1373. {
  1374. gint tokenlen, tvb_LBRKT, tvb_RBRKT;
  1375. gint tvb_next_offset, tvb_current_offset, tvb_offset, equal_offset;
  1376. gint mediaParm;
  1377. proto_tree *megaco_mediadescriptor_tree, *megaco_mediadescriptor_ti;
  1378. /*
  1379. megaco_mediadescriptor_ti = proto_tree_add_text(megaco_tree_command_line,tvb,tvb_previous_offset,tokenlen,"Media Descriptor");
  1380. megaco_mediadescriptor_tree = proto_item_add_subtree(megaco_mediadescriptor_ti, ett_megaco_mediadescriptor);
  1381. */
  1382. while ( tvb_previous_offset < tvb_last_RBRKT){
  1383. /* Start of token */
  1384. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
  1385. /* Find token length */
  1386. for (tvb_next_offset=tvb_current_offset; tvb_next_offset < tvb_last_RBRKT; tvb_next_offset++){
  1387. if (!isalpha(tvb_get_guint8(tvb, tvb_next_offset ))){
  1388. break;
  1389. }
  1390. }
  1391. tokenlen = tvb_next_offset - tvb_current_offset;
  1392. mediaParm = find_megaco_mediaParm_names(tvb, tvb_current_offset, tokenlen);
  1393. tvb_LBRKT = tvb_find_guint8(tvb, tvb_next_offset , tvb_last_RBRKT, '{');
  1394. tvb_next_offset = tvb_find_guint8(tvb, tvb_current_offset+1 , tvb_last_RBRKT, '}');
  1395. tvb_RBRKT = tvb_next_offset;
  1396. tokenlen = tvb_LBRKT - tvb_current_offset +1;
  1397. megaco_mediadescriptor_ti = proto_tree_add_text(megaco_tree_command_line,tvb,tvb_current_offset,
  1398. tokenlen,"%s",tvb_format_text(tvb, tvb_current_offset,tokenlen));
  1399. switch ( mediaParm ){
  1400. case MEGACO_LOCAL_TOKEN:
  1401. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
  1402. dissect_megaco_Localdescriptor(tvb,megaco_tree_command_line , pinfo,
  1403. tvb_RBRKT, tvb_current_offset);
  1404. tvb_current_offset = tvb_RBRKT;
  1405. break;
  1406. case MEGACO_REMOTE_TOKEN:
  1407. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
  1408. dissect_megaco_Localdescriptor(tvb,megaco_tree_command_line , pinfo,
  1409. tvb_RBRKT, tvb_current_offset);
  1410. tvb_current_offset = tvb_RBRKT;
  1411. break;
  1412. case MEGACO_LOCAL_CONTROL_TOKEN:
  1413. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
  1414. dissect_megaco_LocalControldescriptor(tvb,megaco_tree_command_line, pinfo ,
  1415. tvb_RBRKT, tvb_current_offset);
  1416. tvb_current_offset = tvb_RBRKT;
  1417. break;
  1418. case MEGACO_STREAM_TOKEN:
  1419. megaco_mediadescriptor_tree = proto_item_add_subtree(megaco_mediadescriptor_ti, ett_megaco_mediadescriptor);
  1420. equal_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_last_RBRKT, '=');
  1421. tvb_current_offset = megaco_tvb_skip_wsp(tvb, equal_offset+1);
  1422. tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_LBRKT-1);
  1423. tokenlen = tvb_offset - tvb_current_offset;
  1424. proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_streamid, tvb,
  1425. tvb_current_offset, tokenlen, tvb_format_text(tvb, tvb_current_offset,tokenlen));
  1426. tvb_previous_offset = tvb_LBRKT+1;
  1427. continue;
  1428. case MEGACO_TERMINATION_STATE_DESC:
  1429. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
  1430. dissect_megaco_TerminationStatedescriptor(tvb,megaco_tree_command_line ,
  1431. tvb_RBRKT, tvb_current_offset);
  1432. tvb_current_offset = tvb_RBRKT;
  1433. break;
  1434. default:
  1435. break;
  1436. };
  1437. /* more parameters ? */
  1438. tvb_next_offset = tvb_find_guint8(tvb, tvb_current_offset+1 , tvb_last_RBRKT, ',');
  1439. if (tvb_next_offset > tvb_last_RBRKT) tvb_next_offset = tvb_last_RBRKT;
  1440. if ( tvb_next_offset != -1 ){
  1441. tokenlen = tvb_next_offset - tvb_RBRKT+1;
  1442. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_RBRKT, tokenlen,
  1443. "%s", tvb_format_text(tvb, tvb_RBRKT, tokenlen));
  1444. tvb_previous_offset = tvb_next_offset+1;
  1445. }else{
  1446. /* Add the trailing '}'*/
  1447. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_RBRKT, 1,
  1448. "%s", tvb_format_text(tvb, tvb_RBRKT, 1));
  1449. tvb_previous_offset = tvb_last_RBRKT;
  1450. }
  1451. } /* End while */
  1452. }
  1453. static void
  1454. dissect_megaco_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree, gint offset, gint len, gchar *msg)
  1455. {
  1456. /*proto_item *item;*/
  1457. /*proto_tree *tree;*/
  1458. /*item=proto_tree_add_string(megaco_tree, hf_megaco_h245, tvb,
  1459. offset, len, msg );
  1460. */
  1461. /*item = */proto_tree_add_text(megaco_tree, tvb, offset, len, "%s", msg);
  1462. /*tree = proto_item_add_subtree(item, ett_megaco_h245); */
  1463. /* arbitrary maximum length */
  1464. if(len<20480){
  1465. int i;
  1466. tvbuff_t *h245_tvb;
  1467. guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
  1468. /* first, skip to where the encoded pdu starts, this is
  1469. the first hex digit after the '=' char.
  1470. */
  1471. while(1){
  1472. if((*msg==0)||(*msg=='\n')){
  1473. return;
  1474. }
  1475. if(*msg=='='){
  1476. msg++;
  1477. break;
  1478. }
  1479. msg++;
  1480. }
  1481. while(1){
  1482. if((*msg==0)||(*msg=='\n')){
  1483. return;
  1484. }
  1485. if( ((*msg>='0')&&(*msg<='9'))
  1486. || ((*msg>='a')&&(*msg<='f'))
  1487. || ((*msg>='A')&&(*msg<='F'))){
  1488. break;
  1489. }
  1490. msg++;
  1491. }
  1492. i=0;
  1493. while( ((*msg>='0')&&(*msg<='9'))
  1494. ||((*msg>='a')&&(*msg<='f'))
  1495. ||((*msg>='A')&&(*msg<='F')) ){
  1496. int val;
  1497. if((*msg>='0')&&(*msg<='9')){
  1498. val=(*msg)-'0';
  1499. } else if((*msg>='a')&&(*msg<='f')){
  1500. val=(*msg)-'a'+10;
  1501. } else if((*msg>='A')&&(*msg<='F')){
  1502. val=(*msg)-'A'+10;
  1503. } else {
  1504. return;
  1505. }
  1506. val<<=4;
  1507. msg++;
  1508. if((*msg>='0')&&(*msg<='9')){
  1509. val|=(*msg)-'0';
  1510. } else if((*msg>='a')&&(*msg<='f')){
  1511. val|=(*msg)-'a'+10;
  1512. } else if((*msg>='A')&&(*msg<='F')){
  1513. val|=(*msg)-'A'+10;
  1514. } else {
  1515. return;
  1516. }
  1517. msg++;
  1518. buf[i]=(guint8)val;
  1519. i++;
  1520. }
  1521. if(i==0){
  1522. return;
  1523. }
  1524. h245_tvb = tvb_new_child_real_data(tvb, buf,i,i);
  1525. add_new_data_source(pinfo, h245_tvb, "H.245 over MEGACO");
  1526. /* should go through a handle, however, the two h245 entry
  1527. points are different, one is over tpkt and the other is raw
  1528. */
  1529. call_dissector(h245_handle, h245_tvb, pinfo, top_tree);
  1530. /* dissect_h245_MultimediaSystemControlMessage(h245_tvb, pinfo, tree);*/
  1531. }
  1532. }
  1533. static void
  1534. dissect_megaco_h324_h223caprn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree, gint offset _U_, gint len, gchar *msg)
  1535. {
  1536. asn1_ctx_t actx;
  1537. /* arbitrary maximum length */
  1538. if(len<20480){
  1539. int i;
  1540. tvbuff_t *h245_tvb;
  1541. guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
  1542. /* first, skip to where the encoded pdu starts, this is
  1543. the first hex digit after the '=' char.
  1544. */
  1545. while(1){
  1546. if((*msg==0)||(*msg=='\n')){
  1547. return;
  1548. }
  1549. if(*msg=='='){
  1550. msg++;
  1551. break;
  1552. }
  1553. msg++;
  1554. }
  1555. while(1){
  1556. if((*msg==0)||(*msg=='\n')){
  1557. return;
  1558. }
  1559. if( ((*msg>='0')&&(*msg<='9'))
  1560. || ((*msg>='a')&&(*msg<='f'))
  1561. || ((*msg>='A')&&(*msg<='F'))){
  1562. break;
  1563. }
  1564. msg++;
  1565. }
  1566. i=0;
  1567. while( ((*msg>='0')&&(*msg<='9'))
  1568. ||((*msg>='a')&&(*msg<='f'))
  1569. ||((*msg>='A')&&(*msg<='F')) ){
  1570. int val;
  1571. if((*msg>='0')&&(*msg<='9')){
  1572. val=(*msg)-'0';
  1573. } else if((*msg>='a')&&(*msg<='f')){
  1574. val=(*msg)-'a'+10;
  1575. } else if((*msg>='A')&&(*msg<='F')){
  1576. val=(*msg)-'A'+10;
  1577. } else {
  1578. return;
  1579. }
  1580. val<<=4;
  1581. msg++;
  1582. if((*msg>='0')&&(*msg<='9')){
  1583. val|=(*msg)-'0';
  1584. } else if((*msg>='a')&&(*msg<='f')){
  1585. val|=(*msg)-'a'+10;
  1586. } else if((*msg>='A')&&(*msg<='F')){
  1587. val|=(*msg)-'A'+10;
  1588. } else {
  1589. return;
  1590. }
  1591. msg++;
  1592. buf[i]=(guint8)val;
  1593. i++;
  1594. }
  1595. if(i==0){
  1596. return;
  1597. }
  1598. h245_tvb = tvb_new_child_real_data(tvb, buf,i,i);
  1599. add_new_data_source(pinfo, h245_tvb, "H.245 over MEGACO");
  1600. /* should go through a handle, however, the two h245 entry
  1601. points are different, one is over tpkt and the other is raw
  1602. */
  1603. asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
  1604. dissect_h245_H223Capability(h245_tvb, 0, &actx, megaco_tree, hf_megaco_h223Capability);
  1605. }
  1606. }
  1607. static void
  1608. dissect_megaco_eventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  1609. {
  1610. gint tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
  1611. gint tvb_events_end_offset, tvb_LBRKT;
  1612. proto_tree *megaco_eventsdescriptor_tree, *megaco_eventsdescriptor_ti;
  1613. guint8 tempchar;
  1614. gint requested_event_start_offset, requested_event_end_offset;
  1615. proto_tree *megaco_requestedevent_tree, *megaco_requestedevent_ti;
  1616. requested_event_start_offset = 0;
  1617. requested_event_end_offset = 0;
  1618. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  1619. megaco_eventsdescriptor_ti = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
  1620. "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
  1621. /*
  1622. megaco_eventsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_events_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
  1623. */
  1624. megaco_eventsdescriptor_tree = proto_item_add_subtree(megaco_eventsdescriptor_ti, ett_megaco_eventsdescriptor);
  1625. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
  1626. tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
  1627. if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
  1628. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
  1629. tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
  1630. tokenlen = tvb_help_offset - tvb_current_offset;
  1631. proto_tree_add_string(megaco_eventsdescriptor_tree, hf_megaco_requestid, tvb,
  1632. tvb_current_offset, tokenlen,
  1633. tvb_format_text(tvb, tvb_current_offset,
  1634. tokenlen));
  1635. tvb_events_end_offset = tvb_RBRKT;
  1636. tvb_RBRKT = tvb_next_offset+1;
  1637. tvb_LBRKT = tvb_next_offset+1;
  1638. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
  1639. do {
  1640. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  1641. tvb_events_end_offset, '}');
  1642. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
  1643. tvb_events_end_offset, '{');
  1644. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
  1645. tvb_events_end_offset, ',');
  1646. if (tvb_current_offset == -1 || tvb_current_offset > tvb_events_end_offset){
  1647. tvb_current_offset = tvb_events_end_offset;
  1648. }
  1649. /* Descriptor includes no parameters */
  1650. if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
  1651. tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
  1652. }
  1653. /* Descriptor includes Parameters */
  1654. if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
  1655. while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
  1656. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
  1657. tvb_events_end_offset, '{');
  1658. if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
  1659. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  1660. tvb_events_end_offset, '}');
  1661. }
  1662. }
  1663. tvb_help_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_events_end_offset, '{');
  1664. /* if there are eventparameter */
  1665. if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
  1666. requested_event_start_offset = tvb_help_offset;
  1667. requested_event_end_offset = tvb_RBRKT;
  1668. tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
  1669. tokenlen = tvb_help_offset - tvb_previous_offset;
  1670. }
  1671. /* no parameters */
  1672. else {
  1673. tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
  1674. }
  1675. megaco_requestedevent_ti = proto_tree_add_item(megaco_eventsdescriptor_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
  1676. megaco_requestedevent_tree = proto_item_add_subtree(megaco_requestedevent_ti, ett_megaco_requestedevent);
  1677. if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
  1678. tvb_help_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1);
  1679. tempchar = tvb_get_guint8(tvb, tvb_help_offset);
  1680. requested_event_start_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1);
  1681. requested_event_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_event_end_offset-1);
  1682. if ( tempchar == 'D' || tempchar == 'd'){
  1683. dissect_megaco_digitmapdescriptor(tvb, megaco_requestedevent_tree, requested_event_end_offset, requested_event_start_offset);
  1684. }
  1685. else{
  1686. gchar *msg;
  1687. tokenlen = requested_event_end_offset - requested_event_start_offset;
  1688. msg=tvb_format_text(tvb,requested_event_start_offset, tokenlen);
  1689. if(!strncmp("h245", msg, 4)){
  1690. dissect_megaco_h245(tvb, pinfo, megaco_requestedevent_tree, requested_event_start_offset, tokenlen, msg);
  1691. } else {
  1692. proto_tree_add_text(megaco_requestedevent_tree, tvb, requested_event_start_offset, tokenlen,
  1693. "%s", msg);
  1694. }
  1695. }
  1696. }
  1697. tvb_previous_offset = tvb_current_offset;
  1698. tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
  1699. tvb_events_end_offset, ',');
  1700. if (tvb_current_offset == -1 || tvb_current_offset > tvb_events_end_offset || tvb_current_offset < tvb_previous_offset ) {
  1701. tvb_current_offset = tvb_events_end_offset;
  1702. }
  1703. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
  1704. tvb_LBRKT = tvb_previous_offset;
  1705. tvb_RBRKT = tvb_previous_offset;
  1706. } while ( tvb_current_offset < tvb_events_end_offset );
  1707. }
  1708. }
  1709. static void
  1710. dissect_megaco_signaldescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  1711. {
  1712. gint tokenlen, pkg_tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
  1713. gint tvb_signals_end_offset, tvb_signals_start_offset, tvb_LBRKT;
  1714. /*proto_tree *megaco_signalsdescriptor_tree, *megaco_signalsdescriptor_ti;*/
  1715. gint requested_signal_start_offset, requested_signal_end_offset;
  1716. proto_tree *megaco_requestedsignal_tree, *megaco_requestedsignal_ti;
  1717. requested_signal_start_offset = 0;
  1718. requested_signal_end_offset = 0;
  1719. tvb_signals_end_offset = tvb_RBRKT;
  1720. tvb_signals_start_offset = tvb_previous_offset;
  1721. if(toupper(tvb_get_guint8(tvb, tvb_previous_offset+1))=='G')
  1722. tokenlen = 2; /* token is compact text (SG) */
  1723. else
  1724. tokenlen = 7; /* token must be verbose text (Signals) */
  1725. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset+tokenlen);
  1726. if(tvb_get_guint8(tvb, tvb_current_offset)!='{') { /* {} has been omitted */
  1727. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_signals_start_offset, tokenlen,
  1728. "%s", "Empty Signal Descriptor");
  1729. col_append_str(pinfo->cinfo, COL_INFO, " (Signal:none)"); /* then say so */
  1730. return; /* and return */
  1731. }
  1732. tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_signals_end_offset, '{');
  1733. tokenlen = (tvb_LBRKT+1) - tvb_signals_start_offset;
  1734. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_signals_start_offset, tokenlen,
  1735. "%s", tvb_format_text(tvb, tvb_signals_start_offset, tokenlen));
  1736. /*
  1737. megaco_signalsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_signal_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
  1738. megaco_signalsdescriptor_tree = proto_item_add_subtree(megaco_signalsdescriptor_ti, ett_megaco_signalsdescriptor);
  1739. */
  1740. tvb_current_offset = tvb_LBRKT;
  1741. tvb_next_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
  1742. col_append_fstr(pinfo->cinfo, COL_INFO, " (Signal:%s)",tvb_format_text(tvb, tvb_current_offset,tokenlen-tvb_current_offset+tvb_previous_offset));
  1743. if ( tvb_current_offset < tvb_signals_end_offset && tvb_current_offset != -1 && tvb_next_offset != tvb_signals_end_offset){
  1744. tvb_RBRKT = tvb_next_offset+1;
  1745. tvb_LBRKT = tvb_next_offset+1;
  1746. tvb_previous_offset = tvb_next_offset;
  1747. do {
  1748. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  1749. tvb_signals_end_offset, '}');
  1750. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
  1751. tvb_signals_end_offset, '{');
  1752. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
  1753. tvb_signals_end_offset, ',');
  1754. if (tvb_current_offset == -1 || tvb_current_offset > tvb_signals_end_offset){
  1755. tvb_current_offset = tvb_signals_end_offset;
  1756. }
  1757. /* Descriptor includes no parameters */
  1758. if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
  1759. tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
  1760. }
  1761. /* Descriptor includes Parameters */
  1762. if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
  1763. while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
  1764. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
  1765. tvb_signals_end_offset, '{');
  1766. if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
  1767. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  1768. tvb_signals_end_offset, '}');
  1769. }
  1770. }
  1771. tvb_help_offset = tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_signals_end_offset, '{');
  1772. /* if there are signalparameter */
  1773. if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
  1774. requested_signal_start_offset = tvb_help_offset;
  1775. requested_signal_end_offset = tvb_RBRKT;
  1776. tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
  1777. pkg_tokenlen = tvb_help_offset - tvb_previous_offset;
  1778. tokenlen = tvb_LBRKT+1 - tvb_previous_offset;
  1779. }
  1780. /* no parameters */
  1781. else {
  1782. tokenlen = pkg_tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
  1783. }
  1784. megaco_requestedsignal_ti = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
  1785. "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
  1786. megaco_requestedsignal_tree = proto_item_add_subtree(megaco_requestedsignal_ti, ett_megaco_requestedsignal);
  1787. proto_tree_add_item(megaco_requestedsignal_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,pkg_tokenlen, ENC_ASCII|ENC_NA);
  1788. if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
  1789. gchar *msg;
  1790. requested_signal_start_offset = megaco_tvb_skip_wsp(tvb, requested_signal_start_offset +1);
  1791. requested_signal_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_signal_end_offset-1);
  1792. tokenlen = requested_signal_end_offset - requested_signal_start_offset;
  1793. msg=tvb_format_text(tvb,requested_signal_start_offset, tokenlen+1);
  1794. if(!strncmp("h245", msg, 4)){
  1795. dissect_megaco_h245(tvb, pinfo, megaco_tree_command_line, requested_signal_start_offset, tokenlen, msg);
  1796. } else {
  1797. proto_tree_add_text(megaco_tree_command_line, tvb, requested_signal_start_offset, tokenlen,
  1798. "%s", msg);
  1799. }
  1800. /* Print the trailing '}' */
  1801. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_RBRKT, 1,
  1802. "%s", tvb_format_text(tvb, tvb_RBRKT, 1));
  1803. }
  1804. tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
  1805. tvb_signals_end_offset, ',');
  1806. if (tvb_current_offset == -1 || tvb_current_offset > tvb_signals_end_offset || tvb_current_offset < tvb_previous_offset){
  1807. tvb_current_offset = tvb_signals_end_offset;
  1808. }
  1809. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
  1810. tvb_LBRKT = tvb_previous_offset;
  1811. tvb_RBRKT = tvb_previous_offset;
  1812. /* Print the trailing '}' */
  1813. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1,
  1814. "%s", tvb_format_text(tvb, tvb_signals_end_offset, 1));
  1815. } while ( tvb_current_offset < tvb_signals_end_offset );
  1816. }else{
  1817. /* signals{}*/
  1818. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1,
  1819. "%s", tvb_format_text(tvb, tvb_signals_end_offset, 1));
  1820. }
  1821. }
  1822. /*
  1823. auditDescriptor = AuditToken LBRKT [ auditItem *(COMMA auditItem) ] RBRKT
  1824. auditItem = ( MuxToken / ModemToken / MediaToken /
  1825. SignalsToken / EventBufferToken /
  1826. DigitMapToken / StatsToken / EventsToken /
  1827. ObservedEventsToken / PackagesToken ) */
  1828. static void
  1829. dissect_megaco_auditdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree, packet_info *pinfo _U_, gint tvb_stop, gint tvb_offset)
  1830. {
  1831. gint tokenlen, tvb_end, tvb_next, token_index;
  1832. proto_tree *megaco_auditdescriptor_tree, *megaco_auditdescriptor_ti;
  1833. tvb_next = tvb_find_guint8(tvb, tvb_offset, tvb_stop, '{'); /* find opening LBRKT - is this already checked by caller?*/
  1834. if( tvb_next == -1 ) /* complain and give up if not there */
  1835. {
  1836. expert_add_info_format(pinfo, megaco_tree, PI_MALFORMED, PI_ERROR, "Badly constructed audit descriptor (no { )");
  1837. return;
  1838. }
  1839. tokenlen = (tvb_stop + 1) - tvb_offset;
  1840. megaco_auditdescriptor_ti = proto_tree_add_none_format( megaco_tree, hf_megaco_audit_descriptor,
  1841. tvb, tvb_offset, tokenlen, "Audit descriptor" );
  1842. megaco_auditdescriptor_tree = proto_item_add_subtree( megaco_auditdescriptor_ti, ett_megaco_auditdescriptor );
  1843. tokenlen = tvb_next + 1 - tvb_offset;
  1844. proto_tree_add_text( megaco_auditdescriptor_tree, tvb, tvb_offset, tokenlen, "Audit token {" );
  1845. tvb_offset = tvb_next;
  1846. while( tvb_offset < tvb_stop )
  1847. {
  1848. tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1); /* find start of an auditItem */
  1849. if( tvb_get_guint8(tvb, tvb_offset) != '}' ) /* got something */
  1850. {
  1851. tvb_next = tvb_find_guint8(tvb, tvb_offset, tvb_stop, ','); /* end of an auditItem */
  1852. if (tvb_next == -1) tvb_next = tvb_stop; /* last item doesn't have a comma */
  1853. tvb_end = megaco_tvb_skip_wsp_return(tvb, tvb_next-1); /* trim any trailing whitespace */
  1854. tokenlen = tvb_end - tvb_offset; /* get length of token */
  1855. token_index = find_megaco_descriptors_names(tvb, tvb_offset, tokenlen); /* lookup the token */
  1856. if( token_index == -1 ) token_index = 0; /* if not found then 0 => Unknown */
  1857. proto_tree_add_string(megaco_auditdescriptor_tree, hf_megaco_audititem, tvb,
  1858. tvb_offset, tokenlen, megaco_descriptors_names[token_index].name); /* and display the long form */
  1859. tvb_offset = tvb_next; /* advance pointer */
  1860. }
  1861. }
  1862. proto_tree_add_text(megaco_auditdescriptor_tree, tvb, tvb_stop, 1, "}"); /* End of auditDescriptor */
  1863. }
  1864. /*
  1865. * serviceChangeDescriptor = ServicesToken LBRKT serviceChangeParm
  1866. * *(COMMA serviceChangeParm) RBRKT
  1867. *
  1868. * ServicesToken = ("Services" / "SV")
  1869. *
  1870. * serviceChangeParm = (serviceChangeMethod / serviceChangeReason /
  1871. * serviceChangeDelay / serviceChangeAddress /
  1872. * serviceChangeProfile / extension / TimeStamp /
  1873. * serviceChangeMgcId / serviceChangeVersion )
  1874. *
  1875. */
  1876. #define MEGACO_REASON_TOKEN 1
  1877. #define MEGACO_DELAY_TOKEN 2
  1878. #define MEGACO_SC_ADDR_TOKEN 3
  1879. #define MEGACO_MGC_ID_TOKEN 4
  1880. #define MEGACO_PROFILE_TOKEN 5
  1881. #define MEGACO_VERSION_TOKEN 6
  1882. #define MEGACO_METHOD_TOKEN 7
  1883. static const megaco_tokens_t megaco_serviceChangeParm_names[] = {
  1884. { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
  1885. /* streamMode */
  1886. { "Reason", "RE" }, /* 1 ReasonToken*/
  1887. { "Delay", "DL" }, /* 2 DelayToken */
  1888. { "ServiceChangeAddress", "AD" }, /* 3 ServiceChangeAddressToken */
  1889. { "MgcIdToTry", "MG" }, /* 4 MgcIdToken */
  1890. { "Profile", "PF" }, /* 5 ProfileToken */
  1891. { "Version", "V" }, /* 6 VersionToken */
  1892. { "Method", "MT" }, /* 7 MethodToken */
  1893. };
  1894. /* Returns index of megaco_tokens_t */
  1895. static gint find_megaco_megaco_serviceChangeParm_names(tvbuff_t *tvb, int offset, guint header_len)
  1896. {
  1897. guint i;
  1898. for (i = 1; i < array_length(megaco_serviceChangeParm_names); i++) {
  1899. if (header_len == strlen(megaco_serviceChangeParm_names[i].name) &&
  1900. tvb_strncaseeql(tvb, offset, megaco_serviceChangeParm_names[i].name, header_len) == 0)
  1901. return i;
  1902. if (megaco_serviceChangeParm_names[i].compact_name != NULL &&
  1903. header_len == strlen(megaco_serviceChangeParm_names[i].compact_name) &&
  1904. tvb_strncaseeql(tvb, offset, megaco_serviceChangeParm_names[i].compact_name, header_len) == 0)
  1905. return i;
  1906. }
  1907. return -1;
  1908. }
  1909. /*
  1910. * ServiceChangeReasons References
  1911. * -------------------- ----------
  1912. */
  1913. static const value_string MEGACO_ServiceChangeReasons_vals[] = {
  1914. {900, "Service Restored"},
  1915. {901, "Cold Boot"},
  1916. {902, "Warm Boot"},
  1917. {903, "MGC Directed Change"},
  1918. {904, "Termination malfunctioning"},
  1919. {905, "Termination taken out of service"},
  1920. {906, "Loss of lower layer connectivity (e.g. downstream sync)"},
  1921. {907, "Transmission Failure"},
  1922. {908, "MG Impending Failure"},
  1923. {909, "MGC Impending Failure"},
  1924. {910, "Media Capability Failure"},
  1925. {911, "Modem Capability Failure"},
  1926. {912, "Mux Capability Failure"},
  1927. {913, "Signal Capability Failure"},
  1928. {914, "Event Capability Failure"},
  1929. {915, "State Loss"},
  1930. {916, "Packages Change"},
  1931. {917, "Capabilities Change"},
  1932. {918, "Cancel Graceful"},
  1933. {919, "Warm Failover"},
  1934. {920, "Cold Failover"},
  1935. { 0, NULL }
  1936. };
  1937. static void
  1938. dissect_megaco_servicechangedescriptor(tvbuff_t *tvb, proto_tree *megaco_tree, gint tvb_RBRKT, gint tvb_previous_offset)
  1939. {
  1940. gint tokenlen, tvb_LBRKT, tvb_offset;
  1941. gint token_index;
  1942. gint tvb_current_offset;
  1943. gboolean more_params = TRUE;
  1944. proto_item* item;
  1945. gint reason;
  1946. guint8 ServiceChangeReason_str[4];
  1947. tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
  1948. /*
  1949. if (tvb_LBRKT == -1)
  1950. return;
  1951. */
  1952. tokenlen = (tvb_LBRKT + 1) - tvb_previous_offset;
  1953. proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tokenlen,
  1954. "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
  1955. /* Start dissecting serviceChangeParm */
  1956. tvb_previous_offset = tvb_LBRKT + 1;
  1957. while (more_params){
  1958. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
  1959. /* Find token length */
  1960. for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_RBRKT; tvb_offset++){
  1961. if (!isalpha(tvb_get_guint8(tvb, tvb_offset ))){
  1962. break;
  1963. }
  1964. }
  1965. tokenlen = tvb_offset - tvb_previous_offset;
  1966. token_index = find_megaco_megaco_serviceChangeParm_names(tvb, tvb_previous_offset, tokenlen);
  1967. tvb_offset = tvb_find_guint8(tvb, tvb_offset, tvb_RBRKT, ',');
  1968. if ((tvb_offset == -1)||(tvb_offset >=tvb_RBRKT)){
  1969. more_params = FALSE;
  1970. tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_RBRKT-1);
  1971. }
  1972. tokenlen = tvb_offset - tvb_previous_offset;
  1973. if (more_params == TRUE )
  1974. /* Include ',' */
  1975. tokenlen++;
  1976. switch(token_index){
  1977. case MEGACO_REASON_TOKEN:
  1978. /* ReasonToken EQUAL VALUE
  1979. * VALUE = quotedString / 1*(SafeChar)
  1980. */
  1981. item = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tokenlen,
  1982. "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
  1983. /* As the reason code ( if a digit ) can be in quoted string or 'just' digit
  1984. * look for a nine and hope for the best.
  1985. */
  1986. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '9');
  1987. if ( tvb_current_offset == -1)
  1988. break;
  1989. tvb_get_nstringz0(tvb,tvb_current_offset,4,ServiceChangeReason_str);
  1990. reason = atoi(ServiceChangeReason_str);
  1991. proto_item_append_text(item,"[ %s ]", val_to_str(reason, MEGACO_ServiceChangeReasons_vals,"Unknown (%u)"));
  1992. break;
  1993. case MEGACO_DELAY_TOKEN:
  1994. case MEGACO_SC_ADDR_TOKEN:
  1995. case MEGACO_MGC_ID_TOKEN:
  1996. case MEGACO_PROFILE_TOKEN:
  1997. case MEGACO_VERSION_TOKEN:
  1998. case MEGACO_METHOD_TOKEN:
  1999. /* No special dissection: fall trough */
  2000. default:
  2001. /* Unknown or:
  2002. * extension = extensionParameter parmValue
  2003. * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
  2004. */
  2005. proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tokenlen,
  2006. "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
  2007. break;
  2008. }
  2009. tvb_previous_offset = tvb_offset +1;
  2010. }/*End while */
  2011. /* extension = extensionParameter parmValue
  2012. * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
  2013. */
  2014. /*
  2015. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  2016. proto_tree_add_string(megaco_tree_command_line, hf_megaco_servicechange_descriptor, tvb,
  2017. tvb_previous_offset, tokenlen,
  2018. tvb_format_text(tvb, tvb_previous_offset,
  2019. tokenlen));
  2020. */
  2021. proto_tree_add_text(megaco_tree, tvb, tvb_RBRKT, 1,"%s", tvb_format_text(tvb, tvb_RBRKT, 1));
  2022. }
  2023. static void
  2024. dissect_megaco_digitmapdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  2025. {
  2026. gint tokenlen;
  2027. tokenlen = tvb_RBRKT - tvb_previous_offset;
  2028. proto_tree_add_string(megaco_tree_command_line, hf_megaco_digitmap_descriptor, tvb,
  2029. tvb_previous_offset, tokenlen,
  2030. tvb_format_text(tvb, tvb_previous_offset,
  2031. tokenlen));
  2032. }
  2033. static void
  2034. dissect_megaco_statisticsdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  2035. {
  2036. gint tokenlen;
  2037. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  2038. proto_tree_add_string(megaco_tree_command_line, hf_megaco_statistics_descriptor, tvb,
  2039. tvb_previous_offset, tokenlen,
  2040. tvb_format_text(tvb, tvb_previous_offset,
  2041. tokenlen));
  2042. }
  2043. static void
  2044. dissect_megaco_observedeventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  2045. {
  2046. gint tokenlen, pkg_tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
  2047. gint tvb_observedevents_end_offset, tvb_LBRKT;
  2048. proto_tree *megaco_observedeventsdescriptor_tree, *megaco_observedeventsdescriptor_ti;
  2049. gint requested_event_start_offset, requested_event_end_offset, param_start_offset, param_end_offset;
  2050. proto_tree *megaco_observedevent_tree, *megaco_observedevent_ti;
  2051. requested_event_start_offset = 0;
  2052. requested_event_end_offset = 0;
  2053. tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
  2054. tvb_next_offset = tvb_LBRKT;
  2055. tokenlen = (tvb_next_offset+1) - tvb_previous_offset;
  2056. /*
  2057. megaco_observedeventsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_observedevents_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
  2058. megaco_observedeventsdescriptor_tree = proto_item_add_subtree(megaco_observedeventsdescriptor_ti, ett_megaco_observedeventsdescriptor);
  2059. */
  2060. megaco_observedeventsdescriptor_ti = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
  2061. "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
  2062. megaco_observedeventsdescriptor_tree = proto_item_add_subtree(megaco_observedeventsdescriptor_ti, ett_megaco_observedeventsdescriptor);
  2063. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
  2064. tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
  2065. if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
  2066. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
  2067. tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
  2068. tokenlen = tvb_help_offset - tvb_current_offset;
  2069. proto_tree_add_string(megaco_observedeventsdescriptor_tree, hf_megaco_requestid, tvb,
  2070. tvb_current_offset, tokenlen,
  2071. tvb_format_text(tvb, tvb_current_offset,
  2072. tokenlen));
  2073. tvb_observedevents_end_offset = tvb_RBRKT;
  2074. tvb_RBRKT = tvb_next_offset+1;
  2075. tvb_LBRKT = tvb_next_offset+1;
  2076. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
  2077. do {
  2078. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  2079. tvb_observedevents_end_offset, '}');
  2080. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
  2081. tvb_observedevents_end_offset, '{');
  2082. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
  2083. tvb_observedevents_end_offset, ',');
  2084. if (tvb_current_offset == -1 || tvb_current_offset > tvb_observedevents_end_offset){
  2085. tvb_current_offset = tvb_observedevents_end_offset;
  2086. }
  2087. /* Descriptor includes no parameters */
  2088. if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
  2089. tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
  2090. }
  2091. /* Descriptor includes Parameters */
  2092. if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
  2093. while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
  2094. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
  2095. tvb_observedevents_end_offset, '{');
  2096. if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1){
  2097. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  2098. tvb_observedevents_end_offset, '}');
  2099. }
  2100. }
  2101. }
  2102. tvb_LBRKT = tvb_help_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_observedevents_end_offset, '{');
  2103. /* if there are eventparameter */
  2104. if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
  2105. requested_event_start_offset = tvb_help_offset;
  2106. requested_event_end_offset = tvb_RBRKT;
  2107. tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
  2108. pkg_tokenlen = tvb_help_offset - tvb_previous_offset;
  2109. tokenlen = tvb_LBRKT+1 - tvb_previous_offset;
  2110. }
  2111. /* no parameters */
  2112. else {
  2113. tokenlen = pkg_tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
  2114. }
  2115. megaco_observedevent_ti = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
  2116. "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
  2117. megaco_observedevent_tree = proto_item_add_subtree(megaco_observedevent_ti, ett_megaco_observedevent);
  2118. proto_tree_add_item(megaco_observedevent_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,pkg_tokenlen, ENC_ASCII|ENC_NA);
  2119. if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
  2120. requested_event_start_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1)-1;
  2121. requested_event_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_event_end_offset-1);
  2122. tvb_help_offset = requested_event_start_offset;
  2123. do {
  2124. gchar *msg;
  2125. param_start_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset+1);
  2126. tvb_help_offset = tvb_find_guint8(tvb, tvb_help_offset+1,requested_event_end_offset, ',');
  2127. if ( tvb_help_offset > requested_event_end_offset || tvb_help_offset == -1){
  2128. tvb_help_offset = requested_event_end_offset;
  2129. }
  2130. param_end_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset-1);
  2131. tokenlen = param_end_offset - param_start_offset+1;
  2132. msg=tvb_format_text(tvb,param_start_offset, tokenlen);
  2133. if(!strncmp("h245", msg, 4)){
  2134. dissect_megaco_h245(tvb, pinfo, megaco_tree_command_line, param_start_offset, tokenlen, msg);
  2135. } else {
  2136. proto_tree_add_text(megaco_tree_command_line, tvb, param_start_offset, tokenlen,
  2137. "%s", msg);
  2138. }
  2139. } while ( tvb_help_offset < requested_event_end_offset );
  2140. }
  2141. tvb_previous_offset = tvb_current_offset;
  2142. tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
  2143. tvb_observedevents_end_offset, ',');
  2144. if (tvb_current_offset == -1 || tvb_current_offset > tvb_observedevents_end_offset ){
  2145. tvb_current_offset = tvb_observedevents_end_offset;
  2146. }
  2147. if (tvb_current_offset < tvb_previous_offset) {
  2148. expert_add_info_format(pinfo, megaco_observedevent_ti, PI_MALFORMED, PI_ERROR, "[ Parse error: Invalid offset ]");
  2149. return;
  2150. }
  2151. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
  2152. tvb_LBRKT = tvb_previous_offset;
  2153. tvb_RBRKT = tvb_previous_offset;
  2154. /* Print the trailing '}' */
  2155. proto_tree_add_text(megaco_tree_command_line, tvb, tvb_observedevents_end_offset, 1,
  2156. "%s", tvb_format_text(tvb, tvb_observedevents_end_offset, 1));
  2157. } while ( tvb_current_offset < tvb_observedevents_end_offset );
  2158. }
  2159. }
  2160. static void
  2161. dissect_megaco_topologydescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  2162. {
  2163. gint tokenlen;
  2164. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  2165. proto_tree_add_string(megaco_tree_command_line, hf_megaco_topology_descriptor, tvb,
  2166. tvb_previous_offset, tokenlen,
  2167. tvb_format_text_wsp(tvb, tvb_previous_offset,
  2168. tokenlen));
  2169. }
  2170. static void
  2171. dissect_megaco_Packagesdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  2172. {
  2173. gint tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
  2174. gint tvb_packages_end_offset, tvb_LBRKT;
  2175. proto_tree *megaco_packagesdescriptor_tree, *megaco_packagesdescriptor_ti;
  2176. tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
  2177. megaco_packagesdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_packages_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
  2178. megaco_packagesdescriptor_tree = proto_item_add_subtree(megaco_packagesdescriptor_ti, ett_megaco_packagesdescriptor);
  2179. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
  2180. tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
  2181. if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
  2182. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
  2183. tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
  2184. tokenlen = tvb_help_offset - tvb_current_offset;
  2185. proto_tree_add_string(megaco_packagesdescriptor_tree, hf_megaco_requestid, tvb,
  2186. tvb_current_offset, tokenlen,
  2187. tvb_format_text(tvb, tvb_current_offset,
  2188. tokenlen));
  2189. tvb_packages_end_offset = tvb_RBRKT;
  2190. tvb_RBRKT = tvb_next_offset+1;
  2191. tvb_LBRKT = tvb_next_offset+1;
  2192. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
  2193. do {
  2194. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  2195. tvb_packages_end_offset, '}');
  2196. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
  2197. tvb_packages_end_offset, '{');
  2198. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
  2199. tvb_packages_end_offset, ',');
  2200. if (tvb_current_offset == -1 || tvb_current_offset > tvb_packages_end_offset){
  2201. tvb_current_offset = tvb_packages_end_offset;
  2202. }
  2203. /* Descriptor includes no parameters */
  2204. if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
  2205. tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
  2206. }
  2207. /* Descriptor includes Parameters */
  2208. if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
  2209. while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
  2210. tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
  2211. tvb_packages_end_offset, '{');
  2212. if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
  2213. tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
  2214. tvb_packages_end_offset, '}');
  2215. }
  2216. }
  2217. tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
  2218. proto_tree_add_text(megaco_packagesdescriptor_tree, tvb, tvb_previous_offset, tokenlen,
  2219. "%s", tvb_format_text(tvb,tvb_previous_offset,
  2220. tokenlen));
  2221. tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
  2222. tvb_packages_end_offset, ',');
  2223. if (tvb_current_offset == -1 || tvb_current_offset > tvb_packages_end_offset ){
  2224. tvb_current_offset = tvb_packages_end_offset;
  2225. }
  2226. tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
  2227. tvb_LBRKT = tvb_previous_offset;
  2228. tvb_RBRKT = tvb_previous_offset;
  2229. } while ( tvb_current_offset < tvb_packages_end_offset );
  2230. }
  2231. }
  2232. /* The list of error code values is fetched from http://www.iana.org/assignments/megaco-h248 */
  2233. /* 2003-08-28 */
  2234. static const value_string MEGACO_error_code_vals[] = {
  2235. {400, "Syntax error in message"},
  2236. {401, "Protocol Error"},
  2237. {402, "Unauthorized"},
  2238. {403, "Syntax error in transaction request"},
  2239. {406, "Version Not Supported"},
  2240. {410, "Incorrect identifier"},
  2241. {411, "The transaction refers to an unknown ContextId"},
  2242. {412, "No ContextIDs available"},
  2243. {421, "Unknown action or illegal combination of actions"},
  2244. {422, "Syntax Error in Action"},
  2245. {430, "Unknown TerminationID"},
  2246. {431, "No TerminationID matched a wildcard"},
  2247. {432, "Out of TerminationIDs or No TerminationID available"},
  2248. {433, "TerminationID is already in a Context"},
  2249. {434, "Max number of Terminations in a Context exceeded"},
  2250. {435, "Termination ID is not in specified Context"},
  2251. {440, "Unsupported or unknown Package"},
  2252. {441, "Missing Remote or Local Descriptor"},
  2253. {442, "Syntax Error in Command"},
  2254. {443, "Unsupported or Unknown Command"},
  2255. {444, "Unsupported or Unknown Descriptor"},
  2256. {445, "Unsupported or Unknown Property"},
  2257. {446, "Unsupported or Unknown Parameter"},
  2258. {447, "Descriptor not legal in this command"},
  2259. {448, "Descriptor appears twice in a command"},
  2260. {450, "No such property in this package"},
  2261. {451, "No such event in this package"},
  2262. {452, "No such signal in this package"},
  2263. {453, "No such statistic in this package"},
  2264. {454, "No such parameter value in this package"},
  2265. {455, "Property illegal in this Descriptor"},
  2266. {456, "Property appears twice in this Descriptor"},
  2267. {457, "Missing parameter in signal or event"},
  2268. {458, "Unexpected Event/Request ID"},
  2269. {459, "Unsupported or Unknown Profile"},
  2270. {471, "Implied Add for Multiplex failure"},
  2271. {500, "Internal software Failure in MG"},
  2272. {501, "Not Implemented"},
  2273. {502, "Not ready."},
  2274. {503, "Service Unavailable"},
  2275. {504, "Command Received from unauthorized entity"},
  2276. {505, "Transaction Request Received before a Service Change Reply has been received"},
  2277. {506, "Number of Transaction Pendings Exceeded"},
  2278. {510, "Insufficient resources"},
  2279. {512, "Media Gateway unequipped to detect requested Event"},
  2280. {513, "Media Gateway unequipped to generate requested Signals"},
  2281. {514, "Media Gateway cannot send the specified announcement"},
  2282. {515, "Unsupported Media Type"},
  2283. {517, "Unsupported or invalid mode"},
  2284. {518, "Event buffer full"},
  2285. {519, "Out of space to store digit map"},
  2286. {520, "Digit Map undefined in the MG"},
  2287. {521, "Termination is ServiceChanging"},
  2288. {526, "Insufficient bandwidth"},
  2289. {529, "Internal hardware failure in MG"},
  2290. {530, "Temporary Network failure"},
  2291. {531, "Permanent Network failure"},
  2292. {532, "Audited Property, Statistic, Event or Signal does not exist"},
  2293. {533, "Response exceeds maximum transport PDU size"},
  2294. {534, "Illegal write or read only property"},
  2295. {540, "Unexpected initial hook state"},
  2296. {581, "Does Not Exist"},
  2297. {600, "Illegal syntax within an announcement specification"},
  2298. {601, "Variable type not supported"},
  2299. {602, "Variable value out of range"},
  2300. {603, "Category not supported"},
  2301. {604, "Selector type not supported"},
  2302. {605, "Selector value not supported"},
  2303. {606, "Unknown segment ID"},
  2304. {607, "Mismatch between play specification and provisioned data"},
  2305. {608, "Provisioning error"},
  2306. {609, "Invalid offset"},
  2307. {610, "No free segment IDs"},
  2308. {611, "Temporary segment not found"},
  2309. {612, "Segment in use"},
  2310. {613, "ISP port limit overrun"},
  2311. {614, "No modems available"},
  2312. {615, "Calling number unacceptable"},
  2313. {616, "Called number unacceptable"},
  2314. { 0, NULL }
  2315. };
  2316. static void
  2317. dissect_megaco_errordescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
  2318. {
  2319. gint tokenlen;
  2320. gint error_code;
  2321. guint8 error[4];
  2322. gint tvb_current_offset;
  2323. proto_item* item;
  2324. proto_item* hidden_item;
  2325. tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset , tvb_RBRKT, '=');
  2326. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
  2327. tvb_get_nstringz0(tvb,tvb_current_offset,4,error);
  2328. error_code = atoi(error);
  2329. hidden_item = proto_tree_add_string(megaco_tree_command_line, hf_megaco_error_descriptor, tvb,
  2330. tvb_current_offset, 3,
  2331. tvb_format_text(tvb, tvb_current_offset,
  2332. 3));
  2333. PROTO_ITEM_SET_HIDDEN(hidden_item);
  2334. tokenlen = (tvb_RBRKT) - tvb_previous_offset+1;
  2335. proto_tree_add_string(megaco_tree_command_line, hf_megaco_error_descriptor, tvb,
  2336. tvb_previous_offset, tokenlen,
  2337. tvb_format_text(tvb, tvb_previous_offset,
  2338. tokenlen));
  2339. item = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_current_offset, 3,
  2340. "Error code: %s",
  2341. val_to_str(error_code, MEGACO_error_code_vals,
  2342. "Unknown (%u)"));
  2343. PROTO_ITEM_SET_GENERATED(item);
  2344. }
  2345. static void
  2346. dissect_megaco_TerminationStatedescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree, gint tvb_next_offset, gint tvb_current_offset)
  2347. {
  2348. gint tokenlen;
  2349. gint tvb_offset;
  2350. guint8 tempchar;
  2351. proto_tree *megaco_TerminationState_tree, *megaco_TerminationState_ti;
  2352. tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_next_offset, '=');
  2353. tokenlen = tvb_next_offset - tvb_current_offset;
  2354. /*
  2355. megaco_TerminationState_ti = proto_tree_add_item(megaco_mediadescriptor_tree,hf_megaco_TerminationState_descriptor,tvb,tvb_current_offset,tokenlen, ENC_ASCII|ENC_NA);
  2356. megaco_TerminationState_tree = proto_item_add_subtree(megaco_TerminationState_ti, ett_megaco_TerminationState);
  2357. */
  2358. megaco_TerminationState_ti = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_current_offset, tokenlen,
  2359. "%s", tvb_format_text(tvb, tvb_current_offset, tokenlen));
  2360. megaco_TerminationState_tree = proto_item_add_subtree(megaco_TerminationState_ti, ett_megaco_TerminationState);
  2361. while ( tvb_offset < tvb_next_offset && tvb_offset != -1 ){
  2362. tempchar = tvb_get_guint8(tvb, tvb_current_offset);
  2363. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2364. if ( (tempchar >= 'a')&& (tempchar <= 'z'))
  2365. tempchar = tempchar - 0x20;
  2366. switch ( tempchar ){
  2367. case 'S':
  2368. tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
  2369. if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
  2370. tvb_offset = tvb_next_offset;
  2371. }
  2372. tokenlen = tvb_offset - tvb_current_offset;
  2373. proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Service_State, tvb,
  2374. tvb_current_offset, tokenlen,
  2375. tvb_format_text(tvb, tvb_current_offset,
  2376. tokenlen));
  2377. break;
  2378. case 'B':
  2379. tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
  2380. if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
  2381. tvb_offset = tvb_next_offset;
  2382. }
  2383. tokenlen = tvb_offset - tvb_current_offset;
  2384. proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Event_Buffer_Control, tvb,
  2385. tvb_current_offset, tokenlen,
  2386. tvb_format_text(tvb, tvb_current_offset,
  2387. tokenlen));
  2388. break;
  2389. case 'E':
  2390. tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
  2391. if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
  2392. tvb_offset = tvb_next_offset;
  2393. }
  2394. tokenlen = tvb_offset - tvb_current_offset;
  2395. proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Event_Buffer_Control, tvb,
  2396. tvb_current_offset, tokenlen,
  2397. tvb_format_text(tvb, tvb_current_offset,
  2398. tokenlen));
  2399. break;
  2400. default:
  2401. tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
  2402. if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
  2403. tvb_offset = tvb_next_offset;
  2404. }
  2405. tokenlen = tvb_offset - tvb_current_offset;
  2406. proto_tree_add_text(megaco_TerminationState_tree, tvb, tvb_current_offset, tokenlen,
  2407. "%s", tvb_format_text(tvb,tvb_current_offset,tokenlen));
  2408. break;
  2409. }
  2410. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2411. tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_next_offset, '=');
  2412. }
  2413. proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_next_offset, 1,
  2414. "%s", tvb_format_text(tvb, tvb_next_offset, 1));
  2415. }
  2416. static void
  2417. dissect_megaco_Localdescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree,packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset)
  2418. {
  2419. gint tokenlen;
  2420. tvbuff_t *next_tvb;
  2421. proto_tree *megaco_localdescriptor_tree, *megaco_localdescriptor_ti;
  2422. tokenlen = tvb_next_offset - tvb_current_offset;
  2423. /*
  2424. megaco_localdescriptor_ti = proto_tree_add_item(megaco_mediadescriptor_tree,hf_megaco_Local_descriptor,tvb,tvb_current_offset,tokenlen, ENC_ASCII|ENC_NA);
  2425. */
  2426. megaco_localdescriptor_ti = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_current_offset, tokenlen,
  2427. "%s", tvb_format_text(tvb, tvb_current_offset, tokenlen));
  2428. megaco_localdescriptor_tree = proto_item_add_subtree(megaco_localdescriptor_ti, ett_megaco_Localdescriptor);
  2429. tokenlen = tvb_next_offset - tvb_current_offset;
  2430. if ( tokenlen > 3 ){
  2431. next_tvb = tvb_new_subset(tvb, tvb_current_offset, tokenlen, tokenlen);
  2432. call_dissector(sdp_handle, next_tvb, pinfo, megaco_localdescriptor_tree);
  2433. }
  2434. }
  2435. /*
  2436. * localControlDescriptor = LocalControlToken LBRKT localParm
  2437. * *(COMMA localParm) RBRKT
  2438. * ; at-most-once per item
  2439. * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
  2440. */
  2441. #define MEGACO_MODETOKEN 1
  2442. #define MEGACO_RESERVEDVALUETOKEN 2
  2443. #define MEGACO_RESERVEDGROUPTOKEN 3
  2444. #define MEGACO_H324_H223CAPR 4
  2445. #define MEGACO_H324_MUXTBL_IN 5
  2446. #define MEGACO_H324_MUXTBL_OUT 6
  2447. #define MEGACO_DS_DSCP 7
  2448. #define MEGACO_GM_SAF 8
  2449. #define MEGACO_GM_SAM 9
  2450. #define MEGACO_GM_SPF 10
  2451. #define MEGACO_GM_SPR 11
  2452. #define MEGACO_GM_ESAS 12
  2453. #define MEGACO_GM_LSA 13
  2454. #define MEGACO_GM_ESPS 14
  2455. #define MEGACO_GM_LSP 15
  2456. #define MEGACO_GM_RSB 16
  2457. static const megaco_tokens_t megaco_localParam_names[] = {
  2458. { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
  2459. /* streamMode */
  2460. { "Mode", "MO" }, /* 1 */
  2461. { "ReservedValue", "RV" }, /* 2 */
  2462. { "ReservedGroup", "RG" }, /* 3 */
  2463. /* propertyParm = pkgdName parmValue
  2464. * Add more package names as needed.
  2465. */
  2466. { "h324/h223capr", NULL }, /* 4 */
  2467. { "h324/muxtbl_in", NULL }, /* 5 */
  2468. { "h324/muxtbl_out", NULL }, /* 6 */
  2469. { "ds/dscp", NULL }, /* 7 */
  2470. { "gm/saf", NULL }, /* 8 */
  2471. { "gm/sam", NULL }, /* 9 */
  2472. { "gm/spf", NULL }, /* 10 */
  2473. { "gm/spr", NULL }, /* 11 */
  2474. { "gm/esas", NULL }, /* 12 */
  2475. { "gm/lsa", NULL }, /* 13 */
  2476. { "gm/esps", NULL }, /* 14 */
  2477. { "gm/lsp", NULL }, /* 15 */
  2478. { "gm/rsb", NULL }, /* 16 */
  2479. };
  2480. /* Returns index of megaco_tokens_t */
  2481. static gint find_megaco_localParam_names(tvbuff_t *tvb, int offset, guint header_len)
  2482. {
  2483. guint i;
  2484. for (i = 1; i < array_length(megaco_localParam_names); i++) {
  2485. if (header_len == strlen(megaco_localParam_names[i].name) &&
  2486. tvb_strncaseeql(tvb, offset, megaco_localParam_names[i].name, header_len) == 0)
  2487. return i;
  2488. if (megaco_localParam_names[i].compact_name != NULL &&
  2489. header_len == strlen(megaco_localParam_names[i].compact_name) &&
  2490. tvb_strncaseeql(tvb, offset, megaco_localParam_names[i].compact_name, header_len) == 0)
  2491. return i;
  2492. }
  2493. return -1;
  2494. }
  2495. static void
  2496. dissect_megaco_LocalControldescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset)
  2497. {
  2498. gint tokenlen;
  2499. guint token_name_len;
  2500. gint tvb_offset,tvb_help_offset;
  2501. gint token_index = 0;
  2502. gchar *msg;
  2503. proto_item* item;
  2504. guint8 code_str[3];
  2505. /*proto_tree *megaco_LocalControl_tree, *megaco_LocalControl_ti; */
  2506. tvb_offset = 0;
  2507. /*
  2508. tokenlen = tvb_next_offset - tvb_current_offset;
  2509. megaco_LocalControl_ti = proto_tree_add_item(megaco_mediadescriptor_tree,hf_megaco_LocalControl_descriptor,tvb,tvb_current_offset,tokenlen, ENC_ASCII|ENC_NA);
  2510. megaco_LocalControl_tree = proto_item_add_subtree(megaco_LocalControl_ti, ett_megaco_LocalControldescriptor);
  2511. */
  2512. while ( tvb_offset < tvb_next_offset && tvb_offset != -1 ){
  2513. tvb_help_offset = tvb_current_offset;
  2514. /*
  2515. * Find local parameter name
  2516. * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
  2517. * pkgdName = (PackageName SLASH ItemID) ;specific item
  2518. * / (PackageName SLASH "*") ;all events in package
  2519. * / ("*" SLASH "*") ; all events supported by the MG
  2520. */
  2521. /* Find token length */
  2522. for (tvb_offset=tvb_current_offset; tvb_offset < tvb_next_offset; tvb_offset++){
  2523. guint8 octet;
  2524. octet = tvb_get_guint8(tvb, tvb_offset);
  2525. if (!isalnum(octet)){
  2526. if ((octet!='/')&&(octet!='_')){
  2527. break;
  2528. }
  2529. }
  2530. }
  2531. token_name_len = tvb_offset - tvb_current_offset;
  2532. /* Debug Code
  2533. proto_tree_add_text(megaco_LocalControl_tree, tvb, tvb_current_offset, token_name_len,
  2534. "%s", tvb_format_text(tvb,tvb_current_offset,token_name_len));
  2535. */
  2536. token_index = find_megaco_localParam_names(tvb, tvb_current_offset, token_name_len);
  2537. /* Find start of parameter value */
  2538. tvb_offset = tvb_find_guint8(tvb, tvb_offset , tvb_next_offset, '=');
  2539. if (tvb_offset == -1)
  2540. THROW(ReportedBoundsError);
  2541. /* Start search after '=' in case there is no SP*/
  2542. tvb_offset++;
  2543. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
  2544. /* find if there are more parameters or not */
  2545. tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
  2546. if ( tvb_offset < 0 || tvb_offset > tvb_next_offset ){
  2547. tvb_offset = tvb_next_offset;
  2548. }
  2549. tokenlen = megaco_tvb_skip_wsp_return(tvb,tvb_offset-1) - tvb_current_offset;
  2550. /* Debug Code
  2551. proto_tree_add_text(megaco_LocalControl_tree, tvb, tvb_current_offset, tokenlen,
  2552. "%s", tvb_format_text(tvb,tvb_current_offset,tokenlen));
  2553. */
  2554. switch ( token_index ){
  2555. case MEGACO_MODETOKEN: /* Mode */
  2556. proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_mode, tvb,
  2557. tvb_current_offset, tokenlen,
  2558. tvb_format_text(tvb, tvb_current_offset,
  2559. tokenlen));
  2560. col_append_fstr(pinfo->cinfo, COL_INFO, " (Mode:%s)",tvb_format_text(tvb, tvb_current_offset,tokenlen));
  2561. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2562. break;
  2563. case MEGACO_RESERVEDVALUETOKEN: /* ReservedValue */
  2564. proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_reserve_value, tvb,
  2565. tvb_current_offset, tokenlen,
  2566. tvb_format_text(tvb, tvb_current_offset,
  2567. tokenlen));
  2568. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2569. break;
  2570. case MEGACO_RESERVEDGROUPTOKEN: /* ReservedGroup */
  2571. proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_reserve_group, tvb,
  2572. tvb_current_offset, tokenlen,
  2573. tvb_format_text(tvb, tvb_current_offset,
  2574. tokenlen));
  2575. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2576. break;
  2577. case MEGACO_H324_H223CAPR: /* h324/h223capr */
  2578. proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_h324_h223capr, tvb,
  2579. tvb_current_offset, tokenlen,
  2580. tvb_format_text(tvb, tvb_current_offset,
  2581. tokenlen));
  2582. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2583. tokenlen = tvb_offset - tvb_help_offset;
  2584. msg=tvb_format_text(tvb,tvb_help_offset, tokenlen);
  2585. dissect_megaco_h324_h223caprn(tvb, pinfo, megaco_mediadescriptor_tree, tvb_help_offset, tokenlen, msg);
  2586. break;
  2587. case MEGACO_H324_MUXTBL_IN: /* h324/muxtbl_in */
  2588. proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_h324_muxtbl_in, tvb,
  2589. tvb_current_offset, tokenlen,
  2590. tvb_format_text(tvb, tvb_current_offset,
  2591. tokenlen));
  2592. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2593. tokenlen = tvb_offset - tvb_help_offset;
  2594. msg=tvb_format_text(tvb,tvb_help_offset, tokenlen);
  2595. /* Call the existing routine with tree = NULL to avoid an entry to the tree */
  2596. dissect_megaco_h245(tvb, pinfo, NULL, tvb_help_offset, tokenlen, msg);
  2597. break;
  2598. case MEGACO_H324_MUXTBL_OUT:
  2599. proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_h324_muxtbl_out, tvb,
  2600. tvb_current_offset, tokenlen,
  2601. tvb_format_text(tvb, tvb_current_offset,
  2602. tokenlen));
  2603. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2604. tokenlen = tvb_offset - tvb_help_offset;
  2605. msg=tvb_format_text(tvb,tvb_help_offset, tokenlen);
  2606. /* Call the existing routine with tree = NULL to avoid an entry to the tree */
  2607. dissect_megaco_h245(tvb, pinfo, NULL, tvb_help_offset, tokenlen, msg);
  2608. break;
  2609. case MEGACO_DS_DSCP:
  2610. item = proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_ds_dscp, tvb,
  2611. tvb_current_offset, tokenlen,
  2612. tvb_format_text(tvb, tvb_current_offset,
  2613. tokenlen));
  2614. tvb_get_nstringz0(tvb,tvb_current_offset,3,code_str);
  2615. proto_item_append_text(item,"[ %s ]",
  2616. val_to_str_ext((guint32)strtoul(code_str,NULL,16), &dscp_vals_ext,"Unknown (%u)"));
  2617. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2618. break;
  2619. case MEGACO_GM_SAF:
  2620. tokenlen = tvb_offset - tvb_help_offset;
  2621. item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
  2622. "%s", tvb_format_text(tvb,tvb_help_offset,
  2623. tokenlen));
  2624. proto_item_append_text(item," [Remote Source Address Filtering]");
  2625. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2626. break;
  2627. case MEGACO_GM_SAM:
  2628. tokenlen = tvb_offset - tvb_help_offset;
  2629. item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
  2630. "%s", tvb_format_text(tvb,tvb_help_offset,
  2631. tokenlen));
  2632. proto_item_append_text(item," [Remote Source Address Mask]");
  2633. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2634. break;
  2635. case MEGACO_GM_SPF:
  2636. tokenlen = tvb_offset - tvb_help_offset;
  2637. item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
  2638. "%s", tvb_format_text(tvb,tvb_help_offset,
  2639. tokenlen));
  2640. proto_item_append_text(item," [Remote Source Port Filtering]");
  2641. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2642. break;
  2643. case MEGACO_GM_SPR:
  2644. tokenlen = tvb_offset - tvb_help_offset;
  2645. item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
  2646. "%s", tvb_format_text(tvb,tvb_help_offset,
  2647. tokenlen));
  2648. proto_item_append_text(item," [Remote Source Port Range]");
  2649. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2650. break;
  2651. case MEGACO_GM_ESAS:
  2652. tokenlen = tvb_offset - tvb_help_offset;
  2653. item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
  2654. "%s", tvb_format_text(tvb,tvb_help_offset,
  2655. tokenlen));
  2656. proto_item_append_text(item," [Explicit Source Address Setting]");
  2657. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2658. break;
  2659. default:
  2660. tokenlen = tvb_offset - tvb_help_offset;
  2661. proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
  2662. "%s", tvb_format_text(tvb,tvb_help_offset,
  2663. tokenlen));
  2664. tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
  2665. break;
  2666. }
  2667. }
  2668. }
  2669. /* Copied from MGCP dissector, prints whole message in raw text */
  2670. static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree){
  2671. gint tvb_linebegin,tvb_lineend,tvb_len,linelen;
  2672. tvb_linebegin = 0;
  2673. tvb_len = tvb_length(tvb);
  2674. proto_tree_add_text(tree, tvb, 0, -1,"-------------- (RAW text output) ---------------");
  2675. do {
  2676. linelen = tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend,FALSE);
  2677. proto_tree_add_text(tree, tvb, tvb_linebegin, linelen,
  2678. "%s", tvb_format_text_wsp(tvb,tvb_linebegin,
  2679. linelen));
  2680. tvb_linebegin = tvb_lineend;
  2681. } while ( tvb_lineend < tvb_len );
  2682. }
  2683. /*
  2684. * megaco_tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
  2685. * character following offset or offset + maxlength -1 whichever
  2686. * is smaller.
  2687. *
  2688. * Parameters:
  2689. * tvb - The tvbuff in which we are skipping whitespaces, tab and end_of_line characters.
  2690. * offset - The offset in tvb from which we begin trying to skip whitespace.
  2691. *
  2692. * Returns: The position in tvb of the first non-whitespace
  2693. */
  2694. static gint megaco_tvb_skip_wsp(tvbuff_t* tvb, gint offset ){
  2695. gint counter = offset;
  2696. gint end,tvb_len;
  2697. guint8 tempchar;
  2698. tvb_len = tvb_length(tvb);
  2699. end = tvb_len;
  2700. for(counter = offset; counter < end &&
  2701. ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
  2702. tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter++);
  2703. return (counter);
  2704. }
  2705. static gint megaco_tvb_skip_wsp_return(tvbuff_t* tvb, gint offset){
  2706. gint counter = offset;
  2707. gint end;
  2708. guint8 tempchar;
  2709. end = 0;
  2710. for(counter = offset; counter > end &&
  2711. ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
  2712. tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter--);
  2713. counter++;
  2714. return (counter);
  2715. }
  2716. static gint megaco_tvb_find_token(tvbuff_t* tvb, gint offset, gint maxlength){
  2717. gint counter = 0;
  2718. gint pos = offset;
  2719. guchar needle;
  2720. do {
  2721. pos = tvb_pbrk_guint8(tvb, pos + 1, maxlength, "{}", &needle);
  2722. if(pos == -1)
  2723. return -1;
  2724. switch(needle){
  2725. case '{':
  2726. counter++;
  2727. break;
  2728. case '}':
  2729. counter--;
  2730. break;
  2731. default:
  2732. break;
  2733. }
  2734. } while (counter>0);
  2735. if(counter<0)
  2736. return -1;
  2737. else
  2738. {
  2739. pos = megaco_tvb_skip_wsp(tvb,pos+1);
  2740. return pos;
  2741. }
  2742. }
  2743. void proto_reg_handoff_megaco(void);
  2744. void
  2745. proto_register_megaco(void)
  2746. {
  2747. static hf_register_info hf[] = {
  2748. { &hf_megaco_audititem,
  2749. { "Audit Item", "megaco.audititem", FT_STRING, BASE_NONE, NULL, 0x0,
  2750. "Identity of item to be audited", HFILL }},
  2751. { &hf_megaco_audit_descriptor,
  2752. { "Audit Descriptor", "megaco.audit", FT_NONE, BASE_NONE, NULL, 0x0,
  2753. "Audit Descriptor of the megaco Command", HFILL }},
  2754. #if 0
  2755. { &hf_megaco_command_line,
  2756. { "Command line", "megaco.command_line", FT_STRING, BASE_NONE, NULL, 0x0,
  2757. "Commands of this message", HFILL }},
  2758. #endif
  2759. { &hf_megaco_command,
  2760. { "Command", "megaco.command", FT_STRING, BASE_NONE, NULL, 0x0,
  2761. "Command of this message", HFILL }},
  2762. { &hf_megaco_Context,
  2763. { "Context", "megaco.context", FT_STRING, BASE_NONE, NULL, 0x0,
  2764. "Context ID of this message", HFILL }},
  2765. { &hf_megaco_digitmap_descriptor,
  2766. { "DigitMap Descriptor", "megaco.digitmap", FT_STRING, BASE_NONE, NULL, 0x0,
  2767. "DigitMap Descriptor of the megaco Command", HFILL }},
  2768. { &hf_megaco_error_descriptor,
  2769. { "ERROR Descriptor", "megaco.error", FT_STRING, BASE_NONE, NULL, 0x0,
  2770. "Error Descriptor of the megaco Command", HFILL }},
  2771. { &hf_megaco_error_Frame,
  2772. { "ERROR frame", "megaco.error_frame", FT_STRING, BASE_NONE, NULL, 0x0,
  2773. "Syntax error", HFILL }},
  2774. { &hf_megaco_Event_Buffer_Control,
  2775. { "Event Buffer Control", "megaco.eventbuffercontrol", FT_STRING, BASE_NONE, NULL, 0x0,
  2776. "Event Buffer Control in Termination State Descriptor", HFILL }},
  2777. #if 0
  2778. { &hf_megaco_events_descriptor,
  2779. { "Events Descriptor", "megaco.events", FT_STRING, BASE_NONE, NULL, 0x0,
  2780. "Events Descriptor of the megaco Command", HFILL }},
  2781. #endif
  2782. #if 0
  2783. { &hf_megaco_Local_descriptor,
  2784. { "Local Descriptor", "megaco.localdescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
  2785. "Local Descriptor in Media Descriptor", HFILL }},
  2786. #endif
  2787. #if 0
  2788. { &hf_megaco_LocalControl_descriptor,
  2789. { "Local Control Descriptor", "megaco.localcontroldescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
  2790. "Local Control Descriptor in Media Descriptor", HFILL }},
  2791. #endif
  2792. #if 0
  2793. { &hf_megaco_media_descriptor,
  2794. { "Media Descriptor", "megaco.media", FT_STRING, BASE_NONE, NULL, 0x0,
  2795. "Media Descriptor of the megaco Command", HFILL }},
  2796. #endif
  2797. { &hf_megaco_modem_descriptor,
  2798. { "Modem Descriptor", "megaco.modem", FT_STRING, BASE_NONE, NULL, 0x0,
  2799. "Modem Descriptor of the megaco Command", HFILL }},
  2800. { &hf_megaco_mode,
  2801. { "Mode", "megaco.mode", FT_STRING, BASE_NONE, NULL, 0x0,
  2802. "Mode sendonly/receiveonly/inactive/loopback", HFILL }},
  2803. { &hf_megaco_multiplex_descriptor,
  2804. { "Multiplex Descriptor", "megaco.multiplex", FT_STRING, BASE_NONE, NULL, 0x0,
  2805. "Multiplex Descriptor of the megaco Command", HFILL }},
  2806. #if 0
  2807. { &hf_megaco_observedevents_descriptor,
  2808. { "Observed Events Descriptor", "megaco.observedevents", FT_STRING, BASE_NONE, NULL, 0x0,
  2809. "Observed Events Descriptor of the megaco Command", HFILL }},
  2810. #endif
  2811. { &hf_megaco_packages_descriptor,
  2812. { "Packages Descriptor", "megaco.packagesdescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
  2813. NULL, HFILL }},
  2814. { &hf_megaco_pkgdname,
  2815. { "pkgdName", "megaco.pkgdname", FT_STRING, BASE_NONE, NULL, 0x0,
  2816. "PackageName SLASH ItemID", HFILL }},
  2817. #if 0
  2818. { &hf_megaco_Remote_descriptor,
  2819. { "Remote Descriptor", "megaco.remotedescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
  2820. "Remote Descriptor in Media Descriptor", HFILL }},
  2821. #endif
  2822. { &hf_megaco_reserve_group,
  2823. { "Reserve Group", "megaco.reservegroup", FT_STRING, BASE_NONE, NULL, 0x0,
  2824. "Reserve Group on or off", HFILL }},
  2825. { &hf_megaco_h324_muxtbl_in,
  2826. { "h324/muxtbl_in", "megaco.h324_muxtbl_in", FT_STRING, BASE_NONE, NULL, 0x0,
  2827. NULL, HFILL }},
  2828. { &hf_megaco_h324_muxtbl_out,
  2829. { "h324/muxtbl_out", "megaco.h324_muxtbl_out", FT_STRING, BASE_NONE, NULL, 0x0,
  2830. NULL, HFILL }},
  2831. { &hf_megaco_ds_dscp,
  2832. { "ds/dscp", "megaco.ds_dscp", FT_STRING, BASE_NONE, NULL, 0x0,
  2833. "ds/dscp Differentiated Services Code Point", HFILL }},
  2834. { &hf_megaco_h324_h223capr,
  2835. { "h324/h223capr", "megaco.h324_h223capr", FT_STRING, BASE_NONE, NULL, 0x0,
  2836. NULL, HFILL }},
  2837. { &hf_megaco_reserve_value,
  2838. { "Reserve Value", "megaco.reservevalue", FT_STRING, BASE_NONE, NULL, 0x0,
  2839. "Reserve Value on or off", HFILL }},
  2840. { &hf_megaco_requestid,
  2841. { "RequestID", "megaco.requestid", FT_STRING, BASE_NONE, NULL, 0x0,
  2842. "RequestID in Events or Observedevents Descriptor", HFILL }},
  2843. #if 0
  2844. { &hf_megaco_servicechange_descriptor,
  2845. { "Service Change Descriptor", "megaco.servicechange", FT_STRING, BASE_NONE, NULL, 0x0,
  2846. "Service Change Descriptor of the megaco Command", HFILL }},
  2847. #endif
  2848. { &hf_megaco_Service_State,
  2849. { "Service State", "megaco.servicestates", FT_STRING, BASE_NONE, NULL, 0x0,
  2850. "Service States in Termination State Descriptor", HFILL }},
  2851. #if 0
  2852. { &hf_megaco_signal_descriptor,
  2853. { "Signal Descriptor", "megaco.signal", FT_STRING, BASE_NONE, NULL, 0x0,
  2854. "Signal Descriptor of the megaco Command", HFILL }},
  2855. #endif
  2856. { &hf_megaco_statistics_descriptor,
  2857. { "Statistics Descriptor", "megaco.statistics", FT_STRING, BASE_NONE, NULL, 0x0,
  2858. "Statistics Descriptor of the megaco Command", HFILL }},
  2859. { &hf_megaco_streamid,
  2860. { "StreamID", "megaco.streamid", FT_STRING, BASE_NONE, NULL, 0x0,
  2861. "StreamID in the Media Descriptor", HFILL }},
  2862. { &hf_megaco_termid,
  2863. { "Termination ID", "megaco.termid", FT_STRING, BASE_NONE, NULL, 0x0,
  2864. "Termination ID of this Command", HFILL }},
  2865. #if 0
  2866. { &hf_megaco_TerminationState_descriptor,
  2867. { "Termination State Descriptor", "megaco.terminationstate", FT_STRING, BASE_NONE, NULL, 0x0,
  2868. "Termination State Descriptor in Media Descriptor", HFILL }},
  2869. #endif
  2870. { &hf_megaco_topology_descriptor,
  2871. { "Topology Descriptor", "megaco.topology", FT_STRING, BASE_NONE, NULL, 0x0,
  2872. "Topology Descriptor of the megaco Command", HFILL }},
  2873. { &hf_megaco_transaction,
  2874. { "Transaction", "megaco.transaction", FT_STRING, BASE_NONE, NULL, 0x0,
  2875. "Message Originator", HFILL }},
  2876. { &hf_megaco_transid,
  2877. { "Transaction ID", "megaco.transid", FT_STRING, BASE_NONE, NULL, 0x0,
  2878. "Transaction ID of this message", HFILL }},
  2879. { &hf_megaco_mId,
  2880. { "MediagatewayID", "megaco.mId", FT_STRING, BASE_NONE, NULL, 0x0,
  2881. "Mediagateway ID", HFILL }},
  2882. { &hf_megaco_version,
  2883. { "Version", "megaco.version", FT_STRING, BASE_NONE, NULL, 0x0,
  2884. NULL, HFILL }},
  2885. #if 0
  2886. { &hf_megaco_h245,
  2887. { "h245", "megaco.h245", FT_STRING, BASE_NONE, NULL, 0x0,
  2888. "Embedded H.245 message", HFILL }},
  2889. #endif
  2890. { &hf_megaco_h223Capability,
  2891. { "h223Capability", "megaco.h245.h223Capability", FT_NONE, BASE_NONE, NULL, 0,
  2892. "megaco.h245.H223Capability", HFILL }},
  2893. GCP_HF_ARR_ELEMS("megaco",megaco_ctx_ids),
  2894. /* Add more fields here */
  2895. };
  2896. static gint *ett[] = {
  2897. &ett_megaco,
  2898. &ett_megaco_message,
  2899. &ett_megaco_message_body,
  2900. &ett_megaco_context,
  2901. &ett_megaco_command_line,
  2902. &ett_megaco_descriptors,
  2903. &ett_megaco_mediadescriptor,
  2904. &ett_megaco_TerminationState,
  2905. &ett_megaco_Remotedescriptor,
  2906. &ett_megaco_Localdescriptor,
  2907. &ett_megaco_LocalControldescriptor,
  2908. &ett_megaco_auditdescriptor,
  2909. &ett_megaco_eventsdescriptor,
  2910. &ett_megaco_observedeventsdescriptor,
  2911. &ett_megaco_observedevent,
  2912. &ett_megaco_packagesdescriptor,
  2913. &ett_megaco_requestedevent,
  2914. &ett_megaco_signalsdescriptor,
  2915. &ett_megaco_requestedsignal,
  2916. &ett_megaco_h245,
  2917. GCP_ETT_ARR_ELEMS(megaco_ctx_ids),
  2918. };
  2919. static ei_register_info ei[] = {
  2920. { &ei_megaco_errored_command, { "megaco.errored_command", PI_RESPONSE_CODE, PI_WARN, "Errored Command", EXPFILL }},
  2921. };
  2922. module_t *megaco_module;
  2923. expert_module_t* expert_megaco;
  2924. proto_megaco = proto_register_protocol("MEGACO",
  2925. "MEGACO", "megaco");
  2926. register_dissector("megaco", dissect_megaco_text, proto_megaco);
  2927. proto_register_field_array(proto_megaco, hf, array_length(hf));
  2928. proto_register_subtree_array(ett, array_length(ett));
  2929. expert_megaco = expert_register_protocol(proto_megaco);
  2930. expert_register_field_array(expert_megaco, ei, array_length(ei));
  2931. /* Register our configuration options, particularly our ports */
  2932. megaco_module = prefs_register_protocol(proto_megaco, proto_reg_handoff_megaco);
  2933. prefs_register_uint_preference(megaco_module, "sctp.txt_port",
  2934. "MEGACO Text SCTP Port",
  2935. "Set the SCTP port for MEGACO text messages",
  2936. 10, &global_megaco_txt_sctp_port);
  2937. prefs_register_uint_preference(megaco_module, "tcp.txt_port",
  2938. "MEGACO Text TCP Port",
  2939. "Set the TCP port for MEGACO text messages",
  2940. 10, &global_megaco_txt_tcp_port);
  2941. prefs_register_uint_preference(megaco_module, "udp.txt_port",
  2942. "MEGACO Text UDP Port",
  2943. "Set the UDP port for MEGACO text messages",
  2944. 10, &global_megaco_txt_udp_port);
  2945. #if 0
  2946. prefs_register_uint_preference(megaco_module, "sctp.bin_port",
  2947. "MEGACO Binary SCTP Port",
  2948. "Set the SCTP port for MEGACO binary messages",
  2949. 10, &global_megaco_bin_sctp_port);
  2950. prefs_register_uint_preference(megaco_module, "tcp.bin_port",
  2951. "MEGACO Binary TCP Port",
  2952. "Set the TCP port for MEGACO binary messages",
  2953. 10, &global_megaco_bin_tcp_port);
  2954. prefs_register_uint_preference(megaco_module, "udp.bin_port",
  2955. "MEGACO Binary UDP Port",
  2956. "Set the UDP port for MEGACO binary messages",
  2957. 10, &global_megaco_bin_udp_port);
  2958. #endif
  2959. prefs_register_bool_preference(megaco_module, "display_raw_text",
  2960. "Display raw text for MEGACO message",
  2961. "Specifies that the raw text of the "
  2962. "MEGACO message should be displayed "
  2963. "instead of (or in addition to) the "
  2964. "dissection tree",
  2965. &global_megaco_raw_text);
  2966. prefs_register_bool_preference(megaco_module, "display_dissect_tree",
  2967. "Display tree dissection for MEGACO message",
  2968. "Specifies that the dissection tree of the "
  2969. "MEGACO message should be displayed "
  2970. "instead of (or in addition to) the "
  2971. "raw text",
  2972. &global_megaco_dissect_tree);
  2973. prefs_register_bool_preference(megaco_module, "ctx_info",
  2974. "Track Context",
  2975. "Maintain relationships between transactions and contexts "
  2976. "and display an extra tree showing context data",
  2977. &keep_persistent_data);
  2978. megaco_tap = register_tap("megaco");
  2979. }
  2980. /* Register all the bits needed with the filtering engine */
  2981. /* The registration hand-off routine */
  2982. void
  2983. proto_reg_handoff_megaco(void)
  2984. {
  2985. static gboolean megaco_prefs_initialized = FALSE;
  2986. static dissector_handle_t megaco_text_tcp_handle;
  2987. /*
  2988. * Variables to allow for proper deletion of dissector registration when
  2989. * the user changes port from the gui.
  2990. */
  2991. static guint txt_sctp_port;
  2992. static guint txt_tcp_port;
  2993. static guint txt_udp_port;
  2994. #if 0
  2995. static guint bin_sctp_port;
  2996. static guint bin_tcp_port;
  2997. static guint bin_udp_port;
  2998. #endif
  2999. if (!megaco_prefs_initialized) {
  3000. sdp_handle = find_dissector("sdp");
  3001. h245_handle = find_dissector("h245dg");
  3002. h248_handle = find_dissector("h248");
  3003. h248_otp_handle = find_dissector("h248_otp");
  3004. data_handle = find_dissector("data");
  3005. megaco_text_handle = find_dissector("megaco");
  3006. megaco_text_tcp_handle = create_dissector_handle(dissect_megaco_text_tcp, proto_megaco);
  3007. dissector_add_uint("sctp.ppi", H248_PAYLOAD_PROTOCOL_ID, megaco_text_handle);
  3008. megaco_prefs_initialized = TRUE;
  3009. } else {
  3010. dissector_delete_uint("sctp.port", txt_sctp_port, megaco_text_handle);
  3011. dissector_delete_uint("tcp.port", txt_tcp_port, megaco_text_tcp_handle);
  3012. dissector_delete_uint("udp.port", txt_udp_port, megaco_text_handle);
  3013. }
  3014. /* Set our port number for future use */
  3015. txt_sctp_port = global_megaco_txt_sctp_port;
  3016. txt_tcp_port = global_megaco_txt_tcp_port;
  3017. txt_udp_port = global_megaco_txt_udp_port;
  3018. dissector_add_uint("sctp.port", global_megaco_txt_sctp_port, megaco_text_handle);
  3019. dissector_add_uint("tcp.port", global_megaco_txt_tcp_port, megaco_text_tcp_handle);
  3020. dissector_add_uint("udp.port", global_megaco_txt_udp_port, megaco_text_handle);
  3021. }