MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-megaco.c
blobbb06752569211e634bf0f1f58f6b79d7aacaf21c
1 /* packet-megaco.c
2 * Routines for megaco packet disassembly
3 * RFC 3015
5 * $Id$
7 * Christian Falckenberg, 2002/10/17
8 * Copyright (c) 2002 by Christian Falckenberg
9 * <christian.falckenberg@nortelnetworks.com>
11 * Christoph Wiest, 2003/06/28
12 * Modified 2003 by Christoph Wiest
13 * <ch.wiest@tesionmail.de>
14 * Modified 2004 by Anders Broman
15 * <anders.broman@ericsson.com>
16 * To handle TPKT headers if over TCP
17 * Modified 2005 by Karl Knoebl
18 * <karl.knoebl@siemens.com>
19 * provide info to COL_INFO and some "prettification"
21 * Copyright (c) 2006 Anders Broman <anders.broman@ericsson.com>
23 * Wireshark - Network traffic analyzer
24 * By Gerald Combs <gerald@wireshark.org>
25 * Copyright 1999 Gerald Combs
27 * This program is free software; you can redistribute it and/or
28 * modify it under the terms of the GNU General Public License
29 * as published by the Free Software Foundation; either version 2
30 * of the License, or (at your option) any later version.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 #include "config.h"
45 #include <stdlib.h>
46 #include <ctype.h>
48 #include <glib.h>
50 #include <epan/packet.h>
51 #include <epan/exceptions.h>
52 #include <epan/wmem/wmem.h>
53 #include <epan/addr_resolv.h>
54 #include <epan/prefs.h>
55 #include <epan/strutil.h>
56 #include <epan/sctpppids.h>
57 #include <epan/dissectors/packet-tpkt.h>
58 #include <epan/asn1.h>
59 #include <epan/dissectors/packet-per.h>
60 #include <epan/dissectors/packet-h245.h>
61 #include <epan/dissectors/packet-ip.h>
62 #include <epan/dissectors/packet-ber.h>
64 #include <epan/gcp.h>
65 #include <epan/tap.h>
67 #define PORT_MEGACO_TXT 2944
68 #define PORT_MEGACO_BIN 2945
70 /* Define the megaco proto */
71 static int proto_megaco = -1;
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;
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_h324_muxtbl_in = -1;
108 static int hf_megaco_h324_muxtbl_out = -1;
109 static int hf_megaco_ds_dscp = -1;
110 static int hf_megaco_h324_h223capr = -1;
111 static int hf_megaco_reserve_value = -1;
112 static int hf_megaco_streamid = -1;
113 static int hf_megaco_requestid = -1;
114 static int hf_megaco_pkgdname = -1;
115 static int hf_megaco_mId = -1;
116 /* static int hf_megaco_h245 = -1; */
117 static int hf_megaco_h223Capability = -1;
118 static int hf_megaco_audititem = -1;
120 /* Define the trees for megaco */
121 static int ett_megaco = -1;
122 static int ett_megaco_message = -1;
123 static int ett_megaco_message_body = -1;
124 static int ett_megaco_context = -1;
125 static int ett_megaco_command_line = -1;
126 static int ett_megaco_mediadescriptor = -1;
127 static int ett_megaco_descriptors = -1;
128 static int ett_megaco_TerminationState = -1;
129 static int ett_megaco_Localdescriptor = -1;
130 static int ett_megaco_Remotedescriptor = -1;
131 static int ett_megaco_LocalControldescriptor = -1;
132 static int ett_megaco_auditdescriptor = -1;
133 static int ett_megaco_eventsdescriptor = -1;
134 static int ett_megaco_observedeventsdescriptor = -1;
135 static int ett_megaco_observedevent = -1;
136 static int ett_megaco_packagesdescriptor = -1;
137 static int ett_megaco_requestedevent = -1;
138 static int ett_megaco_signalsdescriptor = -1;
139 static int ett_megaco_requestedsignal = -1;
140 static int ett_megaco_h245 = -1;
142 static gcp_hf_ett_t megaco_ctx_ids = {{-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1}};
144 static expert_field ei_megaco_errored_command = EI_INIT;
145 static expert_field ei_megaco_error_descriptor_transaction_list = EI_INIT;
146 static expert_field ei_megaco_parse_error = EI_INIT;
147 static expert_field ei_megaco_audit_descriptor = EI_INIT;
149 static dissector_handle_t megaco_text_handle;
151 static int megaco_tap = -1;
154 * Here are the global variables associated with
155 * the various user definable characteristics of the dissection
157 * MEGACO has two kinds of message formats: text and binary
159 * global_megaco_raw_text determines whether we are going to display
160 * the raw text of the megaco message, much like the HTTP dissector does.
162 * global_megaco_dissect_tree determines whether we are going to display
163 * a detailed tree that expresses a somewhat more semantically meaningful
164 * decode.
166 static guint global_megaco_txt_sctp_port = PORT_MEGACO_TXT;
167 static guint global_megaco_txt_tcp_port = PORT_MEGACO_TXT;
168 static guint global_megaco_txt_udp_port = PORT_MEGACO_TXT;
169 #if 0
170 static guint global_megaco_bin_sctp_port = PORT_MEGACO_BIN;
171 static guint global_megaco_bin_tcp_port = PORT_MEGACO_BIN;
172 static guint global_megaco_bin_udp_port = PORT_MEGACO_BIN;
173 #endif
174 static gboolean global_megaco_raw_text = TRUE;
175 static gboolean global_megaco_dissect_tree = TRUE;
177 /* Some basic utility functions that are specific to this dissector */
178 static gint megaco_tvb_skip_wsp(tvbuff_t* tvb, gint offset);
179 static gint megaco_tvb_skip_wsp_return(tvbuff_t* tvb, gint offset);
181 * The various functions that either dissect some
182 * subpart of MEGACO. These aren't really proto dissectors but they
183 * are written in the same style.
186 static void
187 dissect_megaco_descriptors(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_descriptors_start_offset, gint tvb_descriptors_end_offset);
188 static void
189 dissect_megaco_modemdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
190 static void
191 dissect_megaco_multiplexdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
192 static void
193 dissect_megaco_mediadescriptor(tvbuff_t *tvb, proto_tree *tree,packet_info *pinfo, gint tvb_RBRKT, gint tvb_previous_offset);
194 static void
195 dissect_megaco_eventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
196 static void
197 dissect_megaco_signaldescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
198 static void
199 dissect_megaco_auditdescriptor(tvbuff_t *tvb, proto_tree *tree,packet_info *pinfo, gint tvb_RBRKT, gint tvb_previous_offset);
200 static void
201 dissect_megaco_servicechangedescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
202 static void
203 dissect_megaco_digitmapdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
204 static void
205 dissect_megaco_statisticsdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
206 static void
207 dissect_megaco_observedeventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
208 static void
209 dissect_megaco_topologydescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
210 static void
211 dissect_megaco_errordescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_RBRKT, gint tvb_previous_offset);
212 static void
213 dissect_megaco_TerminationStatedescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_next_offset, gint tvb_current_offset);
214 static void
215 dissect_megaco_Localdescriptor(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset);
216 static void
217 dissect_megaco_LocalControldescriptor(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset);
218 static void
219 dissect_megaco_Packagesdescriptor(tvbuff_t *tvb, proto_tree *tree, gint tvb_next_offset, gint tvb_current_offset);
220 static void
221 tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
222 static void
223 dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
224 static gint
225 megaco_tvb_find_token(tvbuff_t* tvb, gint offset, gint maxlenght);
226 static dissector_handle_t data_handle;
227 static dissector_handle_t sdp_handle;
228 static dissector_handle_t h245_handle;
229 static dissector_handle_t h248_handle;
230 static dissector_handle_t h248_otp_handle;
232 static gboolean keep_persistent_data = FALSE;
234 static proto_tree *top_tree;
236 * dissect_megaco_text over TCP, there will be a TPKT header there
239 static void dissect_megaco_text_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
241 int lv_tpkt_len;
243 /* This code is copied from the Q.931 dissector, some parts skipped.
244 * Check whether this looks like a TPKT-encapsulated
245 * MEGACO packet.
247 * The minimum length of a MEGACO message is 6?:
248 * Re-assembly ?
250 lv_tpkt_len = is_tpkt(tvb, 6);
251 if (lv_tpkt_len == -1) {
253 * It's not a TPKT packet;
254 * Is in MEGACO ?
256 dissect_megaco_text(tvb, pinfo, tree);
258 dissect_tpkt_encap(tvb, pinfo, tree, TRUE,
259 megaco_text_handle);
262 #define ERRORTOKEN 1
263 #define TRANSTOKEN 2
264 #define REPLYTOKEN 3
265 #define PENDINGTOKEN 4
266 #define RESPONSEACKTOKEN 5
268 typedef struct {
269 const char *name;
270 const char *compact_name;
271 } megaco_tokens_t;
273 static const megaco_tokens_t megaco_messageBody_names[] = {
274 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
275 { "Error", "ER" }, /* 1 */
276 { "Transaction", "T" }, /* 2 */
277 { "Reply", "P" }, /* 3 */
278 { "Pending", "PN" }, /* 4 */
279 { "TransactionResponseAck", "K" }, /* 5 */
282 /* Returns index of megaco_tokens_t */
283 static gint find_megaco_messageBody_names(tvbuff_t *tvb, int offset, guint header_len)
285 guint i;
287 for (i = 1; i < array_length(megaco_messageBody_names); i++) {
288 if (header_len == strlen(megaco_messageBody_names[i].name) &&
289 tvb_strncaseeql(tvb, offset, megaco_messageBody_names[i].name, header_len) == 0)
290 return i;
291 if (megaco_messageBody_names[i].compact_name != NULL &&
292 header_len == strlen(megaco_messageBody_names[i].compact_name) &&
293 tvb_strncaseeql(tvb, offset, megaco_messageBody_names[i].compact_name, header_len) == 0)
294 return i;
297 return -1;
300 static proto_item *
301 my_proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
302 gint start, gint length, const char *value)
304 proto_item *pi;
306 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
307 if (!global_megaco_dissect_tree) {
308 PROTO_ITEM_SET_HIDDEN(pi);
311 return(pi);
314 * dissect_megaco_text - The dissector for the MEGACO Protocol, using
315 * text encoding.
317 static void
318 dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
320 gint tvb_len, len;
321 gint tvb_offset,tvb_current_offset,tvb_previous_offset,tvb_next_offset,tokenlen;
322 gint line_start_offset, ver_offset, ver_length, mId_offset, mId_length;
323 gint tvb_command_start_offset, tvb_command_end_offset;
324 gint tvb_descriptors_start_offset, tvb_descriptors_end_offset;
325 gint tvb_transaction_end_offset;
326 proto_tree *megaco_tree, *message_tree, *message_body_tree, *megaco_context_tree, *megaco_tree_command_line, *ti, *sub_ti;
328 guint8 word[7];
329 guint8 TermID[30];
330 guint8 tempchar;
331 gint tvb_RBRKT, tvb_LBRKT, RBRKT_counter, LBRKT_counter;
332 guint token_index=0;
333 guint32 dword;
334 guchar needle;
335 guint8 first;
337 gcp_msg_t* msg = NULL;
338 gcp_trx_t* trx = NULL;
339 gcp_ctx_t* ctx = NULL;
340 gcp_cmd_t* cmd = NULL;
341 gcp_term_t* term = NULL;
342 gcp_trx_type_t trx_type = GCP_TRX_NONE;
343 guint32 trx_id = 0;
344 guint32 ctx_id = 0;
345 gcp_cmd_type_t cmd_type = GCP_CMD_NONE;
346 gcp_wildcard_t wild_term = GCP_WILDCARD_NONE;
347 proto_item *hidden_item;
349 top_tree=tree;
350 /* Initialize variables */
351 tvb_len = tvb_length(tvb);
352 megaco_tree = NULL;
353 ti = NULL;
354 tvb_offset = 0;
355 RBRKT_counter = 0;
356 LBRKT_counter = 0;
358 /* Check if H.248 in otp(Erlang) internal format
359 * XXX Needs improvement?
360 * Ref:
361 * http://www.erlang.org/doc/apps/megaco/part_frame.html
362 * 4.1 Internal form of messages
363 * 4.2 The different encodings
365 dword = tvb_get_ntoh24(tvb,0);
366 if ((dword == 0x836803)&&(h248_otp_handle)){
367 call_dissector(h248_otp_handle, tvb, pinfo, tree);
368 return;
371 msg = gcp_msg(pinfo, tvb_raw_offset(tvb), keep_persistent_data);
374 * Check to see whether we're really dealing with MEGACO by looking
375 * for the "MEGACO" string or a "!".This needs to be improved when supporting
376 * binary encodings. Bugfix add skipping of leading spaces.
378 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
379 line_start_offset = tvb_offset;
380 /* Quick fix for MEGACO not following the RFC, hopefully not breaking any thing
381 * Turned out to be TPKT in case of TCP, added some code to handle that.
383 * tvb_offset = tvb_find_guint8(tvb, tvb_offset, 5, 'M');
385 if(!tvb_get_nstringz0(tvb,tvb_offset,sizeof(word),word)) return;
390 if (g_ascii_strncasecmp(word, "MEGACO", 6) != 0 && tvb_get_guint8(tvb, tvb_offset ) != '!'){
391 gint8 ber_class;
392 gboolean pc;
393 gint32 tag;
394 dissector_handle_t handle = data_handle;
396 get_ber_identifier(tvb, 0, &ber_class, &pc, &tag);
398 if (ber_class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE ) {
399 handle = h248_handle;
402 call_dissector(handle,tvb,pinfo,tree);
404 return;
408 /* Display MEGACO in protocol column */
409 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MEGACO");
411 /* Build the info tree if we've been given a root */
412 /* Create megaco subtree */
413 ti = proto_tree_add_item(tree,proto_megaco,tvb, 0, -1, ENC_NA);
414 megaco_tree = proto_item_add_subtree(ti, ett_megaco);
416 /* Format of 'message' is = MegacopToken SLASH Version SEP mId SEP messageBody */
417 /* MegacopToken = "MEGACO" or "!" */
418 /* According to H248.1-200205 Annex B Text encoding ( protocol version 2 ) */
420 /* Find version */
421 tvb_previous_offset = tvb_find_guint8(tvb, 0,
422 tvb_len, '/');
423 if (tvb_previous_offset == -1) {
424 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
425 "Sorry, no \"/\" in the MEGACO header, I can't parse this packet");
426 return;
429 /* skip / */
430 tvb_previous_offset++;
432 /* assume at least one digit in version */
433 tvb_current_offset = tvb_previous_offset + 1;
435 if (isdigit(tvb_get_guint8(tvb, tvb_current_offset))) {
436 /* 2-digit version */
437 tvb_current_offset++;
440 tokenlen = tvb_current_offset - tvb_previous_offset;
441 ver_offset = tvb_previous_offset;
442 ver_length = tokenlen;
444 tvb_previous_offset = tvb_current_offset;
445 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
447 if (tvb_previous_offset == tvb_current_offset) {
448 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
449 "[ Parse error: missing SEP in MEGACO header ]");
450 return;
453 tvb_previous_offset = tvb_current_offset;
455 /* mId should follow here,
456 * mId = (( domainAddress / domainName ) [":" portNumber]) / mtpAddress / deviceName
457 * domainAddress = "[" (IPv4address / IPv6address) "]"
458 * domainName = "<" (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" /".") ">"
459 * mtpAddress = MTPToken LBRKT 4*8 (HEXDIG) RBRKT
460 * MTPToken = ("MTP")
461 * deviceName = pathNAME
462 * pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )["@" pathDomainName ]
465 tvb_current_offset = tvb_pbrk_guint8(tvb, tvb_current_offset, -1, " \t\r\n", &needle);
466 if (tvb_current_offset == -1) {
467 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
468 "[ Parse error: no body in MEGACO message (missing SEP after mId) ]");
469 return;
472 tokenlen = tvb_current_offset - tvb_previous_offset;
473 tvb_next_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset);
475 /* At this point we should point to the "\n" ending the mId element
476 * or to the next character after white space SEP
478 mId_offset = tvb_previous_offset;
479 mId_length = tokenlen;
481 /* Add the first line to the tree */
482 tokenlen = tvb_next_offset - line_start_offset - 1;
483 ti = proto_tree_add_text(megaco_tree, tvb, line_start_offset, tokenlen,
484 "%s",tvb_format_text(tvb,line_start_offset,tokenlen));
485 message_tree = proto_item_add_subtree(ti, ett_megaco_message);
486 if (tree){
487 if(global_megaco_dissect_tree){
488 proto_tree_add_item(message_tree, hf_megaco_version,tvb, ver_offset, ver_length, ENC_ASCII|ENC_NA);
489 proto_tree_add_item(message_tree, hf_megaco_mId,tvb, mId_offset, mId_length, ENC_ASCII|ENC_NA);
490 }else{
491 hidden_item = proto_tree_add_item(message_tree, hf_megaco_version,tvb, ver_offset, ver_length, ENC_ASCII|ENC_NA);
492 PROTO_ITEM_SET_HIDDEN(hidden_item);
493 hidden_item = proto_tree_add_item(message_tree, hf_megaco_mId,tvb, mId_offset, mId_length, ENC_ASCII|ENC_NA);
494 PROTO_ITEM_SET_HIDDEN(hidden_item);
497 col_clear(pinfo->cinfo, COL_INFO);
498 first = 1;
500 tvb_previous_offset = tvb_next_offset;
502 /* Next part is
503 * : messageBody = ( errorDescriptor / transactionList )
504 * errorDescriptor = ErrorToken EQUAL ErrorCode LBRKT [quotedString] RBRKT
505 * ErrorToken = ("Error" / "ER")
507 * transactionList = 1*( transactionRequest / transactionReply /
508 * transactionPending / transactionResponseAck )
510 * transactionResponseAck = ResponseAckToken LBRKT
511 * transactionAck*(COMMA transactionAck) RBRKT
512 * ResponseAckToken = ("TransactionResponseAck"/ "K")
514 * transactionPending = PendingToken EQUAL TransactionID LBRKT RBRKT
515 * PendingToken = ("Pending" / "PN")
517 * transactionReply = ReplyToken EQUAL TransactionID LBRKT
518 * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
519 * ReplyToken = ("Reply" / "P")
521 * transactionRequest = TransToken EQUAL TransactionID LBRKT
522 * actionRequest *(COMMA actionRequest) RBRKT
523 * TransToken = ("Transaction" / "T")
526 /* Find token length */
527 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_len-1; tvb_offset++){
528 if (!isalpha(tvb_get_guint8(tvb, tvb_offset ))){
529 break;
532 tokenlen = tvb_offset - tvb_previous_offset;
533 token_index = find_megaco_messageBody_names(tvb, tvb_previous_offset, tokenlen);
534 /* Debug code
535 g_warning("token_index %u",token_index);
538 tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_len, '{');
539 tvb_current_offset = tvb_LBRKT;
540 tvb_transaction_end_offset = megaco_tvb_find_token(tvb, tvb_LBRKT - 1, tvb_len);
542 switch ( token_index ){
543 /* errorDescriptor */
544 case ERRORTOKEN:
545 col_set_str(pinfo->cinfo, COL_INFO, "Error ");
547 tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_len); /*tvb_find_guint8(tvb, tvb_offset+1, tvb_len, '}');*/
549 ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset,
550 "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset));
551 message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
553 if (tree) {
554 my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
555 tvb_previous_offset, tokenlen,
556 "Error" );
558 tvb_command_start_offset = tvb_previous_offset;
559 dissect_megaco_errordescriptor(tvb, megaco_tree, tvb_len-1, tvb_command_start_offset);
561 return;
562 /* transactionResponseAck
563 * transactionResponseAck = ResponseAckToken LBRKT transactionAck
564 * *(COMMA transactionAck) RBRKT
565 * transactionAck = transactionID / (transactionID "-" transactionID)
567 case RESPONSEACKTOKEN:
568 tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
569 tvb_offset = tvb_LBRKT;
571 ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_offset-tvb_previous_offset,
572 "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_offset-tvb_previous_offset+1));
573 message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
575 my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
576 tvb_previous_offset, tokenlen,
577 "TransactionResponseAck" );
579 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1);
580 tvb_current_offset = tvb_find_guint8(tvb, tvb_offset+1, tvb_len, '}');
581 /*tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_transaction_end_offset);*/
582 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset)-1; /* cut last RBRKT */
583 len = tvb_current_offset - tvb_previous_offset;
585 if (!first) {
586 col_append_str(pinfo->cinfo, COL_INFO, " ");
588 col_append_fstr(pinfo->cinfo, COL_INFO, "%s TransactionResponseAck",
589 tvb_format_text(tvb,tvb_previous_offset,len));
591 if(tree)
592 my_proto_tree_add_string(message_body_tree, hf_megaco_transid, tvb,
593 tvb_previous_offset, len,
594 tvb_format_text(tvb,tvb_previous_offset,len));
596 if(global_megaco_raw_text){
597 tvb_raw_text_add(tvb, megaco_tree);
599 return;
600 /* Pe and PN is transactionPending, P+"any char" is transactionReply */
601 case PENDINGTOKEN:
603 tvb_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '=')+1;
604 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
605 tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
606 tvb_current_offset = tvb_LBRKT;
607 ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset,
608 "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset+1));
609 message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
611 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1);
612 len = tvb_current_offset - tvb_offset;
613 if (tree)
614 my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
615 tvb_previous_offset, tokenlen,
616 "Pending" );
618 if (!first) {
619 col_append_str(pinfo->cinfo, COL_INFO, " ");
621 col_append_fstr(pinfo->cinfo, COL_INFO, "%s Pending",
622 tvb_format_text(tvb,tvb_offset,len));
624 if(tree)
625 my_proto_tree_add_string(message_body_tree, hf_megaco_transid, tvb,
626 tvb_offset, len,
627 tvb_format_text(tvb,tvb_offset,len));
628 return;
630 /* transactionReply */
631 case REPLYTOKEN:
632 trx_type = GCP_TRX_REPLY;
633 tvb_LBRKT = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '{');
634 ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_LBRKT-tvb_previous_offset,
635 "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_LBRKT-tvb_previous_offset+1));
636 message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
638 if (tree)
639 my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
640 tvb_previous_offset, tokenlen,
641 "Reply" );
643 tvb_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '=')+1;
644 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
645 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_LBRKT-1);
646 len = tvb_current_offset - tvb_offset;
648 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Reply ",
649 tvb_format_text(tvb,tvb_offset,len));
650 trx_id = (guint)strtoul(tvb_format_text(tvb,tvb_offset,len),NULL,10);
652 if(tree)
653 my_proto_tree_add_string(message_body_tree, hf_megaco_transid, tvb,
654 tvb_offset, len, tvb_format_text(tvb,tvb_offset,len));
656 /* Find if we have a errorDescriptor or actionReplyList */
657 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
658 tempchar = tvb_get_guint8(tvb,tvb_offset);
659 if ((tempchar == 'E')||(tempchar == 'e')){
660 dissect_megaco_errordescriptor(tvb, megaco_tree, tvb_transaction_end_offset-1, tvb_offset);
661 return;
663 /* Offset should be at first printable char after { */
664 tvb_previous_offset = tvb_offset;
665 break;
666 case TRANSTOKEN:
667 /* TransactionRequest */
668 trx_type = GCP_TRX_REQUEST;
669 ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset,
670 "%s",tvb_format_text(tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset+1));
671 message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
673 if(tree)
674 my_proto_tree_add_string(message_body_tree, hf_megaco_transaction, tvb,
675 tvb_previous_offset, tokenlen,
676 "Request" );
677 tvb_offset = tvb_find_guint8(tvb, tvb_offset, tvb_transaction_end_offset, '=')+1;
678 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
679 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1);
680 len = tvb_current_offset - tvb_offset;
681 if (!first) {
682 col_append_str(pinfo->cinfo, COL_INFO, " ");
684 col_append_fstr(pinfo->cinfo, COL_INFO, "%s Request",
685 tvb_format_text(tvb,tvb_offset,len));
686 trx_id = (guint)strtoul(tvb_format_text(tvb,tvb_offset,len),NULL,10);
687 if(tree)
688 my_proto_tree_add_string(message_body_tree, hf_megaco_transid, tvb, tvb_offset,len,
689 tvb_format_text(tvb,tvb_offset,len));
690 /* Offset should be at first printable char after { */
691 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
693 break;
694 default :
695 ti = proto_tree_add_item(tree,proto_megaco,tvb, 0, -1, ENC_NA);
696 expert_add_info_format(pinfo, ti, &ei_megaco_error_descriptor_transaction_list,
697 "Sorry, can't understand errorDescriptor / transactionList = %s, can't parse it pos %u",
698 tvb_format_text(tvb,tvb_previous_offset,2),tvb_previous_offset);
699 return;
700 } /* end switch */
701 /* Only these remains now
702 * transactionReply = ReplyToken EQUAL TransactionID LBRKT
703 * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
704 * ReplyToken = ("Reply" / "P")
706 * errorDescriptor = ErrorToken EQUAL ErrorCode
707 * LBRKT [quotedString] RBRKT
709 * transactionRequest = TransToken EQUAL TransactionID LBRKT
710 * actionRequest *(COMMA actionRequest) RBRKT
711 * TransToken = ("Transaction" / "T")
714 trx = gcp_trx(msg , trx_id , trx_type, keep_persistent_data);
716 /* Find Context */
717 nextcontext:
722 tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_transaction_end_offset, '{');
723 ti = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tvb_next_offset-tvb_previous_offset+1,
724 "%s", tvb_format_text(tvb, tvb_previous_offset, tvb_next_offset-tvb_previous_offset+1));
725 megaco_context_tree = proto_item_add_subtree(ti, ett_megaco_context);
727 tvb_previous_offset = tvb_find_guint8(tvb, tvb_current_offset,
728 tvb_transaction_end_offset, '=')+1;
729 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
730 if (tvb_current_offset >= tvb_next_offset) {
731 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error, "Parse error: Invalid offset");
732 return;
734 tvb_current_offset = tvb_next_offset;
737 tokenlen = tvb_current_offset - tvb_previous_offset;
738 tempchar = tvb_get_guint8(tvb, tvb_previous_offset );
740 if (tvb_get_guint8(tvb, tvb_current_offset-1 ) == ' '){
741 tokenlen--;
745 switch ( tempchar ){
746 case '$':
747 ctx_id = CHOOSE_CONTEXT;
748 my_proto_tree_add_string(megaco_context_tree, hf_megaco_Context, tvb,
749 tvb_previous_offset, 1,
750 "Choose one");
751 col_append_str(pinfo->cinfo, COL_INFO, " |=Choose one");
752 break;
753 case '*':
754 ctx_id = ALL_CONTEXTS;
755 my_proto_tree_add_string(megaco_context_tree, hf_megaco_Context, tvb,
756 tvb_previous_offset, 1,
757 "All");
758 col_append_str(pinfo->cinfo, COL_INFO, " |=All");
759 break;
760 case '-':
761 ctx_id = NULL_CONTEXT;
762 proto_tree_add_text(megaco_context_tree, tvb, tvb_previous_offset, tokenlen, "Context: NULL" );
763 col_append_str(pinfo->cinfo, COL_INFO, " |=NULL");
764 break;
765 default:
766 my_proto_tree_add_string(megaco_context_tree, hf_megaco_Context, tvb,
767 tvb_previous_offset, tokenlen,
768 tvb_format_text(tvb, tvb_previous_offset,
769 tokenlen));
770 ctx_id = (guint)strtoul(tvb_format_text(tvb, tvb_previous_offset, tokenlen),NULL,10);
772 col_append_fstr(pinfo->cinfo, COL_INFO, " |=%s",tvb_format_text(tvb, tvb_previous_offset,tokenlen));
775 ctx = gcp_ctx(msg,trx,ctx_id,keep_persistent_data);
777 /* Find Commands */
779 /* If Transaction is is Request, Reply or Pending */
780 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
781 tvb_command_end_offset = tvb_command_start_offset;
783 tvb_LBRKT = tvb_command_start_offset;
784 tvb_RBRKT = tvb_command_start_offset;
786 /* The following loop find the individual contexts, commands and call the for every Descriptor a subroutine */
788 do {
789 tvb_command_end_offset = tvb_find_guint8(tvb, tvb_command_end_offset +1,
790 tvb_transaction_end_offset, ',');
792 if ( tvb_command_end_offset == -1 || tvb_command_end_offset > tvb_transaction_end_offset){
793 tvb_command_end_offset = tvb_transaction_end_offset ;
797 /* checking how many left brackets are before the next comma */
799 while ( tvb_find_guint8(tvb, tvb_LBRKT+1,tvb_transaction_end_offset, '{') != -1
800 && (tvb_find_guint8(tvb, tvb_LBRKT+1,tvb_transaction_end_offset, '{') < tvb_command_end_offset)){
802 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
803 tvb_transaction_end_offset, '{');
805 LBRKT_counter++;
808 /* checking how many right brackets are before the next comma */
810 while ( (tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_transaction_end_offset, '}') != -1 )
811 && (tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_transaction_end_offset, '}') <= tvb_command_end_offset)
812 && LBRKT_counter != 0){
814 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
815 tvb_transaction_end_offset, '}');
816 RBRKT_counter++;
821 /* If equal or more right brackets before the comma, one command is complete */
823 if ( LBRKT_counter <= RBRKT_counter ){
825 tvb_current_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
826 tvb_transaction_end_offset, '{');
829 /* includes no descriptors */
831 if ( LBRKT_counter == 0 ){
833 tvb_current_offset = tvb_command_end_offset;
835 /* the last command in a context */
837 if ( tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}') < tvb_current_offset
838 && tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}') != -1){
840 tvb_previous_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
841 tvb_transaction_end_offset, '}');
843 len = tvb_previous_offset - tvb_command_start_offset;
845 tvb_previous_offset = megaco_tvb_skip_wsp_return(tvb, tvb_previous_offset -1);
847 tokenlen = tvb_previous_offset - tvb_command_start_offset;
851 /* not the last command in a context*/
853 else{
854 len = tvb_current_offset - tvb_command_start_offset;
855 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset -1);
857 tokenlen = tvb_current_offset - tvb_command_start_offset;
861 /* command includes descriptors */
863 else{
864 len = tvb_current_offset - tvb_command_start_offset;
865 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset -1);
867 tokenlen = tvb_current_offset - tvb_command_start_offset;
870 /* if a next context is specified */
872 if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'C'){
873 tvb_current_offset = tvb_command_start_offset;
874 tvb_previous_offset = tvb_command_start_offset;
875 LBRKT_counter = 0;
876 RBRKT_counter = 0;
877 goto nextcontext;
880 sub_ti = proto_tree_add_text(megaco_tree, tvb, tvb_command_start_offset, len+1,
881 "%s", tvb_format_text(tvb, tvb_command_start_offset, len+1));
882 megaco_tree_command_line = proto_item_add_subtree(sub_ti, ett_megaco_command_line);
883 /* creation of the megaco_tree_command_line additionally Command and Transaction ID will be printed in this line */
884 /* Changed to use the lines above. this code is saved if there is complaints
885 sub_ti = proto_tree_add_item(megaco_tree,hf_megaco_command_line,tvb,tvb_command_start_offset,tokenlen, ENC_ASCII|ENC_NA);
886 megaco_tree_command_line = proto_item_add_subtree(sub_ti, ett_megaco_command_line);
889 tvb_next_offset = tvb_command_start_offset + tokenlen;
891 /* Try to dissect Topology Descriptor before the command */
892 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
893 if ( (tempchar >= 'a')&& (tempchar <= 'z')){
894 tempchar = tempchar - 0x20;
896 if ( tempchar == 'T') {
897 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
899 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
900 tempchar = tempchar - 0x20;
902 if ( tempchar == 'P' || tempchar == 'O'){
903 gint tvb_topology_end_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}');
904 if ( tvb_topology_end_offset == -1 ){
905 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"}\"");
906 return;
909 tvb_command_start_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{');
910 if ( tvb_command_start_offset == -1 ){
911 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"{\"");
912 return;
914 dissect_megaco_topologydescriptor(tvb, megaco_tree_command_line, tvb_topology_end_offset-1, tvb_command_start_offset+1);
916 /* Command after Topology Descriptor */
917 tvb_command_start_offset = tvb_find_guint8(tvb, tvb_topology_end_offset + 1,
918 tvb_transaction_end_offset, ',');
920 if ( tvb_command_start_offset == -1 ){
921 /* No Command present after Topology Descriptor */
922 break;
924 } else {
925 /* Try to find the first char of the command */
926 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_command_start_offset + 1);
927 /*tvb_next_offset = tvb_find_guint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{');*/
928 continue;
934 /* Additional value */
936 if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'O'){
938 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_command_start_offset, 2, "O- indicates an optional command" );
939 tvb_command_start_offset = tvb_command_start_offset+2;
943 /* Additional value */
945 if ( tvb_get_guint8(tvb, tvb_command_start_offset ) == 'W'){
947 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_command_start_offset, 2, "W- indicates a wildcarded response to a command" );
948 tvb_command_start_offset = tvb_command_start_offset+2;
954 tvb_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
955 tvb_transaction_end_offset, '=');
956 if (tvb_offset == -1 ) {
957 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"=\"");
958 return;
960 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_offset -1);
961 tokenlen = tvb_offset - tvb_command_start_offset;
963 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
964 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
965 tempchar = tempchar - 0x20;
967 if ( tempchar != 'E' ){
969 /* Short form used */
970 if ( tvb_get_guint8(tvb, 0 ) == '!'){
972 switch ( tempchar ){
974 case 'A':
976 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
977 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
978 tempchar = tempchar - 0x20;
980 switch ( tempchar ){
982 case 'V':
983 switch(trx_type) {
984 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITVAL_REPLY; break;
985 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITVAL_REQ; break;
986 default: cmd_type = GCP_CMD_NONE; break;
989 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
990 tvb_command_start_offset, tokenlen,
991 "AuditValue");
992 col_append_str(pinfo->cinfo, COL_INFO, " AuditValue");
993 break;
995 case 'C':
996 switch(trx_type) {
997 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITCAP_REQ; break;
998 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITCAP_REPLY; break;
999 default: cmd_type = GCP_CMD_NONE; break;
1001 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1002 tvb_command_start_offset, tokenlen,
1003 "AuditCapability");
1004 col_append_str(pinfo->cinfo, COL_INFO, " AuditCapability");
1005 break;
1007 default:
1008 switch(trx_type) {
1009 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_ADD_REQ; break;
1010 case GCP_TRX_REPLY: cmd_type = GCP_CMD_ADD_REPLY; break;
1011 default: cmd_type = GCP_CMD_NONE; break;
1014 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1015 tvb_command_start_offset, tokenlen,
1016 "Add");
1017 col_append_str(pinfo->cinfo, COL_INFO, " Add");
1018 break;
1020 break;
1022 case 'N':
1023 switch(trx_type) {
1024 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_NOTIFY_REQ; break;
1025 case GCP_TRX_REPLY: cmd_type = GCP_CMD_NOTIFY_REPLY; break;
1026 default: cmd_type = GCP_CMD_NONE; break;
1029 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1030 tvb_command_start_offset, tokenlen,
1031 "Notify");
1032 col_append_str(pinfo->cinfo, COL_INFO, " Notify");
1033 break;
1035 case 'M':
1037 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1038 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1039 tempchar = tempchar - 0x20;
1041 switch ( tempchar ){
1042 case 'F':
1043 switch(trx_type) {
1044 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOD_REQ; break;
1045 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOD_REPLY; break;
1046 default: cmd_type = GCP_CMD_NONE; break;
1049 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1050 tvb_command_start_offset, tokenlen,
1051 "Modify");
1052 col_append_str(pinfo->cinfo, COL_INFO, " Modify");
1053 break;
1055 case 'V':
1056 switch(trx_type) {
1057 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOVE_REQ; break;
1058 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOVE_REPLY; break;
1059 default: cmd_type = GCP_CMD_NONE; break;
1061 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1062 tvb_command_start_offset, tokenlen,
1063 "Move");
1064 col_append_str(pinfo->cinfo, COL_INFO, " Move");
1065 break;
1067 break;
1069 case 'P':
1070 cmd_type = GCP_CMD_NONE;
1072 PackagesToken = ("Packages" / "PG")
1073 PendingToken = ("Pending" / "PN")
1074 PriorityToken = ("Priority" / "PR")
1075 ProfileToken = ("Profile" / "PF")
1077 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1078 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1079 tempchar = tempchar - 0x20;
1081 switch ( tempchar ){
1082 case 'G':
1083 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1084 tvb_command_start_offset, tokenlen,
1085 "Packages");
1086 break;
1087 case 'N':
1088 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1089 tvb_command_start_offset, tokenlen,
1090 "Pending");
1091 break;
1092 case 'R':
1093 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1094 tvb_command_start_offset, tokenlen,
1095 "Priority");
1096 break;
1097 case 'F':
1098 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1099 tvb_command_start_offset, tokenlen,
1100 "Profile");
1101 break;
1103 break;
1105 case 'S':
1106 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset+1);
1107 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1108 tempchar = tempchar - 0x20;
1110 switch ( tempchar ){
1112 case 'C':
1113 switch(trx_type) {
1114 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SVCCHG_REQ; break;
1115 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SVCCHG_REPLY; break;
1116 default: cmd_type = GCP_CMD_NONE; break;
1118 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1119 tvb_command_start_offset, tokenlen,
1120 "ServiceChange");
1121 break;
1123 default:
1124 switch(trx_type) {
1125 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
1126 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
1127 default: cmd_type = GCP_CMD_NONE; break;
1129 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1130 tvb_command_start_offset, tokenlen,
1131 "Subtract");
1132 col_append_str(pinfo->cinfo, COL_INFO, " Subtract");
1133 break;
1135 break;
1137 default:
1139 proto_item *item;
1141 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1142 tvb_ensure_bytes_exist(tvb, tvb_previous_offset, tokenlen);
1143 item = proto_tree_add_string(megaco_tree, hf_megaco_error_Frame, tvb,
1144 tvb_previous_offset, tokenlen,
1145 "No Command detectable !");
1146 proto_item_append_text(item,"[ tempchar 0x%x ]", tempchar);
1147 return;
1151 else{
1152 gchar* command = tvb_format_text(tvb, tvb_command_start_offset, tokenlen);
1154 if ( g_str_equal(command,"Subtract") ) {
1155 switch(trx_type) {
1156 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
1157 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
1158 default: cmd_type = GCP_CMD_NONE; break;
1160 } else if ( g_str_equal(command,"AuditValue") ) {
1161 switch(trx_type) {
1162 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITVAL_REPLY; break;
1163 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITVAL_REQ; break;
1164 default: cmd_type = GCP_CMD_NONE; break;
1166 } else if ( g_str_equal(command,"AuditCapability") ) {
1167 switch(trx_type) {
1168 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITCAP_REQ; break;
1169 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITCAP_REPLY; break;
1170 default: cmd_type = GCP_CMD_NONE; break;
1172 } else if ( g_str_equal(command,"Add") ) {
1173 switch(trx_type) {
1174 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_ADD_REQ; break;
1175 case GCP_TRX_REPLY: cmd_type = GCP_CMD_ADD_REPLY; break;
1176 default: cmd_type = GCP_CMD_NONE; break;
1178 } else if ( g_str_equal(command,"Notify") ) {
1179 switch(trx_type) {
1180 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_NOTIFY_REQ; break;
1181 case GCP_TRX_REPLY: cmd_type = GCP_CMD_NOTIFY_REPLY; break;
1182 default: cmd_type = GCP_CMD_NONE; break;
1184 } else if ( g_str_equal(command,"Modify") ) {
1185 switch(trx_type) {
1186 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOD_REQ; break;
1187 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOD_REPLY; break;
1188 default: cmd_type = GCP_CMD_NONE; break;
1190 } else if ( g_str_equal(command,"Move") ) {
1191 switch(trx_type) {
1192 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOVE_REQ; break;
1193 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOVE_REPLY; break;
1194 default: cmd_type = GCP_CMD_NONE; break;
1196 } else if ( g_str_equal(command,"ServiceChange") ) {
1197 switch(trx_type) {
1198 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SVCCHG_REQ; break;
1199 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SVCCHG_REPLY; break;
1200 default: cmd_type = GCP_CMD_NONE; break;
1202 } else if ( g_str_equal(command,"Subtract") ) {
1203 switch(trx_type) {
1204 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
1205 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
1206 default: cmd_type = GCP_CMD_NONE; break;
1208 } else {
1209 switch(trx_type) {
1210 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_OTHER_REQ; break;
1211 case GCP_TRX_REPLY: cmd_type = GCP_CMD_REPLY; break;
1212 default: cmd_type = GCP_CMD_NONE; break;
1217 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1218 tvb_command_start_offset, tokenlen,
1219 tvb_format_text(tvb, tvb_command_start_offset,
1220 tokenlen));
1221 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",command);
1224 if (cmd_type == GCP_CMD_NONE && trx_type == GCP_TRX_REPLY) {
1225 cmd_type = GCP_CMD_REPLY;
1228 if (cmd_type != GCP_CMD_NONE) {
1229 cmd = gcp_cmd(msg, trx, ctx, cmd_type, tvb_command_start_offset, keep_persistent_data);
1230 tap_queue_packet(megaco_tap, pinfo, cmd);
1233 tvb_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
1234 tvb_transaction_end_offset, '=');
1235 if (tvb_offset == -1 ) {
1236 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"=\"");
1237 return;
1239 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1);
1240 tokenlen = tvb_next_offset - tvb_offset;
1241 if (tokenlen+1 <= 0) {
1242 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Invalid token length (%d)", tokenlen+1);
1243 return;
1246 tempchar = tvb_get_guint8(tvb, tvb_offset);
1247 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1248 tempchar = tempchar - 0x20;
1250 term = wmem_new0(wmem_packet_scope(), gcp_term_t);
1251 wild_term = GCP_WILDCARD_NONE;
1252 term->type = GCP_TERM_TYPE_UNKNOWN;
1254 switch ( tempchar ){
1256 case 'E':
1257 if ((tokenlen+1 > (int) sizeof(TermID))) {
1258 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Invalid TermID length (%d)", tokenlen+1);
1259 return;
1261 tvb_get_nstringz0(tvb,tvb_offset,tokenlen+1,TermID);
1262 TermID[0] = 'e';
1264 term->len = tokenlen;
1265 term->str = (const gchar*)(term->buffer = TermID);
1267 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
1269 /*** TERM ***/
1270 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1271 tvb_offset, tokenlen,
1272 TermID);
1273 break;
1275 case '*':
1276 wild_term = GCP_WILDCARD_ALL;
1277 term->len = 1;
1278 term->buffer = (const guint8*)(term->str = "*");
1280 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
1282 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1283 tvb_offset, tokenlen,
1284 "WildCard all");
1285 col_append_str(pinfo->cinfo, COL_INFO, "=*");
1286 break;
1288 case '$':
1289 wild_term = GCP_WILDCARD_CHOOSE;
1291 term->len = 1;
1292 term->buffer = (term->str = "$");
1294 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
1296 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1297 tvb_offset, tokenlen,
1298 "WildCard any");
1299 col_append_str(pinfo->cinfo, COL_INFO, "=$");
1300 break;
1302 default:
1303 /*** TERM ***/
1304 my_proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1305 tvb_offset, tokenlen,
1306 tvb_format_text(tvb, tvb_offset,
1307 tokenlen));
1309 term->len = tokenlen;
1310 term->buffer = (const guint8*)(term->str = tvb_format_text(tvb, tvb_offset, tokenlen));
1312 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, keep_persistent_data);
1314 col_append_fstr(pinfo->cinfo, COL_INFO, "=%s",tvb_format_text(tvb, tvb_offset,tokenlen));
1315 break;
1319 /* Dissect the Descriptors */
1322 if ( LBRKT_counter != 0 && tvb_current_offset != tvb_command_end_offset){
1324 tvb_descriptors_start_offset = tvb_find_guint8(tvb, tvb_command_start_offset,
1325 tvb_transaction_end_offset, '{');
1327 tvb_descriptors_end_offset = tvb_descriptors_start_offset;
1328 if ( tvb_descriptors_end_offset > tvb_transaction_end_offset )
1329 tvb_descriptors_end_offset = tvb_transaction_end_offset;
1331 while ( LBRKT_counter > 0 ){
1333 tvb_descriptors_end_offset = tvb_find_guint8(tvb, tvb_descriptors_end_offset+1,
1334 tvb_transaction_end_offset, '}');
1336 LBRKT_counter--;
1340 tempchar = tvb_get_guint8(tvb, tvb_command_start_offset);
1342 if ( tempchar == 'E'|| tempchar == 'e'){
1343 dissect_megaco_descriptors(tvb, megaco_tree, pinfo, tvb_command_start_offset-1,tvb_descriptors_end_offset);
1345 else {
1346 dissect_megaco_descriptors(tvb, megaco_tree, pinfo, tvb_descriptors_start_offset,tvb_descriptors_end_offset);
1349 RBRKT_counter = 0;
1350 LBRKT_counter = 0;
1351 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_command_end_offset +1);
1352 tvb_LBRKT = tvb_command_start_offset;
1353 tvb_RBRKT = tvb_command_start_offset;
1357 } while ( tvb_command_end_offset < tvb_transaction_end_offset );
1359 if (keep_persistent_data) {
1360 gcp_msg_to_str(msg,keep_persistent_data);
1361 gcp_analyze_msg(megaco_tree, pinfo, tvb, msg, &megaco_ctx_ids, &ei_megaco_errored_command);
1364 tvb_next_offset = tvb_transaction_end_offset;
1366 first = 0;
1368 while( tvb_transaction_end_offset < tvb_len - 2);
1370 if(global_megaco_raw_text){
1371 tvb_raw_text_add(tvb, megaco_tree);
1375 #define MEGACO_MODEM_TOKEN 1
1376 #define MEGACO_MUX_TOKEN 2
1377 #define MEGACO_MEDIA_TOKEN 3
1378 #define MEGACO_SIGNALS_TOKEN 4
1379 #define MEGACO_SERVICES_TOKEN 5
1380 #define MEGACO_STATS_TOKEN 6
1381 #define MEGACO_ERROR_TOKEN 7
1382 #define MEGACO_EVENTS_TOKEN 8
1383 #define MEGACO_AUDIT_TOKEN 9
1384 #define MEGACO_DIGITMAP_TOKEN 10
1385 #define MEGACO_OE_TOKEN 11
1386 #define MEGACO_TOPOLOGY_TOKEN 12
1387 #define MEGACO_PACKAGES_TOKEN 13
1389 static const megaco_tokens_t megaco_descriptors_names[] = {
1390 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
1391 { "Modem", "MD" }, /* 1 */
1392 { "Mux", "MX" }, /* 2 */
1393 { "Media", "M" }, /* 3 */
1394 { "Signals", "SG" }, /* 4 */
1395 { "Services", "SV" }, /* 5 */
1396 { "Statistics", "SA" }, /* 6 */
1397 { "Error", "ER" }, /* 7 */
1398 { "Events", "E" }, /* 8 */
1399 { "Audit", "AT" }, /* 9 */
1400 { "DigitMap", "DM" }, /* 10 */
1401 { "ObservedEvents", "OE" }, /* 11 */
1402 { "Topology", "TP" }, /* 12 */
1403 { "Packages", "PG" }, /* 13 */
1406 /* Returns index of megaco_tokens_t */
1407 /* note - also called by dissect_megaco_auditdescriptor */
1408 static gint find_megaco_descriptors_names(tvbuff_t *tvb, int offset, guint header_len)
1410 guint i;
1412 for (i = 1; i < array_length(megaco_descriptors_names); i++) {
1413 if (header_len == strlen(megaco_descriptors_names[i].name) &&
1414 tvb_strncaseeql(tvb, offset, megaco_descriptors_names[i].name, header_len) == 0)
1415 return i;
1416 if (megaco_descriptors_names[i].compact_name != NULL &&
1417 header_len == strlen(megaco_descriptors_names[i].compact_name) &&
1418 tvb_strncaseeql(tvb, offset, megaco_descriptors_names[i].compact_name, header_len) == 0)
1419 return i;
1421 return -1;
1424 static void
1425 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)
1427 gint tvb_len, token_index, tvb_offset, temp_offset;
1428 gint tvb_current_offset,tvb_previous_offset,tokenlen;
1429 gint tvb_RBRKT, tvb_LBRKT;
1431 tvb_len = tvb_length(tvb);
1434 tvb_LBRKT = megaco_tvb_skip_wsp(tvb, tvb_descriptors_start_offset +1);
1436 tvb_previous_offset = tvb_LBRKT;
1437 tvb_RBRKT = tvb_descriptors_start_offset;
1440 do {
1442 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
1443 tvb_len, '}');
1444 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
1445 tvb_len, '{');
1447 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
1448 tvb_len, ',');
1450 if (tvb_current_offset == -1 || tvb_current_offset > tvb_descriptors_end_offset){
1451 tvb_current_offset = tvb_descriptors_end_offset;
1454 if (tvb_current_offset <= tvb_previous_offset) {
1455 expert_add_info_format(pinfo, megaco_tree_command_line, &ei_megaco_parse_error, "Parse error: Invalid offset");
1456 return;
1461 /* Descriptor includes no parameters */
1463 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
1465 if ( tvb_current_offset > tvb_RBRKT ){
1466 tvb_current_offset = tvb_RBRKT;
1469 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
1472 /* Descriptor includes Parameters */
1473 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
1475 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
1478 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
1479 tvb_len, '{');
1480 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
1481 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,tvb_len, '}');
1486 /* Find token length */
1487 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_descriptors_end_offset -1; tvb_offset++){
1488 if (!isalpha(tvb_get_guint8(tvb, tvb_offset ))){
1489 break;
1492 tokenlen = tvb_offset - tvb_previous_offset;
1493 token_index = find_megaco_descriptors_names(tvb, tvb_previous_offset, tokenlen);
1494 if (tvb_RBRKT > tvb_descriptors_end_offset) tvb_RBRKT = tvb_descriptors_end_offset;
1495 switch ( token_index ){
1496 case MEGACO_MODEM_TOKEN:
1497 dissect_megaco_modemdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1498 break;
1499 case MEGACO_MUX_TOKEN:
1500 dissect_megaco_multiplexdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1501 break;
1502 case MEGACO_MEDIA_TOKEN:
1503 /*TODO: Move this to the top when all branches fixed !!!*/
1504 temp_offset = tvb_find_guint8(tvb, tvb_previous_offset,tvb_descriptors_end_offset, '{');
1505 tokenlen = temp_offset - tvb_previous_offset+1;
1506 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
1507 "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
1509 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, temp_offset +1);
1510 dissect_megaco_mediadescriptor(tvb, megaco_tree_command_line, pinfo, tvb_RBRKT, tvb_previous_offset);
1511 break;
1512 case MEGACO_SIGNALS_TOKEN:
1513 dissect_megaco_signaldescriptor(tvb, pinfo, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1514 break;
1515 case MEGACO_SERVICES_TOKEN:
1516 dissect_megaco_servicechangedescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1517 break;
1518 case MEGACO_STATS_TOKEN:
1519 dissect_megaco_statisticsdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1520 break;
1521 case MEGACO_ERROR_TOKEN:
1522 dissect_megaco_errordescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1523 break;
1524 case MEGACO_EVENTS_TOKEN:
1525 dissect_megaco_eventsdescriptor(tvb, pinfo, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1526 break;
1527 case MEGACO_AUDIT_TOKEN:
1528 dissect_megaco_auditdescriptor(tvb, megaco_tree_command_line, pinfo, tvb_RBRKT, tvb_previous_offset);
1529 break;
1530 case MEGACO_DIGITMAP_TOKEN:
1531 dissect_megaco_digitmapdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1532 break;
1533 case MEGACO_OE_TOKEN:
1534 /* ObservedEventsToken */
1535 dissect_megaco_observedeventsdescriptor(tvb, pinfo, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1536 break;
1537 case MEGACO_TOPOLOGY_TOKEN:
1538 dissect_megaco_topologydescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1539 break;
1540 case MEGACO_PACKAGES_TOKEN:
1541 dissect_megaco_Packagesdescriptor(tvb, megaco_tree_command_line, tvb_RBRKT, tvb_previous_offset);
1542 break;
1543 default:
1544 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1545 proto_tree_add_string(megaco_tree_command_line, hf_megaco_error_Frame, tvb,
1546 tvb_previous_offset, tokenlen,
1547 "No Descriptor detectable !");
1548 break;
1551 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT, tvb_len, ',');
1552 if (tvb_current_offset == -1 || tvb_descriptors_end_offset < tvb_current_offset){
1553 tvb_current_offset = tvb_descriptors_end_offset;
1555 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
1556 tvb_LBRKT = tvb_previous_offset;
1557 tvb_RBRKT = tvb_previous_offset;
1559 } while ( tvb_current_offset < tvb_descriptors_end_offset );
1563 static void
1564 dissect_megaco_modemdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
1567 gint tokenlen;
1569 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1570 proto_tree_add_string(megaco_tree_command_line, hf_megaco_modem_descriptor, tvb,
1571 tvb_previous_offset, tokenlen,
1572 tvb_format_text(tvb, tvb_previous_offset,
1573 tokenlen));
1576 static void
1577 dissect_megaco_multiplexdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
1580 gint tokenlen;
1582 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1583 proto_tree_add_string(megaco_tree_command_line, hf_megaco_multiplex_descriptor, tvb,
1584 tvb_previous_offset, tokenlen,
1585 tvb_format_text(tvb, tvb_previous_offset,
1586 tokenlen));
1590 /* mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
1591 * MediaToken = ("Media" / "M")
1593 * mediaParm = (streamParm / streamDescriptor /terminationStateDescriptor)
1595 * ; at-most one terminationStateDescriptor
1596 * ; and either streamParm(s) or streamDescriptor(s) but not both
1597 * streamParm = ( localDescriptor / remoteDescriptor /localControlDescriptor )
1598 * localDescriptor = LocalToken LBRKT octetString RBRKT
1599 * LocalToken = ("Local" / "L")
1600 * octetString = *(nonEscapeChar)
1601 * nonEscapeChar = ( "\}" / %x01-7C / %x7E-FF )
1602 * remoteDescriptor = RemoteToken LBRKT octetString RBRKT
1603 * RemoteToken = ("Remote" / "R")
1604 * localControlDescriptor = LocalControlToken LBRKT localParm*(COMMA localParm) RBRKT
1605 * LocalControlToken = ("LocalControl" / "O")
1606 * localParm = ( streamMode / propertyParm / reservedValueMode
1607 * streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm*(COMMA streamParm) RBRKT
1608 * StreamToken = ("Stream" / "ST")
1609 * terminationStateDescriptor = TerminationStateToken LBRKTterminationStateParm
1610 * *( COMMA terminationStateParm ) RBRKT
1611 * TerminationStateToken = ("TerminationState" / "TS")
1612 * terminationStateParm =(propertyParm / serviceStates / eventBufferControl )
1615 #define MEGACO_LOCAL_TOKEN 1
1616 #define MEGACO_REMOTE_TOKEN 2
1617 #define MEGACO_LOCAL_CONTROL_TOKEN 3
1618 #define MEGACO_STREAM_TOKEN 4
1619 #define MEGACO_TERMINATION_STATE_DESC 5
1621 static const megaco_tokens_t megaco_mediaParm_names[] = {
1622 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
1623 { "Local", "L" }, /* 1 */
1624 { "Remote", "R" }, /* 2 */
1625 { "LocalControl", "O" }, /* 3 */
1626 { "Stream", "ST" }, /* 4 */
1627 { "TerminationState", "TS" }, /* 5 */
1630 /* Returns index of megaco_tokens_t */
1631 static gint find_megaco_mediaParm_names(tvbuff_t *tvb, int offset, guint header_len)
1633 guint i;
1635 for (i = 1; i < array_length(megaco_mediaParm_names); i++) {
1636 if (header_len == strlen(megaco_mediaParm_names[i].name) &&
1637 tvb_strncaseeql(tvb, offset, megaco_mediaParm_names[i].name, header_len) == 0)
1638 return i;
1639 if (megaco_mediaParm_names[i].compact_name != NULL &&
1640 header_len == strlen(megaco_mediaParm_names[i].compact_name) &&
1641 tvb_strncaseeql(tvb, offset, megaco_mediaParm_names[i].compact_name, header_len) == 0)
1642 return i;
1645 return -1;
1648 static void
1649 dissect_megaco_mediadescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line,packet_info *pinfo, gint tvb_last_RBRKT, gint tvb_previous_offset)
1652 gint tokenlen, tvb_LBRKT, tvb_RBRKT;
1653 gint tvb_next_offset, tvb_current_offset, tvb_offset, equal_offset;
1654 gint mediaParm;
1657 proto_tree *megaco_mediadescriptor_tree, *megaco_mediadescriptor_ti;
1660 megaco_mediadescriptor_ti = proto_tree_add_text(megaco_tree_command_line,tvb,tvb_previous_offset,tokenlen,"Media Descriptor");
1661 megaco_mediadescriptor_tree = proto_item_add_subtree(megaco_mediadescriptor_ti, ett_megaco_mediadescriptor);
1663 while ( tvb_previous_offset < tvb_last_RBRKT){
1664 /* Start of token */
1665 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
1667 /* Find token length */
1668 for (tvb_next_offset=tvb_current_offset; tvb_next_offset < tvb_last_RBRKT; tvb_next_offset++){
1669 if (!isalpha(tvb_get_guint8(tvb, tvb_next_offset ))){
1670 break;
1673 tokenlen = tvb_next_offset - tvb_current_offset;
1675 mediaParm = find_megaco_mediaParm_names(tvb, tvb_current_offset, tokenlen);
1677 tvb_LBRKT = tvb_find_guint8(tvb, tvb_next_offset , tvb_last_RBRKT, '{');
1678 tvb_next_offset = tvb_find_guint8(tvb, tvb_current_offset+1 , tvb_last_RBRKT, '}');
1679 tvb_RBRKT = tvb_next_offset;
1681 tokenlen = tvb_LBRKT - tvb_current_offset +1;
1682 megaco_mediadescriptor_ti = proto_tree_add_text(megaco_tree_command_line,tvb,tvb_current_offset,
1683 tokenlen,"%s",tvb_format_text(tvb, tvb_current_offset,tokenlen));
1685 switch ( mediaParm ){
1686 case MEGACO_LOCAL_TOKEN:
1687 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1688 dissect_megaco_Localdescriptor(tvb,megaco_tree_command_line , pinfo,
1689 tvb_RBRKT, tvb_current_offset);
1690 tvb_current_offset = tvb_RBRKT;
1691 break;
1692 case MEGACO_REMOTE_TOKEN:
1693 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1694 dissect_megaco_Localdescriptor(tvb,megaco_tree_command_line , pinfo,
1695 tvb_RBRKT, tvb_current_offset);
1696 tvb_current_offset = tvb_RBRKT;
1697 break;
1698 case MEGACO_LOCAL_CONTROL_TOKEN:
1699 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1700 dissect_megaco_LocalControldescriptor(tvb,megaco_tree_command_line, pinfo ,
1701 tvb_RBRKT, tvb_current_offset);
1702 tvb_current_offset = tvb_RBRKT;
1703 break;
1704 case MEGACO_STREAM_TOKEN:
1705 megaco_mediadescriptor_tree = proto_item_add_subtree(megaco_mediadescriptor_ti, ett_megaco_mediadescriptor);
1707 equal_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_last_RBRKT, '=');
1708 tvb_current_offset = megaco_tvb_skip_wsp(tvb, equal_offset+1);
1709 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_LBRKT-1);
1710 tokenlen = tvb_offset - tvb_current_offset;
1712 proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_streamid, tvb,
1713 tvb_current_offset, tokenlen, tvb_format_text(tvb, tvb_current_offset,tokenlen));
1714 tvb_previous_offset = tvb_LBRKT+1;
1715 continue;
1716 case MEGACO_TERMINATION_STATE_DESC:
1717 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1718 dissect_megaco_TerminationStatedescriptor(tvb,megaco_tree_command_line ,
1719 tvb_RBRKT, tvb_current_offset);
1720 tvb_current_offset = tvb_RBRKT;
1721 break;
1722 default:
1723 break;
1725 /* more parameters ? */
1726 tvb_next_offset = tvb_find_guint8(tvb, tvb_current_offset+1 , tvb_last_RBRKT, ',');
1727 if (tvb_next_offset > tvb_last_RBRKT) tvb_next_offset = tvb_last_RBRKT;
1728 if ( tvb_next_offset != -1 ){
1729 tokenlen = tvb_next_offset - tvb_RBRKT+1;
1730 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_RBRKT, tokenlen,
1731 "%s", tvb_format_text(tvb, tvb_RBRKT, tokenlen));
1732 tvb_previous_offset = tvb_next_offset+1;
1733 }else{
1734 /* Add the trailing '}'*/
1735 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_RBRKT, 1,
1736 "%s", tvb_format_text(tvb, tvb_RBRKT, 1));
1737 tvb_previous_offset = tvb_last_RBRKT;
1740 } /* End while */
1743 static void
1744 dissect_megaco_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree, gint offset, gint len, gchar *msg)
1746 /*proto_item *item;*/
1747 /*proto_tree *tree;*/
1749 /*item=proto_tree_add_string(megaco_tree, hf_megaco_h245, tvb,
1750 offset, len, msg );
1752 /*item = */proto_tree_add_text(megaco_tree, tvb, offset, len, "%s", msg);
1754 /*tree = proto_item_add_subtree(item, ett_megaco_h245); */
1756 /* arbitrary maximum length */
1757 if(len<20480){
1758 int i;
1759 tvbuff_t *h245_tvb;
1760 guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
1762 /* first, skip to where the encoded pdu starts, this is
1763 the first hex digit after the '=' char.
1765 while(1){
1766 if((*msg==0)||(*msg=='\n')){
1767 return;
1769 if(*msg=='='){
1770 msg++;
1771 break;
1773 msg++;
1775 while(1){
1776 if((*msg==0)||(*msg=='\n')){
1777 return;
1779 if( ((*msg>='0')&&(*msg<='9'))
1780 || ((*msg>='a')&&(*msg<='f'))
1781 || ((*msg>='A')&&(*msg<='F'))){
1782 break;
1784 msg++;
1786 i=0;
1787 while( ((*msg>='0')&&(*msg<='9'))
1788 ||((*msg>='a')&&(*msg<='f'))
1789 ||((*msg>='A')&&(*msg<='F')) ){
1790 int val;
1791 if((*msg>='0')&&(*msg<='9')){
1792 val=(*msg)-'0';
1793 } else if((*msg>='a')&&(*msg<='f')){
1794 val=(*msg)-'a'+10;
1795 } else if((*msg>='A')&&(*msg<='F')){
1796 val=(*msg)-'A'+10;
1797 } else {
1798 return;
1800 val<<=4;
1801 msg++;
1802 if((*msg>='0')&&(*msg<='9')){
1803 val|=(*msg)-'0';
1804 } else if((*msg>='a')&&(*msg<='f')){
1805 val|=(*msg)-'a'+10;
1806 } else if((*msg>='A')&&(*msg<='F')){
1807 val|=(*msg)-'A'+10;
1808 } else {
1809 return;
1811 msg++;
1813 buf[i]=(guint8)val;
1814 i++;
1816 if(i==0){
1817 return;
1819 h245_tvb = tvb_new_child_real_data(tvb, buf,i,i);
1820 add_new_data_source(pinfo, h245_tvb, "H.245 over MEGACO");
1821 /* should go through a handle, however, the two h245 entry
1822 points are different, one is over tpkt and the other is raw
1824 call_dissector(h245_handle, h245_tvb, pinfo, top_tree);
1825 /* dissect_h245_MultimediaSystemControlMessage(h245_tvb, pinfo, tree);*/
1829 static void
1830 dissect_megaco_h324_h223caprn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree, gint offset _U_, gint len, gchar *msg)
1832 asn1_ctx_t actx;
1834 /* arbitrary maximum length */
1835 if(len<20480){
1836 int i;
1837 tvbuff_t *h245_tvb;
1838 guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
1840 /* first, skip to where the encoded pdu starts, this is
1841 the first hex digit after the '=' char.
1843 while(1){
1844 if((*msg==0)||(*msg=='\n')){
1845 return;
1847 if(*msg=='='){
1848 msg++;
1849 break;
1851 msg++;
1853 while(1){
1854 if((*msg==0)||(*msg=='\n')){
1855 return;
1857 if( ((*msg>='0')&&(*msg<='9'))
1858 || ((*msg>='a')&&(*msg<='f'))
1859 || ((*msg>='A')&&(*msg<='F'))){
1860 break;
1862 msg++;
1864 i=0;
1865 while( ((*msg>='0')&&(*msg<='9'))
1866 ||((*msg>='a')&&(*msg<='f'))
1867 ||((*msg>='A')&&(*msg<='F')) ){
1868 int val;
1869 if((*msg>='0')&&(*msg<='9')){
1870 val=(*msg)-'0';
1871 } else if((*msg>='a')&&(*msg<='f')){
1872 val=(*msg)-'a'+10;
1873 } else if((*msg>='A')&&(*msg<='F')){
1874 val=(*msg)-'A'+10;
1875 } else {
1876 return;
1878 val<<=4;
1879 msg++;
1880 if((*msg>='0')&&(*msg<='9')){
1881 val|=(*msg)-'0';
1882 } else if((*msg>='a')&&(*msg<='f')){
1883 val|=(*msg)-'a'+10;
1884 } else if((*msg>='A')&&(*msg<='F')){
1885 val|=(*msg)-'A'+10;
1886 } else {
1887 return;
1889 msg++;
1891 buf[i]=(guint8)val;
1892 i++;
1894 if(i==0){
1895 return;
1897 h245_tvb = tvb_new_child_real_data(tvb, buf,i,i);
1898 add_new_data_source(pinfo, h245_tvb, "H.245 over MEGACO");
1899 /* should go through a handle, however, the two h245 entry
1900 points are different, one is over tpkt and the other is raw
1902 asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
1903 dissect_h245_H223Capability(h245_tvb, 0, &actx, megaco_tree, hf_megaco_h223Capability);
1907 static void
1908 dissect_megaco_eventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
1911 gint tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
1912 gint tvb_events_end_offset, tvb_LBRKT;
1913 proto_tree *megaco_eventsdescriptor_tree, *megaco_eventsdescriptor_ti;
1915 guint8 tempchar;
1916 gint requested_event_start_offset, requested_event_end_offset;
1917 proto_tree *megaco_requestedevent_tree, *megaco_requestedevent_ti;
1919 requested_event_start_offset = 0;
1920 requested_event_end_offset = 0;
1922 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1924 megaco_eventsdescriptor_ti = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
1925 "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
1928 megaco_eventsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_events_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
1930 megaco_eventsdescriptor_tree = proto_item_add_subtree(megaco_eventsdescriptor_ti, ett_megaco_eventsdescriptor);
1932 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
1933 tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
1935 if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
1937 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
1938 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
1940 tokenlen = tvb_help_offset - tvb_current_offset;
1942 proto_tree_add_string(megaco_eventsdescriptor_tree, hf_megaco_requestid, tvb,
1943 tvb_current_offset, tokenlen,
1944 tvb_format_text(tvb, tvb_current_offset,
1945 tokenlen));
1947 tvb_events_end_offset = tvb_RBRKT;
1949 tvb_RBRKT = tvb_next_offset+1;
1950 tvb_LBRKT = tvb_next_offset+1;
1951 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
1954 do {
1956 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
1957 tvb_events_end_offset, '}');
1958 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
1959 tvb_events_end_offset, '{');
1961 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
1962 tvb_events_end_offset, ',');
1964 if (tvb_current_offset == -1 || tvb_current_offset > tvb_events_end_offset){
1965 tvb_current_offset = tvb_events_end_offset;
1969 /* Descriptor includes no parameters */
1971 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
1973 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
1976 /* Descriptor includes Parameters */
1978 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
1980 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
1982 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
1983 tvb_events_end_offset, '{');
1984 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
1985 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
1986 tvb_events_end_offset, '}');
1991 tvb_help_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_events_end_offset, '{');
1993 /* if there are eventparameter */
1995 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
1997 requested_event_start_offset = tvb_help_offset;
1998 requested_event_end_offset = tvb_RBRKT;
1999 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2000 tokenlen = tvb_help_offset - tvb_previous_offset;
2002 /* no parameters */
2003 else {
2004 tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2007 megaco_requestedevent_ti = proto_tree_add_item(megaco_eventsdescriptor_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
2008 megaco_requestedevent_tree = proto_item_add_subtree(megaco_requestedevent_ti, ett_megaco_requestedevent);
2010 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2012 tvb_help_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1);
2013 tempchar = tvb_get_guint8(tvb, tvb_help_offset);
2015 requested_event_start_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1);
2016 requested_event_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_event_end_offset-1);
2018 if ( tempchar == 'D' || tempchar == 'd'){
2019 dissect_megaco_digitmapdescriptor(tvb, megaco_requestedevent_tree, requested_event_end_offset, requested_event_start_offset);
2021 else{
2022 gchar *msg;
2024 tokenlen = requested_event_end_offset - requested_event_start_offset;
2025 msg=tvb_format_text(tvb,requested_event_start_offset, tokenlen);
2026 if(!strncmp("h245", msg, 4)){
2027 dissect_megaco_h245(tvb, pinfo, megaco_requestedevent_tree, requested_event_start_offset, tokenlen, msg);
2028 } else {
2029 proto_tree_add_text(megaco_requestedevent_tree, tvb, requested_event_start_offset, tokenlen,
2030 "%s", msg);
2036 tvb_previous_offset = tvb_current_offset;
2037 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
2038 tvb_events_end_offset, ',');
2040 if (tvb_current_offset == -1 || tvb_current_offset > tvb_events_end_offset || tvb_current_offset < tvb_previous_offset ) {
2041 tvb_current_offset = tvb_events_end_offset;
2044 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2046 tvb_LBRKT = tvb_previous_offset;
2047 tvb_RBRKT = tvb_previous_offset;
2049 } while ( tvb_current_offset < tvb_events_end_offset );
2053 static void
2054 dissect_megaco_signaldescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2057 gint tokenlen, pkg_tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
2058 gint tvb_signals_end_offset, tvb_signals_start_offset, tvb_LBRKT;
2059 /*proto_tree *megaco_signalsdescriptor_tree, *megaco_signalsdescriptor_ti;*/
2061 gint requested_signal_start_offset, requested_signal_end_offset;
2062 proto_tree *megaco_requestedsignal_tree, *megaco_requestedsignal_ti;
2064 requested_signal_start_offset = 0;
2065 requested_signal_end_offset = 0;
2067 tvb_signals_end_offset = tvb_RBRKT;
2068 tvb_signals_start_offset = tvb_previous_offset;
2070 if(toupper(tvb_get_guint8(tvb, tvb_previous_offset+1))=='G')
2071 tokenlen = 2; /* token is compact text (SG) */
2072 else
2073 tokenlen = 7; /* token must be verbose text (Signals) */
2075 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset+tokenlen);
2077 if(tvb_get_guint8(tvb, tvb_current_offset)!='{') { /* {} has been omitted */
2079 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_signals_start_offset, tokenlen,
2080 "%s", "Empty Signal Descriptor");
2082 col_append_str(pinfo->cinfo, COL_INFO, " (Signal:none)"); /* then say so */
2084 return; /* and return */
2087 tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_signals_end_offset, '{');
2088 tokenlen = (tvb_LBRKT+1) - tvb_signals_start_offset;
2090 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_signals_start_offset, tokenlen,
2091 "%s", tvb_format_text(tvb, tvb_signals_start_offset, tokenlen));
2094 megaco_signalsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_signal_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
2095 megaco_signalsdescriptor_tree = proto_item_add_subtree(megaco_signalsdescriptor_ti, ett_megaco_signalsdescriptor);
2098 tvb_current_offset = tvb_LBRKT;
2099 tvb_next_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2100 col_append_fstr(pinfo->cinfo, COL_INFO, " (Signal:%s)",tvb_format_text(tvb, tvb_current_offset,tokenlen-tvb_current_offset+tvb_previous_offset));
2103 if ( tvb_current_offset < tvb_signals_end_offset && tvb_current_offset != -1 && tvb_next_offset != tvb_signals_end_offset){
2106 tvb_RBRKT = tvb_next_offset+1;
2107 tvb_LBRKT = tvb_next_offset+1;
2108 tvb_previous_offset = tvb_next_offset;
2111 do {
2113 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2114 tvb_signals_end_offset, '}');
2115 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
2116 tvb_signals_end_offset, '{');
2118 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
2119 tvb_signals_end_offset, ',');
2121 if (tvb_current_offset == -1 || tvb_current_offset > tvb_signals_end_offset){
2122 tvb_current_offset = tvb_signals_end_offset;
2126 /* Descriptor includes no parameters */
2128 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
2130 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2133 /* Descriptor includes Parameters */
2135 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
2137 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
2139 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
2140 tvb_signals_end_offset, '{');
2141 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
2142 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2143 tvb_signals_end_offset, '}');
2148 tvb_help_offset = tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_signals_end_offset, '{');
2150 /* if there are signalparameter */
2152 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2154 requested_signal_start_offset = tvb_help_offset;
2155 requested_signal_end_offset = tvb_RBRKT;
2156 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2157 pkg_tokenlen = tvb_help_offset - tvb_previous_offset;
2158 tokenlen = tvb_LBRKT+1 - tvb_previous_offset;
2160 /* no parameters */
2161 else {
2162 tokenlen = pkg_tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2165 megaco_requestedsignal_ti = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
2166 "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
2167 megaco_requestedsignal_tree = proto_item_add_subtree(megaco_requestedsignal_ti, ett_megaco_requestedsignal);
2169 proto_tree_add_item(megaco_requestedsignal_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,pkg_tokenlen, ENC_ASCII|ENC_NA);
2171 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2172 gchar *msg;
2174 requested_signal_start_offset = megaco_tvb_skip_wsp(tvb, requested_signal_start_offset +1);
2175 requested_signal_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_signal_end_offset-1);
2177 tokenlen = requested_signal_end_offset - requested_signal_start_offset;
2179 msg=tvb_format_text(tvb,requested_signal_start_offset, tokenlen+1);
2180 if(!strncmp("h245", msg, 4)){
2181 dissect_megaco_h245(tvb, pinfo, megaco_tree_command_line, requested_signal_start_offset, tokenlen, msg);
2182 } else {
2183 proto_tree_add_text(megaco_tree_command_line, tvb, requested_signal_start_offset, tokenlen,
2184 "%s", msg);
2186 /* Print the trailing '}' */
2187 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_RBRKT, 1,
2188 "%s", tvb_format_text(tvb, tvb_RBRKT, 1));
2191 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
2192 tvb_signals_end_offset, ',');
2194 if (tvb_current_offset == -1 || tvb_current_offset > tvb_signals_end_offset || tvb_current_offset < tvb_previous_offset){
2195 tvb_current_offset = tvb_signals_end_offset;
2198 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2200 tvb_LBRKT = tvb_previous_offset;
2201 tvb_RBRKT = tvb_previous_offset;
2202 /* Print the trailing '}' */
2203 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1,
2204 "%s", tvb_format_text(tvb, tvb_signals_end_offset, 1));
2206 } while ( tvb_current_offset < tvb_signals_end_offset );
2207 }else{
2208 /* signals{}*/
2209 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1,
2210 "%s", tvb_format_text(tvb, tvb_signals_end_offset, 1));
2217 auditDescriptor = AuditToken LBRKT [ auditItem *(COMMA auditItem) ] RBRKT
2219 auditItem = ( MuxToken / ModemToken / MediaToken /
2220 SignalsToken / EventBufferToken /
2221 DigitMapToken / StatsToken / EventsToken /
2222 ObservedEventsToken / PackagesToken ) */
2223 static void
2224 dissect_megaco_auditdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree, packet_info *pinfo _U_, gint tvb_stop, gint tvb_offset)
2226 gint tokenlen, tvb_end, tvb_next, token_index;
2227 proto_tree *megaco_auditdescriptor_tree, *megaco_auditdescriptor_ti;
2229 tvb_next = tvb_find_guint8(tvb, tvb_offset, tvb_stop, '{'); /* find opening LBRKT - is this already checked by caller?*/
2230 if( tvb_next == -1 ) /* complain and give up if not there */
2232 expert_add_info(pinfo, megaco_tree, &ei_megaco_audit_descriptor);
2233 return;
2235 tokenlen = (tvb_stop + 1) - tvb_offset;
2237 megaco_auditdescriptor_ti = proto_tree_add_none_format( megaco_tree, hf_megaco_audit_descriptor,
2238 tvb, tvb_offset, tokenlen, "Audit descriptor" );
2240 megaco_auditdescriptor_tree = proto_item_add_subtree( megaco_auditdescriptor_ti, ett_megaco_auditdescriptor );
2242 tokenlen = tvb_next + 1 - tvb_offset;
2244 proto_tree_add_text( megaco_auditdescriptor_tree, tvb, tvb_offset, tokenlen, "Audit token {" );
2246 tvb_offset = tvb_next;
2248 while( tvb_offset < tvb_stop )
2250 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1); /* find start of an auditItem */
2251 if( tvb_get_guint8(tvb, tvb_offset) != '}' ) /* got something */
2253 tvb_next = tvb_find_guint8(tvb, tvb_offset, tvb_stop, ','); /* end of an auditItem */
2254 if (tvb_next == -1) tvb_next = tvb_stop; /* last item doesn't have a comma */
2255 tvb_end = megaco_tvb_skip_wsp_return(tvb, tvb_next-1); /* trim any trailing whitespace */
2256 tokenlen = tvb_end - tvb_offset; /* get length of token */
2258 token_index = find_megaco_descriptors_names(tvb, tvb_offset, tokenlen); /* lookup the token */
2259 if( token_index == -1 ) token_index = 0; /* if not found then 0 => Unknown */
2261 proto_tree_add_string(megaco_auditdescriptor_tree, hf_megaco_audititem, tvb,
2262 tvb_offset, tokenlen, megaco_descriptors_names[token_index].name); /* and display the long form */
2264 tvb_offset = tvb_next; /* advance pointer */
2267 proto_tree_add_text(megaco_auditdescriptor_tree, tvb, tvb_stop, 1, "}"); /* End of auditDescriptor */
2271 * serviceChangeDescriptor = ServicesToken LBRKT serviceChangeParm
2272 * *(COMMA serviceChangeParm) RBRKT
2274 * ServicesToken = ("Services" / "SV")
2276 * serviceChangeParm = (serviceChangeMethod / serviceChangeReason /
2277 * serviceChangeDelay / serviceChangeAddress /
2278 * serviceChangeProfile / extension / TimeStamp /
2279 * serviceChangeMgcId / serviceChangeVersion )
2282 #define MEGACO_REASON_TOKEN 1
2283 #define MEGACO_DELAY_TOKEN 2
2284 #define MEGACO_SC_ADDR_TOKEN 3
2285 #define MEGACO_MGC_ID_TOKEN 4
2286 #define MEGACO_PROFILE_TOKEN 5
2287 #define MEGACO_VERSION_TOKEN 6
2288 #define MEGACO_METHOD_TOKEN 7
2290 static const megaco_tokens_t megaco_serviceChangeParm_names[] = {
2291 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
2292 /* streamMode */
2293 { "Reason", "RE" }, /* 1 ReasonToken*/
2294 { "Delay", "DL" }, /* 2 DelayToken */
2295 { "ServiceChangeAddress", "AD" }, /* 3 ServiceChangeAddressToken */
2296 { "MgcIdToTry", "MG" }, /* 4 MgcIdToken */
2297 { "Profile", "PF" }, /* 5 ProfileToken */
2298 { "Version", "V" }, /* 6 VersionToken */
2299 { "Method", "MT" }, /* 7 MethodToken */
2302 /* Returns index of megaco_tokens_t */
2303 static gint find_megaco_megaco_serviceChangeParm_names(tvbuff_t *tvb, int offset, guint header_len)
2305 guint i;
2307 for (i = 1; i < array_length(megaco_serviceChangeParm_names); i++) {
2308 if (header_len == strlen(megaco_serviceChangeParm_names[i].name) &&
2309 tvb_strncaseeql(tvb, offset, megaco_serviceChangeParm_names[i].name, header_len) == 0)
2310 return i;
2311 if (megaco_serviceChangeParm_names[i].compact_name != NULL &&
2312 header_len == strlen(megaco_serviceChangeParm_names[i].compact_name) &&
2313 tvb_strncaseeql(tvb, offset, megaco_serviceChangeParm_names[i].compact_name, header_len) == 0)
2314 return i;
2317 return -1;
2320 * ServiceChangeReasons References
2321 * -------------------- ----------
2323 static const value_string MEGACO_ServiceChangeReasons_vals[] = {
2324 {900, "Service Restored"},
2325 {901, "Cold Boot"},
2326 {902, "Warm Boot"},
2327 {903, "MGC Directed Change"},
2328 {904, "Termination malfunctioning"},
2329 {905, "Termination taken out of service"},
2330 {906, "Loss of lower layer connectivity (e.g. downstream sync)"},
2331 {907, "Transmission Failure"},
2332 {908, "MG Impending Failure"},
2333 {909, "MGC Impending Failure"},
2334 {910, "Media Capability Failure"},
2335 {911, "Modem Capability Failure"},
2336 {912, "Mux Capability Failure"},
2337 {913, "Signal Capability Failure"},
2338 {914, "Event Capability Failure"},
2339 {915, "State Loss"},
2340 {916, "Packages Change"},
2341 {917, "Capabilities Change"},
2342 {918, "Cancel Graceful"},
2343 {919, "Warm Failover"},
2344 {920, "Cold Failover"},
2345 { 0, NULL }
2348 static void
2349 dissect_megaco_servicechangedescriptor(tvbuff_t *tvb, proto_tree *megaco_tree, gint tvb_RBRKT, gint tvb_previous_offset)
2352 gint tokenlen, tvb_LBRKT, tvb_offset;
2353 gint token_index;
2354 gint tvb_current_offset;
2355 gboolean more_params = TRUE;
2356 proto_item* item;
2357 gint reason;
2358 guint8 ServiceChangeReason_str[4];
2360 tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2362 if (tvb_LBRKT == -1)
2363 return;
2365 tokenlen = (tvb_LBRKT + 1) - tvb_previous_offset;
2366 proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tokenlen,
2367 "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
2370 /* Start dissecting serviceChangeParm */
2371 tvb_previous_offset = tvb_LBRKT + 1;
2372 while (more_params){
2373 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
2374 /* Find token length */
2375 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_RBRKT; tvb_offset++){
2376 if (!isalpha(tvb_get_guint8(tvb, tvb_offset ))){
2377 break;
2380 tokenlen = tvb_offset - tvb_previous_offset;
2381 token_index = find_megaco_megaco_serviceChangeParm_names(tvb, tvb_previous_offset, tokenlen);
2383 tvb_offset = tvb_find_guint8(tvb, tvb_offset, tvb_RBRKT, ',');
2384 if ((tvb_offset == -1)||(tvb_offset >=tvb_RBRKT)){
2385 more_params = FALSE;
2386 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_RBRKT-1);
2388 tokenlen = tvb_offset - tvb_previous_offset;
2389 if (more_params == TRUE )
2390 /* Include ',' */
2391 tokenlen++;
2392 switch(token_index){
2393 case MEGACO_REASON_TOKEN:
2394 /* ReasonToken EQUAL VALUE
2395 * VALUE = quotedString / 1*(SafeChar)
2397 item = proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tokenlen,
2398 "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
2400 /* As the reason code ( if a digit ) can be in quoted string or 'just' digit
2401 * look for a nine and hope for the best.
2403 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '9');
2404 if ( tvb_current_offset == -1)
2405 break;
2407 tvb_get_nstringz0(tvb,tvb_current_offset,4,ServiceChangeReason_str);
2408 reason = atoi(ServiceChangeReason_str);
2410 proto_item_append_text(item,"[ %s ]", val_to_str(reason, MEGACO_ServiceChangeReasons_vals,"Unknown (%u)"));
2411 break;
2412 case MEGACO_DELAY_TOKEN:
2413 case MEGACO_SC_ADDR_TOKEN:
2414 case MEGACO_MGC_ID_TOKEN:
2415 case MEGACO_PROFILE_TOKEN:
2416 case MEGACO_VERSION_TOKEN:
2417 case MEGACO_METHOD_TOKEN:
2418 /* No special dissection: fall trough */
2419 default:
2420 /* Unknown or:
2421 * extension = extensionParameter parmValue
2422 * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
2424 proto_tree_add_text(megaco_tree, tvb, tvb_previous_offset, tokenlen,
2425 "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
2426 break;
2429 tvb_previous_offset = tvb_offset +1;
2431 }/*End while */
2433 /* extension = extensionParameter parmValue
2434 * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
2438 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2439 proto_tree_add_string(megaco_tree_command_line, hf_megaco_servicechange_descriptor, tvb,
2440 tvb_previous_offset, tokenlen,
2441 tvb_format_text(tvb, tvb_previous_offset,
2442 tokenlen));
2444 proto_tree_add_text(megaco_tree, tvb, tvb_RBRKT, 1,"%s", tvb_format_text(tvb, tvb_RBRKT, 1));
2447 static void
2448 dissect_megaco_digitmapdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2451 gint tokenlen;
2453 tokenlen = tvb_RBRKT - tvb_previous_offset;
2454 proto_tree_add_string(megaco_tree_command_line, hf_megaco_digitmap_descriptor, tvb,
2455 tvb_previous_offset, tokenlen,
2456 tvb_format_text(tvb, tvb_previous_offset,
2457 tokenlen));
2460 static void
2461 dissect_megaco_statisticsdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2464 gint tokenlen;
2466 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2467 proto_tree_add_string(megaco_tree_command_line, hf_megaco_statistics_descriptor, tvb,
2468 tvb_previous_offset, tokenlen,
2469 tvb_format_text(tvb, tvb_previous_offset,
2470 tokenlen));
2473 static void
2474 dissect_megaco_observedeventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2477 gint tokenlen, pkg_tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
2478 gint tvb_observedevents_end_offset, tvb_LBRKT;
2479 proto_tree *megaco_observedeventsdescriptor_tree, *megaco_observedeventsdescriptor_ti;
2481 gint requested_event_start_offset, requested_event_end_offset, param_start_offset, param_end_offset;
2482 proto_tree *megaco_observedevent_tree, *megaco_observedevent_ti;
2484 requested_event_start_offset = 0;
2485 requested_event_end_offset = 0;
2488 tvb_LBRKT = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2489 tvb_next_offset = tvb_LBRKT;
2490 tokenlen = (tvb_next_offset+1) - tvb_previous_offset;
2493 megaco_observedeventsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_observedevents_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
2494 megaco_observedeventsdescriptor_tree = proto_item_add_subtree(megaco_observedeventsdescriptor_ti, ett_megaco_observedeventsdescriptor);
2497 megaco_observedeventsdescriptor_ti = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
2498 "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
2499 megaco_observedeventsdescriptor_tree = proto_item_add_subtree(megaco_observedeventsdescriptor_ti, ett_megaco_observedeventsdescriptor);
2501 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
2502 tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2504 if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
2506 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2507 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
2509 tokenlen = tvb_help_offset - tvb_current_offset;
2511 proto_tree_add_string(megaco_observedeventsdescriptor_tree, hf_megaco_requestid, tvb,
2512 tvb_current_offset, tokenlen,
2513 tvb_format_text(tvb, tvb_current_offset,
2514 tokenlen));
2516 tvb_observedevents_end_offset = tvb_RBRKT;
2518 tvb_RBRKT = tvb_next_offset+1;
2519 tvb_LBRKT = tvb_next_offset+1;
2520 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
2523 do {
2525 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2526 tvb_observedevents_end_offset, '}');
2527 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
2528 tvb_observedevents_end_offset, '{');
2530 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
2531 tvb_observedevents_end_offset, ',');
2533 if (tvb_current_offset == -1 || tvb_current_offset > tvb_observedevents_end_offset){
2534 tvb_current_offset = tvb_observedevents_end_offset;
2538 /* Descriptor includes no parameters */
2540 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
2542 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2545 /* Descriptor includes Parameters */
2547 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
2549 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
2551 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
2552 tvb_observedevents_end_offset, '{');
2553 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1){
2554 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2555 tvb_observedevents_end_offset, '}');
2561 tvb_LBRKT = tvb_help_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_observedevents_end_offset, '{');
2563 /* if there are eventparameter */
2565 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2567 requested_event_start_offset = tvb_help_offset;
2568 requested_event_end_offset = tvb_RBRKT;
2569 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2570 pkg_tokenlen = tvb_help_offset - tvb_previous_offset;
2571 tokenlen = tvb_LBRKT+1 - tvb_previous_offset;
2573 /* no parameters */
2574 else {
2575 tokenlen = pkg_tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2578 megaco_observedevent_ti = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_previous_offset, tokenlen,
2579 "%s", tvb_format_text(tvb, tvb_previous_offset, tokenlen));
2581 megaco_observedevent_tree = proto_item_add_subtree(megaco_observedevent_ti, ett_megaco_observedevent);
2583 proto_tree_add_item(megaco_observedevent_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,pkg_tokenlen, ENC_ASCII|ENC_NA);
2585 if ( tvb_help_offset < tvb_RBRKT && tvb_help_offset != -1 ){
2587 requested_event_start_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1)-1;
2588 requested_event_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_event_end_offset-1);
2590 tvb_help_offset = requested_event_start_offset;
2592 do {
2593 gchar *msg;
2595 param_start_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset+1);
2597 tvb_help_offset = tvb_find_guint8(tvb, tvb_help_offset+1,requested_event_end_offset, ',');
2599 if ( tvb_help_offset > requested_event_end_offset || tvb_help_offset == -1){
2600 tvb_help_offset = requested_event_end_offset;
2603 param_end_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset-1);
2605 tokenlen = param_end_offset - param_start_offset+1;
2606 msg=tvb_format_text(tvb,param_start_offset, tokenlen);
2607 if(!strncmp("h245", msg, 4)){
2608 dissect_megaco_h245(tvb, pinfo, megaco_tree_command_line, param_start_offset, tokenlen, msg);
2609 } else {
2610 proto_tree_add_text(megaco_tree_command_line, tvb, param_start_offset, tokenlen,
2611 "%s", msg);
2615 } while ( tvb_help_offset < requested_event_end_offset );
2618 tvb_previous_offset = tvb_current_offset;
2619 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
2620 tvb_observedevents_end_offset, ',');
2622 if (tvb_current_offset == -1 || tvb_current_offset > tvb_observedevents_end_offset ){
2623 tvb_current_offset = tvb_observedevents_end_offset;
2625 if (tvb_current_offset < tvb_previous_offset) {
2626 expert_add_info_format(pinfo, megaco_observedevent_ti, &ei_megaco_parse_error, "Parse error: Invalid offset");
2627 return;
2630 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2632 tvb_LBRKT = tvb_previous_offset;
2633 tvb_RBRKT = tvb_previous_offset;
2634 /* Print the trailing '}' */
2635 proto_tree_add_text(megaco_tree_command_line, tvb, tvb_observedevents_end_offset, 1,
2636 "%s", tvb_format_text(tvb, tvb_observedevents_end_offset, 1));
2638 } while ( tvb_current_offset < tvb_observedevents_end_offset );
2641 static void
2642 dissect_megaco_topologydescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2645 gint tokenlen;
2647 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2648 proto_tree_add_string(megaco_tree_command_line, hf_megaco_topology_descriptor, tvb,
2649 tvb_previous_offset, tokenlen,
2650 tvb_format_text_wsp(tvb, tvb_previous_offset,
2651 tokenlen));
2654 static void
2655 dissect_megaco_Packagesdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2658 gint tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
2659 gint tvb_packages_end_offset, tvb_LBRKT;
2660 proto_tree *megaco_packagesdescriptor_tree, *megaco_packagesdescriptor_ti;
2662 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2664 megaco_packagesdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_packages_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_ASCII|ENC_NA);
2665 megaco_packagesdescriptor_tree = proto_item_add_subtree(megaco_packagesdescriptor_ti, ett_megaco_packagesdescriptor);
2669 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '=');
2670 tvb_next_offset = tvb_find_guint8(tvb, tvb_previous_offset, tvb_RBRKT, '{');
2672 if ( tvb_current_offset < tvb_RBRKT && tvb_current_offset != -1 ){
2674 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2675 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
2677 tokenlen = tvb_help_offset - tvb_current_offset;
2679 proto_tree_add_string(megaco_packagesdescriptor_tree, hf_megaco_requestid, tvb,
2680 tvb_current_offset, tokenlen,
2681 tvb_format_text(tvb, tvb_current_offset,
2682 tokenlen));
2684 tvb_packages_end_offset = tvb_RBRKT;
2686 tvb_RBRKT = tvb_next_offset+1;
2687 tvb_LBRKT = tvb_next_offset+1;
2688 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
2691 do {
2693 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2694 tvb_packages_end_offset, '}');
2695 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT,
2696 tvb_packages_end_offset, '{');
2698 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset,
2699 tvb_packages_end_offset, ',');
2701 if (tvb_current_offset == -1 || tvb_current_offset > tvb_packages_end_offset){
2702 tvb_current_offset = tvb_packages_end_offset;
2706 /* Descriptor includes no parameters */
2708 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT == -1 ){
2710 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2713 /* Descriptor includes Parameters */
2715 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT != -1)){
2717 while ( tvb_LBRKT != -1 && tvb_RBRKT > tvb_LBRKT ){
2719 tvb_LBRKT = tvb_find_guint8(tvb, tvb_LBRKT+1,
2720 tvb_packages_end_offset, '{');
2721 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT != -1)
2722 tvb_RBRKT = tvb_find_guint8(tvb, tvb_RBRKT+1,
2723 tvb_packages_end_offset, '}');
2728 tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2730 proto_tree_add_text(megaco_packagesdescriptor_tree, tvb, tvb_previous_offset, tokenlen,
2731 "%s", tvb_format_text(tvb,tvb_previous_offset,
2732 tokenlen));
2735 tvb_current_offset = tvb_find_guint8(tvb, tvb_RBRKT,
2736 tvb_packages_end_offset, ',');
2738 if (tvb_current_offset == -1 || tvb_current_offset > tvb_packages_end_offset ){
2739 tvb_current_offset = tvb_packages_end_offset;
2742 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2744 tvb_LBRKT = tvb_previous_offset;
2745 tvb_RBRKT = tvb_previous_offset;
2747 } while ( tvb_current_offset < tvb_packages_end_offset );
2751 /* The list of error code values is fetched from http://www.iana.org/assignments/megaco-h248 */
2752 /* 2003-08-28 */
2754 static const value_string MEGACO_error_code_vals[] = {
2756 {400, "Syntax error in message"},
2757 {401, "Protocol Error"},
2758 {402, "Unauthorized"},
2759 {403, "Syntax error in transaction request"},
2760 {406, "Version Not Supported"},
2761 {410, "Incorrect identifier"},
2762 {411, "The transaction refers to an unknown ContextId"},
2763 {412, "No ContextIDs available"},
2764 {421, "Unknown action or illegal combination of actions"},
2765 {422, "Syntax Error in Action"},
2766 {430, "Unknown TerminationID"},
2767 {431, "No TerminationID matched a wildcard"},
2768 {432, "Out of TerminationIDs or No TerminationID available"},
2769 {433, "TerminationID is already in a Context"},
2770 {434, "Max number of Terminations in a Context exceeded"},
2771 {435, "Termination ID is not in specified Context"},
2772 {440, "Unsupported or unknown Package"},
2773 {441, "Missing Remote or Local Descriptor"},
2774 {442, "Syntax Error in Command"},
2775 {443, "Unsupported or Unknown Command"},
2776 {444, "Unsupported or Unknown Descriptor"},
2777 {445, "Unsupported or Unknown Property"},
2778 {446, "Unsupported or Unknown Parameter"},
2779 {447, "Descriptor not legal in this command"},
2780 {448, "Descriptor appears twice in a command"},
2781 {450, "No such property in this package"},
2782 {451, "No such event in this package"},
2783 {452, "No such signal in this package"},
2784 {453, "No such statistic in this package"},
2785 {454, "No such parameter value in this package"},
2786 {455, "Property illegal in this Descriptor"},
2787 {456, "Property appears twice in this Descriptor"},
2788 {457, "Missing parameter in signal or event"},
2789 {458, "Unexpected Event/Request ID"},
2790 {459, "Unsupported or Unknown Profile"},
2791 {471, "Implied Add for Multiplex failure"},
2793 {500, "Internal software Failure in MG"},
2794 {501, "Not Implemented"},
2795 {502, "Not ready."},
2796 {503, "Service Unavailable"},
2797 {504, "Command Received from unauthorized entity"},
2798 {505, "Transaction Request Received before a Service Change Reply has been received"},
2799 {506, "Number of Transaction Pendings Exceeded"},
2800 {510, "Insufficient resources"},
2801 {512, "Media Gateway unequipped to detect requested Event"},
2802 {513, "Media Gateway unequipped to generate requested Signals"},
2803 {514, "Media Gateway cannot send the specified announcement"},
2804 {515, "Unsupported Media Type"},
2805 {517, "Unsupported or invalid mode"},
2806 {518, "Event buffer full"},
2807 {519, "Out of space to store digit map"},
2808 {520, "Digit Map undefined in the MG"},
2809 {521, "Termination is ServiceChanging"},
2810 {526, "Insufficient bandwidth"},
2811 {529, "Internal hardware failure in MG"},
2812 {530, "Temporary Network failure"},
2813 {531, "Permanent Network failure"},
2814 {532, "Audited Property, Statistic, Event or Signal does not exist"},
2815 {533, "Response exceeds maximum transport PDU size"},
2816 {534, "Illegal write or read only property"},
2817 {540, "Unexpected initial hook state"},
2818 {581, "Does Not Exist"},
2820 {600, "Illegal syntax within an announcement specification"},
2821 {601, "Variable type not supported"},
2822 {602, "Variable value out of range"},
2823 {603, "Category not supported"},
2824 {604, "Selector type not supported"},
2825 {605, "Selector value not supported"},
2826 {606, "Unknown segment ID"},
2827 {607, "Mismatch between play specification and provisioned data"},
2828 {608, "Provisioning error"},
2829 {609, "Invalid offset"},
2830 {610, "No free segment IDs"},
2831 {611, "Temporary segment not found"},
2832 {612, "Segment in use"},
2833 {613, "ISP port limit overrun"},
2834 {614, "No modems available"},
2835 {615, "Calling number unacceptable"},
2836 {616, "Called number unacceptable"},
2837 { 0, NULL }
2842 static void
2843 dissect_megaco_errordescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, gint tvb_RBRKT, gint tvb_previous_offset)
2846 gint tokenlen;
2847 gint error_code;
2848 guint8 error[4];
2849 gint tvb_current_offset;
2850 proto_item* item;
2851 proto_item* hidden_item;
2853 tvb_current_offset = tvb_find_guint8(tvb, tvb_previous_offset , tvb_RBRKT, '=');
2854 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2855 tvb_get_nstringz0(tvb,tvb_current_offset,4,error);
2856 error_code = atoi(error);
2857 hidden_item = proto_tree_add_string(megaco_tree_command_line, hf_megaco_error_descriptor, tvb,
2858 tvb_current_offset, 3,
2859 tvb_format_text(tvb, tvb_current_offset,
2860 3));
2861 PROTO_ITEM_SET_HIDDEN(hidden_item);
2863 tokenlen = (tvb_RBRKT) - tvb_previous_offset+1;
2866 proto_tree_add_string(megaco_tree_command_line, hf_megaco_error_descriptor, tvb,
2867 tvb_previous_offset, tokenlen,
2868 tvb_format_text(tvb, tvb_previous_offset,
2869 tokenlen));
2871 item = proto_tree_add_text(megaco_tree_command_line, tvb, tvb_current_offset, 3,
2872 "Error code: %s",
2873 val_to_str(error_code, MEGACO_error_code_vals,
2874 "Unknown (%u)"));
2876 PROTO_ITEM_SET_GENERATED(item);
2879 static void
2880 dissect_megaco_TerminationStatedescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree, gint tvb_next_offset, gint tvb_current_offset)
2882 gint tokenlen;
2883 gint tvb_offset;
2884 guint8 tempchar;
2886 proto_tree *megaco_TerminationState_tree, *megaco_TerminationState_ti;
2888 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_next_offset, '=');
2890 tokenlen = tvb_next_offset - tvb_current_offset;
2892 megaco_TerminationState_ti = proto_tree_add_item(megaco_mediadescriptor_tree,hf_megaco_TerminationState_descriptor,tvb,tvb_current_offset,tokenlen, ENC_ASCII|ENC_NA);
2893 megaco_TerminationState_tree = proto_item_add_subtree(megaco_TerminationState_ti, ett_megaco_TerminationState);
2895 megaco_TerminationState_ti = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_current_offset, tokenlen,
2896 "%s", tvb_format_text(tvb, tvb_current_offset, tokenlen));
2897 megaco_TerminationState_tree = proto_item_add_subtree(megaco_TerminationState_ti, ett_megaco_TerminationState);
2899 while ( tvb_offset < tvb_next_offset && tvb_offset != -1 ){
2901 tempchar = tvb_get_guint8(tvb, tvb_current_offset);
2902 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
2903 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
2904 tempchar = tempchar - 0x20;
2906 switch ( tempchar ){
2908 case 'S':
2909 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
2910 if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
2911 tvb_offset = tvb_next_offset;
2914 tokenlen = tvb_offset - tvb_current_offset;
2916 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Service_State, tvb,
2917 tvb_current_offset, tokenlen,
2918 tvb_format_text(tvb, tvb_current_offset,
2919 tokenlen));
2921 break;
2923 case 'B':
2925 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
2926 if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
2927 tvb_offset = tvb_next_offset;
2930 tokenlen = tvb_offset - tvb_current_offset;
2932 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Event_Buffer_Control, tvb,
2933 tvb_current_offset, tokenlen,
2934 tvb_format_text(tvb, tvb_current_offset,
2935 tokenlen));
2937 break;
2939 case 'E':
2940 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
2941 if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
2942 tvb_offset = tvb_next_offset;
2945 tokenlen = tvb_offset - tvb_current_offset;
2947 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Event_Buffer_Control, tvb,
2948 tvb_current_offset, tokenlen,
2949 tvb_format_text(tvb, tvb_current_offset,
2950 tokenlen));
2952 break;
2954 default:
2955 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
2956 if ( tvb_offset == -1 || tvb_offset > tvb_next_offset ){
2957 tvb_offset = tvb_next_offset;
2960 tokenlen = tvb_offset - tvb_current_offset;
2962 proto_tree_add_text(megaco_TerminationState_tree, tvb, tvb_current_offset, tokenlen,
2963 "%s", tvb_format_text(tvb,tvb_current_offset,tokenlen));
2964 break;
2968 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
2969 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_next_offset, '=');
2972 proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_next_offset, 1,
2973 "%s", tvb_format_text(tvb, tvb_next_offset, 1));
2977 static void
2978 dissect_megaco_Localdescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree,packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset)
2980 gint tokenlen;
2981 tvbuff_t *next_tvb;
2983 proto_tree *megaco_localdescriptor_tree, *megaco_localdescriptor_ti;
2985 tokenlen = tvb_next_offset - tvb_current_offset;
2989 megaco_localdescriptor_ti = proto_tree_add_item(megaco_mediadescriptor_tree,hf_megaco_Local_descriptor,tvb,tvb_current_offset,tokenlen, ENC_ASCII|ENC_NA);
2991 megaco_localdescriptor_ti = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_current_offset, tokenlen,
2992 "%s", tvb_format_text(tvb, tvb_current_offset, tokenlen));
2993 megaco_localdescriptor_tree = proto_item_add_subtree(megaco_localdescriptor_ti, ett_megaco_Localdescriptor);
2995 tokenlen = tvb_next_offset - tvb_current_offset;
2996 if ( tokenlen > 3 ){
2997 next_tvb = tvb_new_subset(tvb, tvb_current_offset, tokenlen, tokenlen);
2998 call_dissector(sdp_handle, next_tvb, pinfo, megaco_localdescriptor_tree);
3003 * localControlDescriptor = LocalControlToken LBRKT localParm
3004 * *(COMMA localParm) RBRKT
3005 * ; at-most-once per item
3006 * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
3009 #define MEGACO_MODETOKEN 1
3010 #define MEGACO_RESERVEDVALUETOKEN 2
3011 #define MEGACO_RESERVEDGROUPTOKEN 3
3012 #define MEGACO_H324_H223CAPR 4
3013 #define MEGACO_H324_MUXTBL_IN 5
3014 #define MEGACO_H324_MUXTBL_OUT 6
3015 #define MEGACO_DS_DSCP 7
3016 #define MEGACO_GM_SAF 8
3017 #define MEGACO_GM_SAM 9
3018 #define MEGACO_GM_SPF 10
3019 #define MEGACO_GM_SPR 11
3020 #define MEGACO_GM_ESAS 12
3021 #define MEGACO_GM_LSA 13
3022 #define MEGACO_GM_ESPS 14
3023 #define MEGACO_GM_LSP 15
3024 #define MEGACO_GM_RSB 16
3026 static const megaco_tokens_t megaco_localParam_names[] = {
3027 { "Unknown-token", NULL }, /* 0 Pad so that the real headers start at index 1 */
3028 /* streamMode */
3029 { "Mode", "MO" }, /* 1 */
3030 { "ReservedValue", "RV" }, /* 2 */
3031 { "ReservedGroup", "RG" }, /* 3 */
3032 /* propertyParm = pkgdName parmValue
3033 * Add more package names as needed.
3035 { "h324/h223capr", NULL }, /* 4 */
3036 { "h324/muxtbl_in", NULL }, /* 5 */
3037 { "h324/muxtbl_out", NULL }, /* 6 */
3038 { "ds/dscp", NULL }, /* 7 */
3039 { "gm/saf", NULL }, /* 8 */
3040 { "gm/sam", NULL }, /* 9 */
3041 { "gm/spf", NULL }, /* 10 */
3042 { "gm/spr", NULL }, /* 11 */
3043 { "gm/esas", NULL }, /* 12 */
3044 { "gm/lsa", NULL }, /* 13 */
3045 { "gm/esps", NULL }, /* 14 */
3046 { "gm/lsp", NULL }, /* 15 */
3047 { "gm/rsb", NULL }, /* 16 */
3050 /* Returns index of megaco_tokens_t */
3051 static gint find_megaco_localParam_names(tvbuff_t *tvb, int offset, guint header_len)
3053 guint i;
3055 for (i = 1; i < array_length(megaco_localParam_names); i++) {
3056 if (header_len == strlen(megaco_localParam_names[i].name) &&
3057 tvb_strncaseeql(tvb, offset, megaco_localParam_names[i].name, header_len) == 0)
3058 return i;
3059 if (megaco_localParam_names[i].compact_name != NULL &&
3060 header_len == strlen(megaco_localParam_names[i].compact_name) &&
3061 tvb_strncaseeql(tvb, offset, megaco_localParam_names[i].compact_name, header_len) == 0)
3062 return i;
3065 return -1;
3068 static void
3069 dissect_megaco_LocalControldescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree, packet_info *pinfo, gint tvb_next_offset, gint tvb_current_offset)
3071 gint tokenlen;
3072 guint token_name_len;
3073 gint tvb_offset,tvb_help_offset;
3074 gint token_index = 0;
3075 gchar *msg;
3076 proto_item* item;
3077 guint8 code_str[3];
3079 /*proto_tree *megaco_LocalControl_tree, *megaco_LocalControl_ti; */
3081 tvb_offset = 0;
3084 tokenlen = tvb_next_offset - tvb_current_offset;
3086 megaco_LocalControl_ti = proto_tree_add_item(megaco_mediadescriptor_tree,hf_megaco_LocalControl_descriptor,tvb,tvb_current_offset,tokenlen, ENC_ASCII|ENC_NA);
3087 megaco_LocalControl_tree = proto_item_add_subtree(megaco_LocalControl_ti, ett_megaco_LocalControldescriptor);
3089 while ( tvb_offset < tvb_next_offset && tvb_offset != -1 ){
3091 tvb_help_offset = tvb_current_offset;
3094 * Find local parameter name
3095 * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
3096 * pkgdName = (PackageName SLASH ItemID) ;specific item
3097 * / (PackageName SLASH "*") ;all events in package
3098 * / ("*" SLASH "*") ; all events supported by the MG
3100 /* Find token length */
3101 for (tvb_offset=tvb_current_offset; tvb_offset < tvb_next_offset; tvb_offset++){
3102 guint8 octet;
3103 octet = tvb_get_guint8(tvb, tvb_offset);
3104 if (!isalnum(octet)){
3105 if ((octet!='/')&&(octet!='_')){
3106 break;
3110 token_name_len = tvb_offset - tvb_current_offset;
3111 /* Debug Code
3112 proto_tree_add_text(megaco_LocalControl_tree, tvb, tvb_current_offset, token_name_len,
3113 "%s", tvb_format_text(tvb,tvb_current_offset,token_name_len));
3116 token_index = find_megaco_localParam_names(tvb, tvb_current_offset, token_name_len);
3117 /* Find start of parameter value */
3118 tvb_offset = tvb_find_guint8(tvb, tvb_offset , tvb_next_offset, '=');
3119 if (tvb_offset == -1)
3120 THROW(ReportedBoundsError);
3121 /* Start search after '=' in case there is no SP*/
3122 tvb_offset++;
3123 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
3125 /* find if there are more parameters or not */
3126 tvb_offset = tvb_find_guint8(tvb, tvb_current_offset , tvb_offset, ',');
3127 if ( tvb_offset < 0 || tvb_offset > tvb_next_offset ){
3128 tvb_offset = tvb_next_offset;
3131 tokenlen = megaco_tvb_skip_wsp_return(tvb,tvb_offset-1) - tvb_current_offset;
3132 /* Debug Code
3133 proto_tree_add_text(megaco_LocalControl_tree, tvb, tvb_current_offset, tokenlen,
3134 "%s", tvb_format_text(tvb,tvb_current_offset,tokenlen));
3137 switch ( token_index ){
3139 case MEGACO_MODETOKEN: /* Mode */
3140 proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_mode, tvb,
3141 tvb_current_offset, tokenlen,
3142 tvb_format_text(tvb, tvb_current_offset,
3143 tokenlen));
3144 col_append_fstr(pinfo->cinfo, COL_INFO, " (Mode:%s)",tvb_format_text(tvb, tvb_current_offset,tokenlen));
3145 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3146 break;
3148 case MEGACO_RESERVEDVALUETOKEN: /* ReservedValue */
3149 proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_reserve_value, tvb,
3150 tvb_current_offset, tokenlen,
3151 tvb_format_text(tvb, tvb_current_offset,
3152 tokenlen));
3154 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3155 break;
3156 case MEGACO_RESERVEDGROUPTOKEN: /* ReservedGroup */
3157 proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_reserve_group, tvb,
3158 tvb_current_offset, tokenlen,
3159 tvb_format_text(tvb, tvb_current_offset,
3160 tokenlen));
3161 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3162 break;
3164 case MEGACO_H324_H223CAPR: /* h324/h223capr */
3165 proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_h324_h223capr, tvb,
3166 tvb_current_offset, tokenlen,
3167 tvb_format_text(tvb, tvb_current_offset,
3168 tokenlen));
3170 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3171 tokenlen = tvb_offset - tvb_help_offset;
3172 msg=tvb_format_text(tvb,tvb_help_offset, tokenlen);
3173 dissect_megaco_h324_h223caprn(tvb, pinfo, megaco_mediadescriptor_tree, tvb_help_offset, tokenlen, msg);
3175 break;
3177 case MEGACO_H324_MUXTBL_IN: /* h324/muxtbl_in */
3179 proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_h324_muxtbl_in, tvb,
3180 tvb_current_offset, tokenlen,
3181 tvb_format_text(tvb, tvb_current_offset,
3182 tokenlen));
3184 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3186 tokenlen = tvb_offset - tvb_help_offset;
3187 msg=tvb_format_text(tvb,tvb_help_offset, tokenlen);
3188 /* Call the existing routine with tree = NULL to avoid an entry to the tree */
3189 dissect_megaco_h245(tvb, pinfo, NULL, tvb_help_offset, tokenlen, msg);
3191 break;
3193 case MEGACO_H324_MUXTBL_OUT:
3195 proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_h324_muxtbl_out, tvb,
3196 tvb_current_offset, tokenlen,
3197 tvb_format_text(tvb, tvb_current_offset,
3198 tokenlen));
3200 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3202 tokenlen = tvb_offset - tvb_help_offset;
3203 msg=tvb_format_text(tvb,tvb_help_offset, tokenlen);
3204 /* Call the existing routine with tree = NULL to avoid an entry to the tree */
3205 dissect_megaco_h245(tvb, pinfo, NULL, tvb_help_offset, tokenlen, msg);
3207 break;
3209 case MEGACO_DS_DSCP:
3210 item = proto_tree_add_string(megaco_mediadescriptor_tree, hf_megaco_ds_dscp, tvb,
3211 tvb_current_offset, tokenlen,
3212 tvb_format_text(tvb, tvb_current_offset,
3213 tokenlen));
3215 tvb_get_nstringz0(tvb,tvb_current_offset,3,code_str);
3216 proto_item_append_text(item,"[ %s ]",
3217 val_to_str_ext((guint32)strtoul(code_str,NULL,16), &dscp_vals_ext,"Unknown (%u)"));
3219 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3220 break;
3222 case MEGACO_GM_SAF:
3223 tokenlen = tvb_offset - tvb_help_offset;
3224 item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
3225 "%s", tvb_format_text(tvb,tvb_help_offset,
3226 tokenlen));
3227 proto_item_append_text(item," [Remote Source Address Filtering]");
3228 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3229 break;
3230 case MEGACO_GM_SAM:
3231 tokenlen = tvb_offset - tvb_help_offset;
3232 item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
3233 "%s", tvb_format_text(tvb,tvb_help_offset,
3234 tokenlen));
3235 proto_item_append_text(item," [Remote Source Address Mask]");
3236 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3237 break;
3238 case MEGACO_GM_SPF:
3239 tokenlen = tvb_offset - tvb_help_offset;
3240 item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
3241 "%s", tvb_format_text(tvb,tvb_help_offset,
3242 tokenlen));
3243 proto_item_append_text(item," [Remote Source Port Filtering]");
3244 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3245 break;
3246 case MEGACO_GM_SPR:
3247 tokenlen = tvb_offset - tvb_help_offset;
3248 item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
3249 "%s", tvb_format_text(tvb,tvb_help_offset,
3250 tokenlen));
3251 proto_item_append_text(item," [Remote Source Port Range]");
3252 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3253 break;
3254 case MEGACO_GM_ESAS:
3255 tokenlen = tvb_offset - tvb_help_offset;
3256 item = proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
3257 "%s", tvb_format_text(tvb,tvb_help_offset,
3258 tokenlen));
3259 proto_item_append_text(item," [Explicit Source Address Setting]");
3260 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3261 break;
3262 default:
3263 tokenlen = tvb_offset - tvb_help_offset;
3264 proto_tree_add_text(megaco_mediadescriptor_tree, tvb, tvb_help_offset, tokenlen,
3265 "%s", tvb_format_text(tvb,tvb_help_offset,
3266 tokenlen));
3267 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3269 break;
3273 /* Copied from MGCP dissector, prints whole message in raw text */
3275 static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree){
3277 gint tvb_linebegin,tvb_lineend,tvb_len,linelen;
3279 tvb_linebegin = 0;
3280 tvb_len = tvb_length(tvb);
3282 proto_tree_add_text(tree, tvb, 0, -1,"-------------- (RAW text output) ---------------");
3284 do {
3285 linelen = tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend,FALSE);
3286 proto_tree_add_text(tree, tvb, tvb_linebegin, linelen,
3287 "%s", tvb_format_text_wsp(tvb,tvb_linebegin,
3288 linelen));
3289 tvb_linebegin = tvb_lineend;
3290 } while ( tvb_lineend < tvb_len );
3294 * megaco_tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
3295 * character following offset or offset + maxlength -1 whichever
3296 * is smaller.
3298 * Parameters:
3299 * tvb - The tvbuff in which we are skipping whitespaces, tab and end_of_line characters.
3300 * offset - The offset in tvb from which we begin trying to skip whitespace.
3302 * Returns: The position in tvb of the first non-whitespace
3304 static gint megaco_tvb_skip_wsp(tvbuff_t* tvb, gint offset ){
3305 gint counter = offset;
3306 gint end,tvb_len;
3307 guint8 tempchar;
3308 tvb_len = tvb_length(tvb);
3309 end = tvb_len;
3311 for(counter = offset; counter < end &&
3312 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
3313 tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter++);
3314 return (counter);
3317 static gint megaco_tvb_skip_wsp_return(tvbuff_t* tvb, gint offset){
3318 gint counter = offset;
3319 gint end;
3320 guint8 tempchar;
3321 end = 0;
3323 for(counter = offset; counter > end &&
3324 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
3325 tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter--);
3326 counter++;
3327 return (counter);
3330 static gint megaco_tvb_find_token(tvbuff_t* tvb, gint offset, gint maxlength){
3331 gint counter = 0;
3332 gint pos = offset;
3333 guchar needle;
3335 do {
3336 pos = tvb_pbrk_guint8(tvb, pos + 1, maxlength, "{}", &needle);
3337 if(pos == -1)
3338 return -1;
3339 switch(needle){
3340 case '{':
3341 counter++;
3342 break;
3343 case '}':
3344 counter--;
3345 break;
3346 default:
3347 break;
3349 } while (counter>0);
3350 if(counter<0)
3351 return -1;
3352 else
3354 pos = megaco_tvb_skip_wsp(tvb,pos+1);
3355 return pos;
3359 void proto_reg_handoff_megaco(void);
3361 void
3362 proto_register_megaco(void)
3364 static hf_register_info hf[] = {
3365 { &hf_megaco_audititem,
3366 { "Audit Item", "megaco.audititem", FT_STRING, BASE_NONE, NULL, 0x0,
3367 "Identity of item to be audited", HFILL }},
3368 { &hf_megaco_audit_descriptor,
3369 { "Audit Descriptor", "megaco.audit", FT_NONE, BASE_NONE, NULL, 0x0,
3370 "Audit Descriptor of the megaco Command", HFILL }},
3371 #if 0
3372 { &hf_megaco_command_line,
3373 { "Command line", "megaco.command_line", FT_STRING, BASE_NONE, NULL, 0x0,
3374 "Commands of this message", HFILL }},
3375 #endif
3376 { &hf_megaco_command,
3377 { "Command", "megaco.command", FT_STRING, BASE_NONE, NULL, 0x0,
3378 "Command of this message", HFILL }},
3379 { &hf_megaco_Context,
3380 { "Context", "megaco.context", FT_STRING, BASE_NONE, NULL, 0x0,
3381 "Context ID of this message", HFILL }},
3382 { &hf_megaco_digitmap_descriptor,
3383 { "DigitMap Descriptor", "megaco.digitmap", FT_STRING, BASE_NONE, NULL, 0x0,
3384 "DigitMap Descriptor of the megaco Command", HFILL }},
3385 { &hf_megaco_error_descriptor,
3386 { "ERROR Descriptor", "megaco.error", FT_STRING, BASE_NONE, NULL, 0x0,
3387 "Error Descriptor of the megaco Command", HFILL }},
3388 { &hf_megaco_error_Frame,
3389 { "ERROR frame", "megaco.error_frame", FT_STRING, BASE_NONE, NULL, 0x0,
3390 "Syntax error", HFILL }},
3391 { &hf_megaco_Event_Buffer_Control,
3392 { "Event Buffer Control", "megaco.eventbuffercontrol", FT_STRING, BASE_NONE, NULL, 0x0,
3393 "Event Buffer Control in Termination State Descriptor", HFILL }},
3394 #if 0
3395 { &hf_megaco_events_descriptor,
3396 { "Events Descriptor", "megaco.events", FT_STRING, BASE_NONE, NULL, 0x0,
3397 "Events Descriptor of the megaco Command", HFILL }},
3398 #endif
3399 #if 0
3400 { &hf_megaco_Local_descriptor,
3401 { "Local Descriptor", "megaco.localdescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
3402 "Local Descriptor in Media Descriptor", HFILL }},
3403 #endif
3404 #if 0
3405 { &hf_megaco_LocalControl_descriptor,
3406 { "Local Control Descriptor", "megaco.localcontroldescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
3407 "Local Control Descriptor in Media Descriptor", HFILL }},
3408 #endif
3409 #if 0
3410 { &hf_megaco_media_descriptor,
3411 { "Media Descriptor", "megaco.media", FT_STRING, BASE_NONE, NULL, 0x0,
3412 "Media Descriptor of the megaco Command", HFILL }},
3413 #endif
3414 { &hf_megaco_modem_descriptor,
3415 { "Modem Descriptor", "megaco.modem", FT_STRING, BASE_NONE, NULL, 0x0,
3416 "Modem Descriptor of the megaco Command", HFILL }},
3417 { &hf_megaco_mode,
3418 { "Mode", "megaco.mode", FT_STRING, BASE_NONE, NULL, 0x0,
3419 "Mode sendonly/receiveonly/inactive/loopback", HFILL }},
3420 { &hf_megaco_multiplex_descriptor,
3421 { "Multiplex Descriptor", "megaco.multiplex", FT_STRING, BASE_NONE, NULL, 0x0,
3422 "Multiplex Descriptor of the megaco Command", HFILL }},
3423 #if 0
3424 { &hf_megaco_observedevents_descriptor,
3425 { "Observed Events Descriptor", "megaco.observedevents", FT_STRING, BASE_NONE, NULL, 0x0,
3426 "Observed Events Descriptor of the megaco Command", HFILL }},
3427 #endif
3428 { &hf_megaco_packages_descriptor,
3429 { "Packages Descriptor", "megaco.packagesdescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
3430 NULL, HFILL }},
3431 { &hf_megaco_pkgdname,
3432 { "pkgdName", "megaco.pkgdname", FT_STRING, BASE_NONE, NULL, 0x0,
3433 "PackageName SLASH ItemID", HFILL }},
3434 #if 0
3435 { &hf_megaco_Remote_descriptor,
3436 { "Remote Descriptor", "megaco.remotedescriptor", FT_STRING, BASE_NONE, NULL, 0x0,
3437 "Remote Descriptor in Media Descriptor", HFILL }},
3438 #endif
3439 { &hf_megaco_reserve_group,
3440 { "Reserve Group", "megaco.reservegroup", FT_STRING, BASE_NONE, NULL, 0x0,
3441 "Reserve Group on or off", HFILL }},
3442 { &hf_megaco_h324_muxtbl_in,
3443 { "h324/muxtbl_in", "megaco.h324_muxtbl_in", FT_STRING, BASE_NONE, NULL, 0x0,
3444 NULL, HFILL }},
3445 { &hf_megaco_h324_muxtbl_out,
3446 { "h324/muxtbl_out", "megaco.h324_muxtbl_out", FT_STRING, BASE_NONE, NULL, 0x0,
3447 NULL, HFILL }},
3448 { &hf_megaco_ds_dscp,
3449 { "ds/dscp", "megaco.ds_dscp", FT_STRING, BASE_NONE, NULL, 0x0,
3450 "ds/dscp Differentiated Services Code Point", HFILL }},
3451 { &hf_megaco_h324_h223capr,
3452 { "h324/h223capr", "megaco.h324_h223capr", FT_STRING, BASE_NONE, NULL, 0x0,
3453 NULL, HFILL }},
3454 { &hf_megaco_reserve_value,
3455 { "Reserve Value", "megaco.reservevalue", FT_STRING, BASE_NONE, NULL, 0x0,
3456 "Reserve Value on or off", HFILL }},
3457 { &hf_megaco_requestid,
3458 { "RequestID", "megaco.requestid", FT_STRING, BASE_NONE, NULL, 0x0,
3459 "RequestID in Events or Observedevents Descriptor", HFILL }},
3460 #if 0
3461 { &hf_megaco_servicechange_descriptor,
3462 { "Service Change Descriptor", "megaco.servicechange", FT_STRING, BASE_NONE, NULL, 0x0,
3463 "Service Change Descriptor of the megaco Command", HFILL }},
3464 #endif
3465 { &hf_megaco_Service_State,
3466 { "Service State", "megaco.servicestates", FT_STRING, BASE_NONE, NULL, 0x0,
3467 "Service States in Termination State Descriptor", HFILL }},
3468 #if 0
3469 { &hf_megaco_signal_descriptor,
3470 { "Signal Descriptor", "megaco.signal", FT_STRING, BASE_NONE, NULL, 0x0,
3471 "Signal Descriptor of the megaco Command", HFILL }},
3472 #endif
3473 { &hf_megaco_statistics_descriptor,
3474 { "Statistics Descriptor", "megaco.statistics", FT_STRING, BASE_NONE, NULL, 0x0,
3475 "Statistics Descriptor of the megaco Command", HFILL }},
3476 { &hf_megaco_streamid,
3477 { "StreamID", "megaco.streamid", FT_STRING, BASE_NONE, NULL, 0x0,
3478 "StreamID in the Media Descriptor", HFILL }},
3479 { &hf_megaco_termid,
3480 { "Termination ID", "megaco.termid", FT_STRING, BASE_NONE, NULL, 0x0,
3481 "Termination ID of this Command", HFILL }},
3482 #if 0
3483 { &hf_megaco_TerminationState_descriptor,
3484 { "Termination State Descriptor", "megaco.terminationstate", FT_STRING, BASE_NONE, NULL, 0x0,
3485 "Termination State Descriptor in Media Descriptor", HFILL }},
3486 #endif
3487 { &hf_megaco_topology_descriptor,
3488 { "Topology Descriptor", "megaco.topology", FT_STRING, BASE_NONE, NULL, 0x0,
3489 "Topology Descriptor of the megaco Command", HFILL }},
3490 { &hf_megaco_transaction,
3491 { "Transaction", "megaco.transaction", FT_STRING, BASE_NONE, NULL, 0x0,
3492 "Message Originator", HFILL }},
3493 { &hf_megaco_transid,
3494 { "Transaction ID", "megaco.transid", FT_STRING, BASE_NONE, NULL, 0x0,
3495 "Transaction ID of this message", HFILL }},
3496 { &hf_megaco_mId,
3497 { "MediagatewayID", "megaco.mId", FT_STRING, BASE_NONE, NULL, 0x0,
3498 "Mediagateway ID", HFILL }},
3499 { &hf_megaco_version,
3500 { "Version", "megaco.version", FT_STRING, BASE_NONE, NULL, 0x0,
3501 NULL, HFILL }},
3502 #if 0
3503 { &hf_megaco_h245,
3504 { "h245", "megaco.h245", FT_STRING, BASE_NONE, NULL, 0x0,
3505 "Embedded H.245 message", HFILL }},
3506 #endif
3507 { &hf_megaco_h223Capability,
3508 { "h223Capability", "megaco.h245.h223Capability", FT_NONE, BASE_NONE, NULL, 0,
3509 "megaco.h245.H223Capability", HFILL }},
3511 GCP_HF_ARR_ELEMS("megaco",megaco_ctx_ids),
3513 /* Add more fields here */
3515 static gint *ett[] = {
3516 &ett_megaco,
3517 &ett_megaco_message,
3518 &ett_megaco_message_body,
3519 &ett_megaco_context,
3520 &ett_megaco_command_line,
3521 &ett_megaco_descriptors,
3522 &ett_megaco_mediadescriptor,
3523 &ett_megaco_TerminationState,
3524 &ett_megaco_Remotedescriptor,
3525 &ett_megaco_Localdescriptor,
3526 &ett_megaco_LocalControldescriptor,
3527 &ett_megaco_auditdescriptor,
3528 &ett_megaco_eventsdescriptor,
3529 &ett_megaco_observedeventsdescriptor,
3530 &ett_megaco_observedevent,
3531 &ett_megaco_packagesdescriptor,
3532 &ett_megaco_requestedevent,
3533 &ett_megaco_signalsdescriptor,
3534 &ett_megaco_requestedsignal,
3535 &ett_megaco_h245,
3536 GCP_ETT_ARR_ELEMS(megaco_ctx_ids),
3539 static ei_register_info ei[] = {
3540 { &ei_megaco_errored_command, { "megaco.errored_command", PI_RESPONSE_CODE, PI_WARN, "Errored Command", EXPFILL }},
3541 { &ei_megaco_parse_error, { "megaco.parse_error", PI_MALFORMED, PI_ERROR, "Parse error", EXPFILL }},
3542 { &ei_megaco_error_descriptor_transaction_list, { "megaco.error_descriptor_transaction_list.invalid", PI_MALFORMED, PI_ERROR, "Sorry, can't understand errorDescriptor / transactionList", EXPFILL }},
3543 { &ei_megaco_audit_descriptor, { "megaco.audit.malformed", PI_MALFORMED, PI_ERROR, "Badly constructed audit descriptor (no { )", EXPFILL }},
3546 module_t *megaco_module;
3547 expert_module_t* expert_megaco;
3549 proto_megaco = proto_register_protocol("MEGACO",
3550 "MEGACO", "megaco");
3552 register_dissector("megaco", dissect_megaco_text, proto_megaco);
3554 proto_register_field_array(proto_megaco, hf, array_length(hf));
3555 proto_register_subtree_array(ett, array_length(ett));
3556 expert_megaco = expert_register_protocol(proto_megaco);
3557 expert_register_field_array(expert_megaco, ei, array_length(ei));
3559 /* Register our configuration options, particularly our ports */
3561 megaco_module = prefs_register_protocol(proto_megaco, proto_reg_handoff_megaco);
3563 prefs_register_uint_preference(megaco_module, "sctp.txt_port",
3564 "MEGACO Text SCTP Port",
3565 "Set the SCTP port for MEGACO text messages",
3566 10, &global_megaco_txt_sctp_port);
3568 prefs_register_uint_preference(megaco_module, "tcp.txt_port",
3569 "MEGACO Text TCP Port",
3570 "Set the TCP port for MEGACO text messages",
3571 10, &global_megaco_txt_tcp_port);
3573 prefs_register_uint_preference(megaco_module, "udp.txt_port",
3574 "MEGACO Text UDP Port",
3575 "Set the UDP port for MEGACO text messages",
3576 10, &global_megaco_txt_udp_port);
3578 #if 0
3579 prefs_register_uint_preference(megaco_module, "sctp.bin_port",
3580 "MEGACO Binary SCTP Port",
3581 "Set the SCTP port for MEGACO binary messages",
3582 10, &global_megaco_bin_sctp_port);
3584 prefs_register_uint_preference(megaco_module, "tcp.bin_port",
3585 "MEGACO Binary TCP Port",
3586 "Set the TCP port for MEGACO binary messages",
3587 10, &global_megaco_bin_tcp_port);
3589 prefs_register_uint_preference(megaco_module, "udp.bin_port",
3590 "MEGACO Binary UDP Port",
3591 "Set the UDP port for MEGACO binary messages",
3592 10, &global_megaco_bin_udp_port);
3593 #endif
3595 prefs_register_bool_preference(megaco_module, "display_raw_text",
3596 "Display raw text for MEGACO message",
3597 "Specifies that the raw text of the "
3598 "MEGACO message should be displayed "
3599 "instead of (or in addition to) the "
3600 "dissection tree",
3601 &global_megaco_raw_text);
3603 prefs_register_bool_preference(megaco_module, "display_dissect_tree",
3604 "Display tree dissection for MEGACO message",
3605 "Specifies that the dissection tree of the "
3606 "MEGACO message should be displayed "
3607 "instead of (or in addition to) the "
3608 "raw text",
3609 &global_megaco_dissect_tree);
3610 prefs_register_bool_preference(megaco_module, "ctx_info",
3611 "Track Context",
3612 "Maintain relationships between transactions and contexts "
3613 "and display an extra tree showing context data",
3614 &keep_persistent_data);
3616 megaco_tap = register_tap("megaco");
3620 /* Register all the bits needed with the filtering engine */
3621 /* The registration hand-off routine */
3622 void
3623 proto_reg_handoff_megaco(void)
3625 static gboolean megaco_prefs_initialized = FALSE;
3626 static dissector_handle_t megaco_text_tcp_handle;
3628 * Variables to allow for proper deletion of dissector registration when
3629 * the user changes port from the gui.
3631 static guint txt_sctp_port;
3632 static guint txt_tcp_port;
3633 static guint txt_udp_port;
3634 #if 0
3635 static guint bin_sctp_port;
3636 static guint bin_tcp_port;
3637 static guint bin_udp_port;
3638 #endif
3640 if (!megaco_prefs_initialized) {
3641 sdp_handle = find_dissector("sdp");
3642 h245_handle = find_dissector("h245dg");
3643 h248_handle = find_dissector("h248");
3644 h248_otp_handle = find_dissector("h248_otp");
3645 data_handle = find_dissector("data");
3647 megaco_text_handle = find_dissector("megaco");
3648 megaco_text_tcp_handle = create_dissector_handle(dissect_megaco_text_tcp, proto_megaco);
3650 dissector_add_uint("sctp.ppi", H248_PAYLOAD_PROTOCOL_ID, megaco_text_handle);
3652 megaco_prefs_initialized = TRUE;
3653 } else {
3654 dissector_delete_uint("sctp.port", txt_sctp_port, megaco_text_handle);
3655 dissector_delete_uint("tcp.port", txt_tcp_port, megaco_text_tcp_handle);
3656 dissector_delete_uint("udp.port", txt_udp_port, megaco_text_handle);
3659 /* Set our port number for future use */
3661 txt_sctp_port = global_megaco_txt_sctp_port;
3662 txt_tcp_port = global_megaco_txt_tcp_port;
3663 txt_udp_port = global_megaco_txt_udp_port;
3665 dissector_add_uint("sctp.port", global_megaco_txt_sctp_port, megaco_text_handle);
3666 dissector_add_uint("tcp.port", global_megaco_txt_tcp_port, megaco_text_tcp_handle);
3667 dissector_add_uint("udp.port", global_megaco_txt_udp_port, megaco_text_handle);