2 * Routines for megaco packet disassembly
5 * Christian Falckenberg, 2002/10/17
6 * Copyright (c) 2002 by Christian Falckenberg
7 * <christian.falckenberg@nortelnetworks.com>
9 * Christoph Wiest, 2003/06/28
10 * Modified 2003 by Christoph Wiest
11 * <ch.wiest@tesionmail.de>
12 * Modified 2004 by Anders Broman
13 * <anders.broman@ericsson.com>
14 * To handle TPKT headers if over TCP
15 * Modified 2005 by Karl Knoebl
16 * <karl.knoebl@siemens.com>
17 * provide info to COL_INFO and some "prettification"
19 * Copyright (c) 2006 Anders Broman <anders.broman@ericsson.com>
21 * Wireshark - Network traffic analyzer
22 * By Gerald Combs <gerald@wireshark.org>
23 * Copyright 1999 Gerald Combs
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version 2
28 * of the License, or (at your option) any later version.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
45 #include <epan/packet.h>
46 #include <epan/exceptions.h>
48 #include <epan/rtd_table.h>
49 #include <epan/prefs.h>
50 #include <epan/prefs-int.h>
51 #include <epan/exported_pdu.h>
52 #include <epan/asn1.h>
53 #include <epan/sctpppids.h>
54 #include <wsutil/strtoi.h>
55 #include "packet-ber.h"
56 #include "packet-tpkt.h"
57 #include "packet-h245.h"
58 #include "packet-h248.h"
59 #include "packet-ip.h"
61 void proto_register_megaco(void);
62 void proto_reg_handoff_megaco(void);
64 #define PORT_MEGACO_TXT 2944
65 #define PORT_MEGACO_BIN 2945
67 /* Define the megaco proto */
68 static int proto_megaco = -1;
70 /* Define headers for megaco */
71 static int hf_megaco_start = -1;
72 static int hf_megaco_version = -1;
73 static int hf_megaco_transaction = -1;
74 static int hf_megaco_transid = -1;
75 static int hf_megaco_Context = -1;
76 /* static int hf_megaco_command_line = -1; */
77 static int hf_megaco_command = -1;
78 static int hf_megaco_command_optional = -1;
79 static int hf_megaco_wildcard_response = -1;
80 static int hf_megaco_termid = -1;
84 /* Define headers in subtree for megaco */
85 static int hf_megaco_modem_descriptor = -1;
86 static int hf_megaco_multiplex_descriptor = -1;
87 static int hf_megaco_media_descriptor = -1;
88 static int hf_megaco_Local_descriptor = -1;
89 static int hf_megaco_events_descriptor = -1;
90 static int hf_megaco_signal_descriptor = -1;
91 static int hf_megaco_audit_descriptor = -1;
92 /* static int hf_megaco_servicechange_descriptor = -1; */
93 static int hf_megaco_digitmap_descriptor = -1;
94 static int hf_megaco_statistics_descriptor = -1;
95 static int hf_megaco_observedevents_descriptor = -1;
96 static int hf_megaco_topology_descriptor = -1;
97 static int hf_megaco_error_descriptor = -1;
98 static int hf_megaco_error_code = -1;
99 static int hf_megaco_error_string = -1;
100 static int hf_megaco_TerminationState_descriptor= -1;
101 /* static int hf_megaco_Remote_descriptor = -1; */
102 static int hf_megaco_LocalControl_descriptor = -1;
103 static int hf_megaco_packages_descriptor = -1;
104 static int hf_megaco_Service_State = -1;
105 static int hf_megaco_Event_Buffer_Control = -1;
106 static int hf_megaco_mode = -1;
107 static int hf_megaco_reserve_group = -1;
108 static int hf_megaco_h324_muxtbl_in = -1;
109 static int hf_megaco_h324_muxtbl_out = -1;
110 static int hf_megaco_ds_dscp = -1;
111 static int hf_megaco_gm_saf = -1;
112 static int hf_megaco_gm_sam = -1;
113 static int hf_megaco_gm_spf = -1;
114 static int hf_megaco_gm_spr = -1;
115 static int hf_megaco_gm_esas = -1;
116 static int hf_megaco_tman_pol = -1;
117 static int hf_megaco_gm_rsb = -1;
118 static int hf_megaco_tman_sdr = -1;
119 static int hf_megaco_tman_mbs = -1;
120 static int hf_megaco_tman_pdr = -1;
121 static int hf_megaco_tman_dvt = -1;
122 static int hf_megaco_ipdc_realm = -1;
123 static int hf_megaco_h324_h223capr = -1;
124 static int hf_megaco_reserve_value = -1;
125 static int hf_megaco_streamid = -1;
126 static int hf_megaco_requestid = -1;
127 static int hf_megaco_pkgdname = -1;
128 static int hf_megaco_mId = -1;
129 static int hf_megaco_h245 = -1;
130 static int hf_megaco_h223Capability = -1;
131 static int hf_megaco_audititem = -1;
133 /* Define the trees for megaco */
134 static int ett_megaco = -1;
135 static int ett_megaco_message = -1;
136 static int ett_megaco_message_body = -1;
137 static int ett_megaco_context = -1;
138 static int ett_megaco_command_line = -1;
139 static int ett_megaco_mediadescriptor = -1;
140 static int ett_megaco_descriptors = -1;
141 static int ett_megaco_raw_text = -1;
142 static int ett_megaco_error_descriptor = -1;
143 static int ett_megaco_TerminationState = -1;
144 static int ett_megaco_Localdescriptor = -1;
145 static int ett_megaco_Remotedescriptor = -1;
146 static int ett_megaco_LocalControldescriptor = -1;
147 static int ett_megaco_auditdescriptor = -1;
148 static int ett_megaco_eventsdescriptor = -1;
149 static int ett_megaco_statisticsdescriptor = -1;
150 static int ett_megaco_observedeventsdescriptor = -1;
151 static int ett_megaco_observedevent = -1;
152 static int ett_megaco_packagesdescriptor = -1;
153 static int ett_megaco_requestedevent = -1;
154 static int ett_megaco_signalsdescriptor = -1;
155 static int ett_megaco_requestedsignal = -1;
156 static int ett_megaco_h245 = -1;
158 static gcp_hf_ett_t megaco_ctx_ids = {{-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1}};
160 static expert_field ei_megaco_errored_command = EI_INIT;
161 static expert_field ei_megaco_no_command = EI_INIT;
162 static expert_field ei_megaco_no_descriptor = EI_INIT;
163 static expert_field ei_megaco_error_descriptor_transaction_list = EI_INIT;
164 static expert_field ei_megaco_parse_error = EI_INIT;
165 static expert_field ei_megaco_audit_descriptor = EI_INIT;
166 static expert_field ei_megaco_signal_descriptor = EI_INIT;
167 static expert_field ei_megaco_reason_invalid = EI_INIT;
168 static expert_field ei_megaco_error_code_invalid = EI_INIT;
170 static dissector_handle_t megaco_text_handle;
172 static int megaco_tap = -1;
173 static gint exported_pdu_tap = -1;
176 /* patterns used for tvb_ws_mempbrk_pattern_guint8 */
177 static ws_mempbrk_pattern pbrk_whitespace;
178 static ws_mempbrk_pattern pbrk_braces;
182 * Here are the global variables associated with
183 * the various user definable characteristics of the dissection
185 * MEGACO has two kinds of message formats: text and binary
187 * global_megaco_raw_text determines whether we are going to display
188 * the raw text of the megaco message, much like the HTTP dissector does.
190 * global_megaco_dissect_tree determines whether we are going to display
191 * a detailed tree that expresses a somewhat more semantically meaningful
194 static guint global_megaco_txt_sctp_port = PORT_MEGACO_TXT;
196 static guint global_megaco_bin_sctp_port = PORT_MEGACO_BIN;
197 static guint global_megaco_bin_tcp_port = PORT_MEGACO_BIN;
198 static guint global_megaco_bin_udp_port = PORT_MEGACO_BIN;
200 static gboolean global_megaco_raw_text = TRUE;
201 static gboolean global_megaco_dissect_tree = TRUE;
203 static const value_string megaco_context_vals[] = {
204 { CHOOSE_CONTEXT, "Choose one" },
205 { ALL_CONTEXTS, "All" },
206 { NULL_CONTEXT, "NULL" },
211 /* Some basic utility functions that are specific to this dissector */
212 static gint megaco_tvb_skip_wsp(tvbuff_t *tvb, gint offset);
213 static gint megaco_tvb_skip_wsp_return(tvbuff_t *tvb, gint offset);
215 #define NUM_TIMESTATS 12
217 static const value_string megaco_message_type[] = {
232 #define GCP_CMD_REPLY_CASE \
233 case GCP_CMD_ADD_REPLY: \
234 case GCP_CMD_MOVE_REPLY: \
235 case GCP_CMD_MOD_REPLY: \
236 case GCP_CMD_SUB_REPLY: \
237 case GCP_CMD_AUDITCAP_REPLY: \
238 case GCP_CMD_AUDITVAL_REPLY: \
239 case GCP_CMD_NOTIFY_REPLY: \
240 case GCP_CMD_SVCCHG_REPLY: \
241 case GCP_CMD_TOPOLOGY_REPLY: \
244 #define GCP_CMD_REQ_CASE \
245 case GCP_CMD_ADD_REQ: \
246 case GCP_CMD_MOVE_REQ: \
247 case GCP_CMD_MOD_REQ: \
248 case GCP_CMD_SUB_REQ: \
249 case GCP_CMD_AUDITCAP_REQ: \
250 case GCP_CMD_AUDITVAL_REQ: \
251 case GCP_CMD_NOTIFY_REQ: \
252 case GCP_CMD_SVCCHG_REQ: \
253 case GCP_CMD_TOPOLOGY_REQ: \
254 case GCP_CMD_CTX_ATTR_AUDIT_REQ: \
255 case GCP_CMD_OTHER_REQ:
258 megacostat_is_duplicate_reply(const gcp_cmd_t* cmd)
264 gcp_cmd_msg_t *cmd_msg;
265 /* cycle through commands to find same command in the transaction */
266 for (cmd_msg = cmd->trx->cmds;
267 (cmd_msg != NULL) && (cmd_msg->cmd->msg->framenum != cmd->msg->framenum);
268 cmd_msg = cmd_msg->next) {
269 if (cmd_msg->cmd->type == cmd->type)
283 megacostat_had_request(const gcp_cmd_t* cmd)
289 gcp_cmd_msg_t *cmd_msg;
290 /* cycle through commands to find a request in the transaction */
291 for (cmd_msg = cmd->trx->cmds;
292 (cmd_msg != NULL) && (cmd_msg->cmd->msg->framenum != cmd->msg->framenum);
293 cmd_msg = cmd_msg->next) {
295 switch (cmd_msg->cmd->type) {
316 megacostat_filtercheck(const char *opt_arg _U_, const char **filter _U_, char** err)
318 pref_t *megaco_ctx_track, *h248_ctx_track;
320 megaco_ctx_track = prefs_find_preference(prefs_find_module("megaco"), "ctx_info");
321 h248_ctx_track = prefs_find_preference(prefs_find_module("h248"), "ctx_info");
323 if (!megaco_ctx_track || !h248_ctx_track) {
324 /* No such preferences */
328 if (!prefs_get_bool_value(megaco_ctx_track, pref_current) || !prefs_get_bool_value(h248_ctx_track, pref_current)) {
329 *err = g_strdup_printf("Track Context option at Protocols -> MEGACO and Protocols -> H248 preferences\n"
330 "has to be set to true to enable measurement of service response times.\n");
335 megacostat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pmi)
337 rtd_data_t* rtd_data = (rtd_data_t*)pms;
338 rtd_stat_table* ms = &rtd_data->stat_table;
339 const gcp_cmd_t *mi=(const gcp_cmd_t*)pmi;
346 if(!mi->trx->initial) {
347 /* Track Context is probably disabled, we cannot
348 * measure service response time */
352 else if(mi->trx->initial->framenum != mi->msg->framenum){
353 /* Duplicate is ignored */
354 ms->time_stats[0].req_dup_num++;
357 ms->time_stats[0].open_req_num++;
362 if(megacostat_is_duplicate_reply(mi)){
363 /* Duplicate is ignored */
364 ms->time_stats[0].rsp_dup_num++;
366 else if (!megacostat_had_request(mi)) {
367 /* no request was seen */
368 ms->time_stats[0].disc_rsp_num++;
371 ms->time_stats[0].open_req_num--;
372 /* calculate time delta between request and response */
373 nstime_delta(&delta, &pinfo->abs_ts, &mi->trx->initial->frametime);
377 case GCP_CMD_ADD_REPLY:
378 time_stat_update(&(ms->time_stats[0].rtd[0]),&delta, pinfo);
380 case GCP_CMD_MOVE_REPLY:
381 time_stat_update(&(ms->time_stats[0].rtd[1]),&delta, pinfo);
383 case GCP_CMD_MOD_REPLY:
384 time_stat_update(&(ms->time_stats[0].rtd[2]),&delta, pinfo);
386 case GCP_CMD_SUB_REPLY:
387 time_stat_update(&(ms->time_stats[0].rtd[3]),&delta, pinfo);
389 case GCP_CMD_AUDITCAP_REPLY:
390 time_stat_update(&(ms->time_stats[0].rtd[4]),&delta, pinfo);
392 case GCP_CMD_AUDITVAL_REPLY:
393 time_stat_update(&(ms->time_stats[0].rtd[5]),&delta, pinfo);
395 case GCP_CMD_NOTIFY_REPLY:
396 time_stat_update(&(ms->time_stats[0].rtd[6]),&delta, pinfo);
398 case GCP_CMD_SVCCHG_REPLY:
399 time_stat_update(&(ms->time_stats[0].rtd[7]),&delta, pinfo);
401 case GCP_CMD_TOPOLOGY_REPLY:
402 time_stat_update(&(ms->time_stats[0].rtd[8]),&delta, pinfo);
405 time_stat_update(&(ms->time_stats[0].rtd[9]),&delta, pinfo);
408 time_stat_update(&(ms->time_stats[0].rtd[11]),&delta, pinfo);
411 time_stat_update(&(ms->time_stats[0].rtd[10]),&delta, pinfo);
423 /* Call the export PDU tap with relevant data */
425 export_megaco_pdu(packet_info *pinfo, tvbuff_t *tvb)
427 exp_pdu_data_t *exp_pdu_data = export_pdu_create_common_tags(pinfo, "megaco", EXP_PDU_TAG_PROTO_NAME);
429 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
430 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
431 exp_pdu_data->pdu_tvb = tvb;
433 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
438 * The various functions that either dissect some
439 * subpart of MEGACO. These aren't really proto dissectors but they
440 * are written in the same style.
444 dissect_megaco_descriptors(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_descriptors_start_offset, gint tvb_descriptors_end_offset, proto_tree *top_tree);
446 dissect_megaco_digitmapdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
448 dissect_megaco_topologydescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
450 dissect_megaco_errordescriptor(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
452 dissect_megaco_TerminationStatedescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_next_offset, gint tvb_current_offset);
454 dissect_megaco_Localdescriptor(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset);
456 dissect_megaco_LocalControldescriptor(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset, proto_tree *top_tree);
458 dissect_megaco_Packagesdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_next_offset, gint tvb_current_offset);
460 tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
462 dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
464 megaco_tvb_find_token(tvbuff_t *tvb, gint offset, gint maxlength);
465 static dissector_handle_t data_handle;
466 static dissector_handle_t sdp_handle;
467 static dissector_handle_t h245_handle;
468 static dissector_handle_t h248_handle;
469 static dissector_handle_t h248_otp_handle;
471 static gboolean keep_persistent_data = FALSE;
474 * dissect_megaco_text over TCP, there will be a TPKT header there
477 static int dissect_megaco_text_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
481 /* This code is copied from the Q.931 dissector, some parts skipped.
482 * Check whether this looks like a TPKT-encapsulated
485 * The minimum length of a MEGACO message is 6?:
488 lv_tpkt_len = is_tpkt(tvb, 6);
489 if (lv_tpkt_len == -1) {
491 * It's not a TPKT packet;
494 dissect_megaco_text(tvb, pinfo, tree, data);
496 dissect_tpkt_encap(tvb, pinfo, tree, TRUE,
499 return tvb_captured_length(tvb);
505 #define PENDINGTOKEN 4
506 #define RESPONSEACKTOKEN 5
510 const char *compact_name;
513 static const megaco_tokens_t megaco_messageBody_names[] = {
514 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
515 { "Error", "ER" }, /* 1 */
516 { "Transaction", "T" }, /* 2 */
517 { "Reply", "P" }, /* 3 */
518 { "Pending", "PN" }, /* 4 */
519 { "TransactionResponseAck", "K" }, /* 5 */
522 /* Returns index of megaco_tokens_t */
523 static gint find_megaco_messageBody_names(tvbuff_t *tvb, int offset, guint header_len)
527 for (i = 1; i < array_length(megaco_messageBody_names); i++) {
528 if (header_len == strlen(megaco_messageBody_names[i].name) &&
529 tvb_strncaseeql(tvb, offset, megaco_messageBody_names[i].name, header_len) == 0)
531 if (megaco_messageBody_names[i].compact_name != NULL &&
532 header_len == strlen(megaco_messageBody_names[i].compact_name) &&
533 tvb_strncaseeql(tvb, offset, megaco_messageBody_names[i].compact_name, header_len) == 0)
541 megaco_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
542 gint start, gint length, const char *value)
546 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
547 if (!global_megaco_dissect_tree) {
548 PROTO_ITEM_SET_HIDDEN(pi);
555 my_proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
556 gint start, gint length, guint32 value)
560 pi = proto_tree_add_uint(tree, hfindex, tvb, start, 1, value);
561 /* String length may be longer than FT_UINT will allow */
562 proto_item_set_len(pi, length);
564 if (!global_megaco_dissect_tree) {
565 PROTO_ITEM_SET_HIDDEN(pi);
572 * dissect_megaco_text - The dissector for the MEGACO Protocol, using
576 dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
579 gint tvb_offset,tvb_current_offset,tvb_previous_offset,tvb_next_offset,tokenlen;
580 gint context_offset, context_length, save_offset, save_length;
581 gint tvb_command_start_offset, tvb_command_end_offset;
582 gint tvb_descriptors_start_offset, tvb_descriptors_end_offset;
583 gint tvb_transaction_end_offset;
584 proto_tree *megaco_tree, *message_body_tree, *megaco_tree_command_line, *ti, *sub_ti;
589 gint tvb_RBRKT, tvb_LBRKT, RBRKT_counter, LBRKT_counter;
594 gcp_msg_t *msg = NULL;
595 gcp_trx_t *trx = NULL;
596 gcp_ctx_t *ctx = NULL;
597 gcp_cmd_t *cmd = NULL;
598 gcp_term_t *term = NULL;
599 gcp_trx_type_t trx_type = GCP_TRX_NONE;
600 guint32 trx_id = 0, pending_id;
602 gcp_cmd_type_t cmd_type = GCP_CMD_NONE;
603 gcp_wildcard_t wild_term = GCP_WILDCARD_NONE;
606 /* Initialize variables */
607 tvb_len = tvb_reported_length(tvb);
614 /* Check if H.248 in otp(Erlang) internal format
615 * XXX Needs improvement?
617 * http://www.erlang.org/doc/apps/megaco/part_frame.html
618 * 4.1 Internal form of messages
619 * 4.2 The different encodings
621 dword = tvb_get_ntoh24(tvb,0);
622 if ((dword == 0x836803)&&(h248_otp_handle)){
623 call_dissector(h248_otp_handle, tvb, pinfo, tree);
624 return tvb_captured_length(tvb);
627 msg = gcp_msg(pinfo, tvb_raw_offset(tvb), keep_persistent_data);
630 * Check to see whether we're really dealing with MEGACO by looking
631 * for the "MEGACO" string or a "!".This needs to be improved when supporting
632 * binary encodings. Bugfix add skipping of leading spaces.
634 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
636 /* Quick fix for MEGACO not following the RFC, hopefully not breaking any thing
637 * Turned out to be TPKT in case of TCP, added some code to handle that.
639 * tvb_offset = tvb_find_guint8(tvb, tvb_offset, 5, 'M');
641 if(!tvb_get_nstringz0(tvb,tvb_offset,sizeof(word),word)) return tvb_captured_length(tvb);
643 /* Quick fix for MEGACO packet with Authentication Header,
644 * marked as "AU" or "Authentication".
646 if ((g_ascii_strncasecmp(word, "Authentication", 14) == 0) ||
647 (g_ascii_strncasecmp(word, "AU", 2) == 0)) {
651 /* move offset to end of auth header (EOL or WSP) */
652 for ( counter = tvb_offset; counter < tvb_len; counter++ ) {
653 needle = tvb_get_guint8(tvb, counter);
654 if (needle == ' ' || needle == '\r' || needle == '\n') {
655 next = tvb_get_guint8(tvb, counter+1);
656 if (next == ' ' || next == '\r' || next == '\n') {
659 tvb_offset = counter + 1;
665 short_form = (tvb_get_guint8(tvb, tvb_offset ) == '!');
667 if (g_ascii_strncasecmp(word, "MEGACO", 6) != 0 && !short_form){
671 dissector_handle_t handle = data_handle;
673 get_ber_identifier(tvb, 0, &ber_class, &pc, &tag);
675 if (ber_class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE ) {
676 handle = h248_handle;
679 call_dissector(handle,tvb,pinfo,tree);
680 return tvb_captured_length(tvb);
684 /* Display MEGACO in protocol column */
685 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MEGACO");
687 /* Report this packet to the tap */
688 if (!pinfo->flags.in_error_pkt) {
689 if (have_tap_listener(exported_pdu_tap)) {
690 export_megaco_pdu(pinfo, tvb);
694 /* Build the info tree if we've been given a root */
695 /* Create megaco subtree */
696 ti = proto_tree_add_item(tree,proto_megaco,tvb, 0, -1, ENC_NA);
697 megaco_tree = proto_item_add_subtree(ti, ett_megaco);
699 /* Format of 'message' is = MegacopToken SLASH Version SEP mId SEP messageBody */
700 /* MegacopToken = "MEGACO" or "!" */
701 /* According to H248.1-200205 Annex B Text encoding ( protocol version 2 ) */
704 tvb_previous_offset = tvb_find_guint8(tvb, 0,
706 if (tvb_previous_offset == -1) {
707 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
708 "Sorry, no \"/\" in the MEGACO header, I can't parse this packet");
709 return tvb_captured_length(tvb);
712 megaco_tree_add_string(megaco_tree, hf_megaco_start, tvb, 0, tvb_previous_offset+1,
713 tvb_get_string_enc(wmem_packet_scope(), tvb, 0, tvb_previous_offset, ENC_UTF_8|ENC_NA));
716 tvb_previous_offset++;
718 /* assume at least one digit in version */
719 tvb_current_offset = tvb_previous_offset + 1;
721 if (g_ascii_isdigit(tvb_get_guint8(tvb, tvb_current_offset))) {
722 /* 2-digit version */
723 tvb_current_offset++;
726 megaco_tree_add_string(megaco_tree, hf_megaco_version, tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset,
727 tvb_get_string_enc(wmem_packet_scope(), tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset, ENC_UTF_8|ENC_NA));
729 tvb_previous_offset = tvb_current_offset;
730 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
732 if (tvb_previous_offset == tvb_current_offset) {
733 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
734 "[ Parse error: missing SEP in MEGACO header ]");
735 return tvb_current_offset;
738 tvb_previous_offset = tvb_current_offset;
740 /* mId should follow here,
741 * mId = (( domainAddress / domainName ) [":" portNumber]) / mtpAddress / deviceName
742 * domainAddress = "[" (IPv4address / IPv6address) "]"
743 * domainName = "<" (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" /".") ">"
744 * mtpAddress = MTPToken LBRKT 4*8 (HEXDIG) RBRKT
746 * deviceName = pathNAME
747 * pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )["@" pathDomainName ]
750 tvb_current_offset = tvb_ws_mempbrk_pattern_guint8(tvb, tvb_current_offset, -1, &pbrk_whitespace, &needle);
751 if (tvb_current_offset == -1) {
752 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
753 "[ Parse error: no body in MEGACO message (missing SEP after mId) ]");
754 return tvb_captured_length(tvb);
757 tvb_next_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset);
759 /* At this point we should point to the "\n" ending the mId element
760 * or to the next character after white space SEP
762 megaco_tree_add_string(megaco_tree, hf_megaco_mId, tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset,
763 tvb_get_string_enc(wmem_packet_scope(), tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset, ENC_UTF_8|ENC_NA));
765 col_clear(pinfo->cinfo, COL_INFO);
767 tvb_previous_offset = tvb_next_offset;
770 * : messageBody = ( errorDescriptor / transactionList )
771 * errorDescriptor = ErrorToken EQUAL ErrorCode LBRKT [quotedString] RBRKT
772 * ErrorToken = ("Error" / "ER")
774 * transactionList = 1*( transactionRequest / transactionReply /
775 * transactionPending / transactionResponseAck )
777 * transactionResponseAck = ResponseAckToken LBRKT
778 * transactionAck*(COMMA transactionAck) RBRKT
779 * ResponseAckToken = ("TransactionResponseAck"/ "K")
781 * transactionPending = PendingToken EQUAL TransactionID LBRKT RBRKT
782 * PendingToken = ("Pending" / "PN")
784 * transactionReply = ReplyToken EQUAL TransactionID LBRKT
785 * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
786 * ReplyToken = ("Reply" / "P")
788 * transactionRequest = TransToken EQUAL TransactionID LBRKT
789 * actionRequest *(COMMA actionRequest) RBRKT
790 * TransToken = ("Transaction" / "T")
793 /* Find token length */
794 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_len-1; tvb_offset++){
795 if (!g_ascii_isalpha(tvb_get_guint8(tvb, tvb_offset ))){
799 tokenlen = tvb_offset - tvb_previous_offset;
800 token_index = find_megaco_messageBody_names(tvb, tvb_previous_offset, tokenlen);
802 g_warning("token_index %u",token_index);
805 tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_len, '{');
806 tvb_current_offset = tvb_LBRKT;
807 tvb_transaction_end_offset = megaco_tvb_find_token(tvb, tvb_LBRKT - 1, tvb_len);
809 switch ( token_index ){
810 /* errorDescriptor */
812 col_set_str(pinfo->cinfo, COL_INFO, "Error ");
814 tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_len); /*tvb_find_guint8(tvb, tvb_offset+1, tvb_len, '}');*/
816 ti = proto_tree_add_format_text(megaco_tree, tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset);
817 message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
820 megaco_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
821 tvb_previous_offset, tokenlen,
824 tvb_command_start_offset = tvb_previous_offset;
825 dissect_megaco_errordescriptor(tvb, pinfo, megaco_tree, tvb_len-1, tvb_command_start_offset);
827 return tvb_captured_length(tvb);
828 /* transactionResponseAck
829 * transactionResponseAck = ResponseAckToken LBRKT transactionAck
830 * *(COMMA transactionAck) RBRKT
831 * transactionAck = transactionID / (transactionID "-" transactionID)
833 case RESPONSEACKTOKEN:
834 tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
835 tvb_offset = tvb_LBRKT;
836 save_offset = tvb_previous_offset;
837 save_length = tvb_current_offset-tvb_previous_offset;
839 megaco_tree_add_string(megaco_tree, hf_megaco_transaction, tvb,
840 save_offset, save_length, "TransactionResponseAck" );
842 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1);
843 tvb_current_offset = tvb_find_guint8(tvb, tvb_offset+1, tvb_len, '}');
844 /*tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_transaction_end_offset);*/
845 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset)-1; /* cut last RBRKT */
846 len = tvb_current_offset - tvb_previous_offset;
848 pending_id = (guint)strtoul(tvb_format_text(tvb,tvb_previous_offset,len),NULL,10);
849 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "%d TransactionResponseAck", pending_id);
851 my_proto_tree_add_uint(megaco_tree, hf_megaco_transid, tvb, save_offset, save_length, pending_id);
853 if(global_megaco_raw_text){
854 tvb_raw_text_add(tvb, megaco_tree);
856 return tvb_captured_length(tvb);
857 /* Pe and PN is transactionPending, P+"any char" is transactionReply */
860 tvb_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '=')+1;
861 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
862 tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
863 tvb_current_offset = tvb_LBRKT;
864 save_offset = tvb_previous_offset;
865 save_length = tvb_current_offset-tvb_previous_offset;
867 megaco_tree_add_string(megaco_tree, hf_megaco_transaction, tvb,
868 save_offset, save_length, "Reply" );
870 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1);
871 len = tvb_current_offset - tvb_offset;
873 pending_id = (guint)strtoul(tvb_format_text(tvb,tvb_offset,len),NULL,10);
874 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "%d Pending", pending_id);
876 my_proto_tree_add_uint(megaco_tree, hf_megaco_transid, tvb, save_offset, save_length, pending_id);
877 return tvb_captured_length(tvb);
879 /* transactionReply */
881 trx_type = GCP_TRX_REPLY;
882 tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
883 save_offset = tvb_previous_offset;
884 save_length = tvb_LBRKT-tvb_previous_offset;
886 megaco_tree_add_string(megaco_tree, hf_megaco_transaction, tvb,
887 save_offset, save_length, "Reply" );
889 tvb_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '=')+1;
890 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
891 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_LBRKT-1);
892 len = tvb_current_offset - tvb_offset;
894 trx_id = (guint)strtoul(tvb_format_text(tvb,tvb_offset,len),NULL,10);
895 col_add_fstr(pinfo->cinfo, COL_INFO, "%d Reply ", trx_id);
897 my_proto_tree_add_uint(megaco_tree, hf_megaco_transid, tvb, save_offset, save_length, trx_id);
899 /* Find if we have a errorDescriptor or actionReplyList */
900 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
901 tempchar = tvb_get_guint8(tvb,tvb_offset);
902 if ((tempchar == 'E')||(tempchar == 'e')){
903 dissect_megaco_errordescriptor(tvb, pinfo, megaco_tree, tvb_transaction_end_offset-1, tvb_offset);
904 return tvb_captured_length(tvb);
906 /* Offset should be at first printable char after { */
907 tvb_previous_offset = tvb_offset;
910 /* TransactionRequest */
911 trx_type = GCP_TRX_REQUEST;
912 save_offset = tvb_previous_offset;
913 save_length = tvb_current_offset-tvb_previous_offset;
914 megaco_tree_add_string(megaco_tree, hf_megaco_transaction, tvb,
915 save_offset, save_length, "Request" );
917 tvb_offset = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '=')+1;
918 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
919 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1);
920 len = tvb_current_offset - tvb_offset;
922 trx_id = (guint)strtoul(tvb_format_text(tvb,tvb_offset,len),NULL,10);
923 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "%d Request", trx_id);
925 my_proto_tree_add_uint(megaco_tree, hf_megaco_transid, tvb, save_offset, save_length, trx_id);
926 /* Offset should be at first printable char after { */
927 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
931 proto_tree_add_expert_format(tree, pinfo, &ei_megaco_error_descriptor_transaction_list, tvb, 0, -1,
932 "Sorry, can't understand errorDescriptor / transactionList = %s, can't parse it pos %u",
933 tvb_format_text(tvb,tvb_previous_offset,2),tvb_previous_offset);
934 return tvb_captured_length(tvb);
936 /* Only these remains now
937 * transactionReply = ReplyToken EQUAL TransactionID LBRKT
938 * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
939 * ReplyToken = ("Reply" / "P")
941 * errorDescriptor = ErrorToken EQUAL ErrorCode
942 * LBRKT [quotedString] RBRKT
944 * transactionRequest = TransToken EQUAL TransactionID LBRKT
945 * actionRequest *(COMMA actionRequest) RBRKT
946 * TransToken = ("Transaction" / "T")
949 trx = gcp_trx(msg , trx_id , trx_type, keep_persistent_data);
957 tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '{');
958 context_offset = tvb_previous_offset;
959 context_length = tvb_next_offset-tvb_previous_offset+1;
961 tvb_previous_offset = tvb_find_guint8(tvb, tvb_current_offset, tvb_transaction_end_offset, '=')+1;
962 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
964 if (tvb_current_offset >= tvb_next_offset) {
965 proto_tree_add_expert_format(megaco_tree, pinfo, &ei_megaco_parse_error,
966 tvb, context_offset, context_length, "Parse error: Invalid offset");
967 return tvb_captured_length(tvb);
969 tvb_current_offset = tvb_next_offset;
972 tokenlen = tvb_current_offset - tvb_previous_offset;
973 tempchar = tvb_get_guint8(tvb, tvb_previous_offset );
975 if (tvb_get_guint8(tvb, tvb_current_offset-1 ) == ' '){
981 ctx_id = CHOOSE_CONTEXT;
984 ctx_id = ALL_CONTEXTS;
987 ctx_id = NULL_CONTEXT;
990 ctx_id = (guint)strtoul(tvb_format_text(tvb, tvb_previous_offset, tokenlen),NULL,10);
993 my_proto_tree_add_uint(megaco_tree, hf_megaco_Context, tvb, context_offset, context_length, ctx_id);
994 col_append_fstr(pinfo->cinfo, COL_INFO, " |=%s", val_to_str(ctx_id, megaco_context_vals, "%d"));
996 ctx = gcp_ctx(msg,trx,ctx_id,keep_persistent_data);
1000 /* If Transaction is is Request, Reply or Pending */
1001 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
1002 tvb_command_end_offset = tvb_command_start_offset;
1004 tvb_LBRKT = tvb_command_start_offset;
1005 tvb_RBRKT = tvb_command_start_offset;
1007 /* The following loop find the individual contexts, commands and call the for every Descriptor a subroutine */
1010 tvb_command_end_offset = tvb_find_guint8(tvb, tvb_command_end_offset +1,
1011 tvb_transaction_end_offset, ',');
1013 if ( tvb_command_end_offset == -1 || tvb_command_end_offset > tvb_transaction_end_offset){
1014 tvb_command_end_offset = tvb_transaction_end_offset ;
1018 /* checking how many left brackets are before the next comma */
1020 while ( tvb_find_guint8(tvb, tvb_LBRKT+1,tvb_transaction_end_offset, '{') != -1
1021 && (tvb_find_guint8(tvb, tvb_LBRKT+1,tvb_transaction_end_offset, '{') < tvb_command_end_offset)){
1023 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
1024 tvb_transaction_end_offset, '{');
1029 /* checking how many right brackets are before the next comma */
1031 while ( (tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_transaction_end_offset, '}') != -1 )
1032 && (tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_transaction_end_offset, '}') <= tvb_command_end_offset)
1033 && LBRKT_counter != 0){
1035 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
1036 tvb_transaction_end_offset, '}');
1042 /* If equal or more right brackets before the comma, one command is complete */
1044 if ( LBRKT_counter <= RBRKT_counter ){
1046 tvb_current_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
1047 tvb_transaction_end_offset, '{');
1050 /* includes no descriptors */
1052 if ( LBRKT_counter == 0 ){
1054 tvb_current_offset = tvb_command_end_offset;
1056 /* the last command in a context */
1058 if ( tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}') < tvb_current_offset
1059 && tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}') != -1){
1061 tvb_previous_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
1062 tvb_transaction_end_offset, '}');
1064 len = tvb_previous_offset - tvb_command_start_offset;
1066 tvb_previous_offset = megaco_tvb_skip_wsp_return(tvb, tvb_previous_offset -1);
1068 tokenlen = tvb_previous_offset - tvb_command_start_offset;
1072 /* not the last command in a context*/
1075 len = tvb_current_offset - tvb_command_start_offset;
1076 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset -1);
1078 tokenlen = tvb_current_offset - tvb_command_start_offset;
1082 /* command includes descriptors */
1085 len = tvb_current_offset - tvb_command_start_offset;
1086 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset -1);
1088 tokenlen = tvb_current_offset - tvb_command_start_offset;
1091 /* if a next context is specified */
1093 if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'C'){
1094 tvb_current_offset = tvb_command_start_offset;
1095 tvb_previous_offset = tvb_command_start_offset;
1101 megaco_tree_command_line = proto_tree_add_subtree(megaco_tree, tvb, tvb_command_start_offset, len+1, ett_megaco_command_line, &sub_ti, "Command: ");
1102 /* creation of the megaco_tree_command_line additionally Command and Transaction ID will be printed in this line */
1103 /* Changed to use the lines above. this code is saved if there is complaints
1104 sub_ti = proto_tree_add_item(megaco_tree,hf_megaco_command_line,tvb,tvb_command_start_offset,tokenlen, ENC_UTF_8|ENC_NA);
1105 megaco_tree_command_line = proto_item_add_subtree(sub_ti, ett_megaco_command_line);
1107 if (!global_megaco_dissect_tree) {
1108 PROTO_ITEM_SET_HIDDEN(sub_ti);
1111 tvb_next_offset = tvb_command_start_offset + tokenlen;
1113 /* Try to dissect Topology Descriptor before the command */
1114 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
1115 if ( (tempchar >= 'a')&& (tempchar <= 'z')){
1116 tempchar = tempchar - 0x20;
1118 if ( tempchar == 'T') {
1119 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1121 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1122 tempchar = tempchar - 0x20;
1124 if ( tempchar == 'P' || tempchar == 'O'){
1125 gint tvb_topology_end_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}');
1126 if ( tvb_topology_end_offset == -1 ){
1127 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"}\"");
1128 return tvb_captured_length(tvb);
1131 tvb_command_start_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{');
1132 if ( tvb_command_start_offset == -1 ){
1133 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"{\"");
1134 return tvb_captured_length(tvb);
1136 dissect_megaco_topologydescriptor(tvb, megaco_tree_command_line, tvb_topology_end_offset-1, tvb_command_start_offset+1);
1138 /* Command after Topology Descriptor */
1139 tvb_command_start_offset = tvb_find_guint8(tvb, tvb_topology_end_offset + 1,
1140 tvb_transaction_end_offset, ',');
1142 if ( tvb_command_start_offset == -1 ){
1143 /* No Command present after Topology Descriptor */
1147 /* Try to find the first char of the command */
1148 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_command_start_offset + 1);
1149 /*tvb_next_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{');*/
1156 /* Additional value */
1157 if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'O'){
1159 proto_tree_add_item(megaco_tree_command_line, hf_megaco_command_optional, tvb, tvb_command_start_offset, 2, ENC_NA);
1160 tvb_command_start_offset = tvb_command_start_offset+2;
1164 /* Additional value */
1165 if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'W'){
1167 proto_tree_add_item(megaco_tree_command_line, hf_megaco_wildcard_response, tvb, tvb_command_start_offset, 2, ENC_NA );
1168 tvb_command_start_offset = tvb_command_start_offset+2;
1171 tvb_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
1172 tvb_transaction_end_offset, '=');
1173 if (tvb_offset == -1 ) {
1174 proto_tree_add_expert_format(megaco_tree, pinfo, &ei_megaco_parse_error, tvb, tvb_command_start_offset, len+1, "Parse error: Missing \"=\"");
1175 return tvb_captured_length(tvb);
1177 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_offset -1);
1178 tokenlen = tvb_offset - tvb_command_start_offset;
1180 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
1181 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1182 tempchar = tempchar - 0x20;
1184 if ( tempchar != 'E' ){
1185 /* Short form used */
1188 switch ( tempchar ){
1192 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1193 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1194 tempchar = tempchar - 0x20;
1196 switch ( tempchar ){
1200 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITVAL_REPLY; break;
1201 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITVAL_REQ; break;
1202 default: cmd_type = GCP_CMD_NONE; break;
1205 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1206 tvb_command_start_offset, tokenlen, "AuditValue");
1207 col_append_str(pinfo->cinfo, COL_INFO, " AuditValue");
1208 proto_item_append_text(sub_ti, "AuditValue");
1213 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITCAP_REQ; break;
1214 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITCAP_REPLY; break;
1215 default: cmd_type = GCP_CMD_NONE; break;
1217 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1218 tvb_command_start_offset, tokenlen, "AuditCapability");
1219 col_append_str(pinfo->cinfo, COL_INFO, " AuditCapability");
1220 proto_item_append_text(sub_ti, "AuditCapability");
1225 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_ADD_REQ; break;
1226 case GCP_TRX_REPLY: cmd_type = GCP_CMD_ADD_REPLY; break;
1227 default: cmd_type = GCP_CMD_NONE; break;
1230 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1231 tvb_command_start_offset, tokenlen, "Add");
1232 col_append_str(pinfo->cinfo, COL_INFO, " Add");
1233 proto_item_append_text(sub_ti, "Add");
1240 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1241 if(tempchar == 'E'){
1242 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1243 tvb_command_start_offset, tokenlen, "IEPSCall");
1244 col_append_str(pinfo->cinfo, COL_INFO, " IEPSCall");
1245 proto_item_append_text(sub_ti, "IEPSCall");
1247 cmd_type = GCP_CMD_NONE;
1251 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_NOTIFY_REQ; break;
1252 case GCP_TRX_REPLY: cmd_type = GCP_CMD_NOTIFY_REPLY; break;
1253 default: cmd_type = GCP_CMD_NONE; break;
1256 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1257 tvb_command_start_offset, tokenlen, "Notify");
1258 col_append_str(pinfo->cinfo, COL_INFO, " Notify");
1259 proto_item_append_text(sub_ti, "Notify");
1264 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1265 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1266 tempchar = tempchar - 0x20;
1268 switch ( tempchar ){
1271 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOD_REQ; break;
1272 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOD_REPLY; break;
1273 default: cmd_type = GCP_CMD_NONE; break;
1276 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1277 tvb_command_start_offset, tokenlen, "Modify");
1278 col_append_str(pinfo->cinfo, COL_INFO, " Modify");
1279 proto_item_append_text(sub_ti, "Modify");
1284 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOVE_REQ; break;
1285 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOVE_REPLY; break;
1286 default: cmd_type = GCP_CMD_NONE; break;
1288 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1289 tvb_command_start_offset, tokenlen, "Move");
1290 col_append_str(pinfo->cinfo, COL_INFO, " Move");
1291 proto_item_append_text(sub_ti, "Move");
1297 cmd_type = GCP_CMD_NONE;
1299 PackagesToken = ("Packages" / "PG")
1300 PendingToken = ("Pending" / "PN")
1301 PriorityToken = ("Priority" / "PR")
1302 ProfileToken = ("Profile" / "PF")
1304 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1305 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1306 tempchar = tempchar - 0x20;
1308 switch ( tempchar ){
1310 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1311 tvb_command_start_offset, tokenlen, "Packages");
1312 col_append_str(pinfo->cinfo, COL_INFO, " Packages");
1313 proto_item_append_text(sub_ti, "Packages");
1316 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1317 tvb_command_start_offset, tokenlen, "Pending");
1318 col_append_str(pinfo->cinfo, COL_INFO, " Pending");
1319 proto_item_append_text(sub_ti, "Pending");
1322 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1323 tvb_command_start_offset, tokenlen, "Priority");
1324 col_append_str(pinfo->cinfo, COL_INFO, " Priority");
1325 proto_item_append_text(sub_ti, "Priority");
1328 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1329 tvb_command_start_offset, tokenlen, "Profile");
1330 col_append_str(pinfo->cinfo, COL_INFO, " Profile");
1331 proto_item_append_text(sub_ti, "Profile");
1337 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1338 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1339 tempchar = tempchar - 0x20;
1341 switch ( tempchar ){
1345 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SVCCHG_REQ; break;
1346 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SVCCHG_REPLY; break;
1347 default: cmd_type = GCP_CMD_NONE; break;
1349 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1350 tvb_command_start_offset, tokenlen, "ServiceChange");
1351 col_append_str(pinfo->cinfo, COL_INFO, " ServiceChange");
1352 proto_item_append_text(sub_ti, "ServiceChange");
1357 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
1358 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
1359 default: cmd_type = GCP_CMD_NONE; break;
1361 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1362 tvb_command_start_offset, tokenlen, "Subtract");
1363 col_append_str(pinfo->cinfo, COL_INFO, " Subtract");
1364 proto_item_append_text(sub_ti, "Subtract");
1370 proto_item_append_text(sub_ti, "<None> 0x%02x", tempchar);
1371 expert_add_info(pinfo, sub_ti, &ei_megaco_no_command);
1372 return tvb_captured_length(tvb);
1376 gchar* command = tvb_format_text(tvb, tvb_command_start_offset, tokenlen);
1378 if ( g_str_equal(command,"Subtract") ) {
1380 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
1381 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
1382 default: cmd_type = GCP_CMD_NONE; break;
1384 } else if ( g_str_equal(command,"AuditValue") ) {
1386 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITVAL_REPLY; break;
1387 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITVAL_REQ; break;
1388 default: cmd_type = GCP_CMD_NONE; break;
1390 } else if ( g_str_equal(command,"AuditCapability") ) {
1392 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITCAP_REQ; break;
1393 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITCAP_REPLY; break;
1394 default: cmd_type = GCP_CMD_NONE; break;
1396 } else if ( g_str_equal(command,"Add") ) {
1398 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_ADD_REQ; break;
1399 case GCP_TRX_REPLY: cmd_type = GCP_CMD_ADD_REPLY; break;
1400 default: cmd_type = GCP_CMD_NONE; break;
1402 } else if ( g_str_equal(command,"Notify") ) {
1404 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_NOTIFY_REQ; break;
1405 case GCP_TRX_REPLY: cmd_type = GCP_CMD_NOTIFY_REPLY; break;
1406 default: cmd_type = GCP_CMD_NONE; break;
1408 } else if ( g_str_equal(command,"Modify") ) {
1410 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOD_REQ; break;
1411 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOD_REPLY; break;
1412 default: cmd_type = GCP_CMD_NONE; break;
1414 } else if ( g_str_equal(command,"Move") ) {
1416 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOVE_REQ; break;
1417 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOVE_REPLY; break;
1418 default: cmd_type = GCP_CMD_NONE; break;
1420 } else if ( g_str_equal(command,"ServiceChange") ) {
1422 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SVCCHG_REQ; break;
1423 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SVCCHG_REPLY; break;
1424 default: cmd_type = GCP_CMD_NONE; break;
1426 } else if ( g_str_equal(command,"Subtract") ) {
1428 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
1429 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
1430 default: cmd_type = GCP_CMD_NONE; break;
1434 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_OTHER_REQ; break;
1435 case GCP_TRX_REPLY: cmd_type = GCP_CMD_REPLY; break;
1436 default: cmd_type = GCP_CMD_NONE; break;
1441 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1442 tvb_command_start_offset, tokenlen, command);
1443 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command);
1444 proto_item_append_text(sub_ti, " %s", command);
1447 if (cmd_type == GCP_CMD_NONE && trx_type == GCP_TRX_REPLY) {
1448 cmd_type = GCP_CMD_REPLY;
1451 if (cmd_type != GCP_CMD_NONE) {
1452 cmd = gcp_cmd(msg, trx, ctx, cmd_type, tvb_command_start_offset, keep_persistent_data);
1453 tap_queue_packet(megaco_tap, pinfo, cmd);
1456 tvb_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
1457 tvb_transaction_end_offset, '=');
1458 if (tvb_offset == -1 ) {
1459 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"=\"");
1460 return tvb_captured_length(tvb);
1462 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1);
1463 tokenlen = tvb_next_offset - tvb_offset;
1464 if (tokenlen+1 <= 0) {
1465 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Invalid token length (%d)", tokenlen+1);
1466 return tvb_captured_length(tvb);
1469 tempchar = tvb_get_guint8(tvb, tvb_offset);
1470 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1471 tempchar = tempchar - 0x20;
1473 term = wmem_new0(wmem_packet_scope(), gcp_term_t);
1474 wild_term = GCP_WILDCARD_NONE;
1475 term->type = GCP_TERM_TYPE_UNKNOWN;
1477 switch ( tempchar ){
1480 if ((tokenlen+1 > (int) sizeof(TermID))) {
1481 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Invalid TermID length (%d)", tokenlen+1);
1482 return tvb_captured_length(tvb);
1484 tvb_get_nstringz0(tvb,tvb_offset,tokenlen+1,TermID);
1487 term->len = tokenlen;
1488 term->str = (const gchar*)(term->buffer = TermID);
1490 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
1493 proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1494 tvb_offset, tokenlen, TermID);
1498 wild_term = GCP_WILDCARD_ALL;
1500 term->buffer = (const guint8*)(term->str = "*");
1502 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
1504 proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1505 tvb_offset, tokenlen,
1507 col_append_str(pinfo->cinfo, COL_INFO, "=*");
1511 wild_term = GCP_WILDCARD_CHOOSE;
1514 term->buffer = (term->str = "$");
1516 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
1518 proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1519 tvb_offset, tokenlen,
1521 col_append_str(pinfo->cinfo, COL_INFO, "=$");
1528 proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1529 tvb_offset, tokenlen,
1530 tvb_format_text(tvb, tvb_offset,
1533 term->len = tokenlen;
1534 term->buffer = (const guint8*)(term->str = tvb_format_text(tvb, tvb_offset, tokenlen));
1536 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
1538 col_append_fstr(pinfo->cinfo, COL_INFO, "=%s",tvb_format_text(tvb, tvb_offset,tokenlen));
1543 /* Dissect the Descriptors */
1546 if ( LBRKT_counter != 0 && tvb_current_offset != tvb_command_end_offset){
1548 tvb_descriptors_start_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
1549 tvb_transaction_end_offset, '{');
1551 tvb_descriptors_end_offset = tvb_descriptors_start_offset;
1552 if ( tvb_descriptors_end_offset > tvb_transaction_end_offset )
1553 tvb_descriptors_end_offset = tvb_transaction_end_offset;
1555 while ( LBRKT_counter > 0 ){
1557 tvb_descriptors_end_offset = tvb_find_guint8(tvb, tvb_descriptors_end_offset+1,
1558 tvb_transaction_end_offset, '}');
1564 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
1566 if ( tempchar == 'E'|| tempchar == 'e'){
1567 dissect_megaco_descriptors(tvb, megaco_tree_command_line, pinfo, tvb_command_start_offset-1,tvb_descriptors_end_offset, tree);
1570 dissect_megaco_descriptors(tvb, megaco_tree_command_line, pinfo, tvb_descriptors_start_offset,tvb_descriptors_end_offset, tree);
1575 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_command_end_offset +1);
1576 tvb_LBRKT = tvb_command_start_offset;
1577 tvb_RBRKT = tvb_command_start_offset;
1581 } while ( tvb_command_end_offset < tvb_transaction_end_offset );
1583 if (keep_persistent_data) {
1584 gcp_msg_to_str(msg,keep_persistent_data);
1585 gcp_analyze_msg(megaco_tree, pinfo, tvb, msg, &megaco_ctx_ids, &ei_megaco_errored_command);
1588 tvb_next_offset = tvb_transaction_end_offset;
1590 while( tvb_transaction_end_offset > 0 && tvb_transaction_end_offset < tvb_len - 2);
1592 if(global_megaco_raw_text){
1593 tvb_raw_text_add(tvb, megaco_tree);
1596 return tvb_captured_length(tvb);
1599 #define MEGACO_MODEM_TOKEN 1
1600 #define MEGACO_MUX_TOKEN 2
1601 #define MEGACO_MEDIA_TOKEN 3
1602 #define MEGACO_SIGNALS_TOKEN 4
1603 #define MEGACO_SERVICES_TOKEN 5
1604 #define MEGACO_STATS_TOKEN 6
1605 #define MEGACO_ERROR_TOKEN 7
1606 #define MEGACO_EVENTS_TOKEN 8
1607 #define MEGACO_AUDIT_TOKEN 9
1608 #define MEGACO_DIGITMAP_TOKEN 10
1609 #define MEGACO_OE_TOKEN 11
1610 #define MEGACO_TOPOLOGY_TOKEN 12
1611 #define MEGACO_PACKAGES_TOKEN 13
1613 static const megaco_tokens_t megaco_descriptors_names[] = {
1614 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
1615 { "Modem", "MD" }, /* 1 */
1616 { "Mux", "MX" }, /* 2 */
1617 { "Media", "M" }, /* 3 */
1618 { "Signals", "SG" }, /* 4 */
1619 { "Services", "SV" }, /* 5 */
1620 { "Statistics", "SA" }, /* 6 */
1621 { "Error", "ER" }, /* 7 */
1622 { "Events", "E" }, /* 8 */
1623 { "Audit", "AT" }, /* 9 */
1624 { "DigitMap", "DM" }, /* 10 */
1625 { "ObservedEvents", "OE" }, /* 11 */
1626 { "Topology", "TP" }, /* 12 */
1627 { "Packages", "PG" }, /* 13 */
1630 /* Returns index of megaco_tokens_t */
1631 /* note - also called by dissect_megaco_auditdescriptor */
1632 static gint find_megaco_descriptors_names(tvbuff_t *tvb, int offset, guint header_len)
1636 for (i = 1; i < array_length(megaco_descriptors_names); i++) {
1637 if (header_len == strlen(megaco_descriptors_names[i].name) &&
1638 tvb_strncaseeql(tvb, offset, megaco_descriptors_names[i].name, header_len) == 0)
1640 if (megaco_descriptors_names[i].compact_name != NULL &&
1641 header_len == strlen(megaco_descriptors_names[i].compact_name) &&
1642 tvb_strncaseeql(tvb, offset, megaco_descriptors_names[i].compact_name, header_len) == 0)
1649 dissect_megaco_modemdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
1654 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1655 proto_tree_add_string(megaco_tree_command_line, hf_megaco_modem_descriptor, tvb,
1656 tvb_previous_offset, tokenlen,
1657 tvb_format_text(tvb, tvb_previous_offset,
1662 dissect_megaco_multiplexdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
1667 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1668 proto_tree_add_string(megaco_tree_command_line, hf_megaco_multiplex_descriptor, tvb,
1669 tvb_previous_offset, tokenlen,
1670 tvb_format_text(tvb, tvb_previous_offset,
1675 /* mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
1676 * MediaToken = ("Media" / "M")
1678 * mediaParm = (streamParm / streamDescriptor /terminationStateDescriptor)
1680 * ; at-most one terminationStateDescriptor
1681 * ; and either streamParm(s) or streamDescriptor(s) but not both
1682 * streamParm = ( localDescriptor / remoteDescriptor /localControlDescriptor )
1683 * localDescriptor = LocalToken LBRKT octetString RBRKT
1684 * LocalToken = ("Local" / "L")
1685 * octetString = *(nonEscapeChar)
1686 * nonEscapeChar = ( "\}" / %x01-7C / %x7E-FF )
1687 * remoteDescriptor = RemoteToken LBRKT octetString RBRKT
1688 * RemoteToken = ("Remote" / "R")
1689 * localControlDescriptor = LocalControlToken LBRKT localParm*(COMMA localParm) RBRKT
1690 * LocalControlToken = ("LocalControl" / "O")
1691 * localParm = ( streamMode / propertyParm / reservedValueMode
1692 * streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm*(COMMA streamParm) RBRKT
1693 * StreamToken = ("Stream" / "ST")
1694 * terminationStateDescriptor = TerminationStateToken LBRKTterminationStateParm
1695 * *( COMMA terminationStateParm ) RBRKT
1696 * TerminationStateToken = ("TerminationState" / "TS")
1697 * terminationStateParm =(propertyParm / serviceStates / eventBufferControl )
1700 #define MEGACO_LOCAL_TOKEN 1
1701 #define MEGACO_REMOTE_TOKEN 2
1702 #define MEGACO_LOCAL_CONTROL_TOKEN 3
1703 #define MEGACO_STREAM_TOKEN 4
1704 #define MEGACO_TERMINATION_STATE_DESC 5
1706 static const megaco_tokens_t megaco_mediaParm_names[] = {
1707 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
1708 { "Local", "L" }, /* 1 */
1709 { "Remote", "R" }, /* 2 */
1710 { "LocalControl", "O" }, /* 3 */
1711 { "Stream", "ST" }, /* 4 */
1712 { "TerminationState", "TS" }, /* 5 */
1715 /* Returns index of megaco_tokens_t */
1716 static gint find_megaco_mediaParm_names(tvbuff_t *tvb, int offset, guint header_len)
1720 for (i = 1; i < array_length(megaco_mediaParm_names); i++) {
1721 if (header_len == strlen(megaco_mediaParm_names[i].name) &&
1722 tvb_strncaseeql(tvb, offset, megaco_mediaParm_names[i].name, header_len) == 0)
1724 if (megaco_mediaParm_names[i].compact_name != NULL &&
1725 header_len == strlen(megaco_mediaParm_names[i].compact_name) &&
1726 tvb_strncaseeql(tvb, offset, megaco_mediaParm_names[i].compact_name, header_len) == 0)
1734 dissect_megaco_mediadescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line,packet_info *pinfo, gint tvb_last_RBRKT,
1735 gint tvb_previous_offset, gint start_offset, proto_tree *top_tree)
1738 gint tokenlen, tvb_LBRKT, tvb_RBRKT;
1739 gint tvb_next_offset, tvb_current_offset, tvb_offset, equal_offset, save_offset;
1743 proto_tree *megaco_mediadescriptor_tree;
1744 proto_item *megaco_mediadescriptor_ti, *ti;
1746 megaco_mediadescriptor_ti = proto_tree_add_item(megaco_tree_command_line, hf_megaco_media_descriptor, tvb, start_offset, 1, ENC_NA);
1747 megaco_mediadescriptor_tree = proto_item_add_subtree(megaco_mediadescriptor_ti, ett_megaco_mediadescriptor);
1749 while ( tvb_previous_offset < tvb_last_RBRKT){
1750 /* Start of token */
1751 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
1753 /* Find token length */
1754 for (tvb_next_offset=tvb_current_offset; tvb_next_offset < tvb_last_RBRKT; tvb_next_offset++){
1755 if (!g_ascii_isalpha(tvb_get_guint8(tvb, tvb_next_offset ))){
1759 tokenlen = tvb_next_offset - tvb_current_offset;
1761 mediaParm = find_megaco_mediaParm_names(tvb, tvb_current_offset, tokenlen);
1763 tvb_LBRKT = tvb_find_guint8(tvb, tvb_next_offset , tvb_last_RBRKT, '{');
1764 tvb_next_offset = tvb_find_guint8(tvb, tvb_current_offset+1 , tvb_last_RBRKT, '}');
1765 tvb_RBRKT = tvb_next_offset;
1767 switch ( mediaParm ){
1768 case MEGACO_LOCAL_TOKEN:
1769 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1770 dissect_megaco_Localdescriptor(tvb, megaco_mediadescriptor_tree, pinfo,
1771 tvb_RBRKT, tvb_current_offset);
1772 tvb_current_offset = tvb_RBRKT;
1774 case MEGACO_REMOTE_TOKEN:
1775 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1776 dissect_megaco_Localdescriptor(tvb, megaco_mediadescriptor_tree, pinfo,
1777 tvb_RBRKT, tvb_current_offset);
1778 tvb_current_offset = tvb_RBRKT;
1780 case MEGACO_LOCAL_CONTROL_TOKEN:
1781 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1782 dissect_megaco_LocalControldescriptor(tvb, megaco_mediadescriptor_tree, pinfo,
1783 tvb_RBRKT, tvb_current_offset, top_tree);
1784 tvb_current_offset = tvb_RBRKT;
1786 case MEGACO_STREAM_TOKEN:
1787 save_offset = tvb_current_offset;
1788 equal_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_last_RBRKT, '=');
1789 tvb_current_offset = megaco_tvb_skip_wsp(tvb, equal_offset+1);
1790 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_LBRKT-1);
1791 tokenlen = tvb_offset - tvb_current_offset;
1793 streamId = (guint)strtoul(tvb_format_text(tvb, tvb_current_offset,tokenlen),NULL,10);
1794 ti = proto_tree_add_uint(megaco_mediadescriptor_tree, hf_megaco_streamid, tvb,
1795 save_offset, 1, streamId);
1796 proto_item_set_len(ti, tvb_offset-save_offset+tokenlen);
1797 tvb_previous_offset = tvb_LBRKT+1;
1799 case MEGACO_TERMINATION_STATE_DESC:
1800 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1801 dissect_megaco_TerminationStatedescriptor(tvb, megaco_mediadescriptor_tree,
1802 tvb_RBRKT, tvb_current_offset);
1803 tvb_current_offset = tvb_RBRKT;
1808 /* more parameters ? */
1809 tvb_next_offset = tvb_find_guint8(tvb, tvb_current_offset+1 , tvb_last_RBRKT, ',');
1810 if (tvb_next_offset > tvb_last_RBRKT) tvb_next_offset = tvb_last_RBRKT;
1811 if ( tvb_next_offset != -1 ){
1812 /* (raw formatting removed)
1813 tokenlen = tvb_next_offset - tvb_RBRKT+1;
1814 proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_RBRKT, tokenlen); */
1815 tvb_previous_offset = tvb_next_offset+1;
1817 /* Add the trailing '}' (raw formatting removed) */
1818 /* proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_RBRKT, 1); */
1819 tvb_previous_offset = tvb_last_RBRKT;
1824 proto_item_set_end(megaco_mediadescriptor_ti, tvb, tvb_previous_offset);
1828 dissect_megaco_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree, gint offset, gint len, proto_tree *top_tree)
1830 /*proto_item *item;*/
1831 /*proto_tree *tree;*/
1832 gchar *msg = tvb_format_text(tvb, offset, len);
1834 /*item= */proto_tree_add_item(megaco_tree, hf_megaco_h245, tvb, offset, len, ENC_NA);
1835 /*tree = proto_item_add_subtree(item, ett_megaco_h245); */
1837 /* arbitrary maximum length */
1841 guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
1843 /* first, skip to where the encoded pdu starts, this is
1844 the first hex digit after the '=' char.
1847 if((*msg==0)||(*msg=='\n')){
1857 if((*msg==0)||(*msg=='\n')){
1860 if( ((*msg>='0')&&(*msg<='9'))
1861 || ((*msg>='a')&&(*msg<='f'))
1862 || ((*msg>='A')&&(*msg<='F'))){
1868 while( ((*msg>='0')&&(*msg<='9'))
1869 ||((*msg>='a')&&(*msg<='f'))
1870 ||((*msg>='A')&&(*msg<='F')) ){
1872 if((*msg>='0')&&(*msg<='9')){
1874 } else if((*msg>='a')&&(*msg<='f')){
1876 } else if((*msg>='A')&&(*msg<='F')){
1883 if((*msg>='0')&&(*msg<='9')){
1885 } else if((*msg>='a')&&(*msg<='f')){
1887 } else if((*msg>='A')&&(*msg<='F')){
1900 h245_tvb = tvb_new_child_real_data(tvb, buf,i,i);
1901 add_new_data_source(pinfo, h245_tvb, "H.245 over MEGACO");
1902 /* should go through a handle, however, the two h245 entry
1903 points are different, one is over tpkt and the other is raw
1905 call_dissector(h245_handle, h245_tvb, pinfo, top_tree);
1906 /* dissect_h245_MultimediaSystemControlMessage(h245_tvb, pinfo, tree);*/
1911 dissect_megaco_h324_h223caprn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree, gint offset _U_, gint len, gchar *msg)
1915 /* arbitrary maximum length */
1919 guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
1921 /* first, skip to where the encoded pdu starts, this is
1922 the first hex digit after the '=' char.
1925 if((*msg==0)||(*msg=='\n')){
1935 if((*msg==0)||(*msg=='\n')){
1938 if( ((*msg>='0')&&(*msg<='9'))
1939 || ((*msg>='a')&&(*msg<='f'))
1940 || ((*msg>='A')&&(*msg<='F'))){
1946 while( ((*msg>='0')&&(*msg<='9'))
1947 ||((*msg>='a')&&(*msg<='f'))
1948 ||((*msg>='A')&&(*msg<='F')) ){
1950 if((*msg>='0')&&(*msg<='9')){
1952 } else if((*msg>='a')&&(*msg<='f')){
1954 } else if((*msg>='A')&&(*msg<='F')){
1961 if((*msg>='0')&&(*msg<='9')){
1963 } else if((*msg>='a')&&(*msg<='f')){
1965 } else if((*msg>='A')&&(*msg<='F')){
1978 h245_tvb = tvb_new_child_real_data(tvb, buf,i,i);
1979 add_new_data_source(pinfo, h245_tvb, "H.245 over MEGACO");
1980 /* should go through a handle, however, the two h245 entry
1981 points are different, one is over tpkt and the other is raw
1983 asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
1984 dissect_h245_H223Capability(h245_tvb, 0, &actx, megaco_tree, hf_megaco_h223Capability);
1989 dissect_megaco_eventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset, proto_tree *top_tree)
1992 gint tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
1993 gint tvb_events_end_offset, tvb_LBRKT;
1994 proto_tree *megaco_eventsdescriptor_tree, *megaco_requestedevent_tree;
1995 proto_item *megaco_eventsdescriptor_ti, *megaco_requestedevent_ti, *ti;
1998 gint requested_event_start_offset = 0,
1999 requested_event_end_offset = 0;
2001 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2003 megaco_eventsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_events_descriptor,tvb,tvb_previous_offset, tokenlen, ENC_NA);
2004 megaco_eventsdescriptor_tree = proto_item_add_subtree(megaco_eventsdescriptor_ti, ett_megaco_eventsdescriptor);
2006 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
2007 tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2009 if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
2011 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2012 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
2014 tokenlen = tvb_help_offset - tvb_current_offset;
2016 ti = proto_tree_add_uint(megaco_eventsdescriptor_tree, hf_megaco_requestid, tvb,
2017 tvb_current_offset, 1,
2018 (guint32) strtoul(tvb_format_text(tvb, tvb_current_offset, tokenlen), NULL, 10));
2019 proto_item_set_len(ti, tokenlen);
2021 tvb_events_end_offset = tvb_RBRKT;
2023 tvb_RBRKT = tvb_next_offset+1;
2024 tvb_LBRKT = tvb_next_offset+1;
2025 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
2030 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2031 tvb_events_end_offset, '}');
2032 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
2033 tvb_events_end_offset, '{');
2035 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
2036 tvb_events_end_offset, ',');
2038 if (tvb_current_offset == -1 || tvb_current_offset > tvb_events_end_offset){
2039 tvb_current_offset = tvb_events_end_offset;
2043 /* Descriptor includes no parameters */
2045 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
2047 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2050 /* Descriptor includes Parameters */
2052 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
2054 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
2056 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
2057 tvb_events_end_offset, '{');
2058 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
2059 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2060 tvb_events_end_offset, '}');
2065 tvb_help_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_events_end_offset, '{');
2067 /* if there are eventparameter */
2069 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2071 requested_event_start_offset = tvb_help_offset;
2072 requested_event_end_offset = tvb_RBRKT;
2073 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2074 tokenlen = tvb_help_offset - tvb_previous_offset;
2078 tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2081 megaco_requestedevent_ti = proto_tree_add_item(megaco_eventsdescriptor_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,tokenlen, ENC_UTF_8|ENC_NA);
2082 megaco_requestedevent_tree = proto_item_add_subtree(megaco_requestedevent_ti, ett_megaco_requestedevent);
2084 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2086 tvb_help_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1);
2087 tempchar = tvb_get_guint8(tvb, tvb_help_offset);
2089 requested_event_start_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1);
2090 requested_event_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_event_end_offset-1);
2092 if ( tempchar == 'D' || tempchar == 'd'){
2093 dissect_megaco_digitmapdescriptor(tvb, megaco_requestedevent_tree, requested_event_end_offset, requested_event_start_offset);
2096 tokenlen = requested_event_end_offset - requested_event_start_offset;
2097 if(!tvb_strneql(tvb, requested_event_start_offset, "h245", 4)){
2098 dissect_megaco_h245(tvb, pinfo, megaco_requestedevent_tree, requested_event_start_offset, tokenlen, top_tree);
2100 proto_tree_add_format_text(megaco_requestedevent_tree, tvb, requested_event_start_offset, tokenlen);
2106 tvb_previous_offset = tvb_current_offset;
2107 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
2108 tvb_events_end_offset, ',');
2110 if (tvb_current_offset == -1 || tvb_current_offset > tvb_events_end_offset || tvb_current_offset < tvb_previous_offset ) {
2111 tvb_current_offset = tvb_events_end_offset;
2114 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2116 tvb_LBRKT = tvb_previous_offset;
2117 tvb_RBRKT = tvb_previous_offset;
2119 } while ( tvb_current_offset < tvb_events_end_offset );
2124 dissect_megaco_signaldescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset, proto_tree *top_tree)
2127 gint tokenlen, pkg_tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
2128 gint tvb_signals_end_offset, tvb_signals_start_offset, tvb_LBRKT;
2129 proto_tree *megaco_signalsdescriptor_tree, *megaco_requestedsignal_tree;
2130 proto_item *megaco_signalsdescriptor_ti, *megaco_requestedsignal_ti;
2132 gint requested_signal_start_offset = 0,
2133 requested_signal_end_offset = 0;
2135 tvb_signals_end_offset = tvb_RBRKT;
2136 tvb_signals_start_offset = tvb_previous_offset;
2138 if(g_ascii_toupper(tvb_get_guint8(tvb, tvb_previous_offset+1))=='G')
2139 tokenlen = 2; /* token is compact text (SG) */
2141 tokenlen = 7; /* token must be verbose text (Signals) */
2143 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset+tokenlen);
2145 if(tvb_get_guint8(tvb, tvb_current_offset)!='{') { /* {} has been omitted */
2147 megaco_signalsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line, hf_megaco_signal_descriptor, tvb, tvb_signals_start_offset, tokenlen, ENC_NA);
2148 expert_add_info(pinfo, megaco_signalsdescriptor_ti, &ei_megaco_signal_descriptor);
2150 col_append_str(pinfo->cinfo, COL_INFO, " (Signal:none)"); /* then say so */
2152 return; /* and return */
2155 tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_signals_end_offset, '{');
2156 tokenlen = (tvb_LBRKT+1) - tvb_signals_start_offset;
2158 megaco_signalsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_signal_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_NA);
2159 megaco_signalsdescriptor_tree = proto_item_add_subtree(megaco_signalsdescriptor_ti, ett_megaco_signalsdescriptor);
2161 tvb_current_offset = tvb_LBRKT;
2162 tvb_next_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2163 col_append_fstr(pinfo->cinfo, COL_INFO, " (Signal:%s)",tvb_format_text(tvb, tvb_current_offset,tokenlen-tvb_current_offset+tvb_previous_offset));
2166 if ( tvb_current_offset < tvb_signals_end_offset && tvb_current_offset != -1 && tvb_next_offset != tvb_signals_end_offset){
2169 tvb_RBRKT = tvb_next_offset+1;
2170 tvb_LBRKT = tvb_next_offset+1;
2171 tvb_previous_offset = tvb_next_offset;
2176 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2177 tvb_signals_end_offset, '}');
2178 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
2179 tvb_signals_end_offset, '{');
2181 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
2182 tvb_signals_end_offset, ',');
2184 if (tvb_current_offset == -1 || tvb_current_offset > tvb_signals_end_offset){
2185 tvb_current_offset = tvb_signals_end_offset;
2189 /* Descriptor includes no parameters */
2191 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
2193 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2196 /* Descriptor includes Parameters */
2198 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
2200 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
2202 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
2203 tvb_signals_end_offset, '{');
2204 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
2205 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2206 tvb_signals_end_offset, '}');
2211 tvb_help_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_signals_end_offset, '{');
2213 /* if there are signalparameter */
2215 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2217 requested_signal_start_offset = tvb_help_offset;
2218 requested_signal_end_offset = tvb_RBRKT;
2219 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2220 pkg_tokenlen = tvb_help_offset - tvb_previous_offset;
2224 pkg_tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2227 megaco_requestedsignal_ti = proto_tree_add_item(megaco_signalsdescriptor_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,pkg_tokenlen, ENC_UTF_8|ENC_NA);
2228 megaco_requestedsignal_tree = proto_item_add_subtree(megaco_requestedsignal_ti, ett_megaco_requestedsignal);
2230 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2231 requested_signal_start_offset = megaco_tvb_skip_wsp(tvb, requested_signal_start_offset +1);
2232 requested_signal_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_signal_end_offset-1);
2234 tokenlen = requested_signal_end_offset - requested_signal_start_offset;
2236 if(!tvb_strneql(tvb, requested_signal_start_offset, "h245", 4)){
2237 dissect_megaco_h245(tvb, pinfo, megaco_requestedsignal_tree, requested_signal_start_offset, tokenlen, top_tree);
2239 proto_tree_add_format_text( megaco_requestedsignal_tree, tvb, requested_signal_start_offset, tokenlen);
2241 /* Print the trailing '}' (raw formatting removed) */
2242 /* proto_tree_add_format_text( megaco_requestedsignal_tree, tvb, tvb_RBRKT, 1); */
2245 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
2246 tvb_signals_end_offset, ',');
2248 if (tvb_current_offset == -1 || tvb_current_offset > tvb_signals_end_offset || tvb_current_offset < tvb_previous_offset){
2249 tvb_current_offset = tvb_signals_end_offset;
2252 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2254 tvb_LBRKT = tvb_previous_offset;
2255 tvb_RBRKT = tvb_previous_offset;
2256 /* Print the trailing '}' (raw formatting removed) */
2257 /* proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1); */
2259 } while ( tvb_current_offset < tvb_signals_end_offset );
2261 /* signals{} (raw formatting removed)
2262 proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1); */
2269 auditDescriptor = AuditToken LBRKT [ auditItem *(COMMA auditItem) ] RBRKT
2271 auditItem = ( MuxToken / ModemToken / MediaToken /
2272 SignalsToken / EventBufferToken /
2273 DigitMapToken / StatsToken / EventsToken /
2274 ObservedEventsToken / PackagesToken ) */
2276 dissect_megaco_auditdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree, packet_info *pinfo _U_, gint tvb_stop, gint tvb_offset)
2278 gint tokenlen, tvb_end, tvb_next, token_index;
2279 proto_tree *megaco_auditdescriptor_tree, *megaco_auditdescriptor_ti;
2281 tvb_next = tvb_find_guint8(tvb, tvb_offset, tvb_stop, '{'); /* find opening LBRKT - is this already checked by caller?*/
2282 if( tvb_next == -1 ) /* complain and give up if not there */
2284 expert_add_info(pinfo, megaco_tree, &ei_megaco_audit_descriptor);
2287 tokenlen = (tvb_stop + 1) - tvb_offset;
2289 megaco_auditdescriptor_ti = proto_tree_add_item( megaco_tree, hf_megaco_audit_descriptor, tvb, tvb_offset, tokenlen, ENC_NA);
2290 megaco_auditdescriptor_tree = proto_item_add_subtree( megaco_auditdescriptor_ti, ett_megaco_auditdescriptor );
2292 tvb_offset = tvb_next;
2294 while( tvb_offset < tvb_stop )
2296 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1); /* find start of an auditItem */
2297 if( tvb_get_guint8(tvb, tvb_offset) != '}' ) /* got something */
2299 tvb_next = tvb_find_guint8(tvb, tvb_offset, tvb_stop, ','); /* end of an auditItem */
2300 if (tvb_next == -1) /* last item doesn't have a comma */
2301 tvb_next = tvb_stop;
2302 tvb_end = megaco_tvb_skip_wsp_return(tvb, tvb_next-1); /* trim any trailing whitespace */
2303 tokenlen = tvb_end - tvb_offset; /* get length of token */
2305 token_index = find_megaco_descriptors_names(tvb, tvb_offset, tokenlen); /* lookup the token */
2306 if( token_index == -1 ) /* if not found then 0 => Unknown */
2309 proto_tree_add_string(megaco_auditdescriptor_tree, hf_megaco_audititem, tvb,
2310 tvb_offset, tokenlen, megaco_descriptors_names[token_index].name); /* and display the long form */
2312 tvb_offset = tvb_next; /* advance pointer */
2318 * serviceChangeDescriptor = ServicesToken LBRKT serviceChangeParm
2319 * *(COMMA serviceChangeParm) RBRKT
2321 * ServicesToken = ("Services" / "SV")
2323 * serviceChangeParm = (serviceChangeMethod / serviceChangeReason /
2324 * serviceChangeDelay / serviceChangeAddress /
2325 * serviceChangeProfile / extension / TimeStamp /
2326 * serviceChangeMgcId / serviceChangeVersion )
2329 #define MEGACO_REASON_TOKEN 1
2330 #define MEGACO_DELAY_TOKEN 2
2331 #define MEGACO_SC_ADDR_TOKEN 3
2332 #define MEGACO_MGC_ID_TOKEN 4
2333 #define MEGACO_PROFILE_TOKEN 5
2334 #define MEGACO_VERSION_TOKEN 6
2335 #define MEGACO_METHOD_TOKEN 7
2337 static const megaco_tokens_t megaco_serviceChangeParm_names[] = {
2338 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
2340 { "Reason", "RE" }, /* 1 ReasonToken*/
2341 { "Delay", "DL" }, /* 2 DelayToken */
2342 { "ServiceChangeAddress", "AD" }, /* 3 ServiceChangeAddressToken */
2343 { "MgcIdToTry", "MG" }, /* 4 MgcIdToken */
2344 { "Profile", "PF" }, /* 5 ProfileToken */
2345 { "Version", "V" }, /* 6 VersionToken */
2346 { "Method", "MT" }, /* 7 MethodToken */
2349 /* Returns index of megaco_tokens_t */
2350 static gint find_megaco_megaco_serviceChangeParm_names(tvbuff_t *tvb, int offset, guint header_len)
2354 for (i = 1; i < array_length(megaco_serviceChangeParm_names); i++) {
2355 if (header_len == strlen(megaco_serviceChangeParm_names[i].name) &&
2356 tvb_strncaseeql(tvb, offset, megaco_serviceChangeParm_names[i].name, header_len) == 0)
2358 if (megaco_serviceChangeParm_names[i].compact_name != NULL &&
2359 header_len == strlen(megaco_serviceChangeParm_names[i].compact_name) &&
2360 tvb_strncaseeql(tvb, offset, megaco_serviceChangeParm_names[i].compact_name, header_len) == 0)
2367 * ServiceChangeReasons References
2368 * -------------------- ----------
2370 static const value_string MEGACO_ServiceChangeReasons_vals[] = {
2371 {900, "Service Restored"},
2374 {903, "MGC Directed Change"},
2375 {904, "Termination malfunctioning"},
2376 {905, "Termination taken out of service"},
2377 {906, "Loss of lower layer connectivity (e.g. downstream sync)"},
2378 {907, "Transmission Failure"},
2379 {908, "MG Impending Failure"},
2380 {909, "MGC Impending Failure"},
2381 {910, "Media Capability Failure"},
2382 {911, "Modem Capability Failure"},
2383 {912, "Mux Capability Failure"},
2384 {913, "Signal Capability Failure"},
2385 {914, "Event Capability Failure"},
2386 {915, "State Loss"},
2387 {916, "Packages Change"},
2388 {917, "Capabilities Change"},
2389 {918, "Cancel Graceful"},
2390 {919, "Warm Failover"},
2391 {920, "Cold Failover"},
2396 dissect_megaco_servicechangedescriptor(tvbuff_t *tvb, packet_info* pinfo, proto_tree *megaco_tree, gint tvb_RBRKT,
2397 gint tvb_previous_offset)
2400 gint tokenlen, tvb_LBRKT, tvb_offset;
2402 gint tvb_current_offset;
2403 gboolean more_params = TRUE;
2406 gboolean reason_valid;
2407 guint8 ServiceChangeReason_str[4];
2409 tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2411 if (tvb_LBRKT == -1)
2414 tokenlen = (tvb_LBRKT + 1) - tvb_previous_offset;
2415 proto_tree_add_format_text(megaco_tree, tvb, tvb_previous_offset, tokenlen);
2417 /* Start dissecting serviceChangeParm */
2418 tvb_previous_offset = tvb_LBRKT + 1;
2419 while (more_params){
2420 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
2421 /* Find token length */
2422 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_RBRKT; tvb_offset++){
2423 if (!g_ascii_isalpha(tvb_get_guint8(tvb, tvb_offset ))){
2427 tokenlen = tvb_offset - tvb_previous_offset;
2428 token_index = find_megaco_megaco_serviceChangeParm_names(tvb, tvb_previous_offset, tokenlen);
2430 tvb_offset = tvb_find_guint8(tvb, tvb_offset, tvb_RBRKT, ',');
2431 if ((tvb_offset == -1)||(tvb_offset >=tvb_RBRKT)){
2432 more_params = FALSE;
2433 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_RBRKT-1);
2435 tokenlen = tvb_offset - tvb_previous_offset;
2436 if (more_params == TRUE )
2439 switch(token_index){
2440 case MEGACO_REASON_TOKEN:
2441 /* ReasonToken EQUAL VALUE
2442 * VALUE = quotedString / 1*(SafeChar)
2444 item = proto_tree_add_format_text(megaco_tree, tvb, tvb_previous_offset, tokenlen);
2446 /* As the reason code ( if a digit ) can be in quoted string or 'just' digit
2447 * look for a nine and hope for the best.
2449 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '9');
2450 if ( tvb_current_offset == -1)
2453 tvb_get_nstringz0(tvb,tvb_current_offset,4,ServiceChangeReason_str);
2454 reason_valid = ws_strtoi32(ServiceChangeReason_str, NULL, &reason);
2455 proto_item_append_text(item,"[ %s ]", val_to_str(reason, MEGACO_ServiceChangeReasons_vals,"Unknown (%u)"));
2457 expert_add_info(pinfo, item, &ei_megaco_reason_invalid);
2459 case MEGACO_DELAY_TOKEN:
2460 case MEGACO_SC_ADDR_TOKEN:
2461 case MEGACO_MGC_ID_TOKEN:
2462 case MEGACO_PROFILE_TOKEN:
2463 case MEGACO_VERSION_TOKEN:
2464 case MEGACO_METHOD_TOKEN:
2465 /* No special dissection: fall through */
2468 * extension = extensionParameter parmValue
2469 * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
2471 proto_tree_add_format_text(megaco_tree, tvb, tvb_previous_offset, tokenlen);
2475 tvb_previous_offset = tvb_offset +1;
2479 /* extension = extensionParameter parmValue
2480 * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
2484 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2485 proto_tree_add_string(megaco_tree_command_line, hf_megaco_servicechange_descriptor, tvb,
2486 tvb_previous_offset, tokenlen,
2487 tvb_format_text(tvb, tvb_previous_offset,
2490 proto_tree_add_format_text(megaco_tree, tvb, tvb_RBRKT, 1);
2494 dissect_megaco_digitmapdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2499 tokenlen = tvb_RBRKT - tvb_previous_offset;
2500 proto_tree_add_string(megaco_tree_command_line, hf_megaco_digitmap_descriptor, tvb,
2501 tvb_previous_offset, tokenlen,
2502 tvb_format_text(tvb, tvb_previous_offset,
2507 dissect_megaco_statisticsdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2510 proto_tree *megaco_statisticsdescriptor_tree;
2511 proto_item *megaco_statisticsdescriptor_ti;
2512 gint tvb_help_offset, param_start_offset, param_end_offset = 0;
2514 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2516 megaco_statisticsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_statistics_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_NA);
2517 megaco_statisticsdescriptor_tree = proto_item_add_subtree(megaco_statisticsdescriptor_ti, ett_megaco_statisticsdescriptor);
2519 tvb_help_offset = tvb_find_guint8(tvb, tvb_previous_offset+1, tvb_RBRKT, '{');
2521 param_start_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset+1);
2523 tvb_help_offset = tvb_find_guint8(tvb, tvb_help_offset+1, tvb_RBRKT, ',');
2525 if ( tvb_help_offset > tvb_RBRKT || tvb_help_offset == -1){
2526 tvb_help_offset = tvb_RBRKT;
2527 param_end_offset = megaco_tvb_skip_wsp_return(tvb, tvb_RBRKT-1);
2528 tokenlen = param_end_offset - param_start_offset;
2530 param_end_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset-1);
2531 tokenlen = param_end_offset - param_start_offset+1;
2534 proto_tree_add_format_text(megaco_statisticsdescriptor_tree, tvb,param_start_offset, tokenlen);
2536 } while ( tvb_help_offset < tvb_RBRKT );
2540 dissect_megaco_observedeventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset, proto_tree *top_tree)
2543 gint tokenlen, pkg_tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
2544 gint tvb_observedevents_end_offset, tvb_LBRKT;
2545 proto_tree *megaco_observedeventsdescriptor_tree, *megaco_observedevent_tree;
2546 proto_item *megaco_observedeventsdescriptor_ti, *megaco_observedevent_ti, *ti;
2548 gint requested_event_start_offset, requested_event_end_offset, param_start_offset, param_end_offset;
2550 requested_event_start_offset = 0;
2551 requested_event_end_offset = 0;
2553 tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2554 tvb_next_offset = tvb_LBRKT;
2555 tokenlen = (tvb_next_offset+1) - tvb_previous_offset;
2557 megaco_observedeventsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_observedevents_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_NA);
2558 megaco_observedeventsdescriptor_tree = proto_item_add_subtree(megaco_observedeventsdescriptor_ti, ett_megaco_observedeventsdescriptor);
2560 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
2561 tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2563 if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
2565 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2566 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
2568 tokenlen = tvb_help_offset - tvb_current_offset;
2570 ti = proto_tree_add_uint(megaco_observedeventsdescriptor_tree, hf_megaco_requestid, tvb,
2571 tvb_current_offset, 1,
2572 (guint32) strtoul(tvb_format_text(tvb, tvb_current_offset, tokenlen), NULL, 10));
2573 proto_item_set_len(ti, tokenlen);
2575 tvb_observedevents_end_offset = tvb_RBRKT;
2577 tvb_RBRKT = tvb_next_offset+1;
2578 tvb_LBRKT = tvb_next_offset+1;
2579 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
2584 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2585 tvb_observedevents_end_offset, '}');
2586 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
2587 tvb_observedevents_end_offset, '{');
2589 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
2590 tvb_observedevents_end_offset, ',');
2592 if (tvb_current_offset == -1 || tvb_current_offset > tvb_observedevents_end_offset){
2593 tvb_current_offset = tvb_observedevents_end_offset;
2597 /* Descriptor includes no parameters */
2599 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
2601 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2604 /* Descriptor includes Parameters */
2606 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
2608 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
2610 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
2611 tvb_observedevents_end_offset, '{');
2612 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1){
2613 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2614 tvb_observedevents_end_offset, '}');
2620 tvb_LBRKT = tvb_help_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_observedevents_end_offset, '{');
2622 /* if there are eventparameter */
2624 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2626 requested_event_start_offset = tvb_help_offset;
2627 requested_event_end_offset = tvb_RBRKT;
2628 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2629 pkg_tokenlen = tvb_help_offset - tvb_previous_offset;
2630 tokenlen = tvb_LBRKT+1 - tvb_previous_offset;
2634 tokenlen = pkg_tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2637 megaco_observedevent_ti = proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen);
2639 megaco_observedevent_tree = proto_item_add_subtree(megaco_observedevent_ti, ett_megaco_observedevent);
2641 proto_tree_add_item(megaco_observedevent_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,pkg_tokenlen, ENC_UTF_8|ENC_NA);
2643 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2645 requested_event_start_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1)-1;
2646 requested_event_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_event_end_offset-1);
2648 tvb_help_offset = requested_event_start_offset;
2651 param_start_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset+1);
2653 tvb_help_offset = tvb_find_guint8(tvb, tvb_help_offset+1,requested_event_end_offset, ',');
2655 if ( tvb_help_offset > requested_event_end_offset || tvb_help_offset == -1){
2656 tvb_help_offset = requested_event_end_offset;
2659 param_end_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset-1);
2661 tokenlen = param_end_offset - param_start_offset+1;
2662 if(!tvb_strneql(tvb, param_start_offset, "h245", 4)){
2663 dissect_megaco_h245(tvb, pinfo, megaco_tree_command_line, param_start_offset, tokenlen, top_tree);
2665 proto_tree_add_format_text(megaco_tree_command_line, tvb, param_start_offset, tokenlen);
2669 } while ( tvb_help_offset < requested_event_end_offset );
2672 tvb_previous_offset = tvb_current_offset;
2673 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
2674 tvb_observedevents_end_offset, ',');
2676 if (tvb_current_offset == -1 || tvb_current_offset > tvb_observedevents_end_offset ){
2677 tvb_current_offset = tvb_observedevents_end_offset;
2679 if (tvb_current_offset < tvb_previous_offset) {
2680 expert_add_info_format(pinfo, megaco_observedevent_ti, &ei_megaco_parse_error, "Parse error: Invalid offset");
2684 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2686 tvb_LBRKT = tvb_previous_offset;
2687 tvb_RBRKT = tvb_previous_offset;
2688 /* Print the trailing '}' (raw formatting removed) */
2689 /* proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_observedevents_end_offset, 1); */
2691 } while ( tvb_current_offset < tvb_observedevents_end_offset );
2695 dissect_megaco_topologydescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2700 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2701 proto_tree_add_string(megaco_tree_command_line, hf_megaco_topology_descriptor, tvb,
2702 tvb_previous_offset, tokenlen,
2703 tvb_format_text_wsp(wmem_packet_scope(), tvb, tvb_previous_offset,
2708 dissect_megaco_Packagesdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2711 gint tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
2712 gint tvb_packages_end_offset, tvb_LBRKT;
2713 proto_tree *megaco_packagesdescriptor_tree;
2714 proto_item *megaco_packagesdescriptor_ti, *ti;
2716 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2718 megaco_packagesdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_packages_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_UTF_8|ENC_NA);
2719 megaco_packagesdescriptor_tree = proto_item_add_subtree(megaco_packagesdescriptor_ti, ett_megaco_packagesdescriptor);
2721 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
2722 tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2724 if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
2726 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2727 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
2729 tokenlen = tvb_help_offset - tvb_current_offset;
2731 ti = proto_tree_add_uint(megaco_packagesdescriptor_tree, hf_megaco_requestid, tvb,
2732 tvb_current_offset, 1,
2733 (guint32) strtoul(tvb_format_text(tvb, tvb_current_offset, tokenlen), NULL, 10));
2734 proto_item_set_len(ti, tokenlen);
2736 tvb_packages_end_offset = tvb_RBRKT;
2738 tvb_RBRKT = tvb_next_offset+1;
2739 tvb_LBRKT = tvb_next_offset+1;
2740 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
2745 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2746 tvb_packages_end_offset, '}');
2747 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
2748 tvb_packages_end_offset, '{');
2750 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
2751 tvb_packages_end_offset, ',');
2753 if (tvb_current_offset == -1 || tvb_current_offset > tvb_packages_end_offset){
2754 tvb_current_offset = tvb_packages_end_offset;
2758 /* Descriptor includes no parameters */
2760 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
2762 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2765 /* Descriptor includes Parameters */
2767 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
2769 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
2771 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
2772 tvb_packages_end_offset, '{');
2773 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
2774 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2775 tvb_packages_end_offset, '}');
2780 tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2782 proto_tree_add_format_text(megaco_packagesdescriptor_tree, tvb, tvb_previous_offset, tokenlen);
2784 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
2785 tvb_packages_end_offset, ',');
2787 if (tvb_current_offset == -1 || tvb_current_offset > tvb_packages_end_offset ){
2788 tvb_current_offset = tvb_packages_end_offset;
2791 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2793 tvb_LBRKT = tvb_previous_offset;
2794 tvb_RBRKT = tvb_previous_offset;
2796 } while ( tvb_current_offset < tvb_packages_end_offset );
2800 /* The list of error code values is fetched from http://www.iana.org/assignments/megaco-h248 */
2803 static const value_string MEGACO_error_code_vals[] = {
2805 {400, "Syntax error in message"},
2806 {401, "Protocol Error"},
2807 {402, "Unauthorized"},
2808 {403, "Syntax error in transaction request"},
2809 {406, "Version Not Supported"},
2810 {410, "Incorrect identifier"},
2811 {411, "The transaction refers to an unknown ContextId"},
2812 {412, "No ContextIDs available"},
2813 {421, "Unknown action or illegal combination of actions"},
2814 {422, "Syntax Error in Action"},
2815 {430, "Unknown TerminationID"},
2816 {431, "No TerminationID matched a wildcard"},
2817 {432, "Out of TerminationIDs or No TerminationID available"},
2818 {433, "TerminationID is already in a Context"},
2819 {434, "Max number of Terminations in a Context exceeded"},
2820 {435, "Termination ID is not in specified Context"},
2821 {440, "Unsupported or unknown Package"},
2822 {441, "Missing Remote or Local Descriptor"},
2823 {442, "Syntax Error in Command"},
2824 {443, "Unsupported or Unknown Command"},
2825 {444, "Unsupported or Unknown Descriptor"},
2826 {445, "Unsupported or Unknown Property"},
2827 {446, "Unsupported or Unknown Parameter"},
2828 {447, "Descriptor not legal in this command"},
2829 {448, "Descriptor appears twice in a command"},
2830 {450, "No such property in this package"},
2831 {451, "No such event in this package"},
2832 {452, "No such signal in this package"},
2833 {453, "No such statistic in this package"},
2834 {454, "No such parameter value in this package"},
2835 {455, "Property illegal in this Descriptor"},
2836 {456, "Property appears twice in this Descriptor"},
2837 {457, "Missing parameter in signal or event"},
2838 {458, "Unexpected Event/Request ID"},
2839 {459, "Unsupported or Unknown Profile"},
2840 {471, "Implied Add for Multiplex failure"},
2842 {500, "Internal software Failure in MG"},
2843 {501, "Not Implemented"},
2844 {502, "Not ready."},
2845 {503, "Service Unavailable"},
2846 {504, "Command Received from unauthorized entity"},
2847 {505, "Transaction Request Received before a Service Change Reply has been received"},
2848 {506, "Number of Transaction Pendings Exceeded"},
2849 {510, "Insufficient resources"},
2850 {512, "Media Gateway unequipped to detect requested Event"},
2851 {513, "Media Gateway unequipped to generate requested Signals"},
2852 {514, "Media Gateway cannot send the specified announcement"},
2853 {515, "Unsupported Media Type"},
2854 {517, "Unsupported or invalid mode"},
2855 {518, "Event buffer full"},
2856 {519, "Out of space to store digit map"},
2857 {520, "Digit Map undefined in the MG"},
2858 {521, "Termination is ServiceChanging"},
2859 {526, "Insufficient bandwidth"},
2860 {529, "Internal hardware failure in MG"},
2861 {530, "Temporary Network failure"},
2862 {531, "Permanent Network failure"},
2863 {532, "Audited Property, Statistic, Event or Signal does not exist"},
2864 {533, "Response exceeds maximum transport PDU size"},
2865 {534, "Illegal write or read only property"},
2866 {540, "Unexpected initial hook state"},
2867 {581, "Does Not Exist"},
2869 {600, "Illegal syntax within an announcement specification"},
2870 {601, "Variable type not supported"},
2871 {602, "Variable value out of range"},
2872 {603, "Category not supported"},
2873 {604, "Selector type not supported"},
2874 {605, "Selector value not supported"},
2875 {606, "Unknown segment ID"},
2876 {607, "Mismatch between play specification and provisioned data"},
2877 {608, "Provisioning error"},
2878 {609, "Invalid offset"},
2879 {610, "No free segment IDs"},
2880 {611, "Temporary segment not found"},
2881 {612, "Segment in use"},
2882 {613, "ISP port limit overrun"},
2883 {614, "No modems available"},
2884 {615, "Calling number unacceptable"},
2885 {616, "Called number unacceptable"},
2892 dissect_megaco_errordescriptor(tvbuff_t *tvb, packet_info* pinfo, proto_tree *megaco_tree_command_line,
2893 gint tvb_RBRKT, gint tvb_previous_offset)
2899 gint tvb_current_offset;
2901 proto_tree* error_tree;
2902 gboolean error_code_valid;
2904 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset , tvb_RBRKT, '=');
2905 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2907 tokenlen = (tvb_RBRKT) - tvb_previous_offset+1;
2909 item = proto_tree_add_item(megaco_tree_command_line, hf_megaco_error_descriptor, tvb,
2910 tvb_previous_offset, tokenlen, ENC_NA);
2911 error_tree = proto_item_add_subtree(item, ett_megaco_error_descriptor);
2913 /* Get the error code */
2914 tvb_get_nstringz0(tvb,tvb_current_offset,4,error);
2915 error_code_valid = ws_strtoi32(error, NULL, &error_code);
2916 item = proto_tree_add_uint(error_tree, hf_megaco_error_code, tvb, tvb_current_offset, 3, error_code);
2917 if (!error_code_valid)
2918 expert_add_info(pinfo, item, &ei_megaco_error_code_invalid);
2920 /* Get the error string (even though we have a value_string that should match) */
2921 tvb_previous_offset = tvb_find_guint8(tvb, tvb_current_offset, tvb_RBRKT, '\"');
2922 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset+1, tvb_RBRKT, '\"');
2924 tokenlen = tvb_current_offset - tvb_previous_offset-1;
2925 proto_tree_add_item(error_tree, hf_megaco_error_string, tvb, tvb_previous_offset+1, tokenlen, ENC_UTF_8|ENC_NA);
2928 dissect_megaco_TerminationStatedescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree, gint tvb_next_offset, gint tvb_current_offset)
2934 proto_tree *megaco_TerminationState_tree, *megaco_TerminationState_ti;
2936 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_next_offset, '=');
2938 tokenlen = tvb_next_offset - tvb_current_offset;
2939 megaco_TerminationState_ti = proto_tree_add_item(megaco_mediadescriptor_tree,hf_megaco_TerminationState_descriptor,tvb,tvb_current_offset,tokenlen, ENC_NA);
2940 megaco_TerminationState_tree = proto_item_add_subtree(megaco_TerminationState_ti, ett_megaco_TerminationState);
2942 while ( tvb_offset < tvb_next_offset && tvb_offset != -1 ){
2944 tempchar = tvb_get_guint8(tvb, tvb_current_offset);
2945 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
2946 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
2947 tempchar = tempchar - 0x20;
2949 switch ( tempchar ){
2952 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
2953 if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
2954 tvb_offset = tvb_next_offset;
2957 tokenlen = tvb_offset - tvb_current_offset;
2959 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Service_State, tvb,
2960 tvb_current_offset, tokenlen,
2961 tvb_format_text(tvb, tvb_current_offset,
2968 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
2969 if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
2970 tvb_offset = tvb_next_offset;
2973 tokenlen = tvb_offset - tvb_current_offset;
2975 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Event_Buffer_Control, tvb,
2976 tvb_current_offset, tokenlen,
2977 tvb_format_text(tvb, tvb_current_offset,
2983 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
2984 if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
2985 tvb_offset = tvb_next_offset;
2988 tokenlen = tvb_offset - tvb_current_offset;
2990 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Event_Buffer_Control, tvb,
2991 tvb_current_offset, tokenlen,
2992 tvb_format_text(tvb, tvb_current_offset,
2998 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
2999 if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
3000 tvb_offset = tvb_next_offset;
3003 tokenlen = tvb_offset - tvb_current_offset;
3005 proto_tree_add_format_text(megaco_TerminationState_tree, tvb, tvb_current_offset, tokenlen);
3010 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3011 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_next_offset, '=');
3014 /* (raw formatting removed)
3015 proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_next_offset, 1); */
3019 dissect_megaco_Localdescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree,packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset)
3024 proto_tree *megaco_localdescriptor_tree;
3025 proto_item *megaco_localdescriptor_item;
3027 tokenlen = tvb_next_offset - tvb_current_offset;
3029 megaco_localdescriptor_item = proto_tree_add_item(megaco_mediadescriptor_tree, hf_megaco_Local_descriptor, tvb, tvb_current_offset, tokenlen, ENC_NA);
3030 megaco_localdescriptor_tree = proto_item_add_subtree(megaco_localdescriptor_item, ett_megaco_Localdescriptor);
3032 if ( tokenlen > 3 ){
3033 next_tvb = tvb_new_subset_length(tvb, tvb_current_offset, tokenlen);
3034 call_dissector(sdp_handle, next_tvb, pinfo, megaco_localdescriptor_tree);
3039 * localControlDescriptor = LocalControlToken LBRKT localParm
3040 * *(COMMA localParm) RBRKT
3041 * ; at-most-once per item
3042 * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
3045 #define MEGACO_MODETOKEN 1
3046 #define MEGACO_RESERVEDVALUETOKEN 2
3047 #define MEGACO_RESERVEDGROUPTOKEN 3
3048 #define MEGACO_H324_H223CAPR 4
3049 #define MEGACO_H324_MUXTBL_IN 5
3050 #define MEGACO_H324_MUXTBL_OUT 6
3051 #define MEGACO_DS_DSCP 7
3052 #define MEGACO_GM_SAF 8
3053 #define MEGACO_GM_SAM 9
3054 #define MEGACO_GM_SPF 10
3055 #define MEGACO_GM_SPR 11
3056 #define MEGACO_GM_ESAS 12
3057 #define MEGACO_GM_LSA 13
3058 #define MEGACO_GM_ESPS 14
3059 #define MEGACO_GM_LSP 15
3060 #define MEGACO_GM_RSB 16
3061 #define MEGACO_TMAN_POL 17
3062 #define MEGACO_TMAN_SDR 18
3063 #define MEGACO_TMAN_MBS 19
3064 #define MEGACO_TMAN_PDR 20
3065 #define MEGACO_TMAN_DVT 21
3066 #define MEGACO_IPDC_REALM 22
3068 static const megaco_tokens_t megaco_localParam_names[] = {
3069 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
3071 { "Mode", "MO" }, /* 1 */
3072 { "ReservedValue", "RV" }, /* 2 */
3073 { "ReservedGroup", "RG" }, /* 3 */
3074 /* propertyParm = pkgdName parmValue
3075 * Add more package names as needed.
3077 { "h324/h223capr", NULL }, /* 4 */
3078 { "h324/muxtbl_in", NULL }, /* 5 */
3079 { "h324/muxtbl_out", NULL }, /* 6 */
3080 { "ds/dscp", NULL }, /* 7 */
3081 { "gm/saf", NULL }, /* 8 */
3082 { "gm/sam", NULL }, /* 9 */
3083 { "gm/spf", NULL }, /* 10 */
3084 { "gm/spr", NULL }, /* 11 */
3085 { "gm/esas", NULL }, /* 12 */
3086 { "gm/lsa", NULL }, /* 13 */
3087 { "gm/esps", NULL }, /* 14 */
3088 { "gm/lsp", NULL }, /* 15 */
3089 { "gm/rsb", NULL }, /* 16 */
3090 { "tman/pol", NULL }, /* 17 */
3091 { "tman/sdr", NULL }, /* 18 */
3092 { "tman/mbs", NULL }, /* 19 */
3093 { "tman/pdr", NULL }, /* 20 */
3094 { "tman/dvt", NULL }, /* 21 */
3095 { "ipdc/realm", NULL }, /* 22 */
3098 /* Returns index of megaco_tokens_t */
3099 static gint find_megaco_localParam_names(tvbuff_t *tvb, int offset, guint header_len)
3103 for (i = 1; i < array_length(megaco_localParam_names); i++) {
3104 if (header_len == strlen(megaco_localParam_names[i].name) &&
3105 tvb_strncaseeql(tvb, offset, megaco_localParam_names[i].name, header_len) == 0)
3107 if (megaco_localParam_names[i].compact_name != NULL &&
3108 header_len == strlen(megaco_localParam_names[i].compact_name) &&
3109 tvb_strncaseeql(tvb, offset, megaco_localParam_names[i].compact_name, header_len) == 0)
3117 dissect_megaco_LocalControldescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset, proto_tree *top_tree)
3120 guint token_name_len;
3121 gint tvb_offset = 0,tvb_help_offset;
3122 gint token_index = 0;
3127 proto_tree *megaco_LocalControl_tree;
3128 proto_item *megaco_LocalControl_item;
3130 tokenlen = tvb_next_offset - tvb_current_offset;
3132 megaco_LocalControl_item = proto_tree_add_item(megaco_mediadescriptor_tree, hf_megaco_LocalControl_descriptor, tvb, tvb_current_offset, tokenlen, ENC_NA);
3133 megaco_LocalControl_tree = proto_item_add_subtree(megaco_LocalControl_item, ett_megaco_LocalControldescriptor);
3135 while ( tvb_offset < tvb_next_offset && tvb_offset != -1 ){
3137 tvb_help_offset = tvb_current_offset;
3140 * Find local parameter name
3141 * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
3142 * pkgdName = (PackageName SLASH ItemID) ;specific item
3143 * / (PackageName SLASH "*") ;all events in package
3144 * / ("*" SLASH "*") ; all events supported by the MG
3146 /* Find token length */
3147 for (tvb_offset=tvb_current_offset; tvb_offset < tvb_next_offset; tvb_offset++){
3149 octet = tvb_get_guint8(tvb, tvb_offset);
3150 if (!g_ascii_isalnum(octet)){
3151 if ((octet!='/')&&(octet!='_')){
3156 token_name_len = tvb_offset - tvb_current_offset;
3158 proto_tree_add_format_text(megaco_LocalControl_tree, tvb, tvb_current_offset, token_name_len);
3160 token_index = find_megaco_localParam_names(tvb, tvb_current_offset, token_name_len);
3161 /* Find start of parameter value */
3162 tvb_offset = tvb_find_guint8(tvb, tvb_offset , tvb_next_offset, '=');
3163 if (tvb_offset == -1) {
3164 expert_add_info(pinfo, megaco_LocalControl_item, &ei_megaco_parse_error);
3167 /* Start search after '=' in case there is no SP*/
3169 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
3171 /* find if there are more parameters or not */
3172 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
3173 if ( tvb_offset < 0 || tvb_offset > tvb_next_offset ){
3174 tvb_offset = tvb_next_offset;
3177 tokenlen = megaco_tvb_skip_wsp_return(tvb,tvb_offset-1) - tvb_current_offset;
3179 proto_tree_add_format_text(megaco_LocalControl_tree, tvb, tvb_current_offset, tokenlen);
3181 switch ( token_index ){
3183 case MEGACO_MODETOKEN: /* Mode */
3184 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_mode, tvb,
3185 tvb_help_offset, tvb_offset-tvb_help_offset,
3186 tvb_format_text(tvb, tvb_current_offset,
3188 col_append_fstr(pinfo->cinfo, COL_INFO, " (Mode:%s)",tvb_format_text(tvb, tvb_current_offset,tokenlen));
3189 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3192 case MEGACO_RESERVEDVALUETOKEN: /* ReservedValue */
3193 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_reserve_value, tvb,
3194 tvb_help_offset, tvb_offset-tvb_help_offset,
3195 tvb_format_text(tvb, tvb_current_offset, tokenlen));
3197 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3199 case MEGACO_RESERVEDGROUPTOKEN: /* ReservedGroup */
3200 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_reserve_group, tvb,
3201 tvb_help_offset, tvb_offset-tvb_help_offset,
3202 tvb_format_text(tvb, tvb_current_offset, tokenlen));
3203 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3206 case MEGACO_H324_H223CAPR: /* h324/h223capr */
3207 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_h324_h223capr, tvb,
3208 tvb_help_offset, tvb_offset-tvb_help_offset,
3209 tvb_format_text(tvb, tvb_current_offset, tokenlen));
3211 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3212 tokenlen = tvb_offset - tvb_help_offset;
3213 msg=tvb_format_text(tvb,tvb_help_offset, tokenlen);
3214 dissect_megaco_h324_h223caprn(tvb, pinfo, megaco_mediadescriptor_tree, tvb_help_offset, tokenlen, msg);
3218 case MEGACO_H324_MUXTBL_IN: /* h324/muxtbl_in */
3220 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_h324_muxtbl_in, tvb,
3221 tvb_help_offset, tvb_offset-tvb_help_offset,
3222 tvb_format_text(tvb, tvb_current_offset, tokenlen));
3224 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3226 tokenlen = tvb_offset - tvb_help_offset;
3227 /* Call the existing routine with tree = NULL to avoid an entry to the tree */
3228 dissect_megaco_h245(tvb, pinfo, NULL, tvb_help_offset, tokenlen, top_tree);
3232 case MEGACO_H324_MUXTBL_OUT:
3234 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_h324_muxtbl_out, tvb,
3235 tvb_current_offset, tokenlen,
3236 tvb_format_text(tvb, tvb_current_offset,
3239 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3241 tokenlen = tvb_offset - tvb_help_offset;
3242 /* Call the existing routine with tree = NULL to avoid an entry to the tree */
3243 dissect_megaco_h245(tvb, pinfo, NULL, tvb_help_offset, tokenlen, top_tree);
3247 case MEGACO_DS_DSCP:
3248 tvb_get_nstringz0(tvb,tvb_current_offset,3,code_str);
3249 item = proto_tree_add_uint(megaco_LocalControl_tree, hf_megaco_ds_dscp, tvb,
3250 tvb_help_offset, 1, (guint32) strtoul(code_str,NULL,16));
3251 proto_item_set_len(item, tvb_offset-tvb_help_offset);
3252 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3256 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_saf, tvb,
3257 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3258 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3261 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_sam, tvb,
3262 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3263 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3266 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_spf, tvb,
3267 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3268 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3271 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_spr, tvb,
3272 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3273 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3275 case MEGACO_GM_ESAS:
3276 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_esas, tvb,
3277 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3278 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3281 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_rsb, tvb,
3282 tvb_help_offset, tvb_offset - tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3283 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset + 1);
3286 case MEGACO_TMAN_POL:
3287 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_pol, tvb,
3288 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3289 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3291 case MEGACO_TMAN_SDR:
3292 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_sdr, tvb,
3293 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3294 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3296 case MEGACO_TMAN_MBS:
3297 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_mbs, tvb,
3298 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3299 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3301 case MEGACO_TMAN_PDR:
3302 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_pdr, tvb,
3303 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3304 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3306 case MEGACO_TMAN_DVT:
3307 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_dvt, tvb,
3308 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3309 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3311 case MEGACO_IPDC_REALM:
3312 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_ipdc_realm, tvb,
3313 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(tvb, tvb_current_offset, tokenlen));
3314 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3318 tokenlen = tvb_offset - tvb_help_offset;
3319 proto_tree_add_format_text(megaco_LocalControl_tree, tvb, tvb_help_offset, tokenlen);
3320 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3328 dissect_megaco_descriptors(tvbuff_t *tvb, proto_tree *megaco_command_tree, packet_info *pinfo, gint tvb_descriptors_start_offset, gint tvb_descriptors_end_offset, proto_tree *top_tree)
3330 gint tvb_len, token_index, tvb_offset, temp_offset;
3331 gint tvb_current_offset,tvb_previous_offset,save_offset,tokenlen;
3332 gint tvb_RBRKT, tvb_LBRKT;
3333 proto_tree* descriptor_tree;
3334 proto_item* descriptor_item;
3336 tvb_len = tvb_reported_length(tvb);
3338 descriptor_tree = proto_tree_add_subtree(megaco_command_tree, tvb, tvb_descriptors_start_offset,
3339 tvb_descriptors_end_offset-tvb_descriptors_start_offset, ett_megaco_descriptors, &descriptor_item, "Descriptors");
3341 tvb_LBRKT = megaco_tvb_skip_wsp(tvb, tvb_descriptors_start_offset +1);
3343 tvb_previous_offset = tvb_LBRKT;
3344 tvb_RBRKT = tvb_descriptors_start_offset;
3349 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
3351 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
3354 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
3357 if (tvb_current_offset == -1 || tvb_current_offset > tvb_descriptors_end_offset){
3358 tvb_current_offset = tvb_descriptors_end_offset;
3361 if (tvb_current_offset <= tvb_previous_offset) {
3362 expert_add_info_format(pinfo, descriptor_item, &ei_megaco_parse_error, "Parse error: Invalid offset");
3366 /* Descriptor includes no parameters */
3368 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
3370 if ( tvb_current_offset > tvb_RBRKT ){
3371 tvb_current_offset = tvb_RBRKT;
3374 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
3377 /* Descriptor includes Parameters */
3378 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
3380 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
3383 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
3385 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
3386 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_len, '}');
3391 /* Find token length */
3392 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_descriptors_end_offset -1; tvb_offset++){
3393 if (!g_ascii_isalpha(tvb_get_guint8(tvb, tvb_offset ))){
3397 tokenlen = tvb_offset - tvb_previous_offset;
3398 token_index = find_megaco_descriptors_names(tvb, tvb_previous_offset, tokenlen);
3399 if (tvb_RBRKT > tvb_descriptors_end_offset)
3400 tvb_RBRKT = tvb_descriptors_end_offset;
3401 switch ( token_index ){
3402 case MEGACO_MODEM_TOKEN:
3403 dissect_megaco_modemdescriptor(tvb, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3405 case MEGACO_MUX_TOKEN:
3406 dissect_megaco_multiplexdescriptor(tvb, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3408 case MEGACO_MEDIA_TOKEN:
3409 /*TODO: Move this to the top when all branches fixed !!!*/
3410 temp_offset = tvb_find_guint8(tvb, tvb_previous_offset,tvb_descriptors_end_offset, '{');
3411 save_offset = tvb_previous_offset;
3413 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, temp_offset +1);
3414 dissect_megaco_mediadescriptor(tvb, descriptor_tree, pinfo, tvb_RBRKT, tvb_previous_offset, save_offset, top_tree);
3416 case MEGACO_SIGNALS_TOKEN:
3417 dissect_megaco_signaldescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset, top_tree);
3419 case MEGACO_SERVICES_TOKEN:
3420 dissect_megaco_servicechangedescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3422 case MEGACO_STATS_TOKEN:
3423 dissect_megaco_statisticsdescriptor(tvb, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3425 case MEGACO_ERROR_TOKEN:
3426 dissect_megaco_errordescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3428 case MEGACO_EVENTS_TOKEN:
3429 dissect_megaco_eventsdescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset, top_tree);
3431 case MEGACO_AUDIT_TOKEN:
3432 dissect_megaco_auditdescriptor(tvb, descriptor_tree, pinfo, tvb_RBRKT, tvb_previous_offset);
3434 case MEGACO_DIGITMAP_TOKEN:
3435 dissect_megaco_digitmapdescriptor(tvb, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3437 case MEGACO_OE_TOKEN:
3438 /* ObservedEventsToken */
3439 dissect_megaco_observedeventsdescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset, top_tree);
3441 case MEGACO_TOPOLOGY_TOKEN:
3442 dissect_megaco_topologydescriptor(tvb, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3444 case MEGACO_PACKAGES_TOKEN:
3445 dissect_megaco_Packagesdescriptor(tvb, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3448 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
3449 proto_tree_add_expert(descriptor_tree, pinfo, &ei_megaco_no_descriptor, tvb, tvb_previous_offset, tokenlen);
3453 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT, tvb_len, ',');
3454 if (tvb_current_offset == -1 || tvb_descriptors_end_offset < tvb_current_offset){
3455 tvb_current_offset = tvb_descriptors_end_offset;
3457 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
3458 tvb_LBRKT = tvb_previous_offset;
3459 tvb_RBRKT = tvb_previous_offset;
3461 } while ( tvb_current_offset < tvb_descriptors_end_offset );
3465 /* Copied from MGCP dissector, prints whole message in raw text */
3467 static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree){
3469 gint tvb_linebegin,tvb_lineend,linelen;
3470 proto_tree* text_tree;
3475 text_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_megaco_raw_text, NULL, "-------------- (RAW text output) ---------------");
3478 linelen = tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend,FALSE);
3479 proto_tree_add_format_wsp_text(text_tree, tvb, tvb_linebegin, linelen);
3480 tvb_linebegin = tvb_lineend;
3481 } while (tvb_offset_exists(tvb, tvb_lineend) && linelen > 0);
3486 * megaco_tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
3487 * character following offset or offset + maxlength -1 whichever
3491 * tvb - The tvbuff in which we are skipping whitespaces, tab and end_of_line characters.
3492 * offset - The offset in tvb from which we begin trying to skip whitespace.
3494 * Returns: The position in tvb of the first non-whitespace
3496 static gint megaco_tvb_skip_wsp(tvbuff_t* tvb, gint offset ){
3497 gint counter = offset;
3498 gint end = tvb_reported_length(tvb);
3500 for(counter = offset; counter < end &&
3501 (g_ascii_isspace(tvb_get_guint8(tvb,counter))); counter++);
3505 static gint megaco_tvb_skip_wsp_return(tvbuff_t* tvb, gint offset){
3506 gint counter = offset;
3509 for(counter = offset; counter > end &&
3510 (g_ascii_isspace(tvb_get_guint8(tvb,counter))); counter--);
3515 static gint megaco_tvb_find_token(tvbuff_t* tvb, gint offset, gint maxlength){
3521 pos = tvb_ws_mempbrk_pattern_guint8(tvb, pos + 1, maxlength, &pbrk_braces, &needle);
3534 } while (counter>0);
3539 pos = megaco_tvb_skip_wsp(tvb,pos+1);
3545 megaco_fmt_content( gchar *result, guint32 context )
3549 case CHOOSE_CONTEXT:
3552 g_strlcpy(result, val_to_str_const(context, megaco_context_vals, "Unknown"), ITEM_LABEL_LENGTH);
3555 g_snprintf( result, ITEM_LABEL_LENGTH, "%d", context);
3560 proto_register_megaco(void)
3562 static hf_register_info hf[] = {
3563 { &hf_megaco_audititem,
3564 { "Audit Item", "megaco.audititem", FT_STRING, BASE_NONE, NULL, 0x0,
3565 "Identity of item to be audited", HFILL }},
3566 { &hf_megaco_audit_descriptor,
3567 { "Audit Descriptor", "megaco.audit", FT_NONE, BASE_NONE, NULL, 0x0,
3568 "Audit Descriptor of the megaco Command", HFILL }},
3570 { &hf_megaco_command_line,
3571 { "Command line", "megaco.command_line", FT_STRING, BASE_NONE, NULL, 0x0,
3572 "Commands of this message", HFILL }},
3574 { &hf_megaco_command,
3575 { "Command", "megaco.command", FT_STRING, BASE_NONE, NULL, 0x0,
3577 { &hf_megaco_command_optional,
3578 { "Optional Command", "megaco.command_optional", FT_NONE, BASE_NONE, NULL, 0x0,
3580 { &hf_megaco_wildcard_response,
3581 { "Wildcarded response to a command", "megaco.wildcard_response", FT_NONE, BASE_NONE, NULL, 0x0,
3584 { &hf_megaco_Context,
3585 { "Context", "megaco.context", FT_UINT32, BASE_CUSTOM, CF_FUNC(megaco_fmt_content), 0x0,
3586 "Context ID of this message", HFILL }},
3587 { &hf_megaco_digitmap_descriptor,
3588 { "DigitMap Descriptor", "megaco.digitmap", FT_STRING, BASE_NONE, NULL, 0x0,
3589 "DigitMap Descriptor of the megaco Command", HFILL }},
3590 { &hf_megaco_error_descriptor,
3591 { "ERROR Descriptor", "megaco.error", FT_NONE, BASE_NONE, NULL, 0x0,
3592 "Error Descriptor of the megaco Command", HFILL }},
3593 { &hf_megaco_error_code,
3594 { "ERROR Code", "megaco.error_code", FT_UINT32, BASE_DEC, VALS(MEGACO_error_code_vals), 0x0,
3595 "Error Code of the megaco Command", HFILL }},
3596 { &hf_megaco_error_string,
3597 { "ERROR String", "megaco.error_string", FT_STRING, BASE_NONE, NULL, 0x0,
3598 "Error String of the megaco Command", HFILL }},
3599 { &hf_megaco_Event_Buffer_Control,
3600 { "Event Buffer Control", "megaco.eventbuffercontrol", FT_STRING, BASE_NONE, NULL, 0x0,
3601 "Event Buffer Control in Termination State Descriptor", HFILL }},
3602 { &hf_megaco_events_descriptor,
3603 { "Events Descriptor", "megaco.events", FT_NONE, BASE_NONE, NULL, 0x0,
3604 "Events Descriptor of the megaco Command", HFILL }},
3605 { &hf_megaco_Local_descriptor,
3606 { "Local Descriptor", "megaco.localdescriptor", FT_NONE, BASE_NONE, NULL, 0x0,
3607 "Local Descriptor in Media Descriptor", HFILL }},
3608 { &hf_megaco_LocalControl_descriptor,
3609 { "Local Control Descriptor", "megaco.localcontroldescriptor", FT_NONE, BASE_NONE, NULL, 0x0,
3610 "Local Control Descriptor in Media Descriptor", HFILL }},
3611 { &hf_megaco_media_descriptor,
3612 { "Media Descriptor", "megaco.media", FT_NONE, BASE_NONE, NULL, 0x0,
3613 "Media Descriptor of the megaco Command", HFILL }},
3614 { &hf_megaco_modem_descriptor,
3615 { "Modem Descriptor", "megaco.modem", FT_STRING, BASE_NONE, NULL, 0x0,
3616 "Modem Descriptor of the megaco Command", HFILL }},
3618 { "Mode", "megaco.mode", FT_STRING, BASE_NONE, NULL, 0x0,
3619 "Mode sendonly/receiveonly/inactive/loopback", HFILL }},
3620 { &hf_megaco_multiplex_descriptor,
3621 { "Multiplex Descriptor", "megaco.multiplex", FT_STRING, BASE_NONE, NULL, 0x0,
3622 "Multiplex Descriptor of the megaco Command", HFILL }},
3623 { &hf_megaco_observedevents_descriptor,
3624 { "Observed Events Descriptor", "megaco.observedevents", FT_NONE, BASE_NONE, NULL, 0x0,
3625 "Observed Events Descriptor of the megaco Command", HFILL }},
3626 { &hf_megaco_packages_descriptor,
3627 { "Packages Descriptor", "megaco.packagesdescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
3629 { &hf_megaco_pkgdname,
3630 { "pkgdName", "megaco.pkgdname", FT_STRING, BASE_NONE, NULL, 0x0,
3631 "PackageName SLASH ItemID", HFILL }},
3633 { &hf_megaco_Remote_descriptor,
3634 { "Remote Descriptor", "megaco.remotedescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
3635 "Remote Descriptor in Media Descriptor", HFILL }},
3637 { &hf_megaco_reserve_group,
3638 { "Reserve Group", "megaco.reservegroup", FT_STRING, BASE_NONE, NULL, 0x0,
3639 "Reserve Group on or off", HFILL }},
3640 { &hf_megaco_h324_muxtbl_in,
3641 { "h324/muxtbl_in", "megaco.h324_muxtbl_in", FT_STRING, BASE_NONE, NULL, 0x0,
3643 { &hf_megaco_h324_muxtbl_out,
3644 { "h324/muxtbl_out", "megaco.h324_muxtbl_out", FT_STRING, BASE_NONE, NULL, 0x0,
3646 { &hf_megaco_ds_dscp,
3647 { "Differentiated Services Code Point", "megaco.ds_dscp", FT_UINT32, BASE_HEX|BASE_EXT_STRING, &dscp_vals_ext, 0x0,
3649 { &hf_megaco_gm_saf,
3650 { "Remote Source Address Filtering", "megaco.gm_saf", FT_STRING, BASE_NONE, NULL, 0x0,
3652 { &hf_megaco_gm_sam,
3653 { "Remote Source Address Mask", "megaco.gm_sam", FT_STRING, BASE_NONE, NULL, 0x0,
3655 { &hf_megaco_gm_spf,
3656 { "Remote Source Port Filtering", "megaco.gm_spf", FT_STRING, BASE_NONE, NULL, 0x0,
3658 { &hf_megaco_gm_spr,
3659 { "Remote Source Port Range", "megaco.gm_spr", FT_STRING, BASE_NONE, NULL, 0x0,
3661 { &hf_megaco_gm_esas,
3662 { "Explicit Source Address Setting", "megaco.gm_esas", FT_STRING, BASE_NONE, NULL, 0x0,
3664 { &hf_megaco_tman_pol,
3665 { "Policing", "megaco.tman_pol", FT_STRING, BASE_NONE, NULL, 0x0,
3667 { &hf_megaco_gm_rsb,
3668 { "RTCP Allocation Specific Behaviour", "megaco.gm_rsb", FT_STRING, BASE_NONE, NULL, 0x0,
3670 { &hf_megaco_tman_sdr,
3671 { "Sustainable Data Rate", "megaco.tman_sdr", FT_STRING, BASE_NONE, NULL, 0x0,
3673 { &hf_megaco_tman_mbs,
3674 { "Maximum Burst Rate", "megaco.tman_mbs", FT_STRING, BASE_NONE, NULL, 0x0,
3676 { &hf_megaco_tman_pdr,
3677 { "Peak Data Rate", "megaco.tman_pdr", FT_STRING, BASE_NONE, NULL, 0x0,
3679 { &hf_megaco_tman_dvt,
3680 { "Delay Variation Tolerance", "megaco.tman_dvt", FT_STRING, BASE_NONE, NULL, 0x0,
3682 { &hf_megaco_ipdc_realm,
3683 { "IP Realm Identifier", "megaco.ipdc_realm", FT_STRING, BASE_NONE, NULL, 0x0,
3685 { &hf_megaco_h324_h223capr,
3686 { "h324/h223capr", "megaco.h324_h223capr", FT_STRING, BASE_NONE, NULL, 0x0,
3688 { &hf_megaco_reserve_value,
3689 { "Reserve Value", "megaco.reservevalue", FT_STRING, BASE_NONE, NULL, 0x0,
3690 "Reserve Value on or off", HFILL }},
3691 { &hf_megaco_requestid,
3692 { "RequestID", "megaco.requestid", FT_UINT32, BASE_DEC, NULL, 0x0,
3693 "RequestID in Events or Observedevents Descriptor", HFILL }},
3695 { &hf_megaco_servicechange_descriptor,
3696 { "Service Change Descriptor", "megaco.servicechange", FT_STRING, BASE_NONE, NULL, 0x0,
3697 "Service Change Descriptor of the megaco Command", HFILL }},
3699 { &hf_megaco_Service_State,
3700 { "Service State", "megaco.servicestates", FT_STRING, BASE_NONE, NULL, 0x0,
3701 "Service States in Termination State Descriptor", HFILL }},
3702 { &hf_megaco_signal_descriptor,
3703 { "Signal Descriptor", "megaco.signal", FT_NONE, BASE_NONE, NULL, 0x0,
3704 "Signal Descriptor of the megaco Command", HFILL }},
3705 { &hf_megaco_statistics_descriptor,
3706 { "Statistics Descriptor", "megaco.statistics", FT_NONE, BASE_NONE, NULL, 0x0,
3707 "Statistics Descriptor of the megaco Command", HFILL }},
3708 { &hf_megaco_streamid,
3709 { "StreamID", "megaco.streamid", FT_UINT32, BASE_DEC, NULL, 0x0,
3710 "StreamID in the Media Descriptor", HFILL }},
3711 { &hf_megaco_termid,
3712 { "Termination ID", "megaco.termid", FT_STRING, BASE_NONE, NULL, 0x0,
3713 "Termination ID of this Command", HFILL }},
3714 { &hf_megaco_TerminationState_descriptor,
3715 { "Termination State Descriptor", "megaco.terminationstate", FT_NONE, BASE_NONE, NULL, 0x0,
3716 "Termination State Descriptor in Media Descriptor", HFILL }},
3717 { &hf_megaco_topology_descriptor,
3718 { "Topology Descriptor", "megaco.topology", FT_STRING, BASE_NONE, NULL, 0x0,
3719 "Topology Descriptor of the megaco Command", HFILL }},
3720 { &hf_megaco_transaction,
3721 { "Transaction", "megaco.transaction", FT_STRING, BASE_NONE, NULL, 0x0,
3722 "Message Originator", HFILL }},
3723 { &hf_megaco_transid,
3724 { "Transaction ID", "megaco.transid", FT_UINT32, BASE_DEC, NULL, 0x0,
3725 "Transaction ID of this message", HFILL }},
3727 { "MediagatewayID", "megaco.mId", FT_STRING, BASE_NONE, NULL, 0x0,
3728 "Mediagateway ID", HFILL }},
3729 { &hf_megaco_version,
3730 { "Version", "megaco.version", FT_STRING, BASE_NONE, NULL, 0x0,
3733 { "Start token", "megaco.start_token", FT_STRING, BASE_NONE, NULL, 0x0,
3736 { "h245", "megaco.h245", FT_NONE, BASE_NONE, NULL, 0x0,
3737 "Embedded H.245 message", HFILL }},
3738 { &hf_megaco_h223Capability,
3739 { "h223Capability", "megaco.h245.h223Capability", FT_NONE, BASE_NONE, NULL, 0,
3740 "megaco.h245.H223Capability", HFILL }},
3742 GCP_HF_ARR_ELEMS("megaco",megaco_ctx_ids),
3744 /* Add more fields here */
3746 static gint *ett[] = {
3748 &ett_megaco_message,
3749 &ett_megaco_message_body,
3750 &ett_megaco_context,
3751 &ett_megaco_command_line,
3752 &ett_megaco_descriptors,
3753 &ett_megaco_raw_text,
3754 &ett_megaco_error_descriptor,
3755 &ett_megaco_mediadescriptor,
3756 &ett_megaco_TerminationState,
3757 &ett_megaco_Remotedescriptor,
3758 &ett_megaco_Localdescriptor,
3759 &ett_megaco_LocalControldescriptor,
3760 &ett_megaco_auditdescriptor,
3761 &ett_megaco_eventsdescriptor,
3762 &ett_megaco_statisticsdescriptor,
3763 &ett_megaco_observedeventsdescriptor,
3764 &ett_megaco_observedevent,
3765 &ett_megaco_packagesdescriptor,
3766 &ett_megaco_requestedevent,
3767 &ett_megaco_signalsdescriptor,
3768 &ett_megaco_requestedsignal,
3770 GCP_ETT_ARR_ELEMS(megaco_ctx_ids),
3773 static ei_register_info ei[] = {
3774 { &ei_megaco_errored_command, { "megaco.errored_command", PI_RESPONSE_CODE, PI_WARN, "Errored Command", EXPFILL }},
3775 { &ei_megaco_parse_error, { "megaco.parse_error", PI_MALFORMED, PI_ERROR, "Parse error", EXPFILL }},
3776 { &ei_megaco_error_descriptor_transaction_list, { "megaco.error_descriptor_transaction_list.invalid", PI_MALFORMED, PI_ERROR, "Sorry, can't understand errorDescriptor / transactionList", EXPFILL }},
3777 { &ei_megaco_audit_descriptor, { "megaco.audit.malformed", PI_MALFORMED, PI_ERROR, "Badly constructed audit descriptor (no { )", EXPFILL }},
3778 { &ei_megaco_signal_descriptor, { "megaco.signal_descriptor.empty", PI_PROTOCOL, PI_NOTE, "Empty Signal Descriptor", EXPFILL }},
3779 { &ei_megaco_no_command, { "megaco.no_command", PI_PROTOCOL, PI_WARN, "No Command detectable", EXPFILL }},
3780 { &ei_megaco_no_descriptor, { "megaco.no_descriptor", PI_PROTOCOL, PI_WARN, "No Descriptor detectable", EXPFILL }},
3781 { &ei_megaco_reason_invalid, { "megaco.change_reason.invalid", PI_MALFORMED, PI_ERROR, "Invalid Service Change Reason", EXPFILL }},
3782 { &ei_megaco_error_code_invalid, { "megaco.error_code.invalid", PI_MALFORMED, PI_ERROR, "Invalid error code", EXPFILL }}
3785 module_t *megaco_module;
3786 expert_module_t* expert_megaco;
3788 proto_megaco = proto_register_protocol("MEGACO", "MEGACO", "megaco");
3790 megaco_text_handle = register_dissector("megaco", dissect_megaco_text, proto_megaco);
3792 proto_register_field_array(proto_megaco, hf, array_length(hf));
3793 proto_register_subtree_array(ett, array_length(ett));
3794 expert_megaco = expert_register_protocol(proto_megaco);
3795 expert_register_field_array(expert_megaco, ei, array_length(ei));
3797 /* Register our configuration options, particularly our ports */
3799 megaco_module = prefs_register_protocol(proto_megaco, proto_reg_handoff_megaco);
3801 prefs_register_uint_preference(megaco_module, "sctp.txt_port",
3802 "MEGACO Text SCTP Port",
3803 "Set the SCTP port for MEGACO text messages",
3804 10, &global_megaco_txt_sctp_port);
3807 prefs_register_uint_preference(megaco_module, "sctp.bin_port",
3808 "MEGACO Binary SCTP Port",
3809 "Set the SCTP port for MEGACO binary messages",
3810 10, &global_megaco_bin_sctp_port);
3812 prefs_register_uint_preference(megaco_module, "tcp.bin_port",
3813 "MEGACO Binary TCP Port",
3814 "Set the TCP port for MEGACO binary messages",
3815 10, &global_megaco_bin_tcp_port);
3817 prefs_register_uint_preference(megaco_module, "udp.bin_port",
3818 "MEGACO Binary UDP Port",
3819 "Set the UDP port for MEGACO binary messages",
3820 10, &global_megaco_bin_udp_port);
3823 prefs_register_bool_preference(megaco_module, "display_raw_text",
3824 "Display raw text for MEGACO message",
3825 "Specifies that the raw text of the "
3826 "MEGACO message should be displayed "
3827 "instead of (or in addition to) the "
3829 &global_megaco_raw_text);
3831 prefs_register_bool_preference(megaco_module, "display_dissect_tree",
3832 "Display tree dissection for MEGACO message",
3833 "Specifies that the dissection tree of the "
3834 "MEGACO message should be displayed "
3835 "instead of (or in addition to) the "
3837 &global_megaco_dissect_tree);
3838 prefs_register_bool_preference(megaco_module, "ctx_info",
3840 "Maintain relationships between transactions and contexts "
3841 "and display an extra tree showing context data",
3842 &keep_persistent_data);
3844 megaco_tap = register_tap("megaco");
3846 /* compile patterns */
3847 ws_mempbrk_compile(&pbrk_whitespace, " \t\r\n");
3848 ws_mempbrk_compile(&pbrk_braces, "{}");
3850 register_rtd_table(proto_megaco, NULL, 1, NUM_TIMESTATS, megaco_message_type, megacostat_packet, megacostat_filtercheck);
3853 /* Register all the bits needed with the filtering engine */
3854 /* The registration hand-off routine */
3856 proto_reg_handoff_megaco(void)
3858 static gboolean megaco_prefs_initialized = FALSE;
3859 static dissector_handle_t megaco_text_tcp_handle;
3861 * Variables to allow for proper deletion of dissector registration when
3862 * the user changes port from the gui.
3864 static guint txt_sctp_port;
3866 static guint bin_sctp_port;
3867 static guint bin_tcp_port;
3868 static guint bin_udp_port;
3871 if (!megaco_prefs_initialized) {
3872 sdp_handle = find_dissector_add_dependency("sdp", proto_megaco);
3873 h245_handle = find_dissector_add_dependency("h245dg", proto_megaco);
3874 h248_handle = find_dissector_add_dependency("h248", proto_megaco);
3875 h248_otp_handle = find_dissector_add_dependency("h248_otp", proto_megaco);
3876 data_handle = find_dissector("data");
3878 megaco_text_tcp_handle = create_dissector_handle(dissect_megaco_text_tcp, proto_megaco);
3880 dissector_add_uint_with_preference("tcp.port", PORT_MEGACO_TXT, megaco_text_tcp_handle);
3881 dissector_add_uint_with_preference("udp.port", PORT_MEGACO_TXT, megaco_text_handle);
3882 dissector_add_uint("sctp.ppi", H248_PAYLOAD_PROTOCOL_ID, megaco_text_handle);
3884 megaco_prefs_initialized = TRUE;
3886 dissector_delete_uint("sctp.port", txt_sctp_port, megaco_text_handle);
3889 /* Set our port number for future use */
3891 txt_sctp_port = global_megaco_txt_sctp_port;
3893 dissector_add_uint("sctp.port", global_megaco_txt_sctp_port, megaco_text_handle);
3895 exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_7);
3900 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3905 * indent-tabs-mode: nil
3908 * vi: set shiftwidth=4 tabstop=8 expandtab:
3909 * :indentSize=4:tabSize=8:noTabs=true: