Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-megaco.c
Warning:line 2768, column 5
Value stored to 'tvb_LBRKT_found' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-megaco.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-01-29-100357-3623-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-megaco.c
1/* packet-megaco.c
2 * Routines for megaco packet disassembly
3 * RFC 3015
4 *
5 * Christian Falckenberg, 2002/10/17
6 * Copyright (c) 2002 by Christian Falckenberg
7 * <[email protected]>
8 *
9 * Christoph Wiest, 2003/06/28
10 * Modified 2003 by Christoph Wiest
11 * <[email protected]>
12 * Modified 2004 by Anders Broman
13 * <[email protected]>
14 * To handle TPKT headers if over TCP
15 * Modified 2005 by Karl Knoebl
16 * <[email protected]>
17 * provide info to COL_INFO and some "prettification"
18 *
19 * Copyright (c) 2006 Anders Broman <[email protected]>
20 *
21 * Wireshark - Network traffic analyzer
22 * By Gerald Combs <[email protected]>
23 * Copyright 1999 Gerald Combs
24 *
25 * SPDX-License-Identifier: GPL-2.0-or-later
26 */
27
28
29#include "config.h"
30
31#include <stdlib.h>
32
33#include <epan/packet.h>
34#include <epan/tap.h>
35#include <epan/rtd_table.h>
36#include <epan/prefs.h>
37#include <epan/prefs-int.h>
38#include <epan/exported_pdu.h>
39#include <epan/asn1.h>
40#include <epan/charsets.h>
41#include <epan/unit_strings.h>
42
43#include <wsutil/array.h>
44#include <wsutil/strtoi.h>
45#include "packet-ber.h"
46#include "packet-tpkt.h"
47#include "packet-h245.h"
48#include "packet-h248.h"
49#include "packet-ip.h"
50#include "packet-media-type.h"
51#include "packet-sdp.h"
52#include "packet-sctp.h"
53
54void proto_register_megaco(void);
55void proto_reg_handoff_megaco(void);
56
57#define PORT_MEGACO_TXT2944 2944
58#define PORT_MEGACO_BIN2945 2945
59
60static pref_t *sip_hide_generated_call_ids;
61
62
63/* Define the megaco proto */
64static int proto_megaco;
65
66/* Define headers for megaco */
67static int hf_megaco_start;
68static int hf_megaco_version;
69static int hf_megaco_transaction;
70static int hf_megaco_transid;
71static int hf_megaco_Context;
72static int hf_megaco_Context_generated;
73/* static int hf_megaco_command_line; */
74static int hf_megaco_command;
75static int hf_megaco_command_optional;
76static int hf_megaco_wildcard_response;
77static int hf_megaco_termid;
78
79
80
81/* Define headers in subtree for megaco */
82static int hf_megaco_modem_descriptor;
83static int hf_megaco_multiplex_descriptor;
84static int hf_megaco_media_descriptor;
85static int hf_megaco_Local_descriptor;
86static int hf_megaco_events_descriptor;
87static int hf_megaco_signal_descriptor;
88static int hf_megaco_audit_descriptor;
89/* static int hf_megaco_servicechange_descriptor; */
90static int hf_megaco_digitmap_descriptor;
91static int hf_megaco_statistics_descriptor;
92static int hf_megaco_observedevents_descriptor;
93static int hf_megaco_topology_descriptor;
94static int hf_megaco_error_descriptor;
95static int hf_megaco_error_code;
96static int hf_megaco_error_string;
97static int hf_megaco_TerminationState_descriptor;
98static int hf_megaco_Remote_descriptor;
99static int hf_megaco_LocalControl_descriptor;
100static int hf_megaco_packages_descriptor;
101static int hf_megaco_Service_State;
102static int hf_megaco_Event_Buffer_Control;
103static int hf_megaco_mode;
104static int hf_megaco_reserve_group;
105static int hf_megaco_h324_muxtbl_in;
106static int hf_megaco_h324_muxtbl_out;
107static int hf_megaco_ds_dscp;
108static int hf_megaco_gm_saf;
109static int hf_megaco_gm_sam;
110static int hf_megaco_gm_spf;
111static int hf_megaco_gm_spr;
112static int hf_megaco_gm_esas;
113static int hf_megaco_tman_pol;
114static int hf_megaco_gm_rsb;
115static int hf_megaco_tman_sdr;
116static int hf_megaco_tman_mbs;
117static int hf_megaco_tman_pdr;
118static int hf_megaco_tman_dvt;
119static int hf_megaco_ipdc_realm;
120static int hf_megaco_h324_h223capr;
121static int hf_megaco_reserve_value;
122static int hf_megaco_streamid;
123static int hf_megaco_requestid;
124static int hf_megaco_pkgdname;
125static int hf_megaco_mId;
126static int hf_megaco_h245;
127static int hf_megaco_h223Capability;
128static int hf_megaco_audititem;
129static int hf_megaco_priority;
130
131/* Define the trees for megaco */
132static int ett_megaco;
133static int ett_megaco_message;
134static int ett_megaco_message_body;
135static int ett_megaco_context;
136static int ett_megaco_command_line;
137static int ett_megaco_mediadescriptor;
138static int ett_megaco_descriptors;
139static int ett_megaco_raw_text;
140static int ett_megaco_error_descriptor;
141static int ett_megaco_TerminationState;
142static int ett_megaco_Localdescriptor;
143static int ett_megaco_Remotedescriptor;
144static int ett_megaco_LocalControldescriptor;
145static int ett_megaco_auditdescriptor;
146static int ett_megaco_eventsdescriptor;
147static int ett_megaco_statisticsdescriptor;
148static int ett_megaco_observedeventsdescriptor;
149static int ett_megaco_observedevent;
150static int ett_megaco_packagesdescriptor;
151static int ett_megaco_requestedevent;
152static int ett_megaco_signalsdescriptor;
153static int ett_megaco_requestedsignal;
154static int ett_megaco_h245;
155
156static gcp_hf_ett_t megaco_ctx_ids;
157
158static expert_field ei_megaco_errored_command;
159static expert_field ei_megaco_no_command;
160static expert_field ei_megaco_no_descriptor;
161static expert_field ei_megaco_error_descriptor_transaction_list;
162static expert_field ei_megaco_parse_error;
163static expert_field ei_megaco_audit_descriptor;
164static expert_field ei_megaco_signal_descriptor;
165static expert_field ei_megaco_reason_invalid;
166static expert_field ei_megaco_error_code_invalid;
167static expert_field ei_megaco_invalid_sdr;
168
169static dissector_handle_t megaco_text_handle;
170
171static int megaco_tap;
172static int exported_pdu_tap = -1;
173
174
175/* patterns used for tvb_ws_mempbrk_pattern_uint8 */
176static ws_mempbrk_pattern pbrk_whitespace;
177static ws_mempbrk_pattern pbrk_braces;
178
179/* Used when command type is needed to differentiate parsing, extend as needed */
180typedef enum
181{
182 MEGACO_CMD_NOT_SET = 0,
183 MEGACO_CMD_PRIORITY,
184} megaco_commands_enum_t;
185
186/*
187* Here are the global variables associated with
188* the various user definable characteristics of the dissection
189*
190* H.248/MEGACO has two kinds of message formats: text and binary (ASN.1).
191* The binary message format is dissected in packet-h248.c
192*
193* global_megaco_raw_text determines whether we are going to display
194* the raw text of the megaco message, much like the HTTP dissector does.
195*
196* global_megaco_dissect_tree determines whether we are going to display
197* a detailed tree that expresses a somewhat more semantically meaningful
198* decode.
199*/
200static bool_Bool global_megaco_raw_text = true1;
201static bool_Bool global_megaco_dissect_tree = true1;
202
203static const value_string megaco_context_vals[] = {
204 { CHOOSE_CONTEXT0xFFFFFFFE, "Choose one" },
205 { ALL_CONTEXTS0xFFFFFFFF, "All" },
206 { NULL_CONTEXT0, "NULL" },
207
208 { 0, NULL((void*)0) }
209};
210
211/* Some basic utility functions that are specific to this dissector */
212static int megaco_tvb_skip_wsp(tvbuff_t *tvb, int offset);
213static int megaco_tvb_skip_wsp_return(tvbuff_t *tvb, int offset);
214
215#define NUM_TIMESTATS12 12
216
217static const value_string megaco_message_type[] = {
218 { 0, "ADD "},
219 { 1, "MOVE"},
220 { 2, "MDFY"},
221 { 3, "SUBT"},
222 { 4, "AUCP"},
223 { 5, "AUVL"},
224 { 6, "NTFY"},
225 { 7, "SVCC"},
226 { 8, "TOPO"},
227 { 9, "NONE"},
228 { 10, "ALL "},
229 { 0, NULL((void*)0)}
230};
231
232#define GCP_CMD_REPLY_CASEcase GCP_CMD_ADD_REPLY: case GCP_CMD_MOVE_REPLY: case GCP_CMD_MOD_REPLY
: case GCP_CMD_SUB_REPLY: case GCP_CMD_AUDITCAP_REPLY: case GCP_CMD_AUDITVAL_REPLY
: case GCP_CMD_NOTIFY_REPLY: case GCP_CMD_SVCCHG_REPLY: case GCP_CMD_TOPOLOGY_REPLY
: case GCP_CMD_REPLY:
\
233 case GCP_CMD_ADD_REPLY: \
234 case GCP_CMD_MOVE_REPLY: \
235 case GCP_CMD_MOD_REPLY: \
236 case GCP_CMD_SUB_REPLY: \
237 case GCP_CMD_AUDITCAP_REPLY: \
238 case GCP_CMD_AUDITVAL_REPLY: \
239 case GCP_CMD_NOTIFY_REPLY: \
240 case GCP_CMD_SVCCHG_REPLY: \
241 case GCP_CMD_TOPOLOGY_REPLY: \
242 case GCP_CMD_REPLY:
243
244#define GCP_CMD_REQ_CASEcase GCP_CMD_ADD_REQ: case GCP_CMD_MOVE_REQ: case GCP_CMD_MOD_REQ
: case GCP_CMD_SUB_REQ: case GCP_CMD_AUDITCAP_REQ: case GCP_CMD_AUDITVAL_REQ
: case GCP_CMD_NOTIFY_REQ: case GCP_CMD_SVCCHG_REQ: case GCP_CMD_TOPOLOGY_REQ
: case GCP_CMD_CTX_ATTR_AUDIT_REQ: case GCP_CMD_OTHER_REQ:
\
245 case GCP_CMD_ADD_REQ: \
246 case GCP_CMD_MOVE_REQ: \
247 case GCP_CMD_MOD_REQ: \
248 case GCP_CMD_SUB_REQ: \
249 case GCP_CMD_AUDITCAP_REQ: \
250 case GCP_CMD_AUDITVAL_REQ: \
251 case GCP_CMD_NOTIFY_REQ: \
252 case GCP_CMD_SVCCHG_REQ: \
253 case GCP_CMD_TOPOLOGY_REQ: \
254 case GCP_CMD_CTX_ATTR_AUDIT_REQ: \
255 case GCP_CMD_OTHER_REQ:
256
257static bool_Bool
258megacostat_is_duplicate_reply(const gcp_cmd_t* cmd)
259{
260 switch (cmd->type) {
261
262 GCP_CMD_REPLY_CASEcase GCP_CMD_ADD_REPLY: case GCP_CMD_MOVE_REPLY: case GCP_CMD_MOD_REPLY
: case GCP_CMD_SUB_REPLY: case GCP_CMD_AUDITCAP_REPLY: case GCP_CMD_AUDITVAL_REPLY
: case GCP_CMD_NOTIFY_REPLY: case GCP_CMD_SVCCHG_REPLY: case GCP_CMD_TOPOLOGY_REPLY
: case GCP_CMD_REPLY:
263 {
264 gcp_cmd_msg_t *cmd_msg;
265 /* cycle through commands to find same command in the transaction */
266 for (cmd_msg = cmd->trx->cmds;
267 (cmd_msg != NULL((void*)0)) && (cmd_msg->cmd->msg->framenum != cmd->msg->framenum);
268 cmd_msg = cmd_msg->next) {
269 if (cmd_msg->cmd->type == cmd->type)
270 return true1;
271 }
272
273 return false0;
274 }
275 break;
276 default:
277 return false0;
278 break;
279 }
280}
281
282static bool_Bool
283megacostat_had_request(const gcp_cmd_t* cmd)
284{
285 switch (cmd->type) {
286
287 GCP_CMD_REPLY_CASEcase GCP_CMD_ADD_REPLY: case GCP_CMD_MOVE_REPLY: case GCP_CMD_MOD_REPLY
: case GCP_CMD_SUB_REPLY: case GCP_CMD_AUDITCAP_REPLY: case GCP_CMD_AUDITVAL_REPLY
: case GCP_CMD_NOTIFY_REPLY: case GCP_CMD_SVCCHG_REPLY: case GCP_CMD_TOPOLOGY_REPLY
: case GCP_CMD_REPLY:
288 {
289 gcp_cmd_msg_t *cmd_msg;
290 /* cycle through commands to find a request in the transaction */
291 for (cmd_msg = cmd->trx->cmds;
292 (cmd_msg != NULL((void*)0)) && (cmd_msg->cmd->msg->framenum != cmd->msg->framenum);
293 cmd_msg = cmd_msg->next) {
294
295 switch (cmd_msg->cmd->type) {
296
297 GCP_CMD_REQ_CASEcase GCP_CMD_ADD_REQ: case GCP_CMD_MOVE_REQ: case GCP_CMD_MOD_REQ
: case GCP_CMD_SUB_REQ: case GCP_CMD_AUDITCAP_REQ: case GCP_CMD_AUDITVAL_REQ
: case GCP_CMD_NOTIFY_REQ: case GCP_CMD_SVCCHG_REQ: case GCP_CMD_TOPOLOGY_REQ
: case GCP_CMD_CTX_ATTR_AUDIT_REQ: case GCP_CMD_OTHER_REQ:
298 return true1;
299 break;
300 default:
301 return false0;
302 break;
303 }
304 }
305
306 return false0;
307 }
308 break;
309 default:
310 return false0;
311 break;
312 }
313}
314
315static void
316megacostat_filtercheck(const char *opt_arg _U___attribute__((unused)), const char **filter _U___attribute__((unused)), char** err)
317{
318 pref_t *megaco_ctx_track, *h248_ctx_track;
319
320 megaco_ctx_track = prefs_find_preference(prefs_find_module("megaco"), "ctx_info");
321 h248_ctx_track = prefs_find_preference(prefs_find_module("h248"), "ctx_info");
322
323 if (!megaco_ctx_track || !h248_ctx_track) {
324 /* No such preferences */
325 return;
326 }
327
328 if (!prefs_get_bool_value(megaco_ctx_track, pref_current) || !prefs_get_bool_value(h248_ctx_track, pref_current)) {
329 *err = ws_strdup_printf("Track Context option at Protocols -> MEGACO and Protocols -> H248 preferences\n"wmem_strdup_printf(((void*)0), "Track Context option at Protocols -> MEGACO and Protocols -> H248 preferences\n"
"has to be set to true to enable measurement of service response times.\n"
)
330 "has to be set to true to enable measurement of service response times.\n")wmem_strdup_printf(((void*)0), "Track Context option at Protocols -> MEGACO and Protocols -> H248 preferences\n"
"has to be set to true to enable measurement of service response times.\n"
)
;
331 }
332}
333
334static tap_packet_status
335megacostat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *pmi, tap_flags_t flags _U___attribute__((unused)))
336{
337 rtd_data_t* rtd_data = (rtd_data_t*)pms;
338 rtd_stat_table* ms = &rtd_data->stat_table;
339 const gcp_cmd_t *mi=(const gcp_cmd_t*)pmi;
340 nstime_t delta;
341 tap_packet_status ret = TAP_PACKET_DONT_REDRAW;
342
343 switch (mi->type) {
344
345 GCP_CMD_REQ_CASEcase GCP_CMD_ADD_REQ: case GCP_CMD_MOVE_REQ: case GCP_CMD_MOD_REQ
: case GCP_CMD_SUB_REQ: case GCP_CMD_AUDITCAP_REQ: case GCP_CMD_AUDITVAL_REQ
: case GCP_CMD_NOTIFY_REQ: case GCP_CMD_SVCCHG_REQ: case GCP_CMD_TOPOLOGY_REQ
: case GCP_CMD_CTX_ATTR_AUDIT_REQ: case GCP_CMD_OTHER_REQ:
346 if(!mi->trx->initial) {
347 /* Track Context is probably disabled, we cannot
348 * measure service response time */
349 return TAP_PACKET_DONT_REDRAW;
350 }
351
352 else if(mi->trx->initial->framenum != mi->msg->framenum){
353 /* Duplicate is ignored */
354 ms->time_stats[0].req_dup_num++;
355 }
356 else {
357 ms->time_stats[0].open_req_num++;
358 }
359 break;
360
361 GCP_CMD_REPLY_CASEcase GCP_CMD_ADD_REPLY: case GCP_CMD_MOVE_REPLY: case GCP_CMD_MOD_REPLY
: case GCP_CMD_SUB_REPLY: case GCP_CMD_AUDITCAP_REPLY: case GCP_CMD_AUDITVAL_REPLY
: case GCP_CMD_NOTIFY_REPLY: case GCP_CMD_SVCCHG_REPLY: case GCP_CMD_TOPOLOGY_REPLY
: case GCP_CMD_REPLY:
362 if(megacostat_is_duplicate_reply(mi)){
363 /* Duplicate is ignored */
364 ms->time_stats[0].rsp_dup_num++;
365 }
366 else if (!megacostat_had_request(mi)) {
367 /* no request was seen */
368 ms->time_stats[0].disc_rsp_num++;
369 }
370 else {
371 ms->time_stats[0].open_req_num--;
372 /* calculate time delta between request and response */
373 nstime_delta(&delta, &pinfo->abs_ts, &mi->trx->initial->frametime);
374
375 switch(mi->type) {
376
377 case GCP_CMD_ADD_REPLY:
378 time_stat_update(&(ms->time_stats[0].rtd[0]),&delta, pinfo);
379 break;
380 case GCP_CMD_MOVE_REPLY:
381 time_stat_update(&(ms->time_stats[0].rtd[1]),&delta, pinfo);
382 break;
383 case GCP_CMD_MOD_REPLY:
384 time_stat_update(&(ms->time_stats[0].rtd[2]),&delta, pinfo);
385 break;
386 case GCP_CMD_SUB_REPLY:
387 time_stat_update(&(ms->time_stats[0].rtd[3]),&delta, pinfo);
388 break;
389 case GCP_CMD_AUDITCAP_REPLY:
390 time_stat_update(&(ms->time_stats[0].rtd[4]),&delta, pinfo);
391 break;
392 case GCP_CMD_AUDITVAL_REPLY:
393 time_stat_update(&(ms->time_stats[0].rtd[5]),&delta, pinfo);
394 break;
395 case GCP_CMD_NOTIFY_REPLY:
396 time_stat_update(&(ms->time_stats[0].rtd[6]),&delta, pinfo);
397 break;
398 case GCP_CMD_SVCCHG_REPLY:
399 time_stat_update(&(ms->time_stats[0].rtd[7]),&delta, pinfo);
400 break;
401 case GCP_CMD_TOPOLOGY_REPLY:
402 time_stat_update(&(ms->time_stats[0].rtd[8]),&delta, pinfo);
403 break;
404 case GCP_CMD_REPLY:
405 time_stat_update(&(ms->time_stats[0].rtd[9]),&delta, pinfo);
406 break;
407 default:
408 time_stat_update(&(ms->time_stats[0].rtd[11]),&delta, pinfo);
409 }
410
411 time_stat_update(&(ms->time_stats[0].rtd[10]),&delta, pinfo);
412 ret = TAP_PACKET_REDRAW;
413 }
414 break;
415
416 default:
417 break;
418 }
419
420 return ret;
421}
422
423/* Call the export PDU tap with relevant data */
424static void
425export_megaco_pdu(packet_info *pinfo, tvbuff_t *tvb)
426{
427 exp_pdu_data_t *exp_pdu_data = export_pdu_create_common_tags(pinfo, "megaco", EXP_PDU_TAG_DISSECTOR_NAME12);
428
429 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
430 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
431 exp_pdu_data->pdu_tvb = tvb;
432
433 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
434
435}
436
437/*
438* The various functions that either dissect some
439* subpart of MEGACO. These aren't really proto dissectors but they
440* are written in the same style.
441*
442*/
443static void
444dissect_megaco_descriptors(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, proto_tree *top_tree, uint32_t context);
445static void
446dissect_megaco_digitmapdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int tvb_RBRKT, int tvb_previous_offset);
447static void
448dissect_megaco_topologydescriptor(tvbuff_t *tvb, proto_tree *tree, unsigned tvb_RBRKT, unsigned tvb_previous_offset);
449static void
450dissect_megaco_errordescriptor(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, unsigned tvb_RBRKT, unsigned tvb_previous_offset);
451static void
452dissect_megaco_statisticsdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line);
453static void
454dissect_megaco_TerminationStatedescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
455static void
456dissect_megaco_LocalRemotedescriptor(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t context, bool_Bool is_local);
457static void
458dissect_megaco_LocalControldescriptor(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, proto_tree *top_tree);
459static void
460dissect_megaco_Packagesdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned tvb_next_offset, unsigned tvb_current_offset);
461static void
462tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
463static int
464dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
465static int
466megaco_tvb_find_token(tvbuff_t *tvb, int offset, int maxlength);
467static dissector_handle_t data_handle;
468static dissector_handle_t sdp_handle;
469static dissector_handle_t h245_handle;
470static dissector_handle_t h248_handle;
471static dissector_handle_t h248_otp_handle;
472
473static bool_Bool keep_persistent_data;
474
475/*
476 * dissect_megaco_text over TCP, there will be a TPKT header there
477 *
478 */
479static int dissect_megaco_text_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))
480{
481
482 /* This code is copied from the Q.931 dissector, some parts skipped.
483 * Check whether this looks like a TPKT-encapsulated
484 * MEGACO packet.
485 *
486 * The minimum length of a MEGACO message is 6?:
487 * Re-assembly ?
488 */
489 if (is_tpkt(tvb, 6, NULL((void*)0))) {
490 /*
491 * It's not a TPKT packet;
492 * Is in MEGACO ?
493 */
494 dissect_megaco_text(tvb, pinfo, tree, data);
495 }
496 dissect_tpkt_encap(tvb, pinfo, tree, true1, megaco_text_handle);
497
498 return tvb_captured_length(tvb);
499}
500
501#define NO_MATCH0 0
502#define ERRORTOKEN1 1
503#define TRANSTOKEN2 2
504#define REPLYTOKEN3 3
505#define PENDINGTOKEN4 4
506#define RESPONSEACKTOKEN5 5
507
508typedef struct {
509 const char *name;
510 const char *compact_name;
511} megaco_tokens_t;
512
513static const megaco_tokens_t megaco_messageBody_names[] = {
514 { "Unknown-token", NULL((void*)0) }, /* 0 Pad so that the real headers start at index 1 */
515 { "Error", "ER" }, /* 1 */
516 { "Transaction", "T" }, /* 2 */
517 { "Reply", "P" }, /* 3 */
518 { "Pending", "PN" }, /* 4 */
519 { "TransactionResponseAck", "K" }, /* 5 */
520};
521
522/* Returns index of megaco_tokens_t */
523static unsigned find_megaco_messageBody_names(tvbuff_t *tvb, unsigned offset, unsigned header_len)
524{
525 unsigned i;
526
527 for (i = 1; i < array_length(megaco_messageBody_names)(sizeof (megaco_messageBody_names) / sizeof (megaco_messageBody_names
)[0])
; i++) {
528 if (header_len == strlen(megaco_messageBody_names[i].name) &&
529 tvb_strncaseeql(tvb, offset, megaco_messageBody_names[i].name, header_len) == 0)
530 return i;
531 if (megaco_messageBody_names[i].compact_name != NULL((void*)0) &&
532 header_len == strlen(megaco_messageBody_names[i].compact_name) &&
533 tvb_strncaseeql(tvb, offset, megaco_messageBody_names[i].compact_name, header_len) == 0)
534 return i;
535 }
536
537 return NO_MATCH0;
538}
539
540static proto_item *
541megaco_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, unsigned start, unsigned length, const char *value)
542{
543 proto_item *pi;
544
545 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
546 if (!global_megaco_dissect_tree) {
547 proto_item_set_hidden(pi);
548 }
549
550 return pi;
551}
552
553static proto_item *
554my_proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
555 unsigned start, unsigned length, uint32_t value)
556{
557 proto_item *pi;
558
559 pi = proto_tree_add_uint(tree, hfindex, tvb, start, 1, value);
560 /* String length may be longer than FT_UINT will allow */
561 proto_item_set_len(pi, length);
562
563 if (!global_megaco_dissect_tree) {
564 proto_item_set_hidden(pi);
565 }
566
567 return pi;
568}
569
570/*
571 * dissect_megaco_text - The dissector for the MEGACO Protocol, using
572 * text encoding.
573 */
574static int
575dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))
576{
577 unsigned tvb_len, len;
578 unsigned tvb_previous_offset, tvb_current_offset, tvb_offset, tvb_next_offset;
579 unsigned tokenlen, toffset;
580 unsigned context_offset, context_length, save_offset, save_length;
581 unsigned tvb_command_start_offset, tvb_command_end_offset;
582 unsigned tvb_transaction_end_offset;
583 proto_tree *megaco_tree, *message_body_tree, *megaco_tree_command_line;
584 proto_item *ti, *sub_ti;
585
586 uint8_t word[15];
587 uint8_t TermID[30];
588 uint8_t tempchar;
589 unsigned tvb_RBRKT, tvb_LBRKT, RBRKT_counter, LBRKT_counter;
590 unsigned token_index=0;
591 uint32_t dword;
592 unsigned char needle;
593
594 gcp_msg_t *msg = NULL((void*)0);
595 gcp_trx_t *trx = NULL((void*)0);
596 gcp_ctx_t *ctx = NULL((void*)0);
597 gcp_cmd_t *cmd = NULL((void*)0);
598 gcp_term_t *term = NULL((void*)0);
599 gcp_trx_type_t trx_type = GCP_TRX_NONE;
600 uint32_t trx_id = 0, pending_id;
601 uint32_t ctx_id = 0;
602 gcp_cmd_type_t cmd_type = GCP_CMD_NONE;
603 gcp_wildcard_t wild_term = GCP_WILDCARD_NONE;
604 bool_Bool short_form;
605
606 megaco_commands_enum_t megaco_command = MEGACO_CMD_NOT_SET;
607 /* Initialize variables */
608 tvb_len = tvb_reported_length(tvb);
609 megaco_tree = NULL((void*)0);
610 ti = NULL((void*)0);
611 tvb_offset = 0;
612 RBRKT_counter = 0;
613 LBRKT_counter = 0;
614
615 /* Check if H.248 in otp(Erlang) internal format
616 * XXX Needs improvement?
617 * Ref:
618 * http://www.erlang.org/doc/apps/megaco/part_frame.html
619 * 4.1 Internal form of messages
620 * 4.2 The different encodings
621 */
622 dword = tvb_get_ntoh24(tvb,0);
623 if ((dword == 0x836803)&&(h248_otp_handle)){
624 call_dissector(h248_otp_handle, tvb, pinfo, tree);
625 return tvb_captured_length(tvb);
626 }
627
628 msg = gcp_msg(pinfo, tvb_raw_offset(tvb), keep_persistent_data);
629
630 /*
631 * Check to see whether we're really dealing with MEGACO by looking
632 * for the "MEGACO" string or a "!".This needs to be improved when supporting
633 * binary encodings. Bugfix add skipping of leading spaces.
634 */
635 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
636
637 if(!tvb_get_raw_bytes_as_stringz(tvb,tvb_offset,sizeof(word),word)) return tvb_captured_length(tvb);
638
639 /* Quick fix for MEGACO packet with Authentication Header,
640 * marked as "AU" or "Authentication".
641 */
642 if ((tvb_strncaseeql(tvb, tvb_offset, "Authentication", 14) == 0) ||
643 (tvb_strncaseeql(tvb, tvb_offset, "AU", 2) == 0)) {
644 unsigned counter;
645 uint8_t next;
646
647 /* move offset to end of auth header (EOL or WSP) */
648 for ( counter = tvb_offset; counter < tvb_len; counter++ ) {
649 needle = tvb_get_uint8(tvb, counter);
650 if (needle == ' ' || needle == '\r' || needle == '\n') {
651 next = tvb_get_uint8(tvb, counter+1);
652 if (next == ' ' || next == '\r' || next == '\n') {
653 continue;
654 }
655 tvb_offset = counter + 1;
656 break;
657 }
658 }
659 }
660
661 short_form = (tvb_get_uint8(tvb, tvb_offset ) == '!');
662
663 if (tvb_strncaseeql(tvb, tvb_offset, "MEGACO", 6) != 0 && !short_form){
664 int8_t ber_class;
665 bool_Bool pc;
666 int32_t tag;
667 dissector_handle_t handle = data_handle;
668
669 get_ber_identifier(tvb, 0, &ber_class, &pc, &tag);
670
671 if (ber_class == BER_CLASS_UNI0 && pc && tag == BER_UNI_TAG_SEQUENCE16 ) {
672 handle = h248_handle;
673 }
674
675 call_dissector(handle,tvb,pinfo,tree);
676 return tvb_captured_length(tvb);
677 }
678
679
680 /* Display MEGACO in protocol column */
681 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MEGACO");
682
683 /* Report this packet to the tap */
684 if (!pinfo->flags.in_error_pkt) {
685 if (have_tap_listener(exported_pdu_tap)) {
686 export_megaco_pdu(pinfo, tvb);
687 }
688 }
689
690 /* Build the info tree if we've been given a root */
691 /* Create megaco subtree */
692 ti = proto_tree_add_item(tree,proto_megaco,tvb, 0, -1, ENC_NA0x00000000);
693 megaco_tree = proto_item_add_subtree(ti, ett_megaco);
694
695 /* Format of 'message' is = MegacopToken SLASH Version SEP mId SEP messageBody */
696 /* MegacopToken = "MEGACO" or "!" */
697 /* According to H248.1-200205 Annex B Text encoding ( protocol version 2 ) */
698
699 /* Find version */
700 if (!tvb_find_uint8_remaining(tvb, 0, '/', &tvb_previous_offset)) {
701 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
702 "Sorry, no \"/\" in the MEGACO header, I can't parse this packet");
703 return tvb_captured_length(tvb);
704 }
705
706 megaco_tree_add_string(megaco_tree, hf_megaco_start, tvb, 0, tvb_previous_offset+1,
707 (char*)tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_previous_offset, ENC_UTF_80x00000002|ENC_NA0x00000000));
708
709 /* skip / */
710 tvb_previous_offset++;
711
712 /* assume at least one digit in version */
713 tvb_current_offset = tvb_previous_offset + 1;
714
715 if (g_ascii_isdigit(tvb_get_uint8(tvb, tvb_current_offset))((g_ascii_table[(guchar) (tvb_get_uint8(tvb, tvb_current_offset
))] & G_ASCII_DIGIT) != 0)
) {
716 /* 2-digit version */
717 tvb_current_offset++;
718 }
719
720 megaco_tree_add_string(megaco_tree, hf_megaco_version, tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset,
721 (char*)tvb_get_string_enc(pinfo->pool, tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset, ENC_UTF_80x00000002|ENC_NA0x00000000));
722
723 tvb_previous_offset = tvb_current_offset;
724 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
725
726 if (tvb_previous_offset == tvb_current_offset) {
727 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
728 "[ Parse error: missing SEP in MEGACO header ]");
729 return tvb_current_offset;
730 }
731
732 tvb_previous_offset = tvb_current_offset;
733
734 /* mId should follow here,
735 * mId = (( domainAddress / domainName ) [":" portNumber]) / mtpAddress / deviceName
736 * domainAddress = "[" (IPv4address / IPv6address) "]"
737 * domainName = "<" (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" /".") ">"
738 * mtpAddress = MTPToken LBRKT 4*8 (HEXDIG) RBRKT
739 * MTPToken = ("MTP")
740 * deviceName = pathNAME
741 * pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )["@" pathDomainName ]
742 */
743
744 if (!tvb_ws_mempbrk_uint8_length(tvb, tvb_current_offset, tvb_len, &pbrk_whitespace, &tvb_current_offset, &needle)) {
745 expert_add_info_format(pinfo, ti, &ei_megaco_parse_error,
746 "[ Parse error: no body in MEGACO message (missing SEP after mId) ]");
747 return tvb_captured_length(tvb);
748 }
749
750 tvb_next_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset);
751
752 /* At this point we should point to the "\n" ending the mId element
753 * or to the next character after white space SEP
754 */
755 megaco_tree_add_string(megaco_tree, hf_megaco_mId, tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset,
756 (char*)tvb_get_string_enc(pinfo->pool, tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset, ENC_UTF_80x00000002|ENC_NA0x00000000));
757
758 col_clear(pinfo->cinfo, COL_INFO);
759 do{
760 tvb_previous_offset = tvb_next_offset;
761
762/* Next part is
763 * : messageBody = ( errorDescriptor / transactionList )
764 * errorDescriptor = ErrorToken EQUAL ErrorCode LBRKT [quotedString] RBRKT
765 * ErrorToken = ("Error" / "ER")
766 *
767 * transactionList = 1*( transactionRequest / transactionReply /
768 * transactionPending / transactionResponseAck )
769 *
770 * transactionResponseAck = ResponseAckToken LBRKT
771 * transactionAck*(COMMA transactionAck) RBRKT
772 * ResponseAckToken = ("TransactionResponseAck"/ "K")
773 *
774 * transactionPending = PendingToken EQUAL TransactionID LBRKT RBRKT
775 * PendingToken = ("Pending" / "PN")
776 *
777 * transactionReply = ReplyToken EQUAL TransactionID LBRKT
778 * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
779 * ReplyToken = ("Reply" / "P")
780 *
781 * transactionRequest = TransToken EQUAL TransactionID LBRKT
782 * actionRequest *(COMMA actionRequest) RBRKT
783 * TransToken = ("Transaction" / "T")
784 */
785
786 /* Find token length */
787 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_len-1; tvb_offset++){
788 if (!g_ascii_isalpha(tvb_get_uint8(tvb, tvb_offset ))((g_ascii_table[(guchar) (tvb_get_uint8(tvb, tvb_offset ))] &
G_ASCII_ALPHA) != 0)
){
789 break;
790 }
791 }
792 tokenlen = tvb_offset - tvb_previous_offset;
793 token_index = find_megaco_messageBody_names(tvb, tvb_previous_offset, tokenlen);
794 /* Debug code
795 ws_warning("token_index %u",token_index);
796 */
797
798 tvb_find_uint8_length(tvb, tvb_offset, tvb_len, '{', &tvb_LBRKT);
799 tvb_current_offset = tvb_LBRKT;
800 tvb_transaction_end_offset = megaco_tvb_find_token(tvb, tvb_LBRKT - 1, tvb_len);
801
802 switch ( token_index ){
803 /* errorDescriptor */
804 case ERRORTOKEN1:
805 col_set_str(pinfo->cinfo, COL_INFO, "Error ");
806
807 tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_len); /*tvb_find_uint8(tvb, tvb_offset+1, tvb_len, '}');*/
808
809 ti = proto_tree_add_format_text(megaco_tree, tvb, tvb_previous_offset, tvb_current_offset-tvb_previous_offset);
810 message_body_tree = proto_item_add_subtree(ti, ett_megaco_message_body);
811
812 if (tree) {
813 megaco_tree_add_string(message_body_tree, hf_megaco_transaction, tvb, tvb_previous_offset, tokenlen, "Error" );
814
815 tvb_command_start_offset = tvb_previous_offset;
816 dissect_megaco_errordescriptor(tvb, pinfo, megaco_tree, tvb_len-1, tvb_command_start_offset);
817 }
818 return tvb_captured_length(tvb);
819 /* transactionResponseAck
820 * transactionResponseAck = ResponseAckToken LBRKT transactionAck
821 * *(COMMA transactionAck) RBRKT
822 * transactionAck = transactionID / (transactionID "-" transactionID)
823 */
824 case RESPONSEACKTOKEN5:
825 tvb_find_uint8_length(tvb, tvb_offset, tvb_transaction_end_offset, '{', &tvb_LBRKT);
826 tvb_offset = tvb_LBRKT;
827 save_offset = tvb_previous_offset;
828 save_length = tvb_current_offset-tvb_previous_offset;
829
830 megaco_tree_add_string(megaco_tree, hf_megaco_transaction, tvb, save_offset, save_length, "TransactionResponseAck" );
831
832 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1);
833 tvb_find_uint8_length(tvb, tvb_offset + 1, tvb_len, '}', &tvb_current_offset);
834 /*tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_transaction_end_offset);*/
835 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset)-1; /* cut last RBRKT */
836 len = tvb_current_offset - tvb_previous_offset;
837
838 pending_id = (unsigned)strtoul(tvb_format_text(pinfo->pool, tvb,tvb_previous_offset,len),NULL((void*)0),10);
839 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "%d TransactionResponseAck", pending_id);
840
841 my_proto_tree_add_uint(megaco_tree, hf_megaco_transid, tvb, save_offset, save_length, pending_id);
842
843 if(global_megaco_raw_text){
844 tvb_raw_text_add(tvb, megaco_tree);
845 }
846 return tvb_captured_length(tvb);
847 /* Pe and PN is transactionPending, P+"any char" is transactionReply */
848 case PENDINGTOKEN4:
849
850 tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_transaction_end_offset, '=', &tvb_offset);
851 tvb_offset += 1;
852 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
853 tvb_find_uint8_length(tvb, tvb_offset, tvb_transaction_end_offset, '{', &tvb_LBRKT);
854 tvb_current_offset = tvb_LBRKT;
855 save_offset = tvb_previous_offset;
856 save_length = tvb_current_offset-tvb_previous_offset;
857
858 megaco_tree_add_string(megaco_tree, hf_megaco_transaction, tvb, save_offset, save_length, "Reply" );
859
860 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1);
861 len = tvb_current_offset - tvb_offset;
862
863 pending_id = (unsigned)strtoul(tvb_format_text(pinfo->pool, tvb,tvb_offset,len),NULL((void*)0),10);
864 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "%d Pending", pending_id);
865
866 my_proto_tree_add_uint(megaco_tree, hf_megaco_transid, tvb, save_offset, save_length, pending_id);
867 return tvb_captured_length(tvb);
868
869 /* transactionReply */
870 case REPLYTOKEN3:
871 trx_type = GCP_TRX_REPLY;
872 tvb_find_uint8_length(tvb, tvb_offset, tvb_transaction_end_offset, '{', &tvb_LBRKT);
873 save_offset = tvb_previous_offset;
874 save_length = tvb_LBRKT-tvb_previous_offset;
875
876 megaco_tree_add_string(megaco_tree, hf_megaco_transaction, tvb, save_offset, save_length, "Reply" );
877
878 tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_transaction_end_offset, '=', &tvb_offset);
879 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
880 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_LBRKT-1);
881 len = tvb_current_offset - tvb_offset;
882
883 trx_id = (unsigned)strtoul(tvb_format_text(pinfo->pool, tvb,tvb_offset,len),NULL((void*)0),10);
884 col_add_fstr(pinfo->cinfo, COL_INFO, "%d Reply ", trx_id);
885
886 my_proto_tree_add_uint(megaco_tree, hf_megaco_transid, tvb, save_offset, save_length, trx_id);
887
888 /* Find if we have a errorDescriptor or actionReplyList */
889 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
890 tempchar = tvb_get_uint8(tvb,tvb_offset);
891 if ((tempchar == 'E')||(tempchar == 'e')){
892 dissect_megaco_errordescriptor(tvb, pinfo, megaco_tree, tvb_transaction_end_offset-1, tvb_offset);
893 return tvb_captured_length(tvb);
894 }
895 /* Offset should be at first printable char after { */
896 tvb_previous_offset = tvb_offset;
897 break;
898 case TRANSTOKEN2:
899 /* TransactionRequest */
900 trx_type = GCP_TRX_REQUEST;
901 save_offset = tvb_previous_offset;
902 save_length = tvb_current_offset-tvb_previous_offset;
903 megaco_tree_add_string(megaco_tree, hf_megaco_transaction, tvb,
904 save_offset, save_length, "Request" );
905
906 tvb_find_uint8_length(tvb, tvb_offset, tvb_transaction_end_offset, '=', &tvb_offset);
907 tvb_offset += 1;
908 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
909 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1);
910 len = tvb_current_offset - tvb_offset;
911
912 trx_id = (unsigned)strtoul(tvb_format_text(pinfo->pool, tvb,tvb_offset,len),NULL((void*)0),10);
913 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "%d Request", trx_id);
914
915 my_proto_tree_add_uint(megaco_tree, hf_megaco_transid, tvb, save_offset, save_length, trx_id);
916 /* Offset should be at first printable char after { */
917 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
918
919 break;
920 default : /* NO_MATCH */
921 proto_tree_add_expert_format_remaining(tree, pinfo, &ei_megaco_error_descriptor_transaction_list, tvb, 0,
922 "Sorry, can't understand errorDescriptor / transactionList = %s, can't parse it pos %u",
923 tvb_format_text(pinfo->pool, tvb,tvb_previous_offset,2),tvb_previous_offset);
924 return tvb_captured_length(tvb);
925 } /* end switch */
926/* Only these remains now
927 * transactionReply = ReplyToken EQUAL TransactionID LBRKT
928 * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
929 * ReplyToken = ("Reply" / "P")
930 *
931 * errorDescriptor = ErrorToken EQUAL ErrorCode
932 * LBRKT [quotedString] RBRKT
933 *
934 * transactionRequest = TransToken EQUAL TransactionID LBRKT
935 * actionRequest *(COMMA actionRequest) RBRKT
936 * TransToken = ("Transaction" / "T")
937 */
938
939 trx = gcp_trx(msg , trx_id , trx_type, pinfo, keep_persistent_data);
940
941 /* Find Context */
942nextcontext:
943
944
945
946 /* Check result???*/
947 tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_transaction_end_offset, '{', &tvb_next_offset);
948 context_offset = tvb_previous_offset;
949 context_length = tvb_next_offset-tvb_previous_offset+1;
950
951 tvb_find_uint8_length(tvb, tvb_current_offset, tvb_transaction_end_offset, '=', &tvb_previous_offset);
952 tvb_previous_offset += 1;
953 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
954
955 if (tvb_current_offset >= tvb_next_offset) {
956 proto_tree_add_expert_format(megaco_tree, pinfo, &ei_megaco_parse_error,
957 tvb, context_offset, context_length, "Parse error: Invalid offset");
958 return tvb_captured_length(tvb);
959 }
960 tvb_current_offset = tvb_next_offset;
961
962
963 tokenlen = tvb_current_offset - tvb_previous_offset;
964 tempchar = tvb_get_uint8(tvb, tvb_previous_offset );
965
966 if (tvb_get_uint8(tvb, tvb_current_offset-1 ) == ' '){
967 tokenlen--;
968 }
969
970 switch ( tempchar ){
971 case '$':
972 ctx_id = CHOOSE_CONTEXT0xFFFFFFFE;
973 break;
974 case '*':
975 ctx_id = ALL_CONTEXTS0xFFFFFFFF;
976 break;
977 case '-':
978 ctx_id = NULL_CONTEXT0;
979 break;
980 default:
981 ctx_id = (unsigned)strtoul(tvb_format_text(pinfo->pool, tvb, tvb_previous_offset, tokenlen),NULL((void*)0),10);
982 }
983
984 my_proto_tree_add_uint(megaco_tree, hf_megaco_Context, tvb, context_offset, context_length, ctx_id);
985 sub_ti = my_proto_tree_add_uint(megaco_tree, hf_megaco_Context_generated, tvb, context_offset, context_length, ctx_id);
986 proto_item_set_generated(sub_ti);
987 col_append_fstr(pinfo->cinfo, COL_INFO, " |=%s", val_to_str(pinfo->pool, ctx_id, megaco_context_vals, "%d"));
988
989 ctx = gcp_ctx(msg,trx,ctx_id,pinfo,keep_persistent_data);
990
991 /* Find Commands */
992
993 /* If Transaction is Request, Reply or Pending */
994 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
995 tvb_command_end_offset = tvb_command_start_offset;
996
997 tvb_LBRKT = tvb_command_start_offset;
998 tvb_RBRKT = tvb_command_start_offset;
999
1000 /* The following loop find the individual contexts, commands and call the for every Descriptor a subroutine */
1001
1002 do {
1003 if ( !tvb_find_uint8_length(tvb, tvb_command_end_offset + 1, tvb_transaction_end_offset, ',', &tvb_command_end_offset) || tvb_command_end_offset > tvb_transaction_end_offset){
1004 tvb_command_end_offset = tvb_transaction_end_offset ;
1005 }
1006
1007 /* checking how many left brackets are before the next comma */
1008 while (tvb_find_uint8_length(tvb, tvb_LBRKT + 1 + 1, tvb_transaction_end_offset, '{', &toffset)
1009 && toffset < tvb_command_end_offset){
1010
1011 tvb_LBRKT = toffset;
1012 LBRKT_counter++;
1013 }
1014
1015 /* checking how many right brackets are before the next comma */
1016
1017 while ( (tvb_find_uint8_length(tvb, tvb_RBRKT+1,tvb_transaction_end_offset, '}', &toffset))
1018 && toffset <= tvb_command_end_offset
1019 && LBRKT_counter != 0){
1020
1021 tvb_find_uint8_length(tvb, tvb_RBRKT + 1, tvb_transaction_end_offset, '}', &tvb_RBRKT);
1022 RBRKT_counter++;
1023
1024
1025 }
1026
1027 /* If equal or more right brackets before the comma, one command is complete */
1028
1029 if ( LBRKT_counter <= RBRKT_counter ){
1030
1031 tvb_find_uint8_length(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{', &tvb_current_offset);
1032
1033
1034 /* includes no descriptors */
1035
1036 if ( LBRKT_counter == 0 ){
1037
1038 tvb_current_offset = tvb_command_end_offset;
1039
1040 /* the last command in a context */
1041 if (tvb_find_uint8_length(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}', &toffset)
1042 && toffset < tvb_current_offset){
1043
1044 tvb_previous_offset = toffset;
1045
1046 len = tvb_previous_offset - tvb_command_start_offset;
1047
1048 tvb_previous_offset = megaco_tvb_skip_wsp_return(tvb, tvb_previous_offset -1);
1049
1050 tokenlen = tvb_previous_offset - tvb_command_start_offset;
1051
1052 }
1053
1054 /* not the last command in a context*/
1055
1056 else{
1057 len = tvb_current_offset - tvb_command_start_offset;
1058 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset -1);
1059
1060 tokenlen = tvb_current_offset - tvb_command_start_offset;
1061 }
1062 }
1063
1064 /* command includes descriptors */
1065
1066 else{
1067 len = tvb_current_offset - tvb_command_start_offset;
1068 tvb_current_offset = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset -1);
1069
1070 tokenlen = tvb_current_offset - tvb_command_start_offset;
1071 }
1072
1073 /* if a next context is specified */
1074
1075 if ( tvb_get_uint8(tvb, tvb_command_start_offset ) == 'C'){
1076 tvb_current_offset = tvb_command_start_offset;
1077 tvb_previous_offset = tvb_command_start_offset;
1078 LBRKT_counter = 0;
1079 RBRKT_counter = 0;
1080 goto nextcontext;
1081 }
1082
1083 megaco_tree_command_line = proto_tree_add_subtree(megaco_tree, tvb, tvb_command_start_offset, len+1, ett_megaco_command_line, &sub_ti, "Command: ");
1084 megaco_command = MEGACO_CMD_NOT_SET;
1085 /* creation of the megaco_tree_command_line additionally Command and Transaction ID will be printed in this line */
1086 /* Changed to use the lines above. this code is saved if there is complaints
1087 sub_ti = proto_tree_add_item(megaco_tree,hf_megaco_command_line,tvb,tvb_command_start_offset,tokenlen, ENC_UTF_8);
1088 megaco_tree_command_line = proto_item_add_subtree(sub_ti, ett_megaco_command_line);
1089 */
1090 if (!global_megaco_dissect_tree) {
1091 proto_item_set_hidden(sub_ti);
1092 }
1093
1094 tvb_next_offset = tvb_command_start_offset + tokenlen;
1095
1096 /* Try to dissect Topology Descriptor before the command */
1097 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset);
1098 if ( (tempchar >= 'a')&& (tempchar <= 'z')){
1099 tempchar = tempchar - 0x20;
1100 }
1101 if ( tempchar == 'T') {
1102 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset+1);
1103
1104 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1105 tempchar = tempchar - 0x20;
1106
1107 if ( tempchar == 'P' || tempchar == 'O'){
1108 unsigned tvb_topology_end_offset;
1109 if ( !tvb_find_uint8_length(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}', &tvb_topology_end_offset) ){
1110 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"}\"");
1111 return tvb_captured_length(tvb);
1112 }
1113
1114 if ( !tvb_find_uint8_length(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '}', &tvb_command_start_offset)){
1115 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"{\"");
1116 return tvb_captured_length(tvb);
1117 }
1118
1119 dissect_megaco_topologydescriptor(tvb, megaco_tree_command_line, tvb_topology_end_offset-1, tvb_command_start_offset+1);
1120
1121 /* Command after Topology Descriptor */
1122 if ( !tvb_find_uint8_length(tvb, tvb_topology_end_offset + 1, tvb_transaction_end_offset, ',', &tvb_command_start_offset)){
1123 /* No Command present after Topology Descriptor */
1124 break;
1125
1126 } else {
1127 /* Try to find the first char of the command */
1128 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_command_start_offset + 1);
1129 RBRKT_counter = 0;
1130 LBRKT_counter = 0;
1131 tvb_LBRKT = tvb_command_start_offset;
1132 tvb_RBRKT = tvb_command_start_offset;
1133 /*tvb_next_offset = tvb_find_uint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{');*/
1134 continue;
1135 }
1136
1137 }
1138 }
1139
1140 /* Additional value */
1141 if ( tvb_get_uint8(tvb, tvb_command_start_offset ) == 'O'){
1142
1143 proto_tree_add_item(megaco_tree_command_line, hf_megaco_command_optional, tvb, tvb_command_start_offset, 2, ENC_NA0x00000000);
1144 tvb_command_start_offset = tvb_command_start_offset+2;
1145
1146 }
1147
1148 /* Additional value */
1149 if ( tvb_get_uint8(tvb, tvb_command_start_offset ) == 'W'){
1150
1151 proto_tree_add_item(megaco_tree_command_line, hf_megaco_wildcard_response, tvb, tvb_command_start_offset, 2, ENC_NA0x00000000 );
1152 tvb_command_start_offset = tvb_command_start_offset+2;
1153 }
1154
1155 if (!tvb_find_uint8_length(tvb, tvb_command_start_offset + 1, tvb_transaction_end_offset, '=', &tvb_offset)) {
1156 proto_tree_add_expert_format(megaco_tree, pinfo, &ei_megaco_parse_error, tvb, tvb_command_start_offset, len+1, "Parse error: Missing \"=\"");
1157 return tvb_captured_length(tvb);
1158 }
1159 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_offset -1);
1160 tokenlen = tvb_offset - tvb_command_start_offset;
1161
1162 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset);
1163 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1164 tempchar = tempchar - 0x20;
1165
1166 if ( tempchar != 'E' ){
1167 /* Short form used */
1168 if (short_form){
1169
1170 switch ( tempchar ){
1171
1172 case 'A':
1173
1174 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset+1);
1175 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1176 tempchar = tempchar - 0x20;
1177
1178 switch ( tempchar ){
1179
1180 case 'V':
1181 switch(trx_type) {
1182 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITVAL_REPLY; break;
1183 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITVAL_REQ; break;
1184 default: cmd_type = GCP_CMD_NONE; break;
1185 }
1186
1187 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1188 tvb_command_start_offset, tokenlen, "AuditValue");
1189 col_append_str(pinfo->cinfo, COL_INFO, " AuditValue");
1190 proto_item_append_text(sub_ti, "AuditValue");
1191 break;
1192
1193 case 'C':
1194 switch(trx_type) {
1195 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITCAP_REQ; break;
1196 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITCAP_REPLY; break;
1197 default: cmd_type = GCP_CMD_NONE; break;
1198 }
1199 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1200 tvb_command_start_offset, tokenlen, "AuditCapability");
1201 col_append_str(pinfo->cinfo, COL_INFO, " AuditCapability");
1202 proto_item_append_text(sub_ti, "AuditCapability");
1203 break;
1204
1205 default:
1206 switch(trx_type) {
1207 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_ADD_REQ; break;
1208 case GCP_TRX_REPLY: cmd_type = GCP_CMD_ADD_REPLY; break;
1209 default: cmd_type = GCP_CMD_NONE; break;
1210 }
1211
1212 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1213 tvb_command_start_offset, tokenlen, "Add");
1214 col_append_str(pinfo->cinfo, COL_INFO, " Add");
1215 proto_item_append_text(sub_ti, "Add");
1216 break;
1217 }
1218 break;
1219
1220 case 'I':
1221 /* "IEPS" */
1222 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset+1);
1223 if(tempchar == 'E'){
1224 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1225 tvb_command_start_offset, tokenlen, "IEPSCall");
1226 col_append_str(pinfo->cinfo, COL_INFO, " IEPSCall");
1227 proto_item_append_text(sub_ti, "IEPSCall");
1228 }
1229 cmd_type = GCP_CMD_NONE;
1230 break;
1231 case 'N':
1232 switch(trx_type) {
1233 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_NOTIFY_REQ; break;
1234 case GCP_TRX_REPLY: cmd_type = GCP_CMD_NOTIFY_REPLY; break;
1235 default: cmd_type = GCP_CMD_NONE; break;
1236 }
1237
1238 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1239 tvb_command_start_offset, tokenlen, "Notify");
1240 col_append_str(pinfo->cinfo, COL_INFO, " Notify");
1241 proto_item_append_text(sub_ti, "Notify");
1242 break;
1243
1244 case 'M':
1245
1246 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset+1);
1247 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1248 tempchar = tempchar - 0x20;
1249
1250 switch ( tempchar ){
1251 case 'F':
1252 switch(trx_type) {
1253 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOD_REQ; break;
1254 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOD_REPLY; break;
1255 default: cmd_type = GCP_CMD_NONE; break;
1256 }
1257
1258 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1259 tvb_command_start_offset, tokenlen, "Modify");
1260 col_append_str(pinfo->cinfo, COL_INFO, " Modify");
1261 proto_item_append_text(sub_ti, "Modify");
1262 break;
1263
1264 case 'V':
1265 switch(trx_type) {
1266 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOVE_REQ; break;
1267 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOVE_REPLY; break;
1268 default: cmd_type = GCP_CMD_NONE; break;
1269 }
1270 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1271 tvb_command_start_offset, tokenlen, "Move");
1272 col_append_str(pinfo->cinfo, COL_INFO, " Move");
1273 proto_item_append_text(sub_ti, "Move");
1274 break;
1275 }
1276 break;
1277
1278 case 'P':
1279 cmd_type = GCP_CMD_NONE;
1280 /*
1281 PackagesToken = ("Packages" / "PG")
1282 PendingToken = ("Pending" / "PN")
1283 PriorityToken = ("Priority" / "PR")
1284 ProfileToken = ("Profile" / "PF")
1285 */
1286 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset+1);
1287 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1288 tempchar = tempchar - 0x20;
1289
1290 switch ( tempchar ){
1291 case 'G':
1292 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1293 tvb_command_start_offset, tokenlen, "Packages");
1294 col_append_str(pinfo->cinfo, COL_INFO, " Packages");
1295 proto_item_append_text(sub_ti, "Packages");
1296 break;
1297 case 'N':
1298 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1299 tvb_command_start_offset, tokenlen, "Pending");
1300 col_append_str(pinfo->cinfo, COL_INFO, " Pending");
1301 proto_item_append_text(sub_ti, "Pending");
1302 break;
1303 case 'R':
1304 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1305 tvb_command_start_offset, tokenlen, "Priority");
1306 col_append_str(pinfo->cinfo, COL_INFO, " Priority");
1307 proto_item_append_text(sub_ti, "Priority");
1308 megaco_command = MEGACO_CMD_PRIORITY;
1309 break;
1310 case 'F':
1311 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1312 tvb_command_start_offset, tokenlen, "Profile");
1313 col_append_str(pinfo->cinfo, COL_INFO, " Profile");
1314 proto_item_append_text(sub_ti, "Profile");
1315 break;
1316 }
1317 break;
1318
1319 case 'S':
1320 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset+1);
1321 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1322 tempchar = tempchar - 0x20;
1323
1324 switch ( tempchar ){
1325
1326 case 'C':
1327 switch(trx_type) {
1328 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SVCCHG_REQ; break;
1329 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SVCCHG_REPLY; break;
1330 default: cmd_type = GCP_CMD_NONE; break;
1331 }
1332 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1333 tvb_command_start_offset, tokenlen, "ServiceChange");
1334 col_append_str(pinfo->cinfo, COL_INFO, " ServiceChange");
1335 proto_item_append_text(sub_ti, "ServiceChange");
1336 break;
1337
1338 default:
1339 switch(trx_type) {
1340 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
1341 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
1342 default: cmd_type = GCP_CMD_NONE; break;
1343 }
1344 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1345 tvb_command_start_offset, tokenlen, "Subtract");
1346 col_append_str(pinfo->cinfo, COL_INFO, " Subtract");
1347 proto_item_append_text(sub_ti, "Subtract");
1348 break;
1349 }
1350 break;
1351
1352 default:
1353 proto_item_append_text(sub_ti, "<None> 0x%02x", tempchar);
1354 expert_add_info(pinfo, sub_ti, &ei_megaco_no_command);
1355 return tvb_captured_length(tvb);
1356 }
1357 }
1358 else{
1359 char* command = tvb_format_text(pinfo->pool, tvb, tvb_command_start_offset, tokenlen);
1360
1361 if ( g_str_equal(command,"Subtract")(strcmp ((const char *) (command), (const char *) ("Subtract"
)) == 0)
) {
1362 switch(trx_type) {
1363 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SUB_REQ; break;
1364 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SUB_REPLY; break;
1365 default: cmd_type = GCP_CMD_NONE; break;
1366 }
1367 } else if ( g_str_equal(command,"AuditValue")(strcmp ((const char *) (command), (const char *) ("AuditValue"
)) == 0)
) {
1368 switch(trx_type) {
1369 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITVAL_REPLY; break;
1370 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITVAL_REQ; break;
1371 default: cmd_type = GCP_CMD_NONE; break;
1372 }
1373 } else if ( g_str_equal(command,"AuditCapability")(strcmp ((const char *) (command), (const char *) ("AuditCapability"
)) == 0)
) {
1374 switch(trx_type) {
1375 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_AUDITCAP_REQ; break;
1376 case GCP_TRX_REPLY: cmd_type = GCP_CMD_AUDITCAP_REPLY; break;
1377 default: cmd_type = GCP_CMD_NONE; break;
1378 }
1379 } else if ( g_str_equal(command,"Add")(strcmp ((const char *) (command), (const char *) ("Add")) ==
0)
) {
1380 switch(trx_type) {
1381 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_ADD_REQ; break;
1382 case GCP_TRX_REPLY: cmd_type = GCP_CMD_ADD_REPLY; break;
1383 default: cmd_type = GCP_CMD_NONE; break;
1384 }
1385 } else if ( g_str_equal(command,"Notify")(strcmp ((const char *) (command), (const char *) ("Notify"))
== 0)
) {
1386 switch(trx_type) {
1387 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_NOTIFY_REQ; break;
1388 case GCP_TRX_REPLY: cmd_type = GCP_CMD_NOTIFY_REPLY; break;
1389 default: cmd_type = GCP_CMD_NONE; break;
1390 }
1391 } else if ( g_str_equal(command,"Modify")(strcmp ((const char *) (command), (const char *) ("Modify"))
== 0)
) {
1392 switch(trx_type) {
1393 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOD_REQ; break;
1394 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOD_REPLY; break;
1395 default: cmd_type = GCP_CMD_NONE; break;
1396 }
1397 } else if ( g_str_equal(command,"Move")(strcmp ((const char *) (command), (const char *) ("Move")) ==
0)
) {
1398 switch(trx_type) {
1399 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_MOVE_REQ; break;
1400 case GCP_TRX_REPLY: cmd_type = GCP_CMD_MOVE_REPLY; break;
1401 default: cmd_type = GCP_CMD_NONE; break;
1402 }
1403 } else if ( g_str_equal(command,"ServiceChange")(strcmp ((const char *) (command), (const char *) ("ServiceChange"
)) == 0)
) {
1404 switch(trx_type) {
1405 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_SVCCHG_REQ; break;
1406 case GCP_TRX_REPLY: cmd_type = GCP_CMD_SVCCHG_REPLY; break;
1407 default: cmd_type = GCP_CMD_NONE; break;
1408 }
1409 } else {
1410 switch(trx_type) {
1411 case GCP_TRX_REQUEST: cmd_type = GCP_CMD_OTHER_REQ; break;
1412 case GCP_TRX_REPLY: cmd_type = GCP_CMD_REPLY; break;
1413 default: cmd_type = GCP_CMD_NONE; break;
1414 }
1415 }
1416
1417
1418 proto_tree_add_string(megaco_tree_command_line, hf_megaco_command, tvb,
1419 tvb_command_start_offset, tokenlen, command);
1420 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command);
1421 proto_item_append_text(sub_ti, " %s", command);
1422 }
1423
1424 if (cmd_type == GCP_CMD_NONE && trx_type == GCP_TRX_REPLY) {
1425 cmd_type = GCP_CMD_REPLY;
1426 }
1427
1428 if (cmd_type != GCP_CMD_NONE) {
1429 cmd = gcp_cmd(msg, trx, ctx, cmd_type, tvb_command_start_offset, pinfo, keep_persistent_data);
1430 tap_queue_packet(megaco_tap, pinfo, cmd);
1431 }
1432
1433 if (!tvb_find_uint8_length(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '=', &tvb_offset)) {
1434 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Missing \"=\"");
1435 return tvb_captured_length(tvb);
1436 }
1437
1438 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1);
1439 tokenlen = tvb_next_offset - tvb_offset;
1440 if (tokenlen == 0) {
1441 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Invalid token length (%d)", tokenlen+1);
1442 return tvb_captured_length(tvb);
1443 }
1444
1445 tempchar = tvb_get_uint8(tvb, tvb_offset);
1446 if ( (tempchar >= 'a')&& (tempchar <= 'z'))
1447 tempchar = tempchar - 0x20;
1448
1449 term = wmem_new0(pinfo->pool, gcp_term_t)((gcp_term_t*)wmem_alloc0((pinfo->pool), sizeof(gcp_term_t
)))
;
1450 wild_term = GCP_WILDCARD_NONE;
1451 term->type = GCP_TERM_TYPE_UNKNOWN0;
1452 int bytelen;
1453
1454 switch ( tempchar ){
1455
1456 case 'E':
1457 if ((tokenlen+1 > (int) sizeof(TermID))) {
1458 expert_add_info_format(pinfo, sub_ti, &ei_megaco_parse_error, "Parse error: Invalid TermID length (%d)", tokenlen+1);
1459 return tvb_captured_length(tvb);
1460 }
1461 bytelen = tvb_get_raw_bytes_as_stringz(tvb,tvb_offset,tokenlen+1,TermID);
1462 TermID[0] = 'e';
1463
1464 term->buffer = get_utf_8_string(pinfo->pool, TermID, bytelen);
1465 term->len = (int)strlen((char*)term->buffer);
1466 term->str = (const char *)term->buffer;
1467
1468 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, pinfo, keep_persistent_data);
1469
1470 /*** TERM ***/
1471 proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1472 tvb_offset, tokenlen, term->str);
1473 break;
1474
1475 case '*':
1476 wild_term = GCP_WILDCARD_ALL;
1477 term->len = 1;
1478 term->buffer = (const uint8_t*)(term->str = "*");
1479
1480 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, pinfo, keep_persistent_data);
1481
1482 proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1483 tvb_offset, tokenlen,
1484 "WildCard all");
1485 col_append_str(pinfo->cinfo, COL_INFO, "=*");
1486 break;
1487
1488 case '$':
1489 wild_term = GCP_WILDCARD_CHOOSE;
1490
1491 term->len = 1;
1492 term->buffer = (const uint8_t*)(term->str = "$");
1493
1494 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, pinfo, keep_persistent_data);
1495
1496 proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1497 tvb_offset, tokenlen,
1498 "WildCard any");
1499 col_append_str(pinfo->cinfo, COL_INFO, "=$");
1500 break;
1501 case 'O':
1502 break;
1503
1504 default:
1505 /*** TERM ***/
1506 switch (megaco_command) {
1507 case MEGACO_CMD_PRIORITY:
1508 proto_tree_add_string(megaco_tree_command_line, hf_megaco_priority, tvb,
1509 tvb_offset, tokenlen,
1510 tvb_format_text(pinfo->pool, tvb, tvb_offset,
1511 tokenlen));
1512 break;
1513 default:
1514 proto_tree_add_string(megaco_tree_command_line, hf_megaco_termid, tvb,
1515 tvb_offset, tokenlen,
1516 tvb_format_text(pinfo->pool, tvb, tvb_offset,
1517 tokenlen));
1518
1519 term->len = tokenlen;
1520 term->buffer = (const uint8_t*)(term->str = tvb_format_text(pinfo->pool, tvb, tvb_offset, tokenlen));
1521
1522 gcp_cmd_add_term(msg, trx, cmd, term, wild_term, pinfo, keep_persistent_data);
1523 break;
1524 }
1525
1526 col_append_fstr(pinfo->cinfo, COL_INFO, "=%s",tvb_format_text(pinfo->pool, tvb, tvb_offset,tokenlen));
1527 break;
1528 }
1529
1530 }
1531 /* Dissect the Descriptors */
1532
1533
1534 if ( LBRKT_counter != 0 && tvb_current_offset != tvb_command_end_offset){
1535
1536 unsigned tvb_descriptors_start_offset, tvb_descriptors_end_offset;
1537 tvb_find_uint8_length(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{', &tvb_descriptors_start_offset);
1538
1539 tvb_descriptors_end_offset = tvb_descriptors_start_offset;
1540 if ( tvb_descriptors_end_offset > tvb_transaction_end_offset )
1541 tvb_descriptors_end_offset = tvb_transaction_end_offset;
1542
1543 while ( LBRKT_counter > 0 ){
1544
1545 tvb_find_uint8_length(tvb, tvb_descriptors_end_offset + 1, tvb_transaction_end_offset, '}', &tvb_descriptors_end_offset);
1546 LBRKT_counter--;
1547
1548 }
1549
1550 tempchar = tvb_get_uint8(tvb, tvb_command_start_offset);
1551
1552 if ( tempchar == 'E'|| tempchar == 'e'){
1553 /* errorDescriptor */
1554 tvb_descriptors_start_offset = tvb_command_start_offset - 1;
1555 }
1556 dissect_megaco_descriptors(tvb_new_subset_length(tvb, tvb_descriptors_start_offset, tvb_descriptors_end_offset - tvb_descriptors_start_offset + 1), megaco_tree_command_line, pinfo, tree, ctx_id);
1557 }
1558 RBRKT_counter = 0;
1559 LBRKT_counter = 0;
1560 tvb_command_start_offset = megaco_tvb_skip_wsp(tvb, tvb_command_end_offset +1);
1561 tvb_LBRKT = tvb_command_start_offset;
1562 tvb_RBRKT = tvb_command_start_offset;
1563
1564 }
1565
1566 } while ( tvb_command_end_offset < tvb_transaction_end_offset );
1567
1568 if (keep_persistent_data) {
1569 gcp_msg_to_str(msg,pinfo->pool,keep_persistent_data);
1570 gcp_analyze_msg(megaco_tree, pinfo, tvb, msg, &megaco_ctx_ids, &ei_megaco_errored_command);
1571 }
1572
1573 tvb_next_offset = tvb_transaction_end_offset;
1574 }
1575 while( tvb_transaction_end_offset > 0 && tvb_transaction_end_offset < tvb_len - 2);
1576
1577 if(global_megaco_raw_text){
1578 tvb_raw_text_add(tvb, megaco_tree);
1579 }
1580
1581 return tvb_captured_length(tvb);
1582}
1583
1584#define MEGACO_MODEM_TOKEN1 1
1585#define MEGACO_MUX_TOKEN2 2
1586#define MEGACO_MEDIA_TOKEN3 3
1587#define MEGACO_SIGNALS_TOKEN4 4
1588#define MEGACO_SERVICES_TOKEN5 5
1589#define MEGACO_STATS_TOKEN6 6
1590#define MEGACO_ERROR_TOKEN7 7
1591#define MEGACO_EVENTS_TOKEN8 8
1592#define MEGACO_AUDIT_TOKEN9 9
1593#define MEGACO_DIGITMAP_TOKEN10 10
1594#define MEGACO_OE_TOKEN11 11
1595#define MEGACO_TOPOLOGY_TOKEN12 12
1596#define MEGACO_PACKAGES_TOKEN13 13
1597
1598static const megaco_tokens_t megaco_descriptors_names[] = {
1599 { "Unknown-token", NULL((void*)0) }, /* 0 Pad so that the real headers start at index 1 */
1600 { "Modem", "MD" }, /* 1 */
1601 { "Mux", "MX" }, /* 2 */
1602 { "Media", "M" }, /* 3 */
1603 { "Signals", "SG" }, /* 4 */
1604 { "Services", "SV" }, /* 5 */
1605 { "Statistics", "SA" }, /* 6 */
1606 { "Error", "ER" }, /* 7 */
1607 { "Events", "E" }, /* 8 */
1608 { "Audit", "AT" }, /* 9 */
1609 { "DigitMap", "DM" }, /* 10 */
1610 { "ObservedEvents", "OE" }, /* 11 */
1611 { "Topology", "TP" }, /* 12 */
1612 { "Packages", "PG" }, /* 13 */
1613};
1614
1615/* Returns index of megaco_tokens_t */
1616/* note - also called by dissect_megaco_auditdescriptor */
1617static int find_megaco_descriptors_names(tvbuff_t *tvb, int offset, unsigned header_len)
1618{
1619 unsigned i;
1620
1621 for (i = 1; i < array_length(megaco_descriptors_names)(sizeof (megaco_descriptors_names) / sizeof (megaco_descriptors_names
)[0])
; i++) {
1622 if (header_len == strlen(megaco_descriptors_names[i].name) &&
1623 tvb_strncaseeql(tvb, offset, megaco_descriptors_names[i].name, header_len) == 0)
1624 return i;
1625 if (megaco_descriptors_names[i].compact_name != NULL((void*)0) &&
1626 header_len == strlen(megaco_descriptors_names[i].compact_name) &&
1627 tvb_strncaseeql(tvb, offset, megaco_descriptors_names[i].compact_name, header_len) == 0)
1628 return i;
1629 }
1630 return -1;
1631}
1632
1633static void
1634dissect_megaco_modemdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, int tvb_RBRKT, int tvb_previous_offset)
1635{
1636
1637 int tokenlen;
1638
1639 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1640 proto_tree_add_string(megaco_tree_command_line, hf_megaco_modem_descriptor, tvb,
1641 tvb_previous_offset, tokenlen,
1642 tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
1643 tokenlen));
1644
1645}
1646static void
1647dissect_megaco_multiplexdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, int tvb_RBRKT, int tvb_previous_offset)
1648{
1649
1650 int tokenlen;
1651
1652 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
1653 proto_tree_add_string(megaco_tree_command_line, hf_megaco_multiplex_descriptor, tvb,
1654 tvb_previous_offset, tokenlen,
1655 tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
1656 tokenlen));
1657
1658}
1659
1660/* mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
1661 * MediaToken = ("Media" / "M")
1662 *
1663 * mediaParm = (streamParm / streamDescriptor /terminationStateDescriptor)
1664 *
1665 * ; at-most one terminationStateDescriptor
1666 * ; and either streamParm(s) or streamDescriptor(s) but not both
1667 * streamParm = ( localDescriptor / remoteDescriptor /localControlDescriptor )
1668 * localDescriptor = LocalToken LBRKT octetString RBRKT
1669 * LocalToken = ("Local" / "L")
1670 * octetString = *(nonEscapeChar)
1671 * nonEscapeChar = ( "\}" / %x01-7C / %x7E-FF )
1672 * remoteDescriptor = RemoteToken LBRKT octetString RBRKT
1673 * RemoteToken = ("Remote" / "R")
1674 * localControlDescriptor = LocalControlToken LBRKT localParm*(COMMA localParm) RBRKT
1675 * LocalControlToken = ("LocalControl" / "O")
1676 * localParm = ( streamMode / propertyParm / reservedValueMode
1677 * streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm*(COMMA streamParm) RBRKT
1678 * StreamToken = ("Stream" / "ST")
1679 * terminationStateDescriptor = TerminationStateToken LBRKTterminationStateParm
1680 * *( COMMA terminationStateParm ) RBRKT
1681 * TerminationStateToken = ("TerminationState" / "TS")
1682 * terminationStateParm =(propertyParm / serviceStates / eventBufferControl )
1683 */
1684
1685#define MEGACO_LOCAL_TOKEN1 1
1686#define MEGACO_REMOTE_TOKEN2 2
1687#define MEGACO_LOCAL_CONTROL_TOKEN3 3
1688#define MEGACO_STREAM_TOKEN4 4
1689#define MEGACO_TERMINATION_STATE_DESC5 5
1690// MEGACO_STATS_TOKEN is already defined as 6 above
1691
1692static const megaco_tokens_t megaco_mediaParm_names[] = {
1693 { "Unknown-token", NULL((void*)0) }, /* 0 Pad so that the real headers start at index 1 */
1694 { "Local", "L" }, /* 1 */
1695 { "Remote", "R" }, /* 2 */
1696 { "LocalControl", "O" }, /* 3 */
1697 { "Stream", "ST" }, /* 4 */
1698 { "TerminationState", "TS" }, /* 5 */
1699 { "Statistics", "SA" }, /* 6 */
1700};
1701
1702/* Returns index of megaco_tokens_t */
1703static unsigned find_megaco_mediaParm_names(tvbuff_t *tvb, int offset, unsigned header_len)
1704{
1705 unsigned i;
1706
1707 for (i = 1; i < array_length(megaco_mediaParm_names)(sizeof (megaco_mediaParm_names) / sizeof (megaco_mediaParm_names
)[0])
; i++) {
1708 if (header_len == strlen(megaco_mediaParm_names[i].name) &&
1709 tvb_strncaseeql(tvb, offset, megaco_mediaParm_names[i].name, header_len) == 0)
1710 return i;
1711 if (megaco_mediaParm_names[i].compact_name != NULL((void*)0) &&
1712 header_len == strlen(megaco_mediaParm_names[i].compact_name) &&
1713 tvb_strncaseeql(tvb, offset, megaco_mediaParm_names[i].compact_name, header_len) == 0)
1714 return i;
1715 }
1716
1717 return 0;
1718}
1719
1720static void
1721dissect_megaco_mediadescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line,packet_info *pinfo, unsigned tvb_last_RBRKT,
1722 unsigned tvb_previous_offset, unsigned start_offset, proto_tree *top_tree, uint32_t context)
1723{
1724
1725 unsigned tokenlen, tvb_LBRKT, tvb_RBRKT;
1726 unsigned tvb_next_offset, tvb_current_offset, tvb_offset, equal_offset, save_offset;
1727 unsigned mediaParm;
1728 unsigned streamId;
1729
1730 proto_tree *megaco_mediadescriptor_tree;
1731 proto_item *megaco_mediadescriptor_ti, *ti;
1732
1733 megaco_mediadescriptor_ti = proto_tree_add_item(megaco_tree_command_line, hf_megaco_media_descriptor, tvb, start_offset, 1, ENC_NA0x00000000);
1734 megaco_mediadescriptor_tree = proto_item_add_subtree(megaco_mediadescriptor_ti, ett_megaco_mediadescriptor);
1735
1736 while ( tvb_previous_offset < tvb_last_RBRKT){
1737 /* Start of token */
1738 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
1739
1740 /* Find token length */
1741 for (tvb_next_offset=tvb_current_offset; tvb_next_offset < tvb_last_RBRKT; tvb_next_offset++){
1742 if (!g_ascii_isalpha(tvb_get_uint8(tvb, tvb_next_offset ))((g_ascii_table[(guchar) (tvb_get_uint8(tvb, tvb_next_offset )
)] & G_ASCII_ALPHA) != 0)
){
1743 break;
1744 }
1745 }
1746 tokenlen = tvb_next_offset - tvb_current_offset;
1747
1748 mediaParm = find_megaco_mediaParm_names(tvb, tvb_current_offset, tokenlen);
1749
1750 if (!tvb_find_uint8_length(tvb, tvb_next_offset, tvb_last_RBRKT, '{', &tvb_LBRKT)) {
1751 // Not found, use the end offset.
1752 tvb_LBRKT = tvb_last_RBRKT;
1753 }
1754
1755 if (!tvb_find_uint8_length(tvb, tvb_current_offset + 1, tvb_last_RBRKT, '}', &tvb_RBRKT)) {
1756 // Not found, use the end offset.
1757 tvb_RBRKT = tvb_last_RBRKT;
1758 }
1759
1760 tvbuff_t *descriptor_tvb;
1761 /* Most of the descriptors here (unlike elsewhere in the dissector don't
1762 * expect to be passed a tvb including the mediaParm token, but the
1763 * dissect_megaco_statisticsdescriptor does), so we can't have a common
1764 * subset tvb.
1765 */
1766 switch ( mediaParm ){
1767 case MEGACO_LOCAL_TOKEN1:
1768 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1769 descriptor_tvb = tvb_new_subset_length(tvb, tvb_current_offset, tvb_RBRKT - tvb_current_offset + 1);
1770 dissect_megaco_LocalRemotedescriptor(descriptor_tvb, megaco_mediadescriptor_tree, pinfo,
1771 context, true1);
1772 tvb_current_offset = tvb_RBRKT;
1773 break;
1774 case MEGACO_REMOTE_TOKEN2:
1775 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1776 descriptor_tvb = tvb_new_subset_length(tvb, tvb_current_offset, tvb_RBRKT - tvb_current_offset + 1);
1777 dissect_megaco_LocalRemotedescriptor(descriptor_tvb, megaco_mediadescriptor_tree, pinfo,
1778 context, false0);
1779 tvb_current_offset = tvb_RBRKT;
1780 break;
1781 case MEGACO_LOCAL_CONTROL_TOKEN3:
1782 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1783 descriptor_tvb = tvb_new_subset_length(tvb, tvb_current_offset, tvb_RBRKT - tvb_current_offset + 1);
1784 dissect_megaco_LocalControldescriptor(descriptor_tvb, megaco_mediadescriptor_tree, pinfo, top_tree);
1785 tvb_current_offset = tvb_RBRKT;
1786 break;
1787 case MEGACO_STREAM_TOKEN4:
1788 save_offset = tvb_current_offset;
1789 tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_last_RBRKT, '=', &equal_offset);
1790 tvb_current_offset = megaco_tvb_skip_wsp(tvb, equal_offset+1);
1791 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_LBRKT-1);
1792 tokenlen = tvb_offset - tvb_current_offset;
1793
1794 streamId = (unsigned)strtoul(tvb_format_text(pinfo->pool, tvb, tvb_current_offset,tokenlen),NULL((void*)0),10);
1795 ti = proto_tree_add_uint(megaco_mediadescriptor_tree, hf_megaco_streamid, tvb,
1796 save_offset, 1, streamId);
1797 proto_item_set_len(ti, tvb_offset-save_offset);
1798 tvb_previous_offset = tvb_LBRKT+1;
1799 continue;
1800 case MEGACO_TERMINATION_STATE_DESC5:
1801 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1802 descriptor_tvb = tvb_new_subset_length(tvb, tvb_current_offset, tvb_RBRKT - tvb_current_offset + 1);
1803 dissect_megaco_TerminationStatedescriptor(descriptor_tvb, pinfo, megaco_mediadescriptor_tree);
1804 tvb_current_offset = tvb_RBRKT;
1805 break;
1806 case MEGACO_STATS_TOKEN6:
1807 // dissect_megaco_statisticsdescriptor wants the previous
1808 // offset, don't skip forward.
1809 //tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1810 descriptor_tvb = tvb_new_subset_length(tvb, tvb_current_offset, tvb_RBRKT - tvb_current_offset + 1);
1811 dissect_megaco_statisticsdescriptor(descriptor_tvb, megaco_mediadescriptor_tree);
1812 tvb_current_offset = tvb_RBRKT;
1813 break;
1814 default:
1815 break;
1816 };
1817 /* more parameters ? */
1818 if ( !tvb_find_uint8_length(tvb, tvb_current_offset + 1, tvb_last_RBRKT, ',', &tvb_next_offset)){
1819 /* (raw formatting removed)
1820 tokenlen = tvb_next_offset - tvb_RBRKT+1;
1821 proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_RBRKT, tokenlen); */
1822 tvb_previous_offset = tvb_next_offset+1;
1823 } else{
1824 if (tvb_next_offset > tvb_last_RBRKT) {
1825 tvb_next_offset = tvb_last_RBRKT;
1826 }
1827 /* Add the trailing '}' (raw formatting removed) */
1828 /* proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_RBRKT, 1); */
1829 tvb_previous_offset = tvb_last_RBRKT;
1830 }
1831
1832 } /* End while */
1833
1834 proto_item_set_end(megaco_mediadescriptor_ti, tvb, tvb_previous_offset);
1835}
1836
1837static void
1838dissect_megaco_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree, int offset, int len, proto_tree *top_tree)
1839{
1840 /*proto_item *item;*/
1841 /*proto_tree *tree;*/
1842 char *msg = tvb_format_text(pinfo->pool, tvb, offset, len);
1843
1844 /*item= */proto_tree_add_item(megaco_tree, hf_megaco_h245, tvb, offset, len, ENC_NA0x00000000);
1845 /*tree = proto_item_add_subtree(item, ett_megaco_h245); */
1846
1847 /* arbitrary maximum length */
1848 if(len<20480){
1849 int i;
1850 tvbuff_t *h245_tvb;
1851 uint8_t *buf = (uint8_t *)wmem_alloc(pinfo->pool, 10240);
1852
1853 /* first, skip to where the encoded pdu starts, this is
1854 the first hex digit after the '=' char.
1855 */
1856 while(1){
1857 if((*msg==0)||(*msg=='\n')){
1858 return;
1859 }
1860 if(*msg=='='){
1861 msg++;
1862 break;
1863 }
1864 msg++;
1865 }
1866 while(1){
1867 if((*msg==0)||(*msg=='\n')){
1868 return;
1869 }
1870 if( ((*msg>='0')&&(*msg<='9'))
1871 || ((*msg>='a')&&(*msg<='f'))
1872 || ((*msg>='A')&&(*msg<='F'))){
1873 break;
1874 }
1875 msg++;
1876 }
1877 i=0;
1878 while( ((*msg>='0')&&(*msg<='9'))
1879 ||((*msg>='a')&&(*msg<='f'))
1880 ||((*msg>='A')&&(*msg<='F')) ){
1881 int val;
1882 if((*msg>='0')&&(*msg<='9')){
1883 val=(*msg)-'0';
1884 } else if((*msg>='a')&&(*msg<='f')){
1885 val=(*msg)-'a'+10;
1886 } else if((*msg>='A')&&(*msg<='F')){
1887 val=(*msg)-'A'+10;
1888 } else {
1889 return;
1890 }
1891 val<<=4;
1892 msg++;
1893 if((*msg>='0')&&(*msg<='9')){
1894 val|=(*msg)-'0';
1895 } else if((*msg>='a')&&(*msg<='f')){
1896 val|=(*msg)-'a'+10;
1897 } else if((*msg>='A')&&(*msg<='F')){
1898 val|=(*msg)-'A'+10;
1899 } else {
1900 return;
1901 }
1902 msg++;
1903
1904 buf[i]=(uint8_t)val;
1905 i++;
1906 }
1907 if(i==0){
1908 return;
1909 }
1910 h245_tvb = tvb_new_child_real_data(tvb, buf,i,i);
1911 add_new_data_source(pinfo, h245_tvb, "H.245 over MEGACO");
1912 /* should go through a handle, however, the two h245 entry
1913 points are different, one is over tpkt and the other is raw
1914 */
1915 call_dissector(h245_handle, h245_tvb, pinfo, top_tree);
1916/* dissect_h245_MultimediaSystemControlMessage(h245_tvb, pinfo, tree);*/
1917 }
1918}
1919
1920static void
1921dissect_megaco_h324_h223caprn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree, int offset _U___attribute__((unused)), int len, char *msg)
1922{
1923 asn1_ctx_t actx;
1924
1925 /* arbitrary maximum length */
1926 if(len<20480){
1927 int i;
1928 tvbuff_t *h245_tvb;
1929 uint8_t *buf = (uint8_t *)wmem_alloc(pinfo->pool, 10240);
1930
1931 /* first, skip to where the encoded pdu starts, this is
1932 the first hex digit after the '=' char.
1933 */
1934 while(1){
1935 if((*msg==0)||(*msg=='\n')){
1936 return;
1937 }
1938 if(*msg=='='){
1939 msg++;
1940 break;
1941 }
1942 msg++;
1943 }
1944 while(1){
1945 if((*msg==0)||(*msg=='\n')){
1946 return;
1947 }
1948 if( ((*msg>='0')&&(*msg<='9'))
1949 || ((*msg>='a')&&(*msg<='f'))
1950 || ((*msg>='A')&&(*msg<='F'))){
1951 break;
1952 }
1953 msg++;
1954 }
1955 i=0;
1956 while( ((*msg>='0')&&(*msg<='9'))
1957 ||((*msg>='a')&&(*msg<='f'))
1958 ||((*msg>='A')&&(*msg<='F')) ){
1959 int val;
1960 if((*msg>='0')&&(*msg<='9')){
1961 val=(*msg)-'0';
1962 } else if((*msg>='a')&&(*msg<='f')){
1963 val=(*msg)-'a'+10;
1964 } else if((*msg>='A')&&(*msg<='F')){
1965 val=(*msg)-'A'+10;
1966 } else {
1967 return;
1968 }
1969 val<<=4;
1970 msg++;
1971 if((*msg>='0')&&(*msg<='9')){
1972 val|=(*msg)-'0';
1973 } else if((*msg>='a')&&(*msg<='f')){
1974 val|=(*msg)-'a'+10;
1975 } else if((*msg>='A')&&(*msg<='F')){
1976 val|=(*msg)-'A'+10;
1977 } else {
1978 return;
1979 }
1980 msg++;
1981
1982 buf[i]=(uint8_t)val;
1983 i++;
1984 }
1985 if(i==0){
1986 return;
1987 }
1988 h245_tvb = tvb_new_child_real_data(tvb, buf,i,i);
1989 add_new_data_source(pinfo, h245_tvb, "H.245 over MEGACO");
1990 /* should go through a handle, however, the two h245 entry
1991 points are different, one is over tpkt and the other is raw
1992 */
1993 asn1_ctx_init(&actx, ASN1_ENC_PER, true1, pinfo);
1994 dissect_h245_H223Capability(h245_tvb, 0, &actx, megaco_tree, hf_megaco_h223Capability);
1995 }
1996}
1997
1998static void
1999dissect_megaco_eventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, proto_tree *top_tree)
2000{
2001
2002 /* eventsDescriptor = EventsToken EQUAL RequestID LBRKT
2003 * requestedEvent *( COMMA requestedEvent ) RBRKT
2004 * requestedEvent = pkgdName [ LBRKT eventParameter
2005 * *( COMMA eventParameter ) RBRKT ]
2006 */
2007
2008 unsigned tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset, tvb_previous_offset;
2009 unsigned tvb_events_end_offset, tvb_LBRKT, tvb_RBRKT;
2010 proto_tree *megaco_eventsdescriptor_tree, *megaco_requestedevent_tree;
2011 proto_item *megaco_eventsdescriptor_ti, *megaco_requestedevent_ti;
2012
2013 unsigned requested_event_start_offset = 0,
2014 requested_event_end_offset = 0;
2015
2016 tvb_events_end_offset = tvb_reported_length(tvb);
2017
2018 megaco_eventsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_events_descriptor, tvb, 0, tvb_events_end_offset, ENC_NA0x00000000);
2019 megaco_eventsdescriptor_tree = proto_item_add_subtree(megaco_eventsdescriptor_ti, ett_megaco_eventsdescriptor);
2020
2021 if (tvb_find_uint8_remaining(tvb, 0, '=', &tvb_current_offset)) {
2022
2023 /* If it fails something's malformed, but handle below. */
2024 tvb_find_uint8_remaining(tvb, 0, '{', &tvb_next_offset);
2025
2026 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2027 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset - 1);
2028
2029 tokenlen = tvb_help_offset - tvb_current_offset;
2030
2031 /* TODO - An example of where tvb_strtou functions, or perhaps better,
2032 * finally implementing ENC_STR_NUM, might be useful. The latter could
2033 * also nicely handle failure cases with expert info. */
2034 proto_tree_add_uint(megaco_eventsdescriptor_tree, hf_megaco_requestid, tvb,
2035 tvb_current_offset, tokenlen,
2036 (uint32_t) strtoul(tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen), NULL((void*)0), 10));
2037
2038 if (tvb_next_offset == tvb_events_end_offset) {
2039 /* No LBRKT before the first requestedEvent (expert info?) */
2040 return;
2041 }
2042 tvb_RBRKT = tvb_next_offset+1;
2043 tvb_LBRKT = tvb_next_offset+1;
2044 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
2045
2046 do {
2047
2048 tvb_find_uint8_remaining(tvb, tvb_RBRKT + 1, '}', &tvb_RBRKT);
2049 tvb_find_uint8_remaining(tvb, tvb_previous_offset, ',', &tvb_current_offset);
2050
2051 if (!tvb_find_uint8_remaining(tvb, tvb_LBRKT, '{', &tvb_LBRKT) || tvb_LBRKT > tvb_current_offset) {
2052 /* Descriptor includes no parameters */
2053 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2054 } else {
2055 /* Descriptor includes Parameters */
2056 /* If the next LBRKT is before RBRKT, then there's nested braces.
2057 * Keep going until balanced or we run out of buffer. */
2058 while (tvb_find_uint8_remaining(tvb, tvb_LBRKT+1, '{', &tvb_LBRKT) && tvb_LBRKT < tvb_RBRKT) {
2059 if (tvb_RBRKT < tvb_events_end_offset) {
2060 tvb_find_uint8_remaining(tvb, tvb_RBRKT+1, '}', &tvb_RBRKT);
2061 }
2062 }
2063 }
2064
2065 tvb_find_uint8_remaining(tvb, tvb_previous_offset, '{', &tvb_help_offset);
2066 /* if there are eventparameter */
2067
2068 if (tvb_help_offset < tvb_RBRKT){
2069
2070 requested_event_start_offset = tvb_help_offset;
2071 requested_event_end_offset = tvb_RBRKT;
2072 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2073 tokenlen = tvb_help_offset - tvb_previous_offset;
2074 }
2075 /* no parameters */
2076 else {
2077 tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2078 }
2079
2080 megaco_requestedevent_ti = proto_tree_add_item(megaco_eventsdescriptor_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,tokenlen, ENC_UTF_80x00000002);
2081 megaco_requestedevent_tree = proto_item_add_subtree(megaco_requestedevent_ti, ett_megaco_requestedevent);
2082
2083 if (tvb_help_offset < tvb_RBRKT) {
2084
2085 requested_event_start_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1);
2086 requested_event_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_event_end_offset-1);
2087
2088 if (!tvb_strncaseeql(tvb, requested_event_start_offset, "dm", 2)) {
2089 dissect_megaco_digitmapdescriptor(tvb, pinfo, megaco_requestedevent_tree, requested_event_end_offset, requested_event_start_offset);
2090 }
2091 else{
2092 tokenlen = requested_event_end_offset - requested_event_start_offset;
2093 if(!tvb_strneql(tvb, requested_event_start_offset, "h245", 4)){
2094 dissect_megaco_h245(tvb, pinfo, megaco_requestedevent_tree, requested_event_start_offset, tokenlen, top_tree);
2095 } else {
2096 proto_tree_add_format_text(megaco_requestedevent_tree, tvb, requested_event_start_offset, tokenlen);
2097 }
2098 }
2099
2100 }
2101
2102 tvb_previous_offset = tvb_current_offset;
2103 tvb_find_uint8_remaining(tvb, tvb_RBRKT, ',', &tvb_current_offset);
2104
2105 if (tvb_current_offset < tvb_previous_offset ) {
2106 tvb_current_offset = tvb_events_end_offset;
2107 }
2108
2109 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2110
2111 tvb_LBRKT = tvb_previous_offset;
2112 tvb_RBRKT = tvb_previous_offset;
2113
2114 } while ( tvb_current_offset < tvb_events_end_offset );
2115 }
2116}
2117
2118static void
2119dissect_megaco_signaldescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, unsigned tvb_RBRKT, unsigned tvb_previous_offset, proto_tree *top_tree)
2120{
2121
2122 unsigned tokenlen, pkg_tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
2123 unsigned tvb_signals_end_offset, tvb_signals_start_offset, tvb_LBRKT;
2124 bool_Bool found, LBRKT_found;
2125 proto_tree *megaco_signalsdescriptor_tree, *megaco_requestedsignal_tree;
2126 proto_item *megaco_signalsdescriptor_ti, *megaco_requestedsignal_ti;
2127
2128 unsigned requested_signal_start_offset = 0, requested_signal_end_offset = 0;
2129
2130 tvb_signals_end_offset = tvb_RBRKT;
2131 tvb_signals_start_offset = tvb_previous_offset;
2132
2133 if(g_ascii_toupper(tvb_get_uint8(tvb, tvb_previous_offset+1))=='G')
2134 tokenlen = 2; /* token is compact text (SG) */
2135 else
2136 tokenlen = 7; /* token must be verbose text (Signals) */
2137
2138 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset+tokenlen);
2139
2140 if(tvb_get_uint8(tvb, tvb_current_offset)!='{') { /* {} has been omitted */
2141
2142 megaco_signalsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line, hf_megaco_signal_descriptor, tvb, tvb_signals_start_offset, tokenlen, ENC_NA0x00000000);
2143 expert_add_info(pinfo, megaco_signalsdescriptor_ti, &ei_megaco_signal_descriptor);
2144
2145 col_append_str(pinfo->cinfo, COL_INFO, " (Signal:none)"); /* then say so */
2146
2147 return; /* and return */
2148 }
2149
2150 LBRKT_found = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_signals_end_offset, '{', &tvb_LBRKT);
2151 if (LBRKT_found == false0) {
2152 // This should not happen, because we should at least find the '{' found
2153 // above at tvb_current_offset. DISSECTOR_ASSERT?
2154 return;
2155 }
2156 tokenlen = (tvb_LBRKT+1) - tvb_signals_start_offset;
2157
2158 megaco_signalsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_signal_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_NA0x00000000);
2159 megaco_signalsdescriptor_tree = proto_item_add_subtree(megaco_signalsdescriptor_ti, ett_megaco_signalsdescriptor);
2160
2161 tvb_current_offset = tvb_LBRKT;
2162 tvb_next_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2163 col_append_fstr(pinfo->cinfo, COL_INFO, " (Signal:%s)",tvb_format_text(pinfo->pool, tvb, tvb_current_offset,tokenlen-tvb_current_offset+tvb_previous_offset));
2164
2165
2166 if ( tvb_current_offset < tvb_signals_end_offset && tvb_next_offset != tvb_signals_end_offset){
2167
2168
2169 tvb_RBRKT = tvb_next_offset+1;
2170 tvb_LBRKT = tvb_next_offset+1;
2171 tvb_previous_offset = tvb_next_offset;
2172
2173
2174 do {
2175
2176 tvb_find_uint8_length(tvb, tvb_RBRKT+1, tvb_signals_end_offset, '}', &tvb_RBRKT);
2177 LBRKT_found = tvb_find_uint8_length(tvb, tvb_LBRKT, tvb_signals_end_offset, '{', &tvb_LBRKT);
2178
2179 found = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_signals_end_offset, ',', &tvb_current_offset);
2180
2181 if (found == false0 || tvb_current_offset > tvb_signals_end_offset){
2182 tvb_current_offset = tvb_signals_end_offset;
2183 }
2184
2185
2186 /* Descriptor includes no parameters */
2187
2188 if ( tvb_LBRKT > tvb_current_offset || LBRKT_found == false0 ){
2189
2190 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2191 }
2192
2193 /* Descriptor includes Parameters */
2194
2195 if ( (tvb_current_offset > tvb_LBRKT && LBRKT_found == true1)){
2196
2197 while (LBRKT_found == true1 && tvb_RBRKT > tvb_LBRKT ){
2198
2199 LBRKT_found = tvb_find_uint8_length(tvb, tvb_LBRKT+1, tvb_signals_end_offset, '{', &tvb_LBRKT);
2200 if ( tvb_LBRKT < tvb_RBRKT && LBRKT_found == true1)
2201 tvb_find_uint8_length(tvb, tvb_RBRKT+1, tvb_signals_end_offset, '}', &tvb_RBRKT);
2202 }
2203
2204 }
2205
2206 found = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_signals_end_offset, '{', &tvb_help_offset);
2207
2208 /* if there are signalparameter */
2209
2210 if ( tvb_help_offset < tvb_RBRKT && found == true1 ){
2211
2212 requested_signal_start_offset = tvb_help_offset;
2213 requested_signal_end_offset = tvb_RBRKT;
2214 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2215 pkg_tokenlen = tvb_help_offset - tvb_previous_offset;
2216 }
2217 /* no parameters */
2218 else {
2219 pkg_tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2220 }
2221
2222 megaco_requestedsignal_ti = proto_tree_add_item(megaco_signalsdescriptor_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,pkg_tokenlen, ENC_UTF_80x00000002);
2223 megaco_requestedsignal_tree = proto_item_add_subtree(megaco_requestedsignal_ti, ett_megaco_requestedsignal);
2224
2225 if ( tvb_help_offset < tvb_RBRKT && found == true1){
2226 requested_signal_start_offset = megaco_tvb_skip_wsp(tvb, requested_signal_start_offset +1);
2227 requested_signal_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_signal_end_offset-1);
2228
2229 tokenlen = requested_signal_end_offset - requested_signal_start_offset;
2230
2231 if(!tvb_strneql(tvb, requested_signal_start_offset, "h245", 4)){
2232 dissect_megaco_h245(tvb, pinfo, megaco_requestedsignal_tree, requested_signal_start_offset, tokenlen, top_tree);
2233 } else {
2234 proto_tree_add_format_text( megaco_requestedsignal_tree, tvb, requested_signal_start_offset, tokenlen);
2235 }
2236 /* Print the trailing '}' (raw formatting removed) */
2237 /* proto_tree_add_format_text( megaco_requestedsignal_tree, tvb, tvb_RBRKT, 1); */
2238 }
2239
2240 found = tvb_find_uint8_length(tvb, tvb_RBRKT, tvb_signals_end_offset, ',', &tvb_current_offset);
2241
2242 if (found == false0 || tvb_current_offset > tvb_signals_end_offset || tvb_current_offset < tvb_previous_offset){
2243 tvb_current_offset = tvb_signals_end_offset;
2244 }
2245
2246 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2247
2248 tvb_LBRKT = tvb_previous_offset;
2249 tvb_RBRKT = tvb_previous_offset;
2250 /* Print the trailing '}' (raw formatting removed) */
2251 /* proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1); */
2252
2253 } while ( tvb_current_offset < tvb_signals_end_offset );
2254 }else{
2255 /* signals{} (raw formatting removed)
2256 proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1); */
2257 }
2258
2259
2260}
2261
2262/*
2263 auditDescriptor = AuditToken LBRKT [ auditItem *(COMMA auditItem) ] RBRKT
2264
2265 V1:
2266 auditItem = ( MuxToken / ModemToken / MediaToken /
2267 SignalsToken / EventBufferToken /
2268 DigitMapToken / StatsToken / EventsToken /
2269 ObservedEventsToken / PackagesToken )
2270
2271 V3:
2272 auditItem = ( auditReturnItem / SignalsToken / EventBufferToken /
2273 EventsToken / indAudterminationAudit )
2274
2275 auditReturnItem = ( MuxToken / ModemToken / MediaToken / DigitMapToken /
2276 StatsToken / ObservedEventsToken / PackagesToken )
2277
2278 indAudauditReturnParameter
2279 = ( indAudmediaDescriptor / indAudeventsDescriptor /
2280 indAudsignalsDescriptor / indAuddigitMapDescriptor /
2281 indAudeventBufferDescriptor /
2282 indAudstatisticsDescriptor / indAudpackagesDescriptor )
2283 */
2284static void
2285dissect_megaco_auditdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree, packet_info *pinfo _U___attribute__((unused)), proto_tree *top_tree, uint32_t context)
2286{
2287 int token_index;
2288 unsigned tokenlen, tvb_offset, tvb_stop, tvb_end, tvb_next, tvb_token_end;
2289 proto_tree *megaco_auditdescriptor_tree, *megaco_auditdescriptor_ti;
2290 bool_Bool descriptor;
2291
2292 /* find opening LBRKT - is this already checked by caller? */
2293 if(!tvb_find_uint8_remaining(tvb, 0, '{', &tvb_next)) {
2294 /* complain and give up if not there */
2295 expert_add_info(pinfo, megaco_tree, &ei_megaco_audit_descriptor);
2296 return;
2297 }
2298
2299 tokenlen = tvb_reported_length(tvb);
2300
2301 megaco_auditdescriptor_ti = proto_tree_add_item( megaco_tree, hf_megaco_audit_descriptor, tvb, 0, tokenlen, ENC_NA0x00000000);
2302 megaco_auditdescriptor_tree = proto_item_add_subtree( megaco_auditdescriptor_ti, ett_megaco_auditdescriptor );
2303
2304 tvb_offset = tvb_next;
2305 tvb_stop = tokenlen - 1;
2306
2307 while( tvb_offset < tvb_stop )
2308 {
2309 tvb_offset = megaco_tvb_skip_wsp(tvb, tvb_offset+1); /* find start of an auditItem */
2310 if( tvb_get_uint8(tvb, tvb_offset) != '}' ) /* got something */
2311 {
2312 /* end of an auditItem */
2313 if(!tvb_find_uint8_remaining(tvb, tvb_offset, ',', &tvb_next)) {
2314 /* last item doesn't have a comma */
2315 tvb_next = tvb_stop;
2316 }
2317
2318 tvb_end = megaco_tvb_skip_wsp_return(tvb, tvb_next-1); /* trim any trailing whitespace */
2319
2320 if (!tvb_find_uint8_length(tvb, tvb_offset, tvb_next - tvb_offset + 1, '{', NULL((void*)0))) {
2321 /* auditItem has no parameters (i.e., is a Token) */
2322 descriptor = false0;
2323 tvb_token_end = tvb_end;
2324 } else {
2325 /* auditItem includes Parameters (i.e., is a Descriptor) */
2326 descriptor = true1;
2327 for (tvb_token_end=tvb_offset; tvb_token_end < tvb_end ; tvb_token_end++){
2328 if (!g_ascii_isalpha(tvb_get_uint8(tvb, tvb_token_end ))((g_ascii_table[(guchar) (tvb_get_uint8(tvb, tvb_token_end ))
] & G_ASCII_ALPHA) != 0)
){
2329 break;
2330 }
2331 }
2332 }
2333
2334 tokenlen = tvb_token_end - tvb_offset; /* get length of token */
2335
2336 token_index = find_megaco_descriptors_names(tvb, tvb_offset, tokenlen); /* lookup the token */
2337 if( token_index == -1 ) /* if not found then 0 => Unknown */
2338 token_index = 0;
2339
2340 if (descriptor) {
2341 tvbuff_t *descriptor_tvb = tvb_new_subset_length(tvb, tvb_offset, tvb_end - tvb_offset + 1);
2342 switch ( token_index ){
2343 case MEGACO_MEDIA_TOKEN3:
2344 {
2345 unsigned temp_offset;
2346 tvb_find_uint8_remaining(tvb, tvb_offset, '{', &temp_offset);
2347 unsigned save_offset = tvb_offset;
2348
2349 tvb_offset = megaco_tvb_skip_wsp(tvb, temp_offset +1);
2350 dissect_megaco_mediadescriptor(tvb, megaco_auditdescriptor_tree, pinfo, tvb_end, tvb_offset, save_offset, top_tree, context);
2351 break;
2352 }
2353 case MEGACO_SIGNALS_TOKEN4:
2354 dissect_megaco_signaldescriptor(tvb, pinfo, megaco_auditdescriptor_tree, tvb_end, tvb_offset, top_tree);
2355 break;
2356 case MEGACO_STATS_TOKEN6:
2357 dissect_megaco_statisticsdescriptor(descriptor_tvb, megaco_auditdescriptor_tree);
2358 break;
2359 case MEGACO_EVENTS_TOKEN8:
2360 dissect_megaco_eventsdescriptor(descriptor_tvb, pinfo, megaco_auditdescriptor_tree, top_tree);
2361 break;
2362 case MEGACO_DIGITMAP_TOKEN10:
2363 dissect_megaco_digitmapdescriptor(tvb, pinfo, megaco_auditdescriptor_tree, tvb_end, tvb_offset);
2364 break;
2365 case MEGACO_PACKAGES_TOKEN13:
2366 dissect_megaco_Packagesdescriptor(tvb, pinfo, megaco_auditdescriptor_tree, tvb_end, tvb_offset);
2367 break;
2368 default:
2369 tokenlen = tvb_end - tvb_offset;
2370 proto_tree_add_string(megaco_auditdescriptor_tree, hf_megaco_audititem, tvb,
2371 tvb_offset, tokenlen, megaco_descriptors_names[token_index].name); /* and display the long form */
2372 break;
2373 }
2374 } else {
2375 proto_tree_add_string(megaco_auditdescriptor_tree, hf_megaco_audititem, tvb,
2376 tvb_offset, tokenlen, megaco_descriptors_names[token_index].name); /* and display the long form */
2377 }
2378
2379 tvb_offset = tvb_next; /* advance pointer */
2380 }
2381 }
2382}
2383
2384/*
2385 * serviceChangeDescriptor = ServicesToken LBRKT serviceChangeParm
2386 * *(COMMA serviceChangeParm) RBRKT
2387 *
2388 * ServicesToken = ("Services" / "SV")
2389 *
2390 * serviceChangeParm = (serviceChangeMethod / serviceChangeReason /
2391 * serviceChangeDelay / serviceChangeAddress /
2392 * serviceChangeProfile / extension / TimeStamp /
2393 * serviceChangeMgcId / serviceChangeVersion )
2394 *
2395 */
2396#define MEGACO_REASON_TOKEN1 1
2397#define MEGACO_DELAY_TOKEN2 2
2398#define MEGACO_SC_ADDR_TOKEN3 3
2399#define MEGACO_MGC_ID_TOKEN4 4
2400#define MEGACO_PROFILE_TOKEN5 5
2401#define MEGACO_VERSION_TOKEN6 6
2402#define MEGACO_METHOD_TOKEN7 7
2403
2404static const megaco_tokens_t megaco_serviceChangeParm_names[] = {
2405 { "Unknown-token", NULL((void*)0) }, /* 0 Pad so that the real headers start at index 1 */
2406 /* streamMode */
2407 { "Reason", "RE" }, /* 1 ReasonToken*/
2408 { "Delay", "DL" }, /* 2 DelayToken */
2409 { "ServiceChangeAddress", "AD" }, /* 3 ServiceChangeAddressToken */
2410 { "MgcIdToTry", "MG" }, /* 4 MgcIdToken */
2411 { "Profile", "PF" }, /* 5 ProfileToken */
2412 { "Version", "V" }, /* 6 VersionToken */
2413 { "Method", "MT" }, /* 7 MethodToken */
2414};
2415
2416/* Returns index of megaco_tokens_t */
2417static int find_megaco_megaco_serviceChangeParm_names(tvbuff_t *tvb, int offset, unsigned header_len)
2418{
2419 unsigned i;
2420
2421 for (i = 1; i < array_length(megaco_serviceChangeParm_names)(sizeof (megaco_serviceChangeParm_names) / sizeof (megaco_serviceChangeParm_names
)[0])
; i++) {
2422 if (header_len == strlen(megaco_serviceChangeParm_names[i].name) &&
2423 tvb_strncaseeql(tvb, offset, megaco_serviceChangeParm_names[i].name, header_len) == 0)
2424 return i;
2425 if (megaco_serviceChangeParm_names[i].compact_name != NULL((void*)0) &&
2426 header_len == strlen(megaco_serviceChangeParm_names[i].compact_name) &&
2427 tvb_strncaseeql(tvb, offset, megaco_serviceChangeParm_names[i].compact_name, header_len) == 0)
2428 return i;
2429 }
2430
2431 return -1;
2432}
2433/*
2434 * ServiceChangeReasons References
2435 * -------------------- ----------
2436 */
2437static const value_string MEGACO_ServiceChangeReasons_vals[] = {
2438 {900, "Service Restored"},
2439 {901, "Cold Boot"},
2440 {902, "Warm Boot"},
2441 {903, "MGC Directed Change"},
2442 {904, "Termination malfunctioning"},
2443 {905, "Termination taken out of service"},
2444 {906, "Loss of lower layer connectivity (e.g. downstream sync)"},
2445 {907, "Transmission Failure"},
2446 {908, "MG Impending Failure"},
2447 {909, "MGC Impending Failure"},
2448 {910, "Media Capability Failure"},
2449 {911, "Modem Capability Failure"},
2450 {912, "Mux Capability Failure"},
2451 {913, "Signal Capability Failure"},
2452 {914, "Event Capability Failure"},
2453 {915, "State Loss"},
2454 {916, "Packages Change"},
2455 {917, "Capabilities Change"},
2456 {918, "Cancel Graceful"},
2457 {919, "Warm Failover"},
2458 {920, "Cold Failover"},
2459 { 0, NULL((void*)0) }
2460};
2461
2462static void
2463dissect_megaco_servicechangedescriptor(tvbuff_t *tvb, packet_info* pinfo, proto_tree *megaco_tree, unsigned tvb_RBRKT,
2464 unsigned tvb_previous_offset)
2465{
2466
2467 unsigned tokenlen, tvb_LBRKT, tvb_offset;
2468 unsigned token_index;
2469 unsigned tvb_current_offset;
2470 bool_Bool found;
2471 bool_Bool more_params = true1;
2472 proto_item* item;
2473 int reason;
2474 bool_Bool reason_valid;
2475 uint8_t ServiceChangeReason_str[4];
2476
2477 tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_RBRKT, '{', &tvb_LBRKT);
2478 /*
2479 if (tvb_LBRKT == -1)
2480 return;
2481 */
2482 tokenlen = (tvb_LBRKT + 1) - tvb_previous_offset;
2483 proto_tree_add_format_text(megaco_tree, tvb, tvb_previous_offset, tokenlen);
2484
2485 /* Start dissecting serviceChangeParm */
2486 tvb_previous_offset = tvb_LBRKT + 1;
2487 while (more_params){
2488 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_previous_offset);
2489 /* Find token length */
2490 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_RBRKT; tvb_offset++){
2491 if (!g_ascii_isalpha(tvb_get_uint8(tvb, tvb_offset ))((g_ascii_table[(guchar) (tvb_get_uint8(tvb, tvb_offset ))] &
G_ASCII_ALPHA) != 0)
){
2492 break;
2493 }
2494 }
2495 tokenlen = tvb_offset - tvb_previous_offset;
2496 token_index = find_megaco_megaco_serviceChangeParm_names(tvb, tvb_previous_offset, tokenlen);
2497
2498 found = tvb_find_uint8_length(tvb, tvb_offset, tvb_RBRKT, ',', &tvb_offset);
2499 if ((found == false0)||(tvb_offset >=tvb_RBRKT)){
2500 more_params = false0;
2501 tvb_offset = megaco_tvb_skip_wsp_return(tvb, tvb_RBRKT-1);
2502 }
2503 tokenlen = tvb_offset - tvb_previous_offset;
2504 if (more_params == true1 )
2505 /* Include ',' */
2506 tokenlen++;
2507 switch(token_index){
2508 case MEGACO_REASON_TOKEN1:
2509 /* ReasonToken EQUAL VALUE
2510 * VALUE = quotedString / 1*(SafeChar)
2511 */
2512 item = proto_tree_add_format_text(megaco_tree, tvb, tvb_previous_offset, tokenlen);
2513
2514 /* As the reason code ( if a digit ) can be in quoted string or 'just' digit
2515 * look for a nine and hope for the best.
2516 */
2517 found = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_RBRKT, '9', &tvb_current_offset);
2518 if ( found == false0)
2519 break;
2520
2521 tvb_get_raw_bytes_as_stringz(tvb,tvb_current_offset,4,ServiceChangeReason_str);
2522 reason_valid = ws_strtoi32((char*)ServiceChangeReason_str, NULL((void*)0), &reason);
2523 proto_item_append_text(item,"[ %s ]", val_to_str(pinfo->pool, reason, MEGACO_ServiceChangeReasons_vals,"Unknown (%u)"));
2524 if (!reason_valid)
2525 expert_add_info(pinfo, item, &ei_megaco_reason_invalid);
2526 break;
2527 case MEGACO_DELAY_TOKEN2:
2528 case MEGACO_SC_ADDR_TOKEN3:
2529 case MEGACO_MGC_ID_TOKEN4:
2530 case MEGACO_PROFILE_TOKEN5:
2531 case MEGACO_VERSION_TOKEN6:
2532 case MEGACO_METHOD_TOKEN7:
2533 /* No special dissection: fall through */
2534 default:
2535 /* Unknown or:
2536 * extension = extensionParameter parmValue
2537 * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
2538 */
2539 proto_tree_add_format_text(megaco_tree, tvb, tvb_previous_offset, tokenlen);
2540 break;
2541 }
2542
2543 tvb_previous_offset = tvb_offset +1;
2544
2545 }/*End while */
2546
2547 /* extension = extensionParameter parmValue
2548 * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
2549 */
2550
2551 /*
2552 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2553 proto_tree_add_string(megaco_tree_command_line, hf_megaco_servicechange_descriptor, tvb,
2554 tvb_previous_offset, tokenlen,
2555 tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
2556 tokenlen));
2557 */
2558 proto_tree_add_format_text(megaco_tree, tvb, tvb_RBRKT, 1);
2559
2560}
2561static void
2562dissect_megaco_digitmapdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, int tvb_RBRKT, int tvb_previous_offset)
2563{
2564
2565 int tokenlen;
2566
2567 tokenlen = tvb_RBRKT - tvb_previous_offset;
2568 proto_tree_add_string(megaco_tree_command_line, hf_megaco_digitmap_descriptor, tvb,
2569 tvb_previous_offset, tokenlen,
2570 tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
2571 tokenlen));
2572
2573}
2574
2575static void
2576dissect_megaco_statisticsdescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line)
2577{
2578 unsigned tokenlen;
2579 proto_tree *megaco_statisticsdescriptor_tree;
2580 proto_item *megaco_statisticsdescriptor_ti;
2581 unsigned tvb_help_offset, param_start_offset, param_end_offset = 0;
2582
2583 /* statisticsDescriptor = StatsToken LBRKT statisticsParameter
2584 * *(COMMA statisticsParameter ) RBRKT
2585 * statisticsParameter = pkgdName EQUAL VALUE
2586 */
2587 tokenlen = tvb_reported_length(tvb);
2588
2589 megaco_statisticsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_statistics_descriptor,tvb,0,tokenlen, ENC_NA0x00000000);
2590 megaco_statisticsdescriptor_tree = proto_item_add_subtree(megaco_statisticsdescriptor_ti, ett_megaco_statisticsdescriptor);
2591
2592 tvb_find_uint8_remaining(tvb, 0, '{', &tvb_help_offset);
2593 do {
2594 param_start_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset+1);
2595
2596 /* Find the COMMA that ends the parameter if not the last */
2597 if (!tvb_find_uint8_remaining(tvb, param_start_offset, ',', &tvb_help_offset)) {
2598 /* Reached end, RBRKT separator should be at tvb_help_offset - 1. */
2599 param_end_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset - 2);
2600 } else {
2601 param_end_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset - 1);
2602 }
2603 tokenlen = param_end_offset - param_start_offset;
2604
2605 proto_tree_add_format_text(megaco_statisticsdescriptor_tree, tvb,param_start_offset, tokenlen);
2606
2607 } while (tvb_captured_length_remaining(tvb, tvb_help_offset));
2608}
2609
2610static void
2611dissect_megaco_observedeventsdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, proto_tree *top_tree)
2612{
2613
2614 /* observedEventsDescriptor = ObservedEventsToken EQUAL RequestID
2615 * LBRKT observedEvent *(COMMA observedEvent) RBRKT
2616 *
2617 * ;time per event, because it might be buffered
2618 * observedEvent = [ TimeStamp LWSP COLON] LWSP
2619 * pkgdName [ LBRKT observedEventParameter
2620 * *(COMMA observedEventParameter) RBRKT ]
2621 */
2622
2623 unsigned tokenlen, pkg_tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset, tvb_previous_offset;
2624 unsigned tvb_observedevents_end_offset, tvb_LBRKT, tvb_RBRKT;
2625 proto_tree *megaco_observedeventsdescriptor_tree, *megaco_observedevent_tree;
2626 proto_item *megaco_observedeventsdescriptor_ti, *megaco_observedevent_ti;
2627
2628 unsigned requested_event_start_offset, requested_event_end_offset, param_start_offset, param_end_offset;
2629
2630 requested_event_start_offset = 0;
2631 requested_event_end_offset = 0;
2632
2633 tvb_observedevents_end_offset = tvb_reported_length(tvb);
2634
2635 megaco_observedeventsdescriptor_ti = proto_tree_add_item(megaco_tree_command_line, hf_megaco_observedevents_descriptor, tvb, 0, tvb_observedevents_end_offset, ENC_NA0x00000000);
2636 megaco_observedeventsdescriptor_tree = proto_item_add_subtree(megaco_observedeventsdescriptor_ti, ett_megaco_observedeventsdescriptor);
2637
2638 if (tvb_find_uint8_remaining(tvb, 0, '=', &tvb_current_offset)) {
2639
2640 /* If this fails, something's malformed; handle below. */
2641 tvb_find_uint8_remaining(tvb, 0, '{', &tvb_next_offset);
2642
2643 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset + 1);
2644 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset - 1);
2645
2646 tokenlen = tvb_help_offset - tvb_current_offset;
2647
2648 proto_tree_add_uint(megaco_observedeventsdescriptor_tree, hf_megaco_requestid, tvb,
2649 tvb_current_offset, tokenlen,
2650 (uint32_t) strtoul(tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen), NULL((void*)0), 10));
2651
2652 if (tvb_next_offset == tvb_observedevents_end_offset) {
2653 /* No LBRKT before the first observedEvent (expert info?) */
2654 return;
2655 }
2656 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
2657
2658 do {
2659
2660 tvb_find_uint8_remaining(tvb, tvb_previous_offset, '}', &tvb_RBRKT);
2661 tvb_find_uint8_remaining(tvb, tvb_previous_offset, ',', &tvb_current_offset);
2662
2663 if (!tvb_find_uint8_remaining(tvb, tvb_previous_offset, '{', &tvb_LBRKT) || tvb_LBRKT > tvb_current_offset) {
2664 /* Descriptor includes no parameters */
2665 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2666 } else {
2667 /* Descriptor includes Parameters */
2668 /* If the next LBRKT is before RBRKT, then there's nested braves.
2669 * Keep going until balanced or we run out of buffer. */
2670 while (tvb_find_uint8_remaining(tvb, tvb_LBRKT+1, '{', &tvb_LBRKT) && tvb_LBRKT < tvb_RBRKT) {
2671 if (tvb_RBRKT < tvb_observedevents_end_offset) {
2672 tvb_find_uint8_remaining(tvb, tvb_RBRKT+1, '}', &tvb_RBRKT);
2673 }
2674 }
2675
2676 }
2677
2678 tvb_find_uint8_remaining(tvb, tvb_previous_offset, '{', &tvb_help_offset);
2679 tvb_LBRKT = tvb_help_offset;
2680 /* if there are eventparameter */
2681
2682 if (tvb_help_offset < tvb_RBRKT) {
2683
2684 requested_event_start_offset = tvb_help_offset;
2685 requested_event_end_offset = tvb_RBRKT;
2686 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_help_offset-1);
2687 pkg_tokenlen = tvb_help_offset - tvb_previous_offset;
2688 tokenlen = tvb_LBRKT+1 - tvb_previous_offset;
2689 }
2690 /* no parameters */
2691 else {
2692 tokenlen = pkg_tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2693 }
2694
2695 megaco_observedevent_ti = proto_tree_add_format_text(megaco_observedeventsdescriptor_tree, tvb, tvb_previous_offset, tokenlen);
2696
2697 megaco_observedevent_tree = proto_item_add_subtree(megaco_observedevent_ti, ett_megaco_observedevent);
2698
2699 proto_tree_add_item(megaco_observedevent_tree,hf_megaco_pkgdname,tvb,tvb_previous_offset,pkg_tokenlen, ENC_UTF_80x00000002);
2700
2701 if (tvb_help_offset < tvb_RBRKT) {
2702
2703 requested_event_start_offset = megaco_tvb_skip_wsp(tvb, requested_event_start_offset +1)-1;
2704 requested_event_end_offset = megaco_tvb_skip_wsp_return(tvb, requested_event_end_offset-1);
2705
2706 tvb_help_offset = requested_event_start_offset;
2707
2708 do {
2709 param_start_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset+1);
2710
2711 tvb_find_uint8_length(tvb, tvb_help_offset + 1, requested_event_end_offset - (tvb_help_offset + 1), ',', &tvb_help_offset);
2712
2713 param_end_offset = megaco_tvb_skip_wsp(tvb, tvb_help_offset-1);
2714
2715 tokenlen = param_end_offset - param_start_offset+1;
2716 if(!tvb_strneql(tvb, param_start_offset, "h245", 4)){
2717 dissect_megaco_h245(tvb, pinfo, megaco_observedevent_tree, param_start_offset, tokenlen, top_tree);
2718 } else {
2719 proto_tree_add_format_text(megaco_observedevent_tree, tvb, param_start_offset, tokenlen);
2720 }
2721
2722
2723 } while ( tvb_help_offset < requested_event_end_offset );
2724 }
2725
2726 tvb_previous_offset = tvb_current_offset;
2727 tvb_find_uint8_remaining(tvb, tvb_RBRKT, ',', &tvb_current_offset);
2728 if (tvb_current_offset < tvb_previous_offset) {
2729 expert_add_info_format(pinfo, megaco_observedevent_ti, &ei_megaco_parse_error, "Parse error: Invalid offset");
2730 return;
2731 }
2732
2733 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2734 /* Print the trailing '}' (raw formatting removed) */
2735 /* proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_observedevents_end_offset, 1); */
2736
2737 } while ( tvb_current_offset < tvb_observedevents_end_offset );
2738 }
2739}
2740static void
2741dissect_megaco_topologydescriptor(tvbuff_t *tvb, proto_tree *megaco_tree_command_line, unsigned tvb_RBRKT, unsigned tvb_previous_offset)
2742{
2743
2744 unsigned tokenlen;
2745
2746 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2747 proto_tree_add_item(megaco_tree_command_line, hf_megaco_topology_descriptor, tvb,
2748 tvb_previous_offset, tokenlen, ENC_ASCII0x00000000);
2749
2750}
2751static void
2752dissect_megaco_Packagesdescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_tree_command_line, unsigned tvb_RBRKT, unsigned tvb_previous_offset)
2753{
2754
2755 unsigned tokenlen, tvb_current_offset, tvb_next_offset, tvb_help_offset;
2756 unsigned tvb_packages_end_offset, tvb_LBRKT;
2757 bool_Bool found, tvb_LBRKT_found;
2758
2759 proto_tree *megaco_packagesdescriptor_tree;
2760 proto_item *megaco_packagesdescriptor_ti, *ti;
2761
2762 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2763
2764 megaco_packagesdescriptor_ti = proto_tree_add_item(megaco_tree_command_line,hf_megaco_packages_descriptor,tvb,tvb_previous_offset,tokenlen, ENC_UTF_80x00000002);
2765 megaco_packagesdescriptor_tree = proto_item_add_subtree(megaco_packagesdescriptor_ti, ett_megaco_packagesdescriptor);
2766
2767 found = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_RBRKT, '=', &tvb_current_offset);
2768 tvb_LBRKT_found = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_RBRKT, '{', &tvb_next_offset);
Value stored to 'tvb_LBRKT_found' is never read
2769
2770 if ( tvb_current_offset < tvb_RBRKT && found == true1 ){
2771
2772 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2773 tvb_help_offset = megaco_tvb_skip_wsp_return(tvb, tvb_next_offset-1);
2774
2775 tokenlen = tvb_help_offset - tvb_current_offset;
2776
2777 ti = proto_tree_add_uint(megaco_packagesdescriptor_tree, hf_megaco_requestid, tvb,
2778 tvb_current_offset, 1,
2779 (uint32_t) strtoul(tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen), NULL((void*)0), 10));
2780 proto_item_set_len(ti, tokenlen);
2781
2782 tvb_packages_end_offset = tvb_RBRKT;
2783
2784 tvb_RBRKT = tvb_next_offset+1;
2785 tvb_LBRKT = tvb_next_offset+1;
2786 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_next_offset+1);
2787
2788
2789 do {
2790
2791 tvb_find_uint8_length(tvb, tvb_RBRKT+1, tvb_packages_end_offset, '}', &tvb_RBRKT);
2792 tvb_LBRKT_found = tvb_find_uint8_length(tvb, tvb_LBRKT, tvb_packages_end_offset, '{', &tvb_LBRKT);
2793
2794 found = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_packages_end_offset, ',', &tvb_current_offset);
2795
2796 if (found == false0 || tvb_current_offset > tvb_packages_end_offset){
2797 tvb_current_offset = tvb_packages_end_offset;
2798 }
2799
2800
2801 /* Descriptor includes no parameters */
2802
2803 if ( tvb_LBRKT > tvb_current_offset || tvb_LBRKT_found == false0){
2804
2805 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
2806 }
2807
2808 /* Descriptor includes Parameters */
2809
2810 if ( (tvb_current_offset > tvb_LBRKT && tvb_LBRKT_found == true1)){
2811
2812 while (tvb_LBRKT_found == true1 && tvb_RBRKT > tvb_LBRKT ){
2813
2814 tvb_LBRKT_found = tvb_find_uint8_length(tvb, tvb_LBRKT+1, tvb_packages_end_offset, '{', &tvb_LBRKT);
2815 if ( tvb_LBRKT < tvb_RBRKT && tvb_LBRKT_found == true1)
2816 tvb_find_uint8_length(tvb, tvb_RBRKT+1, tvb_packages_end_offset, '}', &tvb_RBRKT);
2817 }
2818
2819 }
2820
2821 tokenlen = tvb_RBRKT+1 - tvb_previous_offset;
2822
2823 proto_tree_add_format_text(megaco_packagesdescriptor_tree, tvb, tvb_previous_offset, tokenlen);
2824
2825 found = tvb_find_uint8_length(tvb, tvb_RBRKT, tvb_packages_end_offset, ',', &tvb_current_offset);
2826
2827 if (found == false0 || tvb_current_offset > tvb_packages_end_offset ){
2828 tvb_current_offset = tvb_packages_end_offset;
2829 }
2830
2831 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
2832
2833 tvb_LBRKT = tvb_previous_offset;
2834 tvb_RBRKT = tvb_previous_offset;
2835
2836 } while ( tvb_current_offset < tvb_packages_end_offset );
2837 }
2838
2839}
2840/* The list of error code values is fetched from http://www.iana.org/assignments/megaco-h248 */
2841/* 2003-08-28 */
2842
2843static const value_string MEGACO_error_code_vals[] = {
2844
2845 {400, "Syntax error in message"},
2846 {401, "Protocol Error"},
2847 {402, "Unauthorized"},
2848 {403, "Syntax error in transaction request"},
2849 {406, "Version Not Supported"},
2850 {410, "Incorrect identifier"},
2851 {411, "The transaction refers to an unknown ContextId"},
2852 {412, "No ContextIDs available"},
2853 {421, "Unknown action or illegal combination of actions"},
2854 {422, "Syntax Error in Action"},
2855 {430, "Unknown TerminationID"},
2856 {431, "No TerminationID matched a wildcard"},
2857 {432, "Out of TerminationIDs or No TerminationID available"},
2858 {433, "TerminationID is already in a Context"},
2859 {434, "Max number of Terminations in a Context exceeded"},
2860 {435, "Termination ID is not in specified Context"},
2861 {440, "Unsupported or unknown Package"},
2862 {441, "Missing Remote or Local Descriptor"},
2863 {442, "Syntax Error in Command"},
2864 {443, "Unsupported or Unknown Command"},
2865 {444, "Unsupported or Unknown Descriptor"},
2866 {445, "Unsupported or Unknown Property"},
2867 {446, "Unsupported or Unknown Parameter"},
2868 {447, "Descriptor not legal in this command"},
2869 {448, "Descriptor appears twice in a command"},
2870 {450, "No such property in this package"},
2871 {451, "No such event in this package"},
2872 {452, "No such signal in this package"},
2873 {453, "No such statistic in this package"},
2874 {454, "No such parameter value in this package"},
2875 {455, "Property illegal in this Descriptor"},
2876 {456, "Property appears twice in this Descriptor"},
2877 {457, "Missing parameter in signal or event"},
2878 {458, "Unexpected Event/Request ID"},
2879 {459, "Unsupported or Unknown Profile"},
2880 {471, "Implied Add for Multiplex failure"},
2881
2882 {500, "Internal software Failure in MG"},
2883 {501, "Not Implemented"},
2884 {502, "Not ready."},
2885 {503, "Service Unavailable"},
2886 {504, "Command Received from unauthorized entity"},
2887 {505, "Transaction Request Received before a Service Change Reply has been received"},
2888 {506, "Number of Transaction Pendings Exceeded"},
2889 {510, "Insufficient resources"},
2890 {512, "Media Gateway unequipped to detect requested Event"},
2891 {513, "Media Gateway unequipped to generate requested Signals"},
2892 {514, "Media Gateway cannot send the specified announcement"},
2893 {515, "Unsupported Media Type"},
2894 {517, "Unsupported or invalid mode"},
2895 {518, "Event buffer full"},
2896 {519, "Out of space to store digit map"},
2897 {520, "Digit Map undefined in the MG"},
2898 {521, "Termination is ServiceChanging"},
2899 {526, "Insufficient bandwidth"},
2900 {529, "Internal hardware failure in MG"},
2901 {530, "Temporary Network failure"},
2902 {531, "Permanent Network failure"},
2903 {532, "Audited Property, Statistic, Event or Signal does not exist"},
2904 {533, "Response exceeds maximum transport PDU size"},
2905 {534, "Illegal write or read only property"},
2906 {540, "Unexpected initial hook state"},
2907 {581, "Does Not Exist"},
2908
2909 {600, "Illegal syntax within an announcement specification"},
2910 {601, "Variable type not supported"},
2911 {602, "Variable value out of range"},
2912 {603, "Category not supported"},
2913 {604, "Selector type not supported"},
2914 {605, "Selector value not supported"},
2915 {606, "Unknown segment ID"},
2916 {607, "Mismatch between play specification and provisioned data"},
2917 {608, "Provisioning error"},
2918 {609, "Invalid offset"},
2919 {610, "No free segment IDs"},
2920 {611, "Temporary segment not found"},
2921 {612, "Segment in use"},
2922 {613, "ISP port limit overrun"},
2923 {614, "No modems available"},
2924 {615, "Calling number unacceptable"},
2925 {616, "Called number unacceptable"},
2926 { 0, NULL((void*)0) }
2927};
2928
2929
2930
2931static void
2932dissect_megaco_errordescriptor(tvbuff_t *tvb, packet_info* pinfo, proto_tree *megaco_tree_command_line,
2933 unsigned tvb_RBRKT, unsigned tvb_previous_offset)
2934{
2935
2936 unsigned tokenlen;
2937 int error_code;
2938 uint8_t error[4];
2939 unsigned tvb_current_offset;
2940 proto_item* item;
2941 proto_tree* error_tree;
2942 bool_Bool error_code_valid;
2943
2944 tvb_find_uint8_length(tvb, tvb_previous_offset , tvb_RBRKT, '=', &tvb_current_offset);
2945 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset +1);
2946
2947 tokenlen = (tvb_RBRKT) - tvb_previous_offset+1;
2948
2949 item = proto_tree_add_item(megaco_tree_command_line, hf_megaco_error_descriptor, tvb,
2950 tvb_previous_offset, tokenlen, ENC_NA0x00000000);
2951 error_tree = proto_item_add_subtree(item, ett_megaco_error_descriptor);
2952
2953 /* Get the error code */
2954 tvb_get_raw_bytes_as_stringz(tvb,tvb_current_offset,4,error);
2955 error_code_valid = ws_strtoi32((char*)error, NULL((void*)0), &error_code);
2956 item = proto_tree_add_uint(error_tree, hf_megaco_error_code, tvb, tvb_current_offset, 3, error_code);
2957 if (!error_code_valid)
2958 expert_add_info(pinfo, item, &ei_megaco_error_code_invalid);
2959
2960 /* Get the error string (even though we have a value_string that should match) */
2961 tvb_find_uint8_length(tvb, tvb_current_offset, tvb_RBRKT, '\"', &tvb_previous_offset);
2962 tvb_find_uint8_length(tvb, tvb_previous_offset+1, tvb_RBRKT, '\"', &tvb_current_offset);
2963
2964 tokenlen = tvb_current_offset - tvb_previous_offset-1;
2965 proto_tree_add_item(error_tree, hf_megaco_error_string, tvb, tvb_previous_offset+1, tokenlen, ENC_UTF_80x00000002);
2966}
2967
2968static void
2969dissect_megaco_TerminationStatedescriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *megaco_mediadescriptor_tree)
2970{
2971 unsigned tokenlen;
2972 unsigned tvb_offset, tvb_current_offset=0;
2973 uint8_t tempchar;
2974
2975 proto_tree *megaco_TerminationState_tree, *megaco_TerminationState_ti;
2976
2977 tokenlen = tvb_reported_length(tvb);
2978 megaco_TerminationState_ti = proto_tree_add_item(megaco_mediadescriptor_tree,hf_megaco_TerminationState_descriptor,tvb, 0, tokenlen, ENC_NA0x00000000);
2979 megaco_TerminationState_tree = proto_item_add_subtree(megaco_TerminationState_ti, ett_megaco_TerminationState);
2980
2981 while (tvb_find_uint8_remaining(tvb, tvb_current_offset, '=', &tvb_offset)){
2982
2983 tempchar = tvb_get_uint8(tvb, tvb_current_offset);
2984 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
2985 if ((tempchar >= 'a') && (tempchar <= 'z'))
2986 tempchar = tempchar - 0x20;
2987
2988 if (tvb_find_uint8_remaining(tvb, tvb_current_offset, ',', &tvb_offset)) {
2989 tvb_offset--;
2990 }
2991 tokenlen = tvb_offset - tvb_current_offset;
2992 switch ( tempchar ){
2993
2994 case 'S':
2995 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Service_State, tvb,
2996 tvb_current_offset, tokenlen,
2997 tvb_format_text(pinfo->pool, tvb, tvb_current_offset,
2998 tokenlen));
2999 break;
3000
3001 case 'B':
3002 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Event_Buffer_Control, tvb,
3003 tvb_current_offset, tokenlen,
3004 tvb_format_text(pinfo->pool, tvb, tvb_current_offset,
3005 tokenlen));
3006 break;
3007
3008 case 'E':
3009 proto_tree_add_string(megaco_TerminationState_tree, hf_megaco_Event_Buffer_Control, tvb,
3010 tvb_current_offset, tokenlen,
3011 tvb_format_text(pinfo->pool, tvb, tvb_current_offset,
3012 tokenlen));
3013 break;
3014
3015 default:
3016 proto_tree_add_format_text(megaco_TerminationState_tree, tvb, tvb_current_offset, tokenlen);
3017 break;
3018 }
3019
3020 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset + 1);
3021 }
3022 /* (raw formatting removed)
3023 proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_next_offset, 1); */
3024}
3025
3026static void
3027dissect_megaco_LocalRemotedescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree, packet_info *pinfo,
3028 uint32_t context, bool_Bool is_local)
3029{
3030 int tokenlen;
3031 tvbuff_t *next_tvb;
3032 media_content_info_t content_info = { MEDIA_CONTAINER_SIP_DATA, NULL((void*)0), NULL((void*)0), NULL((void*)0) };
3033
3034 sdp_setup_info_t setup_info;
3035
3036 /* Only fill in the info when we have valid contex */
3037 if ((context != 0) && (context < 0xfffffffe)) {
3038 setup_info = (sdp_setup_info_t){
3039 .hf_id = hf_megaco_Context_generated,
3040 .hf_type = SDP_TRACE_ID_HF_TYPE_UINT32,
3041 .trace_id.num = context,
3042 };
3043 if (!sip_hide_generated_call_ids) {
3044 setup_info.add_hidden = false0;
3045 } else {
3046 setup_info.add_hidden = prefs_get_bool_value(sip_hide_generated_call_ids, pref_current);
3047 }
3048 content_info.data = &setup_info;
3049 }
3050
3051 proto_tree *megaco_localdescriptor_tree;
3052 proto_item *megaco_localdescriptor_item;
3053
3054 tokenlen = tvb_reported_length(tvb);
3055
3056 if (is_local) {
3057 megaco_localdescriptor_item = proto_tree_add_item(megaco_mediadescriptor_tree, hf_megaco_Local_descriptor, tvb, 0, tokenlen, ENC_NA0x00000000);
3058 megaco_localdescriptor_tree = proto_item_add_subtree(megaco_localdescriptor_item, ett_megaco_Localdescriptor);
3059 } else {
3060 megaco_localdescriptor_item = proto_tree_add_item(megaco_mediadescriptor_tree, hf_megaco_Remote_descriptor, tvb, 0, tokenlen, ENC_NA0x00000000);
3061 megaco_localdescriptor_tree = proto_item_add_subtree(megaco_localdescriptor_item, ett_megaco_Remotedescriptor);
3062 }
3063
3064 if ( tokenlen > 3 ){
3065 /* An SDP is supposed to end with a line end. MEGACO allows LWS as part
3066 * of RBRKT but the SDP dissector doesn't like lines with only tabs or
3067 * spaces. Remove WSP before the end but then restore the line end.
3068 * (Restoring is optional, the SDP dissector doesn't really need the
3069 * last line end.)
3070 */
3071 int sdp_end_offset = megaco_tvb_skip_wsp_return(tvb, tokenlen - 2);
3072 tvb_find_line_end(tvb, sdp_end_offset, tokenlen, &sdp_end_offset, false0);
3073 next_tvb = tvb_new_subset_length(tvb, 0, sdp_end_offset);
3074 call_dissector_with_data(sdp_handle, next_tvb, pinfo, megaco_localdescriptor_tree, &content_info);
3075 }
3076}
3077
3078/*
3079 * localControlDescriptor = LocalControlToken LBRKT localParm
3080 * *(COMMA localParm) RBRKT
3081 * ; at-most-once per item
3082 * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
3083 */
3084
3085#define MEGACO_MODETOKEN1 1
3086#define MEGACO_RESERVEDVALUETOKEN2 2
3087#define MEGACO_RESERVEDGROUPTOKEN3 3
3088#define MEGACO_H324_H223CAPR4 4
3089#define MEGACO_H324_MUXTBL_IN5 5
3090#define MEGACO_H324_MUXTBL_OUT6 6
3091#define MEGACO_DS_DSCP7 7
3092#define MEGACO_GM_SAF8 8
3093#define MEGACO_GM_SAM9 9
3094#define MEGACO_GM_SPF10 10
3095#define MEGACO_GM_SPR11 11
3096#define MEGACO_GM_ESAS12 12
3097#define MEGACO_GM_LSA13 13
3098#define MEGACO_GM_ESPS14 14
3099#define MEGACO_GM_LSP15 15
3100#define MEGACO_GM_RSB16 16
3101#define MEGACO_TMAN_POL17 17
3102#define MEGACO_TMAN_SDR18 18
3103#define MEGACO_TMAN_MBS19 19
3104#define MEGACO_TMAN_PDR20 20
3105#define MEGACO_TMAN_DVT21 21
3106#define MEGACO_IPDC_REALM22 22
3107
3108static const megaco_tokens_t megaco_localParam_names[] = {
3109 { "Unknown-token", NULL((void*)0) }, /* 0 Pad so that the real headers start at index 1 */
3110 /* streamMode */
3111 { "Mode", "MO" }, /* 1 */
3112 { "ReservedValue", "RV" }, /* 2 */
3113 { "ReservedGroup", "RG" }, /* 3 */
3114 /* propertyParm = pkgdName parmValue
3115 * Add more package names as needed.
3116 */
3117 { "h324/h223capr", NULL((void*)0) }, /* 4 */
3118 { "h324/muxtbl_in", NULL((void*)0) }, /* 5 */
3119 { "h324/muxtbl_out", NULL((void*)0) }, /* 6 */
3120 { "ds/dscp", NULL((void*)0) }, /* 7 */
3121 { "gm/saf", NULL((void*)0) }, /* 8 */
3122 { "gm/sam", NULL((void*)0) }, /* 9 */
3123 { "gm/spf", NULL((void*)0) }, /* 10 */
3124 { "gm/spr", NULL((void*)0) }, /* 11 */
3125 { "gm/esas", NULL((void*)0) }, /* 12 */
3126 { "gm/lsa", NULL((void*)0) }, /* 13 */
3127 { "gm/esps", NULL((void*)0) }, /* 14 */
3128 { "gm/lsp", NULL((void*)0) }, /* 15 */
3129 { "gm/rsb", NULL((void*)0) }, /* 16 */
3130 { "tman/pol", NULL((void*)0) }, /* 17 */
3131 { "tman/sdr", NULL((void*)0) }, /* 18 */
3132 { "tman/mbs", NULL((void*)0) }, /* 19 */
3133 { "tman/pdr", NULL((void*)0) }, /* 20 */
3134 { "tman/dvt", NULL((void*)0) }, /* 21 */
3135 { "ipdc/realm", NULL((void*)0) }, /* 22 */
3136};
3137
3138/* Returns index of megaco_tokens_t */
3139static int find_megaco_localParam_names(tvbuff_t *tvb, int offset, unsigned header_len)
3140{
3141 unsigned i;
3142
3143 for (i = 1; i < array_length(megaco_localParam_names)(sizeof (megaco_localParam_names) / sizeof (megaco_localParam_names
)[0])
; i++) {
3144 if (header_len == strlen(megaco_localParam_names[i].name) &&
3145 tvb_strncaseeql(tvb, offset, megaco_localParam_names[i].name, header_len) == 0)
3146 return i;
3147 if (megaco_localParam_names[i].compact_name != NULL((void*)0) &&
3148 header_len == strlen(megaco_localParam_names[i].compact_name) &&
3149 tvb_strncaseeql(tvb, offset, megaco_localParam_names[i].compact_name, header_len) == 0)
3150 return i;
3151 }
3152
3153 return -1;
3154}
3155
3156static void
3157dissect_megaco_LocalControldescriptor(tvbuff_t *tvb, proto_tree *megaco_mediadescriptor_tree, packet_info *pinfo, proto_tree *top_tree)
3158{
3159 unsigned tokenlen;
3160 unsigned token_name_len;
3161 unsigned tvb_offset = 0, tvb_help_offset, tvb_current_offset = 0;
3162 int token_index = 0;
3163 char *msg;
3164 proto_item* item;
3165 uint8_t code_str[3];
3166
3167 proto_tree *megaco_LocalControl_tree;
3168 proto_item *megaco_LocalControl_item;
3169
3170 tokenlen = tvb_reported_length(tvb);
3171
3172 megaco_LocalControl_item = proto_tree_add_item(megaco_mediadescriptor_tree, hf_megaco_LocalControl_descriptor, tvb, 0, tokenlen, ENC_NA0x00000000);
3173 megaco_LocalControl_tree = proto_item_add_subtree(megaco_LocalControl_item, ett_megaco_LocalControldescriptor);
3174
3175 while (tvb_captured_length_remaining(tvb, tvb_offset) > 1) {
3176
3177 tvb_help_offset = tvb_current_offset;
3178
3179 /*
3180 * Find local parameter name
3181 * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
3182 * pkgdName = (PackageName SLASH ItemID) ;specific item
3183 * / (PackageName SLASH "*") ;all events in package
3184 * / ("*" SLASH "*") ; all events supported by the MG
3185 */
3186 /* Find token length */
3187 for (tvb_offset=tvb_current_offset; tvb_captured_length_remaining(tvb, tvb_offset); tvb_offset++){
3188 uint8_t octet;
3189 octet = tvb_get_uint8(tvb, tvb_offset);
3190 if (!g_ascii_isalnum(octet)((g_ascii_table[(guchar) (octet)] & G_ASCII_ALNUM) != 0)){
3191 if ((octet!='/')&&(octet!='_')){
3192 break;
3193 }
3194 }
3195 }
3196 token_name_len = tvb_offset - tvb_current_offset;
3197 token_index = find_megaco_localParam_names(tvb, tvb_current_offset, token_name_len);
3198 /* Find start of parameter value */
3199 if (!tvb_find_uint8_remaining(tvb, tvb_offset, '=', &tvb_offset)) {
3200 expert_add_info(pinfo, megaco_LocalControl_item, &ei_megaco_parse_error);
3201 return;
3202 }
3203 /* Start search after '=' in case there is no SP*/
3204 tvb_offset++;
3205 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset);
3206
3207 /* find if there are more parameters or not */
3208 if (!tvb_find_uint8_remaining(tvb, tvb_current_offset, ',', &tvb_offset)) {
3209 tvb_offset--;
3210 }
3211
3212 tokenlen = megaco_tvb_skip_wsp_return(tvb,tvb_offset-1) - tvb_current_offset;
3213 switch ( token_index ){
3214
3215 case MEGACO_MODETOKEN1: /* Mode */
3216 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_mode, tvb,
3217 tvb_help_offset, tvb_offset-tvb_help_offset,
3218 tvb_format_text(pinfo->pool, tvb, tvb_current_offset,
3219 tokenlen));
3220 col_append_fstr(pinfo->cinfo, COL_INFO, " (Mode:%s)",tvb_format_text(pinfo->pool, tvb, tvb_current_offset,tokenlen));
3221 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3222 break;
3223
3224 case MEGACO_RESERVEDVALUETOKEN2: /* ReservedValue */
3225 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_reserve_value, tvb,
3226 tvb_help_offset, tvb_offset-tvb_help_offset,
3227 tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3228
3229 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3230 break;
3231 case MEGACO_RESERVEDGROUPTOKEN3: /* ReservedGroup */
3232 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_reserve_group, tvb,
3233 tvb_help_offset, tvb_offset-tvb_help_offset,
3234 tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3235 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3236 break;
3237
3238 case MEGACO_H324_H223CAPR4: /* h324/h223capr */
3239 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_h324_h223capr, tvb,
3240 tvb_help_offset, tvb_offset-tvb_help_offset,
3241 tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3242
3243 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3244 tokenlen = tvb_offset - tvb_help_offset;
3245 msg=tvb_format_text(pinfo->pool, tvb,tvb_help_offset, tokenlen);
3246 dissect_megaco_h324_h223caprn(tvb, pinfo, megaco_mediadescriptor_tree, tvb_help_offset, tokenlen, msg);
3247
3248 break;
3249
3250 case MEGACO_H324_MUXTBL_IN5: /* h324/muxtbl_in */
3251
3252 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_h324_muxtbl_in, tvb,
3253 tvb_help_offset, tvb_offset-tvb_help_offset,
3254 tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3255
3256 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3257
3258 tokenlen = tvb_offset - tvb_help_offset;
3259 /* Call the existing routine with tree = NULL to avoid an entry to the tree */
3260 dissect_megaco_h245(tvb, pinfo, NULL((void*)0), tvb_help_offset, tokenlen, top_tree);
3261
3262 break;
3263
3264 case MEGACO_H324_MUXTBL_OUT6:
3265
3266 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_h324_muxtbl_out, tvb,
3267 tvb_current_offset, tokenlen,
3268 tvb_format_text(pinfo->pool, tvb, tvb_current_offset,
3269 tokenlen));
3270
3271 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3272
3273 tokenlen = tvb_offset - tvb_help_offset;
3274 /* Call the existing routine with tree = NULL to avoid an entry to the tree */
3275 dissect_megaco_h245(tvb, pinfo, NULL((void*)0), tvb_help_offset, tokenlen, top_tree);
3276
3277 break;
3278
3279 case MEGACO_DS_DSCP7:
3280 tvb_get_raw_bytes_as_stringz(tvb,tvb_current_offset,3,code_str);
3281 item = proto_tree_add_uint(megaco_LocalControl_tree, hf_megaco_ds_dscp, tvb,
3282 tvb_help_offset, 1, (uint32_t) strtoul((char*)code_str,NULL((void*)0),16));
3283 proto_item_set_len(item, tvb_offset-tvb_help_offset);
3284 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3285 break;
3286
3287 case MEGACO_GM_SAF8:
3288 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_saf, tvb,
3289 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3290 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3291 break;
3292 case MEGACO_GM_SAM9:
3293 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_sam, tvb,
3294 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3295 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3296 break;
3297 case MEGACO_GM_SPF10:
3298 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_spf, tvb,
3299 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3300 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3301 break;
3302 case MEGACO_GM_SPR11:
3303 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_spr, tvb,
3304 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3305 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3306 break;
3307 case MEGACO_GM_ESAS12:
3308 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_esas, tvb,
3309 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3310 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3311 break;
3312 case MEGACO_GM_RSB16:
3313 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_gm_rsb, tvb,
3314 tvb_help_offset, tvb_offset - tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3315 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset + 1);
3316 break;
3317 case MEGACO_TMAN_POL17:
3318 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_pol, tvb,
3319 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3320 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3321 break;
3322 case MEGACO_TMAN_SDR18:
3323 {
3324 int32_t sdr;
3325 bool_Bool sdr_valid;
3326 proto_item* pi;
3327
3328 sdr_valid = ws_strtoi32(tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen), NULL((void*)0), &sdr);
3329 pi =proto_tree_add_int(megaco_LocalControl_tree, hf_megaco_tman_sdr, tvb, tvb_help_offset,
3330 tvb_offset - tvb_help_offset, sdr);
3331 proto_item_append_text(pi, " [%i b/s]", sdr*8);
3332 if (!sdr_valid) {
3333 expert_add_info(pinfo, pi, &ei_megaco_invalid_sdr);
3334 }
3335 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset + 1);
3336 }
3337 break;
3338 case MEGACO_TMAN_MBS19:
3339 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_mbs, tvb,
3340 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3341 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3342 break;
3343 case MEGACO_TMAN_PDR20:
3344 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_pdr, tvb,
3345 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3346 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3347 break;
3348 case MEGACO_TMAN_DVT21:
3349 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_tman_dvt, tvb,
3350 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3351 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3352 break;
3353 case MEGACO_IPDC_REALM22:
3354 proto_tree_add_string(megaco_LocalControl_tree, hf_megaco_ipdc_realm, tvb,
3355 tvb_help_offset, tvb_offset-tvb_help_offset, tvb_format_text(pinfo->pool, tvb, tvb_current_offset, tokenlen));
3356 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3357 break;
3358
3359 default:
3360 tokenlen = tvb_offset - tvb_help_offset;
3361 proto_tree_add_format_text(megaco_LocalControl_tree, tvb, tvb_help_offset, tokenlen);
3362 tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_offset +1);
3363
3364 break;
3365 }
3366 }
3367}
3368
3369static void
3370dissect_megaco_descriptors(tvbuff_t *tvb, proto_tree *megaco_command_tree, packet_info *pinfo, proto_tree *top_tree, uint32_t context)
3371{
3372 unsigned tvb_len, token_index, tvb_offset, temp_offset;
3373 unsigned tvb_current_offset,tvb_previous_offset,save_offset,tokenlen;
3374 unsigned tvb_RBRKT, tvb_LBRKT;
3375 bool_Bool found, found_LBRKT, found_RBRKT;
3376 tvbuff_t* descriptor_tvb;
3377 proto_tree* descriptor_tree;
3378 proto_item* descriptor_item;
3379
3380 tvb_len = tvb_reported_length(tvb);
3381 unsigned tvb_descriptors_end_offset = tvb_len - 1;
3382
3383 descriptor_tree = proto_tree_add_subtree(megaco_command_tree, tvb, 0, tvb_len,
3384 ett_megaco_descriptors, &descriptor_item, "Descriptors");
3385
3386 tvb_LBRKT = megaco_tvb_skip_wsp(tvb, 1);
3387
3388 tvb_previous_offset = tvb_LBRKT;
3389 tvb_RBRKT = 0;
3390
3391 do {
3392 /* Find the end of this descriptor / start of next. */
3393 found = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_len, ',', &tvb_current_offset);
3394
3395 if (found == false0) {
3396 tvb_current_offset = tvb_descriptors_end_offset;
3397 }
3398 if (tvb_current_offset <= tvb_previous_offset) {
3399 expert_add_info_format(pinfo, descriptor_item, &ei_megaco_parse_error, "Parse error: Invalid offset");
3400 return;
3401 }
3402
3403 /* Look for parameters in the next description */
3404 found_LBRKT = tvb_find_uint8_length(tvb, tvb_previous_offset, tvb_current_offset - tvb_previous_offset, '{', &tvb_LBRKT);
3405 found_RBRKT = tvb_find_uint8_length(tvb, tvb_RBRKT+1, tvb_len, '}', &tvb_RBRKT);
3406 if (found_RBRKT == false0)
3407 tvb_RBRKT = tvb_descriptors_end_offset;
3408
3409 if (found_LBRKT == false0) {
3410 /* Descriptor includes no parameters */
3411 if (tvb_current_offset > tvb_RBRKT){
3412 tvb_current_offset = tvb_RBRKT;
3413 }
3414 tvb_RBRKT = megaco_tvb_skip_wsp_return(tvb, tvb_current_offset-1)-1;
3415 } else {
3416 /* Descriptor includes Parameters */
3417 while (found_LBRKT == true1 && tvb_RBRKT > tvb_LBRKT ){
3418
3419 found_LBRKT = tvb_find_uint8_length(tvb, tvb_LBRKT+1, tvb_len, '{', &tvb_LBRKT);
3420 if ( tvb_LBRKT < tvb_RBRKT && found_LBRKT == true1)
3421 found_RBRKT = tvb_find_uint8_length(tvb, tvb_RBRKT+1, tvb_len, '}', &tvb_RBRKT);
3422 }
3423 }
3424 if (found_RBRKT == false0)
3425 tvb_RBRKT = tvb_descriptors_end_offset;
3426
3427 /* Find token length */
3428 for (tvb_offset=tvb_previous_offset; tvb_offset < tvb_descriptors_end_offset; tvb_offset++){
3429 if (!g_ascii_isalpha(tvb_get_uint8(tvb, tvb_offset ))((g_ascii_table[(guchar) (tvb_get_uint8(tvb, tvb_offset ))] &
G_ASCII_ALPHA) != 0)
){
3430 break;
3431 }
3432 }
3433 tokenlen = tvb_offset - tvb_previous_offset;
3434 token_index = find_megaco_descriptors_names(tvb, tvb_previous_offset, tokenlen);
3435 descriptor_tvb = tvb_new_subset_length(tvb, tvb_previous_offset, tvb_RBRKT - tvb_previous_offset + 1);
3436 switch ( token_index ){
3437 case MEGACO_MODEM_TOKEN1:
3438 dissect_megaco_modemdescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3439 break;
3440 case MEGACO_MUX_TOKEN2:
3441 dissect_megaco_multiplexdescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3442 break;
3443 case MEGACO_MEDIA_TOKEN3:
3444 /*TODO: Move this to the top when all branches fixed !!!*/
3445 tvb_find_uint8_length(tvb, tvb_previous_offset,tvb_descriptors_end_offset, '{', &temp_offset);
3446 save_offset = tvb_previous_offset;
3447
3448 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, temp_offset +1);
3449 dissect_megaco_mediadescriptor(tvb, descriptor_tree, pinfo, tvb_RBRKT, tvb_previous_offset, save_offset, top_tree, context);
3450 break;
3451 case MEGACO_SIGNALS_TOKEN4:
3452 dissect_megaco_signaldescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset, top_tree);
3453 break;
3454 case MEGACO_SERVICES_TOKEN5:
3455 dissect_megaco_servicechangedescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3456 break;
3457 case MEGACO_STATS_TOKEN6:
3458 dissect_megaco_statisticsdescriptor(descriptor_tvb, descriptor_tree);
3459 break;
3460 case MEGACO_ERROR_TOKEN7:
3461 dissect_megaco_errordescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3462 break;
3463 case MEGACO_EVENTS_TOKEN8:
3464 dissect_megaco_eventsdescriptor(descriptor_tvb, pinfo, descriptor_tree, top_tree);
3465 break;
3466 case MEGACO_AUDIT_TOKEN9:
3467 dissect_megaco_auditdescriptor(descriptor_tvb, descriptor_tree, pinfo, top_tree, context);
3468 break;
3469 case MEGACO_DIGITMAP_TOKEN10:
3470 dissect_megaco_digitmapdescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3471 break;
3472 case MEGACO_OE_TOKEN11:
3473 /* ObservedEventsToken */
3474 dissect_megaco_observedeventsdescriptor(descriptor_tvb, pinfo, descriptor_tree, top_tree);
3475 break;
3476 case MEGACO_TOPOLOGY_TOKEN12:
3477 dissect_megaco_topologydescriptor(tvb, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3478 break;
3479 case MEGACO_PACKAGES_TOKEN13:
3480 dissect_megaco_Packagesdescriptor(tvb, pinfo, descriptor_tree, tvb_RBRKT, tvb_previous_offset);
3481 break;
3482 default:
3483 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
3484 proto_tree_add_expert(descriptor_tree, pinfo, &ei_megaco_no_descriptor, tvb, tvb_previous_offset, tokenlen);
3485 break;
3486 }
3487
3488 found = tvb_find_uint8_length(tvb, tvb_RBRKT, tvb_len, ',', &tvb_current_offset);
3489 if (found == false0) {
3490 tvb_current_offset = tvb_descriptors_end_offset;
3491 }
3492 tvb_previous_offset = megaco_tvb_skip_wsp(tvb, tvb_current_offset+1);
3493 tvb_RBRKT = tvb_previous_offset;
3494
3495 } while ( tvb_current_offset < tvb_descriptors_end_offset );
3496
3497}
3498
3499/* Copied from MGCP dissector, prints whole message in raw text */
3500
3501static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree){
3502
3503 int tvb_linebegin,tvb_lineend,linelen;
3504 proto_tree* text_tree;
3505
3506 tvb_linebegin = 0;
3507
3508 if (tree) {
3509 text_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_megaco_raw_text, NULL((void*)0), "-------------- (RAW text output) ---------------");
3510
3511 do {
3512 linelen = tvb_find_line_end(tvb,tvb_linebegin,-1,&tvb_lineend,false0);
3513 proto_tree_add_format_wsp_text(text_tree, tvb, tvb_linebegin, linelen);
3514 tvb_linebegin = tvb_lineend;
3515 } while (tvb_offset_exists(tvb, tvb_lineend) && linelen > 0);
3516 }
3517}
3518
3519/*
3520* megaco_tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
3521* character following offset or offset + maxlength -1 whichever
3522* is smaller.
3523*
3524* Parameters:
3525* tvb - The tvbuff in which we are skipping whitespaces, tab and end_of_line characters.
3526* offset - The offset in tvb from which we begin trying to skip whitespace.
3527*
3528* Returns: The position in tvb of the first non-whitespace
3529*/
3530static int megaco_tvb_skip_wsp(tvbuff_t* tvb, int offset ){
3531 int counter = offset;
3532 int end = tvb_reported_length(tvb);
3533
3534 for(counter = offset; counter < end &&
3535 (g_ascii_isspace(tvb_get_uint8(tvb,counter))((g_ascii_table[(guchar) (tvb_get_uint8(tvb,counter))] & G_ASCII_SPACE
) != 0)
); counter++);
3536 return (counter);
3537}
3538
3539static int megaco_tvb_skip_wsp_return(tvbuff_t* tvb, int offset){
3540 int counter = offset;
3541 int end = 0;
3542
3543 for(counter = offset; counter > end &&
3544 (g_ascii_isspace(tvb_get_uint8(tvb,counter))((g_ascii_table[(guchar) (tvb_get_uint8(tvb,counter))] & G_ASCII_SPACE
) != 0)
); counter--);
3545 counter++;
3546 return (counter);
3547}
3548
3549static int megaco_tvb_find_token(tvbuff_t* tvb, int offset, int maxlength){
3550 int counter = 0;
3551 int pos = offset;
3552 unsigned char needle;
3553
3554 do {
3555 pos = tvb_ws_mempbrk_pattern_uint8(tvb, pos + 1, maxlength, &pbrk_braces, &needle);
3556 if(pos == -1)
3557 return -1;
3558 switch(needle){
3559 case '{':
3560 counter++;
3561 break;
3562 case '}':
3563 counter--;
3564 break;
3565 default:
3566 break;
3567 }
3568 } while (counter>0);
3569 if(counter<0)
3570 return -1;
3571 else
3572 {
3573 pos = megaco_tvb_skip_wsp(tvb,pos+1);
3574 return pos;
3575 }
3576}
3577
3578static void
3579megaco_fmt_content( char *result, uint32_t context )
3580{
3581 switch(context)
3582 {
3583 case CHOOSE_CONTEXT0xFFFFFFFE:
3584 case ALL_CONTEXTS0xFFFFFFFF:
3585 case NULL_CONTEXT0:
3586 (void) g_strlcpy(result, val_to_str_const(context, megaco_context_vals, "Unknown"), ITEM_LABEL_LENGTH240);
3587 break;
3588 default:
3589 snprintf( result, ITEM_LABEL_LENGTH240, "%d", context);
3590 }
3591}
3592
3593void
3594proto_register_megaco(void)
3595{
3596 static hf_register_info hf[] = {
3597 { &hf_megaco_audititem,
3598 { "Audit Item", "megaco.audititem", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3599 "Identity of item to be audited", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3600 { &hf_megaco_audit_descriptor,
3601 { "Audit Descriptor", "megaco.audit", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3602 "Audit Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3603#if 0
3604 { &hf_megaco_command_line,
3605 { "Command line", "megaco.command_line", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3606 "Commands of this message", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3607#endif
3608 { &hf_megaco_command,
3609 { "Command", "megaco.command", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3610 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3611 { &hf_megaco_command_optional,
3612 { "Optional Command", "megaco.command_optional", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3613 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3614 { &hf_megaco_wildcard_response,
3615 { "Wildcarded response to a command", "megaco.wildcard_response", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3616 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3617
3618 { &hf_megaco_Context,
3619 { "Context", "megaco.context", FT_UINT32, BASE_CUSTOM, CF_FUNC(megaco_fmt_content)((const void *) (size_t) (megaco_fmt_content)), 0x0,
3620 "Context ID of this message", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3621 { &hf_megaco_Context_generated,
3622 { "Generated Context", "megaco.context.generated", FT_UINT32, BASE_CUSTOM, CF_FUNC(megaco_fmt_content)((const void *) (size_t) (megaco_fmt_content)), 0x0,
3623 "Used to track Context ID across protocols", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3624 { &hf_megaco_digitmap_descriptor,
3625 { "DigitMap Descriptor", "megaco.digitmap", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3626 "DigitMap Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3627 { &hf_megaco_error_descriptor,
3628 { "ERROR Descriptor", "megaco.error", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3629 "Error Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3630 { &hf_megaco_error_code,
3631 { "ERROR Code", "megaco.error_code", FT_UINT32, BASE_DEC, VALS(MEGACO_error_code_vals)((0 ? (const struct _value_string*)0 : ((MEGACO_error_code_vals
))))
, 0x0,
3632 "Error Code of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3633 { &hf_megaco_error_string,
3634 { "ERROR String", "megaco.error_string", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3635 "Error String of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3636 { &hf_megaco_Event_Buffer_Control,
3637 { "Event Buffer Control", "megaco.eventbuffercontrol", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3638 "Event Buffer Control in Termination State Descriptor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3639 { &hf_megaco_events_descriptor,
3640 { "Events Descriptor", "megaco.events", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3641 "Events Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3642 { &hf_megaco_Local_descriptor,
3643 { "Local Descriptor", "megaco.localdescriptor", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3644 "Local Descriptor in Media Descriptor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3645 { &hf_megaco_LocalControl_descriptor,
3646 { "Local Control Descriptor", "megaco.localcontroldescriptor", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3647 "Local Control Descriptor in Media Descriptor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3648 { &hf_megaco_media_descriptor,
3649 { "Media Descriptor", "megaco.media", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3650 "Media Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3651 { &hf_megaco_modem_descriptor,
3652 { "Modem Descriptor", "megaco.modem", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3653 "Modem Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3654 { &hf_megaco_mode,
3655 { "Mode", "megaco.mode", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3656 "Mode sendonly/receiveonly/inactive/loopback", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3657 { &hf_megaco_multiplex_descriptor,
3658 { "Multiplex Descriptor", "megaco.multiplex", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3659 "Multiplex Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3660 { &hf_megaco_observedevents_descriptor,
3661 { "Observed Events Descriptor", "megaco.observedevents", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3662 "Observed Events Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3663 { &hf_megaco_packages_descriptor,
3664 { "Packages Descriptor", "megaco.packagesdescriptor", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3665 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3666 { &hf_megaco_pkgdname,
3667 { "pkgdName", "megaco.pkgdname", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3668 "PackageName SLASH ItemID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3669 { &hf_megaco_Remote_descriptor,
3670 { "Remote Descriptor", "megaco.remotedescriptor", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3671 "Remote Descriptor in Media Descriptor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3672 { &hf_megaco_reserve_group,
3673 { "Reserve Group", "megaco.reservegroup", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3674 "Reserve Group on or off", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3675 { &hf_megaco_h324_muxtbl_in,
3676 { "h324/muxtbl_in", "megaco.h324_muxtbl_in", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3677 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3678 { &hf_megaco_h324_muxtbl_out,
3679 { "h324/muxtbl_out", "megaco.h324_muxtbl_out", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3680 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3681 { &hf_megaco_ds_dscp,
3682 { "Differentiated Services Code Point", "megaco.ds_dscp", FT_UINT32, BASE_HEX|BASE_EXT_STRING0x00000200, &dscp_vals_ext, 0x0,
3683 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3684 { &hf_megaco_gm_saf,
3685 { "Remote Source Address Filtering", "megaco.gm_saf", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3686 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3687 { &hf_megaco_gm_sam,
3688 { "Remote Source Address Mask", "megaco.gm_sam", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3689 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3690 { &hf_megaco_gm_spf,
3691 { "Remote Source Port Filtering", "megaco.gm_spf", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3692 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3693 { &hf_megaco_gm_spr,
3694 { "Remote Source Port Range", "megaco.gm_spr", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3695 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3696 { &hf_megaco_gm_esas,
3697 { "Explicit Source Address Setting", "megaco.gm_esas", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3698 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3699 { &hf_megaco_tman_pol,
3700 { "Policing", "megaco.tman_pol", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3701 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3702 { &hf_megaco_gm_rsb,
3703 { "RTCP Allocation Specific Behaviour", "megaco.gm_rsb", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3704 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3705 { &hf_megaco_tman_sdr,
3706 { "Sustainable Data Rate", "megaco.tman_sdr", FT_INT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_byte_bytespsecond)((0 ? (const struct unit_name_string*)0 : ((&units_byte_bytespsecond
))))
, 0x0,
3707 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3708 { &hf_megaco_tman_mbs,
3709 { "Maximum Burst Rate", "megaco.tman_mbs", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3710 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3711 { &hf_megaco_tman_pdr,
3712 { "Peak Data Rate", "megaco.tman_pdr", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3713 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3714 { &hf_megaco_tman_dvt,
3715 { "Delay Variation Tolerance", "megaco.tman_dvt", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3716 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3717 { &hf_megaco_ipdc_realm,
3718 { "IP Realm Identifier", "megaco.ipdc_realm", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3719 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3720 { &hf_megaco_h324_h223capr,
3721 { "h324/h223capr", "megaco.h324_h223capr", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3722 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3723 { &hf_megaco_reserve_value,
3724 { "Reserve Value", "megaco.reservevalue", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3725 "Reserve Value on or off", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3726 { &hf_megaco_requestid,
3727 { "RequestID", "megaco.requestid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3728 "RequestID in Events or Observedevents Descriptor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3729#if 0
3730 { &hf_megaco_servicechange_descriptor,
3731 { "Service Change Descriptor", "megaco.servicechange", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3732 "Service Change Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3733#endif
3734 { &hf_megaco_Service_State,
3735 { "Service State", "megaco.servicestates", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3736 "Service States in Termination State Descriptor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3737 { &hf_megaco_signal_descriptor,
3738 { "Signal Descriptor", "megaco.signal", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3739 "Signal Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3740 { &hf_megaco_statistics_descriptor,
3741 { "Statistics Descriptor", "megaco.statistics", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3742 "Statistics Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3743 { &hf_megaco_streamid,
3744 { "StreamID", "megaco.streamid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3745 "StreamID in the Media Descriptor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3746 { &hf_megaco_termid,
3747 { "Termination ID", "megaco.termid", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3748 "Termination ID of this Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3749 { &hf_megaco_TerminationState_descriptor,
3750 { "Termination State Descriptor", "megaco.terminationstate", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3751 "Termination State Descriptor in Media Descriptor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3752 { &hf_megaco_topology_descriptor,
3753 { "Topology Descriptor", "megaco.topology", FT_STRING, BASE_STR_WSP, NULL((void*)0), 0x0,
3754 "Topology Descriptor of the megaco Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3755 { &hf_megaco_transaction,
3756 { "Transaction", "megaco.transaction", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3757 "Message Originator", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3758 { &hf_megaco_transid,
3759 { "Transaction ID", "megaco.transid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3760 "Transaction ID of this message", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3761 { &hf_megaco_mId,
3762 { "MediagatewayID", "megaco.mId", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3763 "Mediagateway ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3764 { &hf_megaco_version,
3765 { "Version", "megaco.version", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3766 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3767 { &hf_megaco_start,
3768 { "Start token", "megaco.start_token", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
3769 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3770 { &hf_megaco_h245,
3771 { "h245", "megaco.h245", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3772 "Embedded H.245 message", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3773 { &hf_megaco_h223Capability,
3774 { "h223Capability", "megaco.h245.h223Capability", FT_NONE, BASE_NONE, NULL((void*)0), 0,
3775 "megaco.h245.H223Capability", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3776 { &hf_megaco_priority,
3777 { "Priority", "megaco.priority", FT_STRING, BASE_NONE, NULL((void*)0), 0,
3778 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
3779
3780 GCP_HF_ARR_ELEMS("megaco",megaco_ctx_ids){ &(megaco_ctx_ids.hf.ctx), { "Context", "megaco" ".ctx",
FT_UINT32, BASE_HEX, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) }}, { &(megaco_ctx_ids.hf.ctx_term), { "Termination"
, "megaco" ".ctx.term", FT_STRING, BASE_NONE, ((void*)0), 0, (
(void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, { &
(megaco_ctx_ids.hf.ctx_term_type), { "Type", "megaco" ".ctx.term.type"
, FT_UINT32, BASE_HEX, ((0 ? (const struct _value_string*)0 :
((gcp_term_types)))), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) }}, { &(megaco_ctx_ids.hf.ctx_term_bir),
{ "BIR", "megaco" ".ctx.term.bir", FT_STRING, BASE_NONE, ((void
*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
}, { &(megaco_ctx_ids.hf.ctx_term_nsap), { "NSAP", "megaco"
".ctx.term.nsap", FT_STRING, BASE_NONE, ((void*)0), 0, ((void
*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, { &(megaco_ctx_ids
.hf.ctx_cmd), { "Command in Frame", "megaco" ".ctx.cmd", FT_FRAMENUM
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) }}
,
3781
3782 /* Add more fields here */
3783 };
3784 static int *ett[] = {
3785 &ett_megaco,
3786 &ett_megaco_message,
3787 &ett_megaco_message_body,
3788 &ett_megaco_context,
3789 &ett_megaco_command_line,
3790 &ett_megaco_descriptors,
3791 &ett_megaco_raw_text,
3792 &ett_megaco_error_descriptor,
3793 &ett_megaco_mediadescriptor,
3794 &ett_megaco_TerminationState,
3795 &ett_megaco_Remotedescriptor,
3796 &ett_megaco_Localdescriptor,
3797 &ett_megaco_LocalControldescriptor,
3798 &ett_megaco_auditdescriptor,
3799 &ett_megaco_eventsdescriptor,
3800 &ett_megaco_statisticsdescriptor,
3801 &ett_megaco_observedeventsdescriptor,
3802 &ett_megaco_observedevent,
3803 &ett_megaco_packagesdescriptor,
3804 &ett_megaco_requestedevent,
3805 &ett_megaco_signalsdescriptor,
3806 &ett_megaco_requestedsignal,
3807 &ett_megaco_h245,
3808 GCP_ETT_ARR_ELEMS(megaco_ctx_ids)&(megaco_ctx_ids.ett.ctx),&(megaco_ctx_ids.ett.ctx_cmds
),&(megaco_ctx_ids.ett.ctx_terms),&(megaco_ctx_ids.ett
.ctx_term)
,
3809 };
3810
3811 static ei_register_info ei[] = {
3812 { &ei_megaco_errored_command, { "megaco.errored_command", PI_RESPONSE_CODE0x03000000, PI_WARN0x00600000, "Errored Command", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
3813 { &ei_megaco_parse_error, { "megaco.parse_error", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Parse error", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
3814 { &ei_megaco_error_descriptor_transaction_list, { "megaco.error_descriptor_transaction_list.invalid", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Sorry, can't understand errorDescriptor / transactionList", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
3815 { &ei_megaco_audit_descriptor, { "megaco.audit.malformed", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Badly constructed audit descriptor (no { )", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
3816 { &ei_megaco_signal_descriptor, { "megaco.signal_descriptor.empty", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "Empty Signal Descriptor", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
3817 { &ei_megaco_no_command, { "megaco.no_command", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "No Command detectable", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
3818 { &ei_megaco_no_descriptor, { "megaco.no_descriptor", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "No Descriptor detectable", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
3819 { &ei_megaco_reason_invalid, { "megaco.change_reason.invalid", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Invalid Service Change Reason", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
3820 { &ei_megaco_error_code_invalid,{ "megaco.error_code.invalid", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Invalid error code", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
3821 { &ei_megaco_invalid_sdr, { "megaco.sdr.invalid", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Invalid Sustainable Data Rate", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}}
3822 };
3823
3824 module_t *megaco_module;
3825 expert_module_t* expert_megaco;
3826
3827 proto_megaco = proto_register_protocol("MEGACO", "MEGACO", "megaco");
3828
3829 megaco_text_handle = register_dissector("megaco", dissect_megaco_text, proto_megaco);
3830
3831 proto_register_field_array(proto_megaco, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
3832 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
3833 expert_megaco = expert_register_protocol(proto_megaco);
3834 expert_register_field_array(expert_megaco, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
3835
3836 /* Register our configuration options, particularly our ports */
3837
3838 megaco_module = prefs_register_protocol(proto_megaco, NULL((void*)0));
3839
3840 prefs_register_bool_preference(megaco_module, "display_raw_text",
3841 "Display raw text for MEGACO message",
3842 "Specifies that the raw text of the "
3843 "MEGACO message should be displayed "
3844 "instead of (or in addition to) the "
3845 "dissection tree",
3846 &global_megaco_raw_text);
3847
3848 prefs_register_bool_preference(megaco_module, "display_dissect_tree",
3849 "Display tree dissection for MEGACO message",
3850 "Specifies that the dissection tree of the "
3851 "MEGACO message should be displayed "
3852 "instead of (or in addition to) the "
3853 "raw text",
3854 &global_megaco_dissect_tree);
3855 prefs_register_bool_preference(megaco_module, "ctx_info",
3856 "Track Context",
3857 "Maintain relationships between transactions and contexts "
3858 "and display an extra tree showing context data",
3859 &keep_persistent_data);
3860
3861 megaco_tap = register_tap("megaco");
3862
3863 /* compile patterns */
3864 ws_mempbrk_compile(&pbrk_whitespace, " \t\r\n");
3865 ws_mempbrk_compile(&pbrk_braces, "{}");
3866
3867 register_rtd_table(proto_megaco, NULL((void*)0), 1, NUM_TIMESTATS12, megaco_message_type, megacostat_packet, megacostat_filtercheck);
3868}
3869
3870/* Register all the bits needed with the filtering engine */
3871/* The registration hand-off routine */
3872void
3873proto_reg_handoff_megaco(void)
3874{
3875 dissector_handle_t megaco_text_tcp_handle;
3876
3877 sdp_handle = find_dissector_add_dependency("sdp", proto_megaco);
3878 h245_handle = find_dissector_add_dependency("h245dg", proto_megaco);
3879 h248_handle = find_dissector_add_dependency("h248", proto_megaco);
3880 h248_otp_handle = find_dissector_add_dependency("h248_otp", proto_megaco);
3881 data_handle = find_dissector("data");
3882
3883 megaco_text_tcp_handle = create_dissector_handle(dissect_megaco_text_tcp, proto_megaco);
3884
3885 dissector_add_uint_with_preference("tcp.port", PORT_MEGACO_TXT2944, megaco_text_tcp_handle);
3886 dissector_add_uint_with_preference("udp.port", PORT_MEGACO_TXT2944, megaco_text_handle);
3887 dissector_add_uint_with_preference("sctp.port", PORT_MEGACO_TXT2944, megaco_text_handle);
3888 dissector_add_uint("sctp.ppi", H248_PAYLOAD_PROTOCOL_ID7, megaco_text_handle);
3889
3890 exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_7"OSI layer 7");
3891
3892 sip_hide_generated_call_ids = prefs_find_preference(prefs_find_module("sip"), "hide_generated_call_id");
3893
3894}
3895
3896/*
3897 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3898 *
3899 * Local variables:
3900 * c-basic-offset: 4
3901 * tab-width: 8
3902 * indent-tabs-mode: nil
3903 * End:
3904 *
3905 * vi: set shiftwidth=4 tabstop=8 expandtab:
3906 * :indentSize=4:tabSize=8:noTabs=true:
3907 */