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