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