2 * Routines for megaco packet disassembly
5 * Christian Falckenberg, 2002/10/17
6 * Copyright (c) 2002 by Christian Falckenberg
7 * <christian.falckenberg@nortelnetworks.com>
9 * Christoph Wiest, 2003/06/28
10 * Modified 2003 by Christoph Wiest
11 * <ch.wiest@tesionmail.de>
12 * Modified 2004 by Anders Broman
13 * <anders.broman@ericsson.com>
14 * To handle TPKT headers if over TCP
15 * Modified 2005 by Karl Knoebl
16 * <karl.knoebl@siemens.com>
17 * provide info to COL_INFO and some "prettification"
19 * Copyright (c) 2006 Anders Broman <anders.broman@ericsson.com>
21 * Wireshark - Network traffic analyzer
22 * By Gerald Combs <gerald@wireshark.org>
23 * Copyright 1999 Gerald Combs
25 * SPDX-License-Identifier: GPL-2.0-or-later
33 #include <epan/packet.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/sctpppids.h>
41 #include <epan/charsets.h>
42 #include <epan/unit_strings.h>
44 #include <wsutil/array.h>
45 #include <wsutil/strtoi.h>
46 #include "packet-ber.h"
47 #include "packet-tpkt.h"
48 #include "packet-h245.h"
49 #include "packet-h248.h"
50 #include "packet-ip.h"
51 #include "packet-media-type.h"
52 #include "packet-sdp.h"
54 void proto_register_megaco(void);
55 void proto_reg_handoff_megaco(void);
57 #define PORT_MEGACO_TXT 2944
58 #define PORT_MEGACO_BIN 2945
60 static pref_t
*sip_hide_generated_call_ids
;
63 /* Define the megaco proto */
64 static int proto_megaco
;
66 /* Define headers for megaco */
67 static int hf_megaco_start
;
68 static int hf_megaco_version
;
69 static int hf_megaco_transaction
;
70 static int hf_megaco_transid
;
71 static int hf_megaco_Context
;
72 /* static int hf_megaco_command_line; */
73 static int hf_megaco_command
;
74 static int hf_megaco_command_optional
;
75 static int hf_megaco_wildcard_response
;
76 static int hf_megaco_termid
;
80 /* Define headers in subtree for megaco */
81 static int hf_megaco_modem_descriptor
;
82 static int hf_megaco_multiplex_descriptor
;
83 static int hf_megaco_media_descriptor
;
84 static int hf_megaco_Local_descriptor
;
85 static int hf_megaco_events_descriptor
;
86 static int hf_megaco_signal_descriptor
;
87 static int hf_megaco_audit_descriptor
;
88 /* static int hf_megaco_servicechange_descriptor; */
89 static int hf_megaco_digitmap_descriptor
;
90 static int hf_megaco_statistics_descriptor
;
91 static int hf_megaco_observedevents_descriptor
;
92 static int hf_megaco_topology_descriptor
;
93 static int hf_megaco_error_descriptor
;
94 static int hf_megaco_error_code
;
95 static int hf_megaco_error_string
;
96 static int hf_megaco_TerminationState_descriptor
;
97 static int hf_megaco_Remote_descriptor
;
98 static int hf_megaco_LocalControl_descriptor
;
99 static int hf_megaco_packages_descriptor
;
100 static int hf_megaco_Service_State
;
101 static int hf_megaco_Event_Buffer_Control
;
102 static int hf_megaco_mode
;
103 static int hf_megaco_reserve_group
;
104 static int hf_megaco_h324_muxtbl_in
;
105 static int hf_megaco_h324_muxtbl_out
;
106 static int hf_megaco_ds_dscp
;
107 static int hf_megaco_gm_saf
;
108 static int hf_megaco_gm_sam
;
109 static int hf_megaco_gm_spf
;
110 static int hf_megaco_gm_spr
;
111 static int hf_megaco_gm_esas
;
112 static int hf_megaco_tman_pol
;
113 static int hf_megaco_gm_rsb
;
114 static int hf_megaco_tman_sdr
;
115 static int hf_megaco_tman_mbs
;
116 static int hf_megaco_tman_pdr
;
117 static int hf_megaco_tman_dvt
;
118 static int hf_megaco_ipdc_realm
;
119 static int hf_megaco_h324_h223capr
;
120 static int hf_megaco_reserve_value
;
121 static int hf_megaco_streamid
;
122 static int hf_megaco_requestid
;
123 static int hf_megaco_pkgdname
;
124 static int hf_megaco_mId
;
125 static int hf_megaco_h245
;
126 static int hf_megaco_h223Capability
;
127 static int hf_megaco_audititem
;
128 static int hf_megaco_priority
;
130 /* Define the trees for megaco */
131 static int ett_megaco
;
132 static int ett_megaco_message
;
133 static int ett_megaco_message_body
;
134 static int ett_megaco_context
;
135 static int ett_megaco_command_line
;
136 static int ett_megaco_mediadescriptor
;
137 static int ett_megaco_descriptors
;
138 static int ett_megaco_raw_text
;
139 static int ett_megaco_error_descriptor
;
140 static int ett_megaco_TerminationState
;
141 static int ett_megaco_Localdescriptor
;
142 static int ett_megaco_Remotedescriptor
;
143 static int ett_megaco_LocalControldescriptor
;
144 static int ett_megaco_auditdescriptor
;
145 static int ett_megaco_eventsdescriptor
;
146 static int ett_megaco_statisticsdescriptor
;
147 static int ett_megaco_observedeventsdescriptor
;
148 static int ett_megaco_observedevent
;
149 static int ett_megaco_packagesdescriptor
;
150 static int ett_megaco_requestedevent
;
151 static int ett_megaco_signalsdescriptor
;
152 static int ett_megaco_requestedsignal
;
153 static int ett_megaco_h245
;
155 static gcp_hf_ett_t megaco_ctx_ids
;
157 static expert_field ei_megaco_errored_command
;
158 static expert_field ei_megaco_no_command
;
159 static expert_field ei_megaco_no_descriptor
;
160 static expert_field ei_megaco_error_descriptor_transaction_list
;
161 static expert_field ei_megaco_parse_error
;
162 static expert_field ei_megaco_audit_descriptor
;
163 static expert_field ei_megaco_signal_descriptor
;
164 static expert_field ei_megaco_reason_invalid
;
165 static expert_field ei_megaco_error_code_invalid
;
166 static expert_field ei_megaco_invalid_sdr
;
168 static dissector_handle_t megaco_text_handle
;
170 static int megaco_tap
;
171 static int exported_pdu_tap
= -1;
174 /* patterns used for tvb_ws_mempbrk_pattern_uint8 */
175 static ws_mempbrk_pattern pbrk_whitespace
;
176 static ws_mempbrk_pattern pbrk_braces
;
178 /* Used when command type is needed to differentiate parsing, extend as needed */
181 MEGACO_CMD_NOT_SET
= 0,
183 } megaco_commands_enum_t
;
186 * Here are the global variables associated with
187 * the various user definable characteristics of the dissection
189 * H.248/MEGACO has two kinds of message formats: text and binary (ASN.1).
190 * The binary message format is dissected in packet-h248.c
192 * global_megaco_raw_text determines whether we are going to display
193 * the raw text of the megaco message, much like the HTTP dissector does.
195 * global_megaco_dissect_tree determines whether we are going to display
196 * a detailed tree that expresses a somewhat more semantically meaningful
199 static bool global_megaco_raw_text
= true;
200 static bool global_megaco_dissect_tree
= true;
202 static const value_string megaco_context_vals
[] = {
203 { CHOOSE_CONTEXT
, "Choose one" },
204 { ALL_CONTEXTS
, "All" },
205 { NULL_CONTEXT
, "NULL" },
210 /* Some basic utility functions that are specific to this dissector */
211 static int megaco_tvb_skip_wsp(tvbuff_t
*tvb
, int offset
);
212 static int megaco_tvb_skip_wsp_return(tvbuff_t
*tvb
, int offset
);
214 #define NUM_TIMESTATS 12
216 static const value_string megaco_message_type
[] = {
231 #define GCP_CMD_REPLY_CASE \
232 case GCP_CMD_ADD_REPLY: \
233 case GCP_CMD_MOVE_REPLY: \
234 case GCP_CMD_MOD_REPLY: \
235 case GCP_CMD_SUB_REPLY: \
236 case GCP_CMD_AUDITCAP_REPLY: \
237 case GCP_CMD_AUDITVAL_REPLY: \
238 case GCP_CMD_NOTIFY_REPLY: \
239 case GCP_CMD_SVCCHG_REPLY: \
240 case GCP_CMD_TOPOLOGY_REPLY: \
243 #define GCP_CMD_REQ_CASE \
244 case GCP_CMD_ADD_REQ: \
245 case GCP_CMD_MOVE_REQ: \
246 case GCP_CMD_MOD_REQ: \
247 case GCP_CMD_SUB_REQ: \
248 case GCP_CMD_AUDITCAP_REQ: \
249 case GCP_CMD_AUDITVAL_REQ: \
250 case GCP_CMD_NOTIFY_REQ: \
251 case GCP_CMD_SVCCHG_REQ: \
252 case GCP_CMD_TOPOLOGY_REQ: \
253 case GCP_CMD_CTX_ATTR_AUDIT_REQ: \
254 case GCP_CMD_OTHER_REQ:
257 megacostat_is_duplicate_reply(const gcp_cmd_t
* cmd
)
263 gcp_cmd_msg_t
*cmd_msg
;
264 /* cycle through commands to find same command in the transaction */
265 for (cmd_msg
= cmd
->trx
->cmds
;
266 (cmd_msg
!= NULL
) && (cmd_msg
->cmd
->msg
->framenum
!= cmd
->msg
->framenum
);
267 cmd_msg
= cmd_msg
->next
) {
268 if (cmd_msg
->cmd
->type
== cmd
->type
)
282 megacostat_had_request(const gcp_cmd_t
* cmd
)
288 gcp_cmd_msg_t
*cmd_msg
;
289 /* cycle through commands to find a request in the transaction */
290 for (cmd_msg
= cmd
->trx
->cmds
;
291 (cmd_msg
!= NULL
) && (cmd_msg
->cmd
->msg
->framenum
!= cmd
->msg
->framenum
);
292 cmd_msg
= cmd_msg
->next
) {
294 switch (cmd_msg
->cmd
->type
) {
315 megacostat_filtercheck(const char *opt_arg _U_
, const char **filter _U_
, char** err
)
317 pref_t
*megaco_ctx_track
, *h248_ctx_track
;
319 megaco_ctx_track
= prefs_find_preference(prefs_find_module("megaco"), "ctx_info");
320 h248_ctx_track
= prefs_find_preference(prefs_find_module("h248"), "ctx_info");
322 if (!megaco_ctx_track
|| !h248_ctx_track
) {
323 /* No such preferences */
327 if (!prefs_get_bool_value(megaco_ctx_track
, pref_current
) || !prefs_get_bool_value(h248_ctx_track
, pref_current
)) {
328 *err
= ws_strdup_printf("Track Context option at Protocols -> MEGACO and Protocols -> H248 preferences\n"
329 "has to be set to true to enable measurement of service response times.\n");
333 static tap_packet_status
334 megacostat_packet(void *pms
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *pmi
, tap_flags_t flags _U_
)
336 rtd_data_t
* rtd_data
= (rtd_data_t
*)pms
;
337 rtd_stat_table
* ms
= &rtd_data
->stat_table
;
338 const gcp_cmd_t
*mi
=(const gcp_cmd_t
*)pmi
;
340 tap_packet_status ret
= TAP_PACKET_DONT_REDRAW
;
345 if(!mi
->trx
->initial
) {
346 /* Track Context is probably disabled, we cannot
347 * measure service response time */
348 return TAP_PACKET_DONT_REDRAW
;
351 else if(mi
->trx
->initial
->framenum
!= mi
->msg
->framenum
){
352 /* Duplicate is ignored */
353 ms
->time_stats
[0].req_dup_num
++;
356 ms
->time_stats
[0].open_req_num
++;
361 if(megacostat_is_duplicate_reply(mi
)){
362 /* Duplicate is ignored */
363 ms
->time_stats
[0].rsp_dup_num
++;
365 else if (!megacostat_had_request(mi
)) {
366 /* no request was seen */
367 ms
->time_stats
[0].disc_rsp_num
++;
370 ms
->time_stats
[0].open_req_num
--;
371 /* calculate time delta between request and response */
372 nstime_delta(&delta
, &pinfo
->abs_ts
, &mi
->trx
->initial
->frametime
);
376 case GCP_CMD_ADD_REPLY
:
377 time_stat_update(&(ms
->time_stats
[0].rtd
[0]),&delta
, pinfo
);
379 case GCP_CMD_MOVE_REPLY
:
380 time_stat_update(&(ms
->time_stats
[0].rtd
[1]),&delta
, pinfo
);
382 case GCP_CMD_MOD_REPLY
:
383 time_stat_update(&(ms
->time_stats
[0].rtd
[2]),&delta
, pinfo
);
385 case GCP_CMD_SUB_REPLY
:
386 time_stat_update(&(ms
->time_stats
[0].rtd
[3]),&delta
, pinfo
);
388 case GCP_CMD_AUDITCAP_REPLY
:
389 time_stat_update(&(ms
->time_stats
[0].rtd
[4]),&delta
, pinfo
);
391 case GCP_CMD_AUDITVAL_REPLY
:
392 time_stat_update(&(ms
->time_stats
[0].rtd
[5]),&delta
, pinfo
);
394 case GCP_CMD_NOTIFY_REPLY
:
395 time_stat_update(&(ms
->time_stats
[0].rtd
[6]),&delta
, pinfo
);
397 case GCP_CMD_SVCCHG_REPLY
:
398 time_stat_update(&(ms
->time_stats
[0].rtd
[7]),&delta
, pinfo
);
400 case GCP_CMD_TOPOLOGY_REPLY
:
401 time_stat_update(&(ms
->time_stats
[0].rtd
[8]),&delta
, pinfo
);
404 time_stat_update(&(ms
->time_stats
[0].rtd
[9]),&delta
, pinfo
);
407 time_stat_update(&(ms
->time_stats
[0].rtd
[11]),&delta
, pinfo
);
410 time_stat_update(&(ms
->time_stats
[0].rtd
[10]),&delta
, pinfo
);
411 ret
= TAP_PACKET_REDRAW
;
422 /* Call the export PDU tap with relevant data */
424 export_megaco_pdu(packet_info
*pinfo
, tvbuff_t
*tvb
)
426 exp_pdu_data_t
*exp_pdu_data
= export_pdu_create_common_tags(pinfo
, "megaco", EXP_PDU_TAG_DISSECTOR_NAME
);
428 exp_pdu_data
->tvb_captured_length
= tvb_captured_length(tvb
);
429 exp_pdu_data
->tvb_reported_length
= tvb_reported_length(tvb
);
430 exp_pdu_data
->pdu_tvb
= tvb
;
432 tap_queue_packet(exported_pdu_tap
, pinfo
, exp_pdu_data
);
437 * The various functions that either dissect some
438 * subpart of MEGACO. These aren't really proto dissectors but they
439 * are written in the same style.
443 dissect_megaco_descriptors(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int tvb_descriptors_start_offset
, int tvb_descriptors_end_offset
, proto_tree
*top_tree
, uint32_t context
);
445 dissect_megaco_digitmapdescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int tvb_RBRKT
, int tvb_previous_offset
);
447 dissect_megaco_topologydescriptor(tvbuff_t
*tvb
, proto_tree
*tree
, int tvb_RBRKT
, int tvb_previous_offset
);
449 dissect_megaco_errordescriptor(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, int tvb_RBRKT
, int tvb_previous_offset
);
451 dissect_megaco_statisticsdescriptor(tvbuff_t
*tvb
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
);
453 dissect_megaco_TerminationStatedescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int tvb_next_offset
, int tvb_current_offset
);
455 dissect_megaco_LocalRemotedescriptor(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int tvb_next_offset
, int tvb_current_offset
, uint32_t context
, bool is_local
);
457 dissect_megaco_LocalControldescriptor(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int tvb_next_offset
, int tvb_current_offset
, proto_tree
*top_tree
);
459 dissect_megaco_Packagesdescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int tvb_next_offset
, int tvb_current_offset
);
461 tvb_raw_text_add(tvbuff_t
*tvb
, proto_tree
*tree
);
463 dissect_megaco_text(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
);
465 megaco_tvb_find_token(tvbuff_t
*tvb
, int offset
, int maxlength
);
466 static dissector_handle_t data_handle
;
467 static dissector_handle_t sdp_handle
;
468 static dissector_handle_t h245_handle
;
469 static dissector_handle_t h248_handle
;
470 static dissector_handle_t h248_otp_handle
;
472 static bool keep_persistent_data
;
475 * dissect_megaco_text over TCP, there will be a TPKT header there
478 static int dissect_megaco_text_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
482 /* This code is copied from the Q.931 dissector, some parts skipped.
483 * Check whether this looks like a TPKT-encapsulated
486 * The minimum length of a MEGACO message is 6?:
489 lv_tpkt_len
= is_tpkt(tvb
, 6);
490 if (lv_tpkt_len
== -1) {
492 * It's not a TPKT packet;
495 dissect_megaco_text(tvb
, pinfo
, tree
, data
);
497 dissect_tpkt_encap(tvb
, pinfo
, tree
, true,
500 return tvb_captured_length(tvb
);
506 #define PENDINGTOKEN 4
507 #define RESPONSEACKTOKEN 5
511 const char *compact_name
;
514 static const megaco_tokens_t megaco_messageBody_names
[] = {
515 { "Unknown-token", NULL
}, /* 0 Pad so that the real headers start at index 1 */
516 { "Error", "ER" }, /* 1 */
517 { "Transaction", "T" }, /* 2 */
518 { "Reply", "P" }, /* 3 */
519 { "Pending", "PN" }, /* 4 */
520 { "TransactionResponseAck", "K" }, /* 5 */
523 /* Returns index of megaco_tokens_t */
524 static int find_megaco_messageBody_names(tvbuff_t
*tvb
, int offset
, unsigned header_len
)
528 for (i
= 1; i
< array_length(megaco_messageBody_names
); i
++) {
529 if (header_len
== strlen(megaco_messageBody_names
[i
].name
) &&
530 tvb_strncaseeql(tvb
, offset
, megaco_messageBody_names
[i
].name
, header_len
) == 0)
532 if (megaco_messageBody_names
[i
].compact_name
!= NULL
&&
533 header_len
== strlen(megaco_messageBody_names
[i
].compact_name
) &&
534 tvb_strncaseeql(tvb
, offset
, megaco_messageBody_names
[i
].compact_name
, header_len
) == 0)
542 megaco_tree_add_string(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
543 int start
, int length
, const char *value
)
547 pi
= proto_tree_add_string(tree
, hfindex
, tvb
, start
, length
, value
);
548 if (!global_megaco_dissect_tree
) {
549 proto_item_set_hidden(pi
);
556 my_proto_tree_add_uint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
557 int start
, int length
, uint32_t value
)
561 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, start
, 1, value
);
562 /* String length may be longer than FT_UINT will allow */
563 proto_item_set_len(pi
, length
);
565 if (!global_megaco_dissect_tree
) {
566 proto_item_set_hidden(pi
);
573 * dissect_megaco_text - The dissector for the MEGACO Protocol, using
577 dissect_megaco_text(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
580 int tvb_offset
,tvb_current_offset
,tvb_previous_offset
,tvb_next_offset
,tokenlen
;
581 int context_offset
, context_length
, save_offset
, save_length
;
582 int tvb_command_start_offset
, tvb_command_end_offset
;
583 int tvb_descriptors_start_offset
, tvb_descriptors_end_offset
;
584 int tvb_transaction_end_offset
;
585 proto_tree
*megaco_tree
, *message_body_tree
, *megaco_tree_command_line
, *ti
, *sub_ti
;
590 int tvb_RBRKT
, tvb_LBRKT
, RBRKT_counter
, LBRKT_counter
;
591 unsigned token_index
=0;
593 unsigned char needle
;
595 gcp_msg_t
*msg
= NULL
;
596 gcp_trx_t
*trx
= NULL
;
597 gcp_ctx_t
*ctx
= NULL
;
598 gcp_cmd_t
*cmd
= NULL
;
599 gcp_term_t
*term
= NULL
;
600 gcp_trx_type_t trx_type
= GCP_TRX_NONE
;
601 uint32_t trx_id
= 0, pending_id
;
603 gcp_cmd_type_t cmd_type
= GCP_CMD_NONE
;
604 gcp_wildcard_t wild_term
= GCP_WILDCARD_NONE
;
607 megaco_commands_enum_t megaco_command
= MEGACO_CMD_NOT_SET
;
608 /* Initialize variables */
609 tvb_len
= tvb_reported_length(tvb
);
616 /* Check if H.248 in otp(Erlang) internal format
617 * XXX Needs improvement?
619 * http://www.erlang.org/doc/apps/megaco/part_frame.html
620 * 4.1 Internal form of messages
621 * 4.2 The different encodings
623 dword
= tvb_get_ntoh24(tvb
,0);
624 if ((dword
== 0x836803)&&(h248_otp_handle
)){
625 call_dissector(h248_otp_handle
, tvb
, pinfo
, tree
);
626 return tvb_captured_length(tvb
);
629 msg
= gcp_msg(pinfo
, tvb_raw_offset(tvb
), keep_persistent_data
);
632 * Check to see whether we're really dealing with MEGACO by looking
633 * for the "MEGACO" string or a "!".This needs to be improved when supporting
634 * binary encodings. Bugfix add skipping of leading spaces.
636 tvb_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
);
638 if(!tvb_get_raw_bytes_as_stringz(tvb
,tvb_offset
,sizeof(word
),word
)) return tvb_captured_length(tvb
);
640 /* Quick fix for MEGACO packet with Authentication Header,
641 * marked as "AU" or "Authentication".
643 if ((g_ascii_strncasecmp(word
, "Authentication", 14) == 0) ||
644 (g_ascii_strncasecmp(word
, "AU", 2) == 0)) {
648 /* move offset to end of auth header (EOL or WSP) */
649 for ( counter
= tvb_offset
; counter
< tvb_len
; counter
++ ) {
650 needle
= tvb_get_uint8(tvb
, counter
);
651 if (needle
== ' ' || needle
== '\r' || needle
== '\n') {
652 next
= tvb_get_uint8(tvb
, counter
+1);
653 if (next
== ' ' || next
== '\r' || next
== '\n') {
656 tvb_offset
= counter
+ 1;
662 short_form
= (tvb_get_uint8(tvb
, tvb_offset
) == '!');
664 if (g_ascii_strncasecmp(word
, "MEGACO", 6) != 0 && !short_form
){
668 dissector_handle_t handle
= data_handle
;
670 get_ber_identifier(tvb
, 0, &ber_class
, &pc
, &tag
);
672 if (ber_class
== BER_CLASS_UNI
&& pc
&& tag
== BER_UNI_TAG_SEQUENCE
) {
673 handle
= h248_handle
;
676 call_dissector(handle
,tvb
,pinfo
,tree
);
677 return tvb_captured_length(tvb
);
681 /* Display MEGACO in protocol column */
682 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MEGACO");
684 /* Report this packet to the tap */
685 if (!pinfo
->flags
.in_error_pkt
) {
686 if (have_tap_listener(exported_pdu_tap
)) {
687 export_megaco_pdu(pinfo
, tvb
);
691 /* Build the info tree if we've been given a root */
692 /* Create megaco subtree */
693 ti
= proto_tree_add_item(tree
,proto_megaco
,tvb
, 0, -1, ENC_NA
);
694 megaco_tree
= proto_item_add_subtree(ti
, ett_megaco
);
696 /* Format of 'message' is = MegacopToken SLASH Version SEP mId SEP messageBody */
697 /* MegacopToken = "MEGACO" or "!" */
698 /* According to H248.1-200205 Annex B Text encoding ( protocol version 2 ) */
701 tvb_previous_offset
= tvb_find_uint8(tvb
, 0,
703 if (tvb_previous_offset
== -1) {
704 expert_add_info_format(pinfo
, ti
, &ei_megaco_parse_error
,
705 "Sorry, no \"/\" in the MEGACO header, I can't parse this packet");
706 return tvb_captured_length(tvb
);
709 megaco_tree_add_string(megaco_tree
, hf_megaco_start
, tvb
, 0, tvb_previous_offset
+1,
710 tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_previous_offset
, ENC_UTF_8
|ENC_NA
));
713 tvb_previous_offset
++;
715 /* assume at least one digit in version */
716 tvb_current_offset
= tvb_previous_offset
+ 1;
718 if (g_ascii_isdigit(tvb_get_uint8(tvb
, tvb_current_offset
))) {
719 /* 2-digit version */
720 tvb_current_offset
++;
723 megaco_tree_add_string(megaco_tree
, hf_megaco_version
, tvb
, tvb_previous_offset
, tvb_current_offset
- tvb_previous_offset
,
724 tvb_get_string_enc(pinfo
->pool
, tvb
, tvb_previous_offset
, tvb_current_offset
- tvb_previous_offset
, ENC_UTF_8
|ENC_NA
));
726 tvb_previous_offset
= tvb_current_offset
;
727 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_previous_offset
);
729 if (tvb_previous_offset
== tvb_current_offset
) {
730 expert_add_info_format(pinfo
, ti
, &ei_megaco_parse_error
,
731 "[ Parse error: missing SEP in MEGACO header ]");
732 return tvb_current_offset
;
735 tvb_previous_offset
= tvb_current_offset
;
737 /* mId should follow here,
738 * mId = (( domainAddress / domainName ) [":" portNumber]) / mtpAddress / deviceName
739 * domainAddress = "[" (IPv4address / IPv6address) "]"
740 * domainName = "<" (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" /".") ">"
741 * mtpAddress = MTPToken LBRKT 4*8 (HEXDIG) RBRKT
743 * deviceName = pathNAME
744 * pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )["@" pathDomainName ]
747 tvb_current_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, tvb_current_offset
, -1, &pbrk_whitespace
, &needle
);
748 if (tvb_current_offset
== -1) {
749 expert_add_info_format(pinfo
, ti
, &ei_megaco_parse_error
,
750 "[ Parse error: no body in MEGACO message (missing SEP after mId) ]");
751 return tvb_captured_length(tvb
);
754 tvb_next_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
);
756 /* At this point we should point to the "\n" ending the mId element
757 * or to the next character after white space SEP
759 megaco_tree_add_string(megaco_tree
, hf_megaco_mId
, tvb
, tvb_previous_offset
, tvb_current_offset
- tvb_previous_offset
,
760 tvb_get_string_enc(pinfo
->pool
, tvb
, tvb_previous_offset
, tvb_current_offset
- tvb_previous_offset
, ENC_UTF_8
|ENC_NA
));
762 col_clear(pinfo
->cinfo
, COL_INFO
);
764 tvb_previous_offset
= tvb_next_offset
;
767 * : messageBody = ( errorDescriptor / transactionList )
768 * errorDescriptor = ErrorToken EQUAL ErrorCode LBRKT [quotedString] RBRKT
769 * ErrorToken = ("Error" / "ER")
771 * transactionList = 1*( transactionRequest / transactionReply /
772 * transactionPending / transactionResponseAck )
774 * transactionResponseAck = ResponseAckToken LBRKT
775 * transactionAck*(COMMA transactionAck) RBRKT
776 * ResponseAckToken = ("TransactionResponseAck"/ "K")
778 * transactionPending = PendingToken EQUAL TransactionID LBRKT RBRKT
779 * PendingToken = ("Pending" / "PN")
781 * transactionReply = ReplyToken EQUAL TransactionID LBRKT
782 * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
783 * ReplyToken = ("Reply" / "P")
785 * transactionRequest = TransToken EQUAL TransactionID LBRKT
786 * actionRequest *(COMMA actionRequest) RBRKT
787 * TransToken = ("Transaction" / "T")
790 /* Find token length */
791 for (tvb_offset
=tvb_previous_offset
; tvb_offset
< tvb_len
-1; tvb_offset
++){
792 if (!g_ascii_isalpha(tvb_get_uint8(tvb
, tvb_offset
))){
796 tokenlen
= tvb_offset
- tvb_previous_offset
;
797 token_index
= find_megaco_messageBody_names(tvb
, tvb_previous_offset
, tokenlen
);
799 ws_warning("token_index %u",token_index);
802 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_offset
, tvb_len
, '{');
803 tvb_current_offset
= tvb_LBRKT
;
804 tvb_transaction_end_offset
= megaco_tvb_find_token(tvb
, tvb_LBRKT
- 1, tvb_len
);
806 switch ( token_index
){
807 /* errorDescriptor */
809 col_set_str(pinfo
->cinfo
, COL_INFO
, "Error ");
811 tvb_current_offset
= megaco_tvb_find_token(tvb
, tvb_offset
, tvb_len
); /*tvb_find_uint8(tvb, tvb_offset+1, tvb_len, '}');*/
813 ti
= proto_tree_add_format_text(megaco_tree
, tvb
, tvb_previous_offset
, tvb_current_offset
-tvb_previous_offset
);
814 message_body_tree
= proto_item_add_subtree(ti
, ett_megaco_message_body
);
817 megaco_tree_add_string(message_body_tree
, hf_megaco_transaction
, tvb
,
818 tvb_previous_offset
, tokenlen
,
821 tvb_command_start_offset
= tvb_previous_offset
;
822 dissect_megaco_errordescriptor(tvb
, pinfo
, megaco_tree
, tvb_len
-1, tvb_command_start_offset
);
824 return tvb_captured_length(tvb
);
825 /* transactionResponseAck
826 * transactionResponseAck = ResponseAckToken LBRKT transactionAck
827 * *(COMMA transactionAck) RBRKT
828 * transactionAck = transactionID / (transactionID "-" transactionID)
830 case RESPONSEACKTOKEN
:
831 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_offset
, tvb_transaction_end_offset
, '{');
832 tvb_offset
= tvb_LBRKT
;
833 save_offset
= tvb_previous_offset
;
834 save_length
= tvb_current_offset
-tvb_previous_offset
;
836 megaco_tree_add_string(megaco_tree
, hf_megaco_transaction
, tvb
,
837 save_offset
, save_length
, "TransactionResponseAck" );
839 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
840 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_offset
+1, tvb_len
, '}');
841 /*tvb_current_offset = megaco_tvb_find_token(tvb, tvb_offset, tvb_transaction_end_offset);*/
842 tvb_current_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
)-1; /* cut last RBRKT */
843 len
= tvb_current_offset
- tvb_previous_offset
;
845 pending_id
= (unsigned)strtoul(tvb_format_text(pinfo
->pool
, tvb
,tvb_previous_offset
,len
),NULL
,10);
846 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "%d TransactionResponseAck", pending_id
);
848 my_proto_tree_add_uint(megaco_tree
, hf_megaco_transid
, tvb
, save_offset
, save_length
, pending_id
);
850 if(global_megaco_raw_text
){
851 tvb_raw_text_add(tvb
, megaco_tree
);
853 return tvb_captured_length(tvb
);
854 /* Pe and PN is transactionPending, P+"any char" is transactionReply */
857 tvb_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_transaction_end_offset
, '=')+1;
858 tvb_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
);
859 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_offset
, tvb_transaction_end_offset
, '{');
860 tvb_current_offset
= tvb_LBRKT
;
861 save_offset
= tvb_previous_offset
;
862 save_length
= tvb_current_offset
-tvb_previous_offset
;
864 megaco_tree_add_string(megaco_tree
, hf_megaco_transaction
, tvb
,
865 save_offset
, save_length
, "Reply" );
867 tvb_current_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1);
868 len
= tvb_current_offset
- tvb_offset
;
870 pending_id
= (unsigned)strtoul(tvb_format_text(pinfo
->pool
, tvb
,tvb_offset
,len
),NULL
,10);
871 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "%d Pending", pending_id
);
873 my_proto_tree_add_uint(megaco_tree
, hf_megaco_transid
, tvb
, save_offset
, save_length
, pending_id
);
874 return tvb_captured_length(tvb
);
876 /* transactionReply */
878 trx_type
= GCP_TRX_REPLY
;
879 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_offset
, tvb_transaction_end_offset
, '{');
880 save_offset
= tvb_previous_offset
;
881 save_length
= tvb_LBRKT
-tvb_previous_offset
;
883 megaco_tree_add_string(megaco_tree
, hf_megaco_transaction
, tvb
,
884 save_offset
, save_length
, "Reply" );
886 tvb_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_transaction_end_offset
, '=')+1;
887 tvb_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
);
888 tvb_current_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_LBRKT
-1);
889 len
= tvb_current_offset
- tvb_offset
;
891 trx_id
= (unsigned)strtoul(tvb_format_text(pinfo
->pool
, tvb
,tvb_offset
,len
),NULL
,10);
892 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%d Reply ", trx_id
);
894 my_proto_tree_add_uint(megaco_tree
, hf_megaco_transid
, tvb
, save_offset
, save_length
, trx_id
);
896 /* Find if we have a errorDescriptor or actionReplyList */
897 tvb_offset
= megaco_tvb_skip_wsp(tvb
, tvb_LBRKT
+1);
898 tempchar
= tvb_get_uint8(tvb
,tvb_offset
);
899 if ((tempchar
== 'E')||(tempchar
== 'e')){
900 dissect_megaco_errordescriptor(tvb
, pinfo
, megaco_tree
, tvb_transaction_end_offset
-1, tvb_offset
);
901 return tvb_captured_length(tvb
);
903 /* Offset should be at first printable char after { */
904 tvb_previous_offset
= tvb_offset
;
907 /* TransactionRequest */
908 trx_type
= GCP_TRX_REQUEST
;
909 save_offset
= tvb_previous_offset
;
910 save_length
= tvb_current_offset
-tvb_previous_offset
;
911 megaco_tree_add_string(megaco_tree
, hf_megaco_transaction
, tvb
,
912 save_offset
, save_length
, "Request" );
914 tvb_offset
= tvb_find_uint8(tvb
, tvb_offset
, tvb_transaction_end_offset
, '=')+1;
915 tvb_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
);
916 tvb_current_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1);
917 len
= tvb_current_offset
- tvb_offset
;
919 trx_id
= (unsigned)strtoul(tvb_format_text(pinfo
->pool
, tvb
,tvb_offset
,len
),NULL
,10);
920 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "%d Request", trx_id
);
922 my_proto_tree_add_uint(megaco_tree
, hf_megaco_transid
, tvb
, save_offset
, save_length
, trx_id
);
923 /* Offset should be at first printable char after { */
924 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_LBRKT
+1);
928 proto_tree_add_expert_format(tree
, pinfo
, &ei_megaco_error_descriptor_transaction_list
, tvb
, 0, -1,
929 "Sorry, can't understand errorDescriptor / transactionList = %s, can't parse it pos %u",
930 tvb_format_text(pinfo
->pool
, tvb
,tvb_previous_offset
,2),tvb_previous_offset
);
931 return tvb_captured_length(tvb
);
933 /* Only these remains now
934 * transactionReply = ReplyToken EQUAL TransactionID LBRKT
935 * [ ImmAckRequiredToken COMMA]( errorDescriptor / actionReplyList ) RBRKT
936 * ReplyToken = ("Reply" / "P")
938 * errorDescriptor = ErrorToken EQUAL ErrorCode
939 * LBRKT [quotedString] RBRKT
941 * transactionRequest = TransToken EQUAL TransactionID LBRKT
942 * actionRequest *(COMMA actionRequest) RBRKT
943 * TransToken = ("Transaction" / "T")
946 trx
= gcp_trx(msg
, trx_id
, trx_type
, pinfo
, keep_persistent_data
);
954 tvb_next_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_transaction_end_offset
, '{');
955 context_offset
= tvb_previous_offset
;
956 context_length
= tvb_next_offset
-tvb_previous_offset
+1;
958 tvb_previous_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_transaction_end_offset
, '=')+1;
959 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_previous_offset
);
961 if (tvb_current_offset
>= tvb_next_offset
) {
962 proto_tree_add_expert_format(megaco_tree
, pinfo
, &ei_megaco_parse_error
,
963 tvb
, context_offset
, context_length
, "Parse error: Invalid offset");
964 return tvb_captured_length(tvb
);
966 tvb_current_offset
= tvb_next_offset
;
969 tokenlen
= tvb_current_offset
- tvb_previous_offset
;
970 tempchar
= tvb_get_uint8(tvb
, tvb_previous_offset
);
972 if (tvb_get_uint8(tvb
, tvb_current_offset
-1 ) == ' '){
978 ctx_id
= CHOOSE_CONTEXT
;
981 ctx_id
= ALL_CONTEXTS
;
984 ctx_id
= NULL_CONTEXT
;
987 ctx_id
= (unsigned)strtoul(tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
, tokenlen
),NULL
,10);
990 my_proto_tree_add_uint(megaco_tree
, hf_megaco_Context
, tvb
, context_offset
, context_length
, ctx_id
);
991 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " |=%s", val_to_str(ctx_id
, megaco_context_vals
, "%d"));
993 ctx
= gcp_ctx(msg
,trx
,ctx_id
,pinfo
,keep_persistent_data
);
997 /* If Transaction is Request, Reply or Pending */
998 tvb_command_start_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
999 tvb_command_end_offset
= tvb_command_start_offset
;
1001 tvb_LBRKT
= tvb_command_start_offset
;
1002 tvb_RBRKT
= tvb_command_start_offset
;
1004 /* The following loop find the individual contexts, commands and call the for every Descriptor a subroutine */
1007 tvb_command_end_offset
= tvb_find_uint8(tvb
, tvb_command_end_offset
+1,
1008 tvb_transaction_end_offset
, ',');
1010 if ( tvb_command_end_offset
== -1 || tvb_command_end_offset
> tvb_transaction_end_offset
){
1011 tvb_command_end_offset
= tvb_transaction_end_offset
;
1015 /* checking how many left brackets are before the next comma */
1017 while ( tvb_find_uint8(tvb
, tvb_LBRKT
+1,tvb_transaction_end_offset
, '{') != -1
1018 && (tvb_find_uint8(tvb
, tvb_LBRKT
+1,tvb_transaction_end_offset
, '{') < tvb_command_end_offset
)){
1020 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
+1,
1021 tvb_transaction_end_offset
, '{');
1026 /* checking how many right brackets are before the next comma */
1028 while ( (tvb_find_uint8(tvb
, tvb_RBRKT
+1,tvb_transaction_end_offset
, '}') != -1 )
1029 && (tvb_find_uint8(tvb
, tvb_RBRKT
+1,tvb_transaction_end_offset
, '}') <= tvb_command_end_offset
)
1030 && LBRKT_counter
!= 0){
1032 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
1033 tvb_transaction_end_offset
, '}');
1039 /* If equal or more right brackets before the comma, one command is complete */
1041 if ( LBRKT_counter
<= RBRKT_counter
){
1043 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_command_start_offset
,
1044 tvb_transaction_end_offset
, '{');
1047 /* includes no descriptors */
1049 if ( LBRKT_counter
== 0 ){
1051 tvb_current_offset
= tvb_command_end_offset
;
1053 /* the last command in a context */
1055 if ( tvb_find_uint8(tvb
, tvb_command_start_offset
, tvb_transaction_end_offset
, '}') < tvb_current_offset
1056 && tvb_find_uint8(tvb
, tvb_command_start_offset
, tvb_transaction_end_offset
, '}') != -1){
1058 tvb_previous_offset
= tvb_find_uint8(tvb
, tvb_command_start_offset
,
1059 tvb_transaction_end_offset
, '}');
1061 len
= tvb_previous_offset
- tvb_command_start_offset
;
1063 tvb_previous_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_previous_offset
-1);
1065 tokenlen
= tvb_previous_offset
- tvb_command_start_offset
;
1069 /* not the last command in a context*/
1072 len
= tvb_current_offset
- tvb_command_start_offset
;
1073 tvb_current_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1);
1075 tokenlen
= tvb_current_offset
- tvb_command_start_offset
;
1079 /* command includes descriptors */
1082 len
= tvb_current_offset
- tvb_command_start_offset
;
1083 tvb_current_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1);
1085 tokenlen
= tvb_current_offset
- tvb_command_start_offset
;
1088 /* if a next context is specified */
1090 if ( tvb_get_uint8(tvb
, tvb_command_start_offset
) == 'C'){
1091 tvb_current_offset
= tvb_command_start_offset
;
1092 tvb_previous_offset
= tvb_command_start_offset
;
1098 megaco_tree_command_line
= proto_tree_add_subtree(megaco_tree
, tvb
, tvb_command_start_offset
, len
+1, ett_megaco_command_line
, &sub_ti
, "Command: ");
1099 megaco_command
= MEGACO_CMD_NOT_SET
;
1100 /* creation of the megaco_tree_command_line additionally Command and Transaction ID will be printed in this line */
1101 /* Changed to use the lines above. this code is saved if there is complaints
1102 sub_ti = proto_tree_add_item(megaco_tree,hf_megaco_command_line,tvb,tvb_command_start_offset,tokenlen, ENC_UTF_8);
1103 megaco_tree_command_line = proto_item_add_subtree(sub_ti, ett_megaco_command_line);
1105 if (!global_megaco_dissect_tree
) {
1106 proto_item_set_hidden(sub_ti
);
1109 tvb_next_offset
= tvb_command_start_offset
+ tokenlen
;
1111 /* Try to dissect Topology Descriptor before the command */
1112 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
);
1113 if ( (tempchar
>= 'a')&& (tempchar
<= 'z')){
1114 tempchar
= tempchar
- 0x20;
1116 if ( tempchar
== 'T') {
1117 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
+1);
1119 if ( (tempchar
>= 'a')&& (tempchar
<= 'z'))
1120 tempchar
= tempchar
- 0x20;
1122 if ( tempchar
== 'P' || tempchar
== 'O'){
1123 int tvb_topology_end_offset
= tvb_find_uint8(tvb
, tvb_command_start_offset
, tvb_transaction_end_offset
, '}');
1124 if ( tvb_topology_end_offset
== -1 ){
1125 expert_add_info_format(pinfo
, sub_ti
, &ei_megaco_parse_error
, "Parse error: Missing \"}\"");
1126 return tvb_captured_length(tvb
);
1129 tvb_command_start_offset
= tvb_find_uint8(tvb
, tvb_command_start_offset
, tvb_transaction_end_offset
, '{');
1130 if ( tvb_command_start_offset
== -1 ){
1131 expert_add_info_format(pinfo
, sub_ti
, &ei_megaco_parse_error
, "Parse error: Missing \"{\"");
1132 return tvb_captured_length(tvb
);
1134 dissect_megaco_topologydescriptor(tvb
, megaco_tree_command_line
, tvb_topology_end_offset
-1, tvb_command_start_offset
+1);
1136 /* Command after Topology Descriptor */
1137 tvb_command_start_offset
= tvb_find_uint8(tvb
, tvb_topology_end_offset
+ 1,
1138 tvb_transaction_end_offset
, ',');
1140 if ( tvb_command_start_offset
== -1 ){
1141 /* No Command present after Topology Descriptor */
1145 /* Try to find the first char of the command */
1146 tvb_command_start_offset
= megaco_tvb_skip_wsp(tvb
, tvb_command_start_offset
+ 1);
1149 tvb_LBRKT
= tvb_command_start_offset
;
1150 tvb_RBRKT
= tvb_command_start_offset
;
1151 /*tvb_next_offset = tvb_find_uint8(tvb, tvb_command_start_offset, tvb_transaction_end_offset, '{');*/
1158 /* Additional value */
1159 if ( tvb_get_uint8(tvb
, tvb_command_start_offset
) == 'O'){
1161 proto_tree_add_item(megaco_tree_command_line
, hf_megaco_command_optional
, tvb
, tvb_command_start_offset
, 2, ENC_NA
);
1162 tvb_command_start_offset
= tvb_command_start_offset
+2;
1166 /* Additional value */
1167 if ( tvb_get_uint8(tvb
, tvb_command_start_offset
) == 'W'){
1169 proto_tree_add_item(megaco_tree_command_line
, hf_megaco_wildcard_response
, tvb
, tvb_command_start_offset
, 2, ENC_NA
);
1170 tvb_command_start_offset
= tvb_command_start_offset
+2;
1173 tvb_offset
= tvb_find_uint8(tvb
, tvb_command_start_offset
,
1174 tvb_transaction_end_offset
, '=');
1175 if (tvb_offset
== -1 ) {
1176 proto_tree_add_expert_format(megaco_tree
, pinfo
, &ei_megaco_parse_error
, tvb
, tvb_command_start_offset
, len
+1, "Parse error: Missing \"=\"");
1177 return tvb_captured_length(tvb
);
1179 tvb_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_offset
-1);
1180 tokenlen
= tvb_offset
- tvb_command_start_offset
;
1182 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
);
1183 if ( (tempchar
>= 'a')&& (tempchar
<= 'z'))
1184 tempchar
= tempchar
- 0x20;
1186 if ( tempchar
!= 'E' ){
1187 /* Short form used */
1190 switch ( tempchar
){
1194 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
+1);
1195 if ( (tempchar
>= 'a')&& (tempchar
<= 'z'))
1196 tempchar
= tempchar
- 0x20;
1198 switch ( tempchar
){
1202 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_AUDITVAL_REPLY
; break;
1203 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_AUDITVAL_REQ
; break;
1204 default: cmd_type
= GCP_CMD_NONE
; break;
1207 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1208 tvb_command_start_offset
, tokenlen
, "AuditValue");
1209 col_append_str(pinfo
->cinfo
, COL_INFO
, " AuditValue");
1210 proto_item_append_text(sub_ti
, "AuditValue");
1215 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_AUDITCAP_REQ
; break;
1216 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_AUDITCAP_REPLY
; break;
1217 default: cmd_type
= GCP_CMD_NONE
; break;
1219 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1220 tvb_command_start_offset
, tokenlen
, "AuditCapability");
1221 col_append_str(pinfo
->cinfo
, COL_INFO
, " AuditCapability");
1222 proto_item_append_text(sub_ti
, "AuditCapability");
1227 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_ADD_REQ
; break;
1228 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_ADD_REPLY
; break;
1229 default: cmd_type
= GCP_CMD_NONE
; break;
1232 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1233 tvb_command_start_offset
, tokenlen
, "Add");
1234 col_append_str(pinfo
->cinfo
, COL_INFO
, " Add");
1235 proto_item_append_text(sub_ti
, "Add");
1242 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
+1);
1243 if(tempchar
== 'E'){
1244 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1245 tvb_command_start_offset
, tokenlen
, "IEPSCall");
1246 col_append_str(pinfo
->cinfo
, COL_INFO
, " IEPSCall");
1247 proto_item_append_text(sub_ti
, "IEPSCall");
1249 cmd_type
= GCP_CMD_NONE
;
1253 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_NOTIFY_REQ
; break;
1254 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_NOTIFY_REPLY
; break;
1255 default: cmd_type
= GCP_CMD_NONE
; break;
1258 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1259 tvb_command_start_offset
, tokenlen
, "Notify");
1260 col_append_str(pinfo
->cinfo
, COL_INFO
, " Notify");
1261 proto_item_append_text(sub_ti
, "Notify");
1266 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
+1);
1267 if ( (tempchar
>= 'a')&& (tempchar
<= 'z'))
1268 tempchar
= tempchar
- 0x20;
1270 switch ( tempchar
){
1273 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_MOD_REQ
; break;
1274 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_MOD_REPLY
; break;
1275 default: cmd_type
= GCP_CMD_NONE
; break;
1278 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1279 tvb_command_start_offset
, tokenlen
, "Modify");
1280 col_append_str(pinfo
->cinfo
, COL_INFO
, " Modify");
1281 proto_item_append_text(sub_ti
, "Modify");
1286 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_MOVE_REQ
; break;
1287 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_MOVE_REPLY
; break;
1288 default: cmd_type
= GCP_CMD_NONE
; break;
1290 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1291 tvb_command_start_offset
, tokenlen
, "Move");
1292 col_append_str(pinfo
->cinfo
, COL_INFO
, " Move");
1293 proto_item_append_text(sub_ti
, "Move");
1299 cmd_type
= GCP_CMD_NONE
;
1301 PackagesToken = ("Packages" / "PG")
1302 PendingToken = ("Pending" / "PN")
1303 PriorityToken = ("Priority" / "PR")
1304 ProfileToken = ("Profile" / "PF")
1306 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
+1);
1307 if ( (tempchar
>= 'a')&& (tempchar
<= 'z'))
1308 tempchar
= tempchar
- 0x20;
1310 switch ( tempchar
){
1312 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1313 tvb_command_start_offset
, tokenlen
, "Packages");
1314 col_append_str(pinfo
->cinfo
, COL_INFO
, " Packages");
1315 proto_item_append_text(sub_ti
, "Packages");
1318 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1319 tvb_command_start_offset
, tokenlen
, "Pending");
1320 col_append_str(pinfo
->cinfo
, COL_INFO
, " Pending");
1321 proto_item_append_text(sub_ti
, "Pending");
1324 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1325 tvb_command_start_offset
, tokenlen
, "Priority");
1326 col_append_str(pinfo
->cinfo
, COL_INFO
, " Priority");
1327 proto_item_append_text(sub_ti
, "Priority");
1328 megaco_command
= MEGACO_CMD_PRIORITY
;
1331 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1332 tvb_command_start_offset
, tokenlen
, "Profile");
1333 col_append_str(pinfo
->cinfo
, COL_INFO
, " Profile");
1334 proto_item_append_text(sub_ti
, "Profile");
1340 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
+1);
1341 if ( (tempchar
>= 'a')&& (tempchar
<= 'z'))
1342 tempchar
= tempchar
- 0x20;
1344 switch ( tempchar
){
1348 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_SVCCHG_REQ
; break;
1349 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_SVCCHG_REPLY
; break;
1350 default: cmd_type
= GCP_CMD_NONE
; break;
1352 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1353 tvb_command_start_offset
, tokenlen
, "ServiceChange");
1354 col_append_str(pinfo
->cinfo
, COL_INFO
, " ServiceChange");
1355 proto_item_append_text(sub_ti
, "ServiceChange");
1360 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_SUB_REQ
; break;
1361 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_SUB_REPLY
; break;
1362 default: cmd_type
= GCP_CMD_NONE
; break;
1364 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1365 tvb_command_start_offset
, tokenlen
, "Subtract");
1366 col_append_str(pinfo
->cinfo
, COL_INFO
, " Subtract");
1367 proto_item_append_text(sub_ti
, "Subtract");
1373 proto_item_append_text(sub_ti
, "<None> 0x%02x", tempchar
);
1374 expert_add_info(pinfo
, sub_ti
, &ei_megaco_no_command
);
1375 return tvb_captured_length(tvb
);
1379 char* command
= tvb_format_text(pinfo
->pool
, tvb
, tvb_command_start_offset
, tokenlen
);
1381 if ( g_str_equal(command
,"Subtract") ) {
1383 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_SUB_REQ
; break;
1384 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_SUB_REPLY
; break;
1385 default: cmd_type
= GCP_CMD_NONE
; break;
1387 } else if ( g_str_equal(command
,"AuditValue") ) {
1389 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_AUDITVAL_REPLY
; break;
1390 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_AUDITVAL_REQ
; break;
1391 default: cmd_type
= GCP_CMD_NONE
; break;
1393 } else if ( g_str_equal(command
,"AuditCapability") ) {
1395 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_AUDITCAP_REQ
; break;
1396 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_AUDITCAP_REPLY
; break;
1397 default: cmd_type
= GCP_CMD_NONE
; break;
1399 } else if ( g_str_equal(command
,"Add") ) {
1401 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_ADD_REQ
; break;
1402 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_ADD_REPLY
; break;
1403 default: cmd_type
= GCP_CMD_NONE
; break;
1405 } else if ( g_str_equal(command
,"Notify") ) {
1407 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_NOTIFY_REQ
; break;
1408 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_NOTIFY_REPLY
; break;
1409 default: cmd_type
= GCP_CMD_NONE
; break;
1411 } else if ( g_str_equal(command
,"Modify") ) {
1413 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_MOD_REQ
; break;
1414 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_MOD_REPLY
; break;
1415 default: cmd_type
= GCP_CMD_NONE
; break;
1417 } else if ( g_str_equal(command
,"Move") ) {
1419 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_MOVE_REQ
; break;
1420 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_MOVE_REPLY
; break;
1421 default: cmd_type
= GCP_CMD_NONE
; break;
1423 } else if ( g_str_equal(command
,"ServiceChange") ) {
1425 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_SVCCHG_REQ
; break;
1426 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_SVCCHG_REPLY
; break;
1427 default: cmd_type
= GCP_CMD_NONE
; break;
1431 case GCP_TRX_REQUEST
: cmd_type
= GCP_CMD_OTHER_REQ
; break;
1432 case GCP_TRX_REPLY
: cmd_type
= GCP_CMD_REPLY
; break;
1433 default: cmd_type
= GCP_CMD_NONE
; break;
1438 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_command
, tvb
,
1439 tvb_command_start_offset
, tokenlen
, command
);
1440 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s", command
);
1441 proto_item_append_text(sub_ti
, " %s", command
);
1444 if (cmd_type
== GCP_CMD_NONE
&& trx_type
== GCP_TRX_REPLY
) {
1445 cmd_type
= GCP_CMD_REPLY
;
1448 if (cmd_type
!= GCP_CMD_NONE
) {
1449 cmd
= gcp_cmd(msg
, trx
, ctx
, cmd_type
, tvb_command_start_offset
, pinfo
, keep_persistent_data
);
1450 tap_queue_packet(megaco_tap
, pinfo
, cmd
);
1453 tvb_offset
= tvb_find_uint8(tvb
, tvb_command_start_offset
,
1454 tvb_transaction_end_offset
, '=');
1455 if (tvb_offset
== -1 ) {
1456 expert_add_info_format(pinfo
, sub_ti
, &ei_megaco_parse_error
, "Parse error: Missing \"=\"");
1457 return tvb_captured_length(tvb
);
1459 tvb_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
1460 tokenlen
= tvb_next_offset
- tvb_offset
;
1461 if (tokenlen
+1 <= 0) {
1462 expert_add_info_format(pinfo
, sub_ti
, &ei_megaco_parse_error
, "Parse error: Invalid token length (%d)", tokenlen
+1);
1463 return tvb_captured_length(tvb
);
1466 tempchar
= tvb_get_uint8(tvb
, tvb_offset
);
1467 if ( (tempchar
>= 'a')&& (tempchar
<= 'z'))
1468 tempchar
= tempchar
- 0x20;
1470 term
= wmem_new0(pinfo
->pool
, gcp_term_t
);
1471 wild_term
= GCP_WILDCARD_NONE
;
1472 term
->type
= GCP_TERM_TYPE_UNKNOWN
;
1475 switch ( tempchar
){
1478 if ((tokenlen
+1 > (int) sizeof(TermID
))) {
1479 expert_add_info_format(pinfo
, sub_ti
, &ei_megaco_parse_error
, "Parse error: Invalid TermID length (%d)", tokenlen
+1);
1480 return tvb_captured_length(tvb
);
1482 bytelen
= tvb_get_raw_bytes_as_stringz(tvb
,tvb_offset
,tokenlen
+1,TermID
);
1485 term
->buffer
= get_utf_8_string(pinfo
->pool
, TermID
, bytelen
);
1486 term
->len
= (int)strlen(term
->buffer
);
1487 term
->str
= (const char *)term
->buffer
;
1489 gcp_cmd_add_term(msg
, trx
, cmd
, term
, wild_term
, pinfo
, keep_persistent_data
);
1492 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_termid
, tvb
,
1493 tvb_offset
, tokenlen
, term
->str
);
1497 wild_term
= GCP_WILDCARD_ALL
;
1499 term
->buffer
= (const uint8_t*)(term
->str
= "*");
1501 gcp_cmd_add_term(msg
, trx
, cmd
, term
, wild_term
, pinfo
, keep_persistent_data
);
1503 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_termid
, tvb
,
1504 tvb_offset
, tokenlen
,
1506 col_append_str(pinfo
->cinfo
, COL_INFO
, "=*");
1510 wild_term
= GCP_WILDCARD_CHOOSE
;
1513 term
->buffer
= (term
->str
= "$");
1515 gcp_cmd_add_term(msg
, trx
, cmd
, term
, wild_term
, pinfo
, keep_persistent_data
);
1517 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_termid
, tvb
,
1518 tvb_offset
, tokenlen
,
1520 col_append_str(pinfo
->cinfo
, COL_INFO
, "=$");
1527 switch (megaco_command
) {
1528 case MEGACO_CMD_PRIORITY
:
1529 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_priority
, tvb
,
1530 tvb_offset
, tokenlen
,
1531 tvb_format_text(pinfo
->pool
, tvb
, tvb_offset
,
1535 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_termid
, tvb
,
1536 tvb_offset
, tokenlen
,
1537 tvb_format_text(pinfo
->pool
, tvb
, tvb_offset
,
1540 term
->len
= tokenlen
;
1541 term
->buffer
= (const uint8_t*)(term
->str
= tvb_format_text(pinfo
->pool
, tvb
, tvb_offset
, tokenlen
));
1543 gcp_cmd_add_term(msg
, trx
, cmd
, term
, wild_term
, pinfo
, keep_persistent_data
);
1547 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "=%s",tvb_format_text(pinfo
->pool
, tvb
, tvb_offset
,tokenlen
));
1552 /* Dissect the Descriptors */
1555 if ( LBRKT_counter
!= 0 && tvb_current_offset
!= tvb_command_end_offset
){
1557 tvb_descriptors_start_offset
= tvb_find_uint8(tvb
, tvb_command_start_offset
,
1558 tvb_transaction_end_offset
, '{');
1560 tvb_descriptors_end_offset
= tvb_descriptors_start_offset
;
1561 if ( tvb_descriptors_end_offset
> tvb_transaction_end_offset
)
1562 tvb_descriptors_end_offset
= tvb_transaction_end_offset
;
1564 while ( LBRKT_counter
> 0 ){
1566 tvb_descriptors_end_offset
= tvb_find_uint8(tvb
, tvb_descriptors_end_offset
+1,
1567 tvb_transaction_end_offset
, '}');
1573 tempchar
= tvb_get_uint8(tvb
, tvb_command_start_offset
);
1575 if ( tempchar
== 'E'|| tempchar
== 'e'){
1576 dissect_megaco_descriptors(tvb
, megaco_tree_command_line
, pinfo
, tvb_command_start_offset
-1,tvb_descriptors_end_offset
, tree
, ctx_id
);
1579 dissect_megaco_descriptors(tvb
, megaco_tree_command_line
, pinfo
, tvb_descriptors_start_offset
,tvb_descriptors_end_offset
, tree
, ctx_id
);
1584 tvb_command_start_offset
= megaco_tvb_skip_wsp(tvb
, tvb_command_end_offset
+1);
1585 tvb_LBRKT
= tvb_command_start_offset
;
1586 tvb_RBRKT
= tvb_command_start_offset
;
1590 } while ( tvb_command_end_offset
< tvb_transaction_end_offset
);
1592 if (keep_persistent_data
) {
1593 gcp_msg_to_str(msg
,pinfo
->pool
,keep_persistent_data
);
1594 gcp_analyze_msg(megaco_tree
, pinfo
, tvb
, msg
, &megaco_ctx_ids
, &ei_megaco_errored_command
);
1597 tvb_next_offset
= tvb_transaction_end_offset
;
1599 while( tvb_transaction_end_offset
> 0 && tvb_transaction_end_offset
< tvb_len
- 2);
1601 if(global_megaco_raw_text
){
1602 tvb_raw_text_add(tvb
, megaco_tree
);
1605 return tvb_captured_length(tvb
);
1608 #define MEGACO_MODEM_TOKEN 1
1609 #define MEGACO_MUX_TOKEN 2
1610 #define MEGACO_MEDIA_TOKEN 3
1611 #define MEGACO_SIGNALS_TOKEN 4
1612 #define MEGACO_SERVICES_TOKEN 5
1613 #define MEGACO_STATS_TOKEN 6
1614 #define MEGACO_ERROR_TOKEN 7
1615 #define MEGACO_EVENTS_TOKEN 8
1616 #define MEGACO_AUDIT_TOKEN 9
1617 #define MEGACO_DIGITMAP_TOKEN 10
1618 #define MEGACO_OE_TOKEN 11
1619 #define MEGACO_TOPOLOGY_TOKEN 12
1620 #define MEGACO_PACKAGES_TOKEN 13
1622 static const megaco_tokens_t megaco_descriptors_names
[] = {
1623 { "Unknown-token", NULL
}, /* 0 Pad so that the real headers start at index 1 */
1624 { "Modem", "MD" }, /* 1 */
1625 { "Mux", "MX" }, /* 2 */
1626 { "Media", "M" }, /* 3 */
1627 { "Signals", "SG" }, /* 4 */
1628 { "Services", "SV" }, /* 5 */
1629 { "Statistics", "SA" }, /* 6 */
1630 { "Error", "ER" }, /* 7 */
1631 { "Events", "E" }, /* 8 */
1632 { "Audit", "AT" }, /* 9 */
1633 { "DigitMap", "DM" }, /* 10 */
1634 { "ObservedEvents", "OE" }, /* 11 */
1635 { "Topology", "TP" }, /* 12 */
1636 { "Packages", "PG" }, /* 13 */
1639 /* Returns index of megaco_tokens_t */
1640 /* note - also called by dissect_megaco_auditdescriptor */
1641 static int find_megaco_descriptors_names(tvbuff_t
*tvb
, int offset
, unsigned header_len
)
1645 for (i
= 1; i
< array_length(megaco_descriptors_names
); i
++) {
1646 if (header_len
== strlen(megaco_descriptors_names
[i
].name
) &&
1647 tvb_strncaseeql(tvb
, offset
, megaco_descriptors_names
[i
].name
, header_len
) == 0)
1649 if (megaco_descriptors_names
[i
].compact_name
!= NULL
&&
1650 header_len
== strlen(megaco_descriptors_names
[i
].compact_name
) &&
1651 tvb_strncaseeql(tvb
, offset
, megaco_descriptors_names
[i
].compact_name
, header_len
) == 0)
1658 dissect_megaco_modemdescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
)
1663 tokenlen
= (tvb_RBRKT
+1) - tvb_previous_offset
;
1664 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_modem_descriptor
, tvb
,
1665 tvb_previous_offset
, tokenlen
,
1666 tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
,
1671 dissect_megaco_multiplexdescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
)
1676 tokenlen
= (tvb_RBRKT
+1) - tvb_previous_offset
;
1677 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_multiplex_descriptor
, tvb
,
1678 tvb_previous_offset
, tokenlen
,
1679 tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
,
1684 /* mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
1685 * MediaToken = ("Media" / "M")
1687 * mediaParm = (streamParm / streamDescriptor /terminationStateDescriptor)
1689 * ; at-most one terminationStateDescriptor
1690 * ; and either streamParm(s) or streamDescriptor(s) but not both
1691 * streamParm = ( localDescriptor / remoteDescriptor /localControlDescriptor )
1692 * localDescriptor = LocalToken LBRKT octetString RBRKT
1693 * LocalToken = ("Local" / "L")
1694 * octetString = *(nonEscapeChar)
1695 * nonEscapeChar = ( "\}" / %x01-7C / %x7E-FF )
1696 * remoteDescriptor = RemoteToken LBRKT octetString RBRKT
1697 * RemoteToken = ("Remote" / "R")
1698 * localControlDescriptor = LocalControlToken LBRKT localParm*(COMMA localParm) RBRKT
1699 * LocalControlToken = ("LocalControl" / "O")
1700 * localParm = ( streamMode / propertyParm / reservedValueMode
1701 * streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm*(COMMA streamParm) RBRKT
1702 * StreamToken = ("Stream" / "ST")
1703 * terminationStateDescriptor = TerminationStateToken LBRKTterminationStateParm
1704 * *( COMMA terminationStateParm ) RBRKT
1705 * TerminationStateToken = ("TerminationState" / "TS")
1706 * terminationStateParm =(propertyParm / serviceStates / eventBufferControl )
1709 #define MEGACO_LOCAL_TOKEN 1
1710 #define MEGACO_REMOTE_TOKEN 2
1711 #define MEGACO_LOCAL_CONTROL_TOKEN 3
1712 #define MEGACO_STREAM_TOKEN 4
1713 #define MEGACO_TERMINATION_STATE_DESC 5
1714 // MEGACO_STATS_TOKEN is already defined as 6 above
1716 static const megaco_tokens_t megaco_mediaParm_names
[] = {
1717 { "Unknown-token", NULL
}, /* 0 Pad so that the real headers start at index 1 */
1718 { "Local", "L" }, /* 1 */
1719 { "Remote", "R" }, /* 2 */
1720 { "LocalControl", "O" }, /* 3 */
1721 { "Stream", "ST" }, /* 4 */
1722 { "TerminationState", "TS" }, /* 5 */
1723 { "Statistics", "SA" }, /* 6 */
1726 /* Returns index of megaco_tokens_t */
1727 static int find_megaco_mediaParm_names(tvbuff_t
*tvb
, int offset
, unsigned header_len
)
1731 for (i
= 1; i
< array_length(megaco_mediaParm_names
); i
++) {
1732 if (header_len
== strlen(megaco_mediaParm_names
[i
].name
) &&
1733 tvb_strncaseeql(tvb
, offset
, megaco_mediaParm_names
[i
].name
, header_len
) == 0)
1735 if (megaco_mediaParm_names
[i
].compact_name
!= NULL
&&
1736 header_len
== strlen(megaco_mediaParm_names
[i
].compact_name
) &&
1737 tvb_strncaseeql(tvb
, offset
, megaco_mediaParm_names
[i
].compact_name
, header_len
) == 0)
1745 dissect_megaco_mediadescriptor(tvbuff_t
*tvb
, proto_tree
*megaco_tree_command_line
,packet_info
*pinfo
, int tvb_last_RBRKT
,
1746 int tvb_previous_offset
, int start_offset
, proto_tree
*top_tree
, uint32_t context
)
1749 int tokenlen
, tvb_LBRKT
, tvb_RBRKT
;
1750 int tvb_next_offset
, tvb_current_offset
, tvb_offset
, equal_offset
, save_offset
;
1754 proto_tree
*megaco_mediadescriptor_tree
;
1755 proto_item
*megaco_mediadescriptor_ti
, *ti
;
1757 megaco_mediadescriptor_ti
= proto_tree_add_item(megaco_tree_command_line
, hf_megaco_media_descriptor
, tvb
, start_offset
, 1, ENC_NA
);
1758 megaco_mediadescriptor_tree
= proto_item_add_subtree(megaco_mediadescriptor_ti
, ett_megaco_mediadescriptor
);
1760 while ( tvb_previous_offset
< tvb_last_RBRKT
){
1761 /* Start of token */
1762 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_previous_offset
);
1764 /* Find token length */
1765 for (tvb_next_offset
=tvb_current_offset
; tvb_next_offset
< tvb_last_RBRKT
; tvb_next_offset
++){
1766 if (!g_ascii_isalpha(tvb_get_uint8(tvb
, tvb_next_offset
))){
1770 tokenlen
= tvb_next_offset
- tvb_current_offset
;
1772 mediaParm
= find_megaco_mediaParm_names(tvb
, tvb_current_offset
, tokenlen
);
1774 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_next_offset
, tvb_last_RBRKT
, '{');
1775 tvb_next_offset
= tvb_find_uint8(tvb
, tvb_current_offset
+1 , tvb_last_RBRKT
, '}');
1776 tvb_RBRKT
= tvb_next_offset
;
1778 switch ( mediaParm
){
1779 case MEGACO_LOCAL_TOKEN
:
1780 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_LBRKT
+1);
1781 dissect_megaco_LocalRemotedescriptor(tvb
, megaco_mediadescriptor_tree
, pinfo
,
1782 tvb_RBRKT
, tvb_current_offset
, context
, true);
1783 tvb_current_offset
= tvb_RBRKT
;
1785 case MEGACO_REMOTE_TOKEN
:
1786 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_LBRKT
+1);
1787 dissect_megaco_LocalRemotedescriptor(tvb
, megaco_mediadescriptor_tree
, pinfo
,
1788 tvb_RBRKT
, tvb_current_offset
, context
, false);
1789 tvb_current_offset
= tvb_RBRKT
;
1791 case MEGACO_LOCAL_CONTROL_TOKEN
:
1792 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_LBRKT
+1);
1793 dissect_megaco_LocalControldescriptor(tvb
, megaco_mediadescriptor_tree
, pinfo
,
1794 tvb_RBRKT
, tvb_current_offset
, top_tree
);
1795 tvb_current_offset
= tvb_RBRKT
;
1797 case MEGACO_STREAM_TOKEN
:
1798 save_offset
= tvb_current_offset
;
1799 equal_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_last_RBRKT
, '=');
1800 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, equal_offset
+1);
1801 tvb_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_LBRKT
-1);
1802 tokenlen
= tvb_offset
- tvb_current_offset
;
1804 streamId
= (unsigned)strtoul(tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
,tokenlen
),NULL
,10);
1805 ti
= proto_tree_add_uint(megaco_mediadescriptor_tree
, hf_megaco_streamid
, tvb
,
1806 save_offset
, 1, streamId
);
1807 proto_item_set_len(ti
, tvb_offset
-save_offset
);
1808 tvb_previous_offset
= tvb_LBRKT
+1;
1810 case MEGACO_TERMINATION_STATE_DESC
:
1811 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_LBRKT
+1);
1812 dissect_megaco_TerminationStatedescriptor(tvb
, pinfo
, megaco_mediadescriptor_tree
,
1813 tvb_RBRKT
, tvb_current_offset
);
1814 tvb_current_offset
= tvb_RBRKT
;
1816 case MEGACO_STATS_TOKEN
:
1817 // dissect_megaco_statisticsdescriptor wants the previous
1818 // offset, don't skip forward.
1819 //tvb_current_offset = megaco_tvb_skip_wsp(tvb, tvb_LBRKT+1);
1820 dissect_megaco_statisticsdescriptor(tvb
, megaco_mediadescriptor_tree
,
1821 tvb_RBRKT
, tvb_current_offset
);
1822 tvb_current_offset
= tvb_RBRKT
;
1827 /* more parameters ? */
1828 tvb_next_offset
= tvb_find_uint8(tvb
, tvb_current_offset
+1 , tvb_last_RBRKT
, ',');
1829 if (tvb_next_offset
> tvb_last_RBRKT
) tvb_next_offset
= tvb_last_RBRKT
;
1830 if ( tvb_next_offset
!= -1 ){
1831 /* (raw formatting removed)
1832 tokenlen = tvb_next_offset - tvb_RBRKT+1;
1833 proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_RBRKT, tokenlen); */
1834 tvb_previous_offset
= tvb_next_offset
+1;
1836 /* Add the trailing '}' (raw formatting removed) */
1837 /* proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_RBRKT, 1); */
1838 tvb_previous_offset
= tvb_last_RBRKT
;
1843 proto_item_set_end(megaco_mediadescriptor_ti
, tvb
, tvb_previous_offset
);
1847 dissect_megaco_h245(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree
, int offset
, int len
, proto_tree
*top_tree
)
1849 /*proto_item *item;*/
1850 /*proto_tree *tree;*/
1851 char *msg
= tvb_format_text(pinfo
->pool
, tvb
, offset
, len
);
1853 /*item= */proto_tree_add_item(megaco_tree
, hf_megaco_h245
, tvb
, offset
, len
, ENC_NA
);
1854 /*tree = proto_item_add_subtree(item, ett_megaco_h245); */
1856 /* arbitrary maximum length */
1860 uint8_t *buf
= (uint8_t *)wmem_alloc(pinfo
->pool
, 10240);
1862 /* first, skip to where the encoded pdu starts, this is
1863 the first hex digit after the '=' char.
1866 if((*msg
==0)||(*msg
=='\n')){
1876 if((*msg
==0)||(*msg
=='\n')){
1879 if( ((*msg
>='0')&&(*msg
<='9'))
1880 || ((*msg
>='a')&&(*msg
<='f'))
1881 || ((*msg
>='A')&&(*msg
<='F'))){
1887 while( ((*msg
>='0')&&(*msg
<='9'))
1888 ||((*msg
>='a')&&(*msg
<='f'))
1889 ||((*msg
>='A')&&(*msg
<='F')) ){
1891 if((*msg
>='0')&&(*msg
<='9')){
1893 } else if((*msg
>='a')&&(*msg
<='f')){
1895 } else if((*msg
>='A')&&(*msg
<='F')){
1902 if((*msg
>='0')&&(*msg
<='9')){
1904 } else if((*msg
>='a')&&(*msg
<='f')){
1906 } else if((*msg
>='A')&&(*msg
<='F')){
1913 buf
[i
]=(uint8_t)val
;
1919 h245_tvb
= tvb_new_child_real_data(tvb
, buf
,i
,i
);
1920 add_new_data_source(pinfo
, h245_tvb
, "H.245 over MEGACO");
1921 /* should go through a handle, however, the two h245 entry
1922 points are different, one is over tpkt and the other is raw
1924 call_dissector(h245_handle
, h245_tvb
, pinfo
, top_tree
);
1925 /* dissect_h245_MultimediaSystemControlMessage(h245_tvb, pinfo, tree);*/
1930 dissect_megaco_h324_h223caprn(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree
, int offset _U_
, int len
, char *msg
)
1934 /* arbitrary maximum length */
1938 uint8_t *buf
= (uint8_t *)wmem_alloc(pinfo
->pool
, 10240);
1940 /* first, skip to where the encoded pdu starts, this is
1941 the first hex digit after the '=' char.
1944 if((*msg
==0)||(*msg
=='\n')){
1954 if((*msg
==0)||(*msg
=='\n')){
1957 if( ((*msg
>='0')&&(*msg
<='9'))
1958 || ((*msg
>='a')&&(*msg
<='f'))
1959 || ((*msg
>='A')&&(*msg
<='F'))){
1965 while( ((*msg
>='0')&&(*msg
<='9'))
1966 ||((*msg
>='a')&&(*msg
<='f'))
1967 ||((*msg
>='A')&&(*msg
<='F')) ){
1969 if((*msg
>='0')&&(*msg
<='9')){
1971 } else if((*msg
>='a')&&(*msg
<='f')){
1973 } else if((*msg
>='A')&&(*msg
<='F')){
1980 if((*msg
>='0')&&(*msg
<='9')){
1982 } else if((*msg
>='a')&&(*msg
<='f')){
1984 } else if((*msg
>='A')&&(*msg
<='F')){
1991 buf
[i
]=(uint8_t)val
;
1997 h245_tvb
= tvb_new_child_real_data(tvb
, buf
,i
,i
);
1998 add_new_data_source(pinfo
, h245_tvb
, "H.245 over MEGACO");
1999 /* should go through a handle, however, the two h245 entry
2000 points are different, one is over tpkt and the other is raw
2002 asn1_ctx_init(&actx
, ASN1_ENC_PER
, true, pinfo
);
2003 dissect_h245_H223Capability(h245_tvb
, 0, &actx
, megaco_tree
, hf_megaco_h223Capability
);
2008 dissect_megaco_eventsdescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
, proto_tree
*top_tree
)
2011 int tokenlen
, tvb_current_offset
, tvb_next_offset
, tvb_help_offset
;
2012 int tvb_events_end_offset
, tvb_LBRKT
;
2013 proto_tree
*megaco_eventsdescriptor_tree
, *megaco_requestedevent_tree
;
2014 proto_item
*megaco_eventsdescriptor_ti
, *megaco_requestedevent_ti
, *ti
;
2016 int requested_event_start_offset
= 0,
2017 requested_event_end_offset
= 0;
2019 tokenlen
= (tvb_RBRKT
+1) - tvb_previous_offset
;
2021 megaco_eventsdescriptor_ti
= proto_tree_add_item(megaco_tree_command_line
,hf_megaco_events_descriptor
,tvb
,tvb_previous_offset
, tokenlen
, ENC_NA
);
2022 megaco_eventsdescriptor_tree
= proto_item_add_subtree(megaco_eventsdescriptor_ti
, ett_megaco_eventsdescriptor
);
2024 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '=');
2025 tvb_next_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '{');
2027 if ( tvb_current_offset
< tvb_RBRKT
&& tvb_current_offset
!= -1 ){
2029 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2030 tvb_help_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_next_offset
-1);
2032 tokenlen
= tvb_help_offset
- tvb_current_offset
;
2034 ti
= proto_tree_add_uint(megaco_eventsdescriptor_tree
, hf_megaco_requestid
, tvb
,
2035 tvb_current_offset
, 1,
2036 (uint32_t) strtoul(tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
), NULL
, 10));
2037 proto_item_set_len(ti
, tokenlen
);
2039 tvb_events_end_offset
= tvb_RBRKT
;
2041 tvb_RBRKT
= tvb_next_offset
+1;
2042 tvb_LBRKT
= tvb_next_offset
+1;
2043 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_next_offset
+1);
2048 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
2049 tvb_events_end_offset
, '}');
2050 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
,
2051 tvb_events_end_offset
, '{');
2053 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
,
2054 tvb_events_end_offset
, ',');
2056 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_events_end_offset
){
2057 tvb_current_offset
= tvb_events_end_offset
;
2061 /* Descriptor includes no parameters */
2063 if ( tvb_LBRKT
> tvb_current_offset
|| tvb_LBRKT
== -1 ){
2065 tvb_RBRKT
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1)-1;
2068 /* Descriptor includes Parameters */
2070 if ( (tvb_current_offset
> tvb_LBRKT
&& tvb_LBRKT
!= -1)){
2072 while ( tvb_LBRKT
!= -1 && tvb_RBRKT
> tvb_LBRKT
){
2074 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
+1,
2075 tvb_events_end_offset
, '{');
2076 if ( tvb_LBRKT
< tvb_RBRKT
&& tvb_LBRKT
!= -1)
2077 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
2078 tvb_events_end_offset
, '}');
2083 tvb_help_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_events_end_offset
, '{');
2085 /* if there are eventparameter */
2087 if ( tvb_help_offset
< tvb_RBRKT
&& tvb_help_offset
!= -1 ){
2089 requested_event_start_offset
= tvb_help_offset
;
2090 requested_event_end_offset
= tvb_RBRKT
;
2091 tvb_help_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_help_offset
-1);
2092 tokenlen
= tvb_help_offset
- tvb_previous_offset
;
2096 tokenlen
= tvb_RBRKT
+1 - tvb_previous_offset
;
2099 megaco_requestedevent_ti
= proto_tree_add_item(megaco_eventsdescriptor_tree
,hf_megaco_pkgdname
,tvb
,tvb_previous_offset
,tokenlen
, ENC_UTF_8
);
2100 megaco_requestedevent_tree
= proto_item_add_subtree(megaco_requestedevent_ti
, ett_megaco_requestedevent
);
2102 if ( tvb_help_offset
< tvb_RBRKT
&& tvb_help_offset
!= -1 ){
2104 requested_event_start_offset
= megaco_tvb_skip_wsp(tvb
, requested_event_start_offset
+1);
2105 requested_event_end_offset
= megaco_tvb_skip_wsp_return(tvb
, requested_event_end_offset
-1);
2107 if (!tvb_strncaseeql(tvb
, requested_event_start_offset
, "dm", 2)) {
2108 dissect_megaco_digitmapdescriptor(tvb
, pinfo
, megaco_requestedevent_tree
, requested_event_end_offset
, requested_event_start_offset
);
2111 tokenlen
= requested_event_end_offset
- requested_event_start_offset
;
2112 if(!tvb_strneql(tvb
, requested_event_start_offset
, "h245", 4)){
2113 dissect_megaco_h245(tvb
, pinfo
, megaco_requestedevent_tree
, requested_event_start_offset
, tokenlen
, top_tree
);
2115 proto_tree_add_format_text(megaco_requestedevent_tree
, tvb
, requested_event_start_offset
, tokenlen
);
2121 tvb_previous_offset
= tvb_current_offset
;
2122 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_RBRKT
,
2123 tvb_events_end_offset
, ',');
2125 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_events_end_offset
|| tvb_current_offset
< tvb_previous_offset
) {
2126 tvb_current_offset
= tvb_events_end_offset
;
2129 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2131 tvb_LBRKT
= tvb_previous_offset
;
2132 tvb_RBRKT
= tvb_previous_offset
;
2134 } while ( tvb_current_offset
< tvb_events_end_offset
);
2139 dissect_megaco_signaldescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
, proto_tree
*top_tree
)
2142 int tokenlen
, pkg_tokenlen
, tvb_current_offset
, tvb_next_offset
, tvb_help_offset
;
2143 int tvb_signals_end_offset
, tvb_signals_start_offset
, tvb_LBRKT
;
2144 proto_tree
*megaco_signalsdescriptor_tree
, *megaco_requestedsignal_tree
;
2145 proto_item
*megaco_signalsdescriptor_ti
, *megaco_requestedsignal_ti
;
2147 int requested_signal_start_offset
= 0,
2148 requested_signal_end_offset
= 0;
2150 tvb_signals_end_offset
= tvb_RBRKT
;
2151 tvb_signals_start_offset
= tvb_previous_offset
;
2153 if(g_ascii_toupper(tvb_get_uint8(tvb
, tvb_previous_offset
+1))=='G')
2154 tokenlen
= 2; /* token is compact text (SG) */
2156 tokenlen
= 7; /* token must be verbose text (Signals) */
2158 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_previous_offset
+tokenlen
);
2160 if(tvb_get_uint8(tvb
, tvb_current_offset
)!='{') { /* {} has been omitted */
2162 megaco_signalsdescriptor_ti
= proto_tree_add_item(megaco_tree_command_line
, hf_megaco_signal_descriptor
, tvb
, tvb_signals_start_offset
, tokenlen
, ENC_NA
);
2163 expert_add_info(pinfo
, megaco_signalsdescriptor_ti
, &ei_megaco_signal_descriptor
);
2165 col_append_str(pinfo
->cinfo
, COL_INFO
, " (Signal:none)"); /* then say so */
2167 return; /* and return */
2170 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_signals_end_offset
, '{');
2171 tokenlen
= (tvb_LBRKT
+1) - tvb_signals_start_offset
;
2173 megaco_signalsdescriptor_ti
= proto_tree_add_item(megaco_tree_command_line
,hf_megaco_signal_descriptor
,tvb
,tvb_previous_offset
,tokenlen
, ENC_NA
);
2174 megaco_signalsdescriptor_tree
= proto_item_add_subtree(megaco_signalsdescriptor_ti
, ett_megaco_signalsdescriptor
);
2176 tvb_current_offset
= tvb_LBRKT
;
2177 tvb_next_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2178 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
));
2181 if ( tvb_current_offset
< tvb_signals_end_offset
&& tvb_current_offset
!= -1 && tvb_next_offset
!= tvb_signals_end_offset
){
2184 tvb_RBRKT
= tvb_next_offset
+1;
2185 tvb_LBRKT
= tvb_next_offset
+1;
2186 tvb_previous_offset
= tvb_next_offset
;
2191 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
2192 tvb_signals_end_offset
, '}');
2193 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
,
2194 tvb_signals_end_offset
, '{');
2196 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
,
2197 tvb_signals_end_offset
, ',');
2199 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_signals_end_offset
){
2200 tvb_current_offset
= tvb_signals_end_offset
;
2204 /* Descriptor includes no parameters */
2206 if ( tvb_LBRKT
> tvb_current_offset
|| tvb_LBRKT
== -1 ){
2208 tvb_RBRKT
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1)-1;
2211 /* Descriptor includes Parameters */
2213 if ( (tvb_current_offset
> tvb_LBRKT
&& tvb_LBRKT
!= -1)){
2215 while ( tvb_LBRKT
!= -1 && tvb_RBRKT
> tvb_LBRKT
){
2217 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
+1,
2218 tvb_signals_end_offset
, '{');
2219 if ( tvb_LBRKT
< tvb_RBRKT
&& tvb_LBRKT
!= -1)
2220 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
2221 tvb_signals_end_offset
, '}');
2226 tvb_help_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_signals_end_offset
, '{');
2228 /* if there are signalparameter */
2230 if ( tvb_help_offset
< tvb_RBRKT
&& tvb_help_offset
!= -1 ){
2232 requested_signal_start_offset
= tvb_help_offset
;
2233 requested_signal_end_offset
= tvb_RBRKT
;
2234 tvb_help_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_help_offset
-1);
2235 pkg_tokenlen
= tvb_help_offset
- tvb_previous_offset
;
2239 pkg_tokenlen
= tvb_RBRKT
+1 - tvb_previous_offset
;
2242 megaco_requestedsignal_ti
= proto_tree_add_item(megaco_signalsdescriptor_tree
,hf_megaco_pkgdname
,tvb
,tvb_previous_offset
,pkg_tokenlen
, ENC_UTF_8
);
2243 megaco_requestedsignal_tree
= proto_item_add_subtree(megaco_requestedsignal_ti
, ett_megaco_requestedsignal
);
2245 if ( tvb_help_offset
< tvb_RBRKT
&& tvb_help_offset
!= -1 ){
2246 requested_signal_start_offset
= megaco_tvb_skip_wsp(tvb
, requested_signal_start_offset
+1);
2247 requested_signal_end_offset
= megaco_tvb_skip_wsp_return(tvb
, requested_signal_end_offset
-1);
2249 tokenlen
= requested_signal_end_offset
- requested_signal_start_offset
;
2251 if(!tvb_strneql(tvb
, requested_signal_start_offset
, "h245", 4)){
2252 dissect_megaco_h245(tvb
, pinfo
, megaco_requestedsignal_tree
, requested_signal_start_offset
, tokenlen
, top_tree
);
2254 proto_tree_add_format_text( megaco_requestedsignal_tree
, tvb
, requested_signal_start_offset
, tokenlen
);
2256 /* Print the trailing '}' (raw formatting removed) */
2257 /* proto_tree_add_format_text( megaco_requestedsignal_tree, tvb, tvb_RBRKT, 1); */
2260 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_RBRKT
,
2261 tvb_signals_end_offset
, ',');
2263 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_signals_end_offset
|| tvb_current_offset
< tvb_previous_offset
){
2264 tvb_current_offset
= tvb_signals_end_offset
;
2267 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2269 tvb_LBRKT
= tvb_previous_offset
;
2270 tvb_RBRKT
= tvb_previous_offset
;
2271 /* Print the trailing '}' (raw formatting removed) */
2272 /* proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1); */
2274 } while ( tvb_current_offset
< tvb_signals_end_offset
);
2276 /* signals{} (raw formatting removed)
2277 proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_signals_end_offset, 1); */
2284 auditDescriptor = AuditToken LBRKT [ auditItem *(COMMA auditItem) ] RBRKT
2287 auditItem = ( MuxToken / ModemToken / MediaToken /
2288 SignalsToken / EventBufferToken /
2289 DigitMapToken / StatsToken / EventsToken /
2290 ObservedEventsToken / PackagesToken )
2293 auditItem = ( auditReturnItem / SignalsToken / EventBufferToken /
2294 EventsToken / indAudterminationAudit )
2296 auditReturnItem = ( MuxToken / ModemToken / MediaToken / DigitMapToken /
2297 StatsToken / ObservedEventsToken / PackagesToken )
2299 indAudauditReturnParameter
2300 = ( indAudmediaDescriptor / indAudeventsDescriptor /
2301 indAudsignalsDescriptor / indAuddigitMapDescriptor /
2302 indAudeventBufferDescriptor /
2303 indAudstatisticsDescriptor / indAudpackagesDescriptor )
2306 dissect_megaco_auditdescriptor(tvbuff_t
*tvb
, proto_tree
*megaco_tree
, packet_info
*pinfo _U_
, int tvb_stop
, int tvb_offset
, proto_tree
*top_tree
, uint32_t context
)
2308 int tokenlen
, tvb_end
, tvb_next
, tvb_LBRKT
, tvb_token_end
, token_index
;
2309 proto_tree
*megaco_auditdescriptor_tree
, *megaco_auditdescriptor_ti
;
2312 tvb_next
= tvb_find_uint8(tvb
, tvb_offset
, tvb_stop
, '{'); /* find opening LBRKT - is this already checked by caller?*/
2313 if( tvb_next
== -1 ) /* complain and give up if not there */
2315 expert_add_info(pinfo
, megaco_tree
, &ei_megaco_audit_descriptor
);
2318 tokenlen
= (tvb_stop
+ 1) - tvb_offset
;
2320 megaco_auditdescriptor_ti
= proto_tree_add_item( megaco_tree
, hf_megaco_audit_descriptor
, tvb
, tvb_offset
, tokenlen
, ENC_NA
);
2321 megaco_auditdescriptor_tree
= proto_item_add_subtree( megaco_auditdescriptor_ti
, ett_megaco_auditdescriptor
);
2323 tvb_offset
= tvb_next
;
2325 while( tvb_offset
< tvb_stop
)
2327 tvb_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1); /* find start of an auditItem */
2328 if( tvb_get_uint8(tvb
, tvb_offset
) != '}' ) /* got something */
2330 tvb_next
= tvb_find_uint8(tvb
, tvb_offset
, tvb_stop
, ','); /* end of an auditItem */
2331 if (tvb_next
== -1) /* last item doesn't have a comma */
2332 tvb_next
= tvb_stop
;
2334 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_offset
, tvb_stop
, '{');
2336 tvb_end
= megaco_tvb_skip_wsp_return(tvb
, tvb_next
-1); /* trim any trailing whitespace */
2338 if ( tvb_LBRKT
> tvb_next
|| tvb_LBRKT
== -1 ){
2339 /* auditItem has no parameters (i.e., is a Token) */
2341 tvb_token_end
= tvb_end
;
2343 /* auditItem includes Parameters (i.e., is a Descriptor) */
2345 for (tvb_token_end
=tvb_offset
; tvb_token_end
< tvb_end
; tvb_token_end
++){
2346 if (!g_ascii_isalpha(tvb_get_uint8(tvb
, tvb_token_end
))){
2352 tokenlen
= tvb_token_end
- tvb_offset
; /* get length of token */
2354 token_index
= find_megaco_descriptors_names(tvb
, tvb_offset
, tokenlen
); /* lookup the token */
2355 if( token_index
== -1 ) /* if not found then 0 => Unknown */
2360 switch ( token_index
){
2361 case MEGACO_MEDIA_TOKEN
:
2363 int temp_offset
= tvb_find_uint8(tvb
, tvb_offset
, tvb_stop
, '{');
2364 int save_offset
= tvb_offset
;
2366 tvb_offset
= megaco_tvb_skip_wsp(tvb
, temp_offset
+1);
2367 dissect_megaco_mediadescriptor(tvb
, megaco_auditdescriptor_tree
, pinfo
, tvb_end
, tvb_offset
, save_offset
, top_tree
, context
);
2370 case MEGACO_SIGNALS_TOKEN
:
2371 dissect_megaco_signaldescriptor(tvb
, pinfo
, megaco_auditdescriptor_tree
, tvb_end
, tvb_offset
, top_tree
);
2373 case MEGACO_STATS_TOKEN
:
2374 dissect_megaco_statisticsdescriptor(tvb
, megaco_auditdescriptor_tree
, tvb_end
, tvb_offset
);
2376 case MEGACO_EVENTS_TOKEN
:
2377 dissect_megaco_eventsdescriptor(tvb
, pinfo
, megaco_auditdescriptor_tree
, tvb_end
, tvb_offset
, top_tree
);
2379 case MEGACO_DIGITMAP_TOKEN
:
2380 dissect_megaco_digitmapdescriptor(tvb
, pinfo
, megaco_auditdescriptor_tree
, tvb_end
, tvb_offset
);
2382 case MEGACO_PACKAGES_TOKEN
:
2383 dissect_megaco_Packagesdescriptor(tvb
, pinfo
, megaco_auditdescriptor_tree
, tvb_end
, tvb_offset
);
2386 tokenlen
= tvb_end
- tvb_offset
;
2387 proto_tree_add_string(megaco_auditdescriptor_tree
, hf_megaco_audititem
, tvb
,
2388 tvb_offset
, tokenlen
, megaco_descriptors_names
[token_index
].name
); /* and display the long form */
2392 proto_tree_add_string(megaco_auditdescriptor_tree
, hf_megaco_audititem
, tvb
,
2393 tvb_offset
, tokenlen
, megaco_descriptors_names
[token_index
].name
); /* and display the long form */
2396 tvb_offset
= tvb_next
; /* advance pointer */
2402 * serviceChangeDescriptor = ServicesToken LBRKT serviceChangeParm
2403 * *(COMMA serviceChangeParm) RBRKT
2405 * ServicesToken = ("Services" / "SV")
2407 * serviceChangeParm = (serviceChangeMethod / serviceChangeReason /
2408 * serviceChangeDelay / serviceChangeAddress /
2409 * serviceChangeProfile / extension / TimeStamp /
2410 * serviceChangeMgcId / serviceChangeVersion )
2413 #define MEGACO_REASON_TOKEN 1
2414 #define MEGACO_DELAY_TOKEN 2
2415 #define MEGACO_SC_ADDR_TOKEN 3
2416 #define MEGACO_MGC_ID_TOKEN 4
2417 #define MEGACO_PROFILE_TOKEN 5
2418 #define MEGACO_VERSION_TOKEN 6
2419 #define MEGACO_METHOD_TOKEN 7
2421 static const megaco_tokens_t megaco_serviceChangeParm_names
[] = {
2422 { "Unknown-token", NULL
}, /* 0 Pad so that the real headers start at index 1 */
2424 { "Reason", "RE" }, /* 1 ReasonToken*/
2425 { "Delay", "DL" }, /* 2 DelayToken */
2426 { "ServiceChangeAddress", "AD" }, /* 3 ServiceChangeAddressToken */
2427 { "MgcIdToTry", "MG" }, /* 4 MgcIdToken */
2428 { "Profile", "PF" }, /* 5 ProfileToken */
2429 { "Version", "V" }, /* 6 VersionToken */
2430 { "Method", "MT" }, /* 7 MethodToken */
2433 /* Returns index of megaco_tokens_t */
2434 static int find_megaco_megaco_serviceChangeParm_names(tvbuff_t
*tvb
, int offset
, unsigned header_len
)
2438 for (i
= 1; i
< array_length(megaco_serviceChangeParm_names
); i
++) {
2439 if (header_len
== strlen(megaco_serviceChangeParm_names
[i
].name
) &&
2440 tvb_strncaseeql(tvb
, offset
, megaco_serviceChangeParm_names
[i
].name
, header_len
) == 0)
2442 if (megaco_serviceChangeParm_names
[i
].compact_name
!= NULL
&&
2443 header_len
== strlen(megaco_serviceChangeParm_names
[i
].compact_name
) &&
2444 tvb_strncaseeql(tvb
, offset
, megaco_serviceChangeParm_names
[i
].compact_name
, header_len
) == 0)
2451 * ServiceChangeReasons References
2452 * -------------------- ----------
2454 static const value_string MEGACO_ServiceChangeReasons_vals
[] = {
2455 {900, "Service Restored"},
2458 {903, "MGC Directed Change"},
2459 {904, "Termination malfunctioning"},
2460 {905, "Termination taken out of service"},
2461 {906, "Loss of lower layer connectivity (e.g. downstream sync)"},
2462 {907, "Transmission Failure"},
2463 {908, "MG Impending Failure"},
2464 {909, "MGC Impending Failure"},
2465 {910, "Media Capability Failure"},
2466 {911, "Modem Capability Failure"},
2467 {912, "Mux Capability Failure"},
2468 {913, "Signal Capability Failure"},
2469 {914, "Event Capability Failure"},
2470 {915, "State Loss"},
2471 {916, "Packages Change"},
2472 {917, "Capabilities Change"},
2473 {918, "Cancel Graceful"},
2474 {919, "Warm Failover"},
2475 {920, "Cold Failover"},
2480 dissect_megaco_servicechangedescriptor(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*megaco_tree
, int tvb_RBRKT
,
2481 int tvb_previous_offset
)
2484 int tokenlen
, tvb_LBRKT
, tvb_offset
;
2486 int tvb_current_offset
;
2487 bool more_params
= true;
2491 uint8_t ServiceChangeReason_str
[4];
2493 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '{');
2495 if (tvb_LBRKT == -1)
2498 tokenlen
= (tvb_LBRKT
+ 1) - tvb_previous_offset
;
2499 proto_tree_add_format_text(megaco_tree
, tvb
, tvb_previous_offset
, tokenlen
);
2501 /* Start dissecting serviceChangeParm */
2502 tvb_previous_offset
= tvb_LBRKT
+ 1;
2503 while (more_params
){
2504 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_previous_offset
);
2505 /* Find token length */
2506 for (tvb_offset
=tvb_previous_offset
; tvb_offset
< tvb_RBRKT
; tvb_offset
++){
2507 if (!g_ascii_isalpha(tvb_get_uint8(tvb
, tvb_offset
))){
2511 tokenlen
= tvb_offset
- tvb_previous_offset
;
2512 token_index
= find_megaco_megaco_serviceChangeParm_names(tvb
, tvb_previous_offset
, tokenlen
);
2514 tvb_offset
= tvb_find_uint8(tvb
, tvb_offset
, tvb_RBRKT
, ',');
2515 if ((tvb_offset
== -1)||(tvb_offset
>=tvb_RBRKT
)){
2516 more_params
= false;
2517 tvb_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_RBRKT
-1);
2519 tokenlen
= tvb_offset
- tvb_previous_offset
;
2520 if (more_params
== true )
2523 switch(token_index
){
2524 case MEGACO_REASON_TOKEN
:
2525 /* ReasonToken EQUAL VALUE
2526 * VALUE = quotedString / 1*(SafeChar)
2528 item
= proto_tree_add_format_text(megaco_tree
, tvb
, tvb_previous_offset
, tokenlen
);
2530 /* As the reason code ( if a digit ) can be in quoted string or 'just' digit
2531 * look for a nine and hope for the best.
2533 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '9');
2534 if ( tvb_current_offset
== -1)
2537 tvb_get_raw_bytes_as_stringz(tvb
,tvb_current_offset
,4,ServiceChangeReason_str
);
2538 reason_valid
= ws_strtoi32(ServiceChangeReason_str
, NULL
, &reason
);
2539 proto_item_append_text(item
,"[ %s ]", val_to_str(reason
, MEGACO_ServiceChangeReasons_vals
,"Unknown (%u)"));
2541 expert_add_info(pinfo
, item
, &ei_megaco_reason_invalid
);
2543 case MEGACO_DELAY_TOKEN
:
2544 case MEGACO_SC_ADDR_TOKEN
:
2545 case MEGACO_MGC_ID_TOKEN
:
2546 case MEGACO_PROFILE_TOKEN
:
2547 case MEGACO_VERSION_TOKEN
:
2548 case MEGACO_METHOD_TOKEN
:
2549 /* No special dissection: fall through */
2552 * extension = extensionParameter parmValue
2553 * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
2555 proto_tree_add_format_text(megaco_tree
, tvb
, tvb_previous_offset
, tokenlen
);
2559 tvb_previous_offset
= tvb_offset
+1;
2563 /* extension = extensionParameter parmValue
2564 * extensionParameter = "X" ("-" / "+") 1*6(ALPHA / DIGIT)
2568 tokenlen = (tvb_RBRKT+1) - tvb_previous_offset;
2569 proto_tree_add_string(megaco_tree_command_line, hf_megaco_servicechange_descriptor, tvb,
2570 tvb_previous_offset, tokenlen,
2571 tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
2574 proto_tree_add_format_text(megaco_tree
, tvb
, tvb_RBRKT
, 1);
2578 dissect_megaco_digitmapdescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
)
2583 tokenlen
= tvb_RBRKT
- tvb_previous_offset
;
2584 proto_tree_add_string(megaco_tree_command_line
, hf_megaco_digitmap_descriptor
, tvb
,
2585 tvb_previous_offset
, tokenlen
,
2586 tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
,
2591 dissect_megaco_statisticsdescriptor(tvbuff_t
*tvb
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
)
2594 proto_tree
*megaco_statisticsdescriptor_tree
;
2595 proto_item
*megaco_statisticsdescriptor_ti
;
2596 int tvb_help_offset
, param_start_offset
, param_end_offset
= 0;
2598 tokenlen
= (tvb_RBRKT
+1) - tvb_previous_offset
;
2600 megaco_statisticsdescriptor_ti
= proto_tree_add_item(megaco_tree_command_line
,hf_megaco_statistics_descriptor
,tvb
,tvb_previous_offset
,tokenlen
, ENC_NA
);
2601 megaco_statisticsdescriptor_tree
= proto_item_add_subtree(megaco_statisticsdescriptor_ti
, ett_megaco_statisticsdescriptor
);
2603 tvb_help_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
+1, tvb_RBRKT
, '{');
2605 param_start_offset
= megaco_tvb_skip_wsp(tvb
, tvb_help_offset
+1);
2607 tvb_help_offset
= tvb_find_uint8(tvb
, tvb_help_offset
+1, tvb_RBRKT
, ',');
2609 if ( tvb_help_offset
> tvb_RBRKT
|| tvb_help_offset
== -1){
2610 tvb_help_offset
= tvb_RBRKT
;
2611 param_end_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_RBRKT
-1);
2612 tokenlen
= param_end_offset
- param_start_offset
;
2614 param_end_offset
= megaco_tvb_skip_wsp(tvb
, tvb_help_offset
-1);
2615 tokenlen
= param_end_offset
- param_start_offset
+1;
2618 proto_tree_add_format_text(megaco_statisticsdescriptor_tree
, tvb
,param_start_offset
, tokenlen
);
2620 } while ( tvb_help_offset
< tvb_RBRKT
);
2624 dissect_megaco_observedeventsdescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
, proto_tree
*top_tree
)
2627 int tokenlen
, pkg_tokenlen
, tvb_current_offset
, tvb_next_offset
, tvb_help_offset
;
2628 int tvb_observedevents_end_offset
, tvb_LBRKT
;
2629 proto_tree
*megaco_observedeventsdescriptor_tree
, *megaco_observedevent_tree
;
2630 proto_item
*megaco_observedeventsdescriptor_ti
, *megaco_observedevent_ti
, *ti
;
2632 int requested_event_start_offset
, requested_event_end_offset
, param_start_offset
, param_end_offset
;
2634 requested_event_start_offset
= 0;
2635 requested_event_end_offset
= 0;
2637 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '{');
2638 tvb_next_offset
= tvb_LBRKT
;
2639 tokenlen
= (tvb_next_offset
+1) - tvb_previous_offset
;
2641 megaco_observedeventsdescriptor_ti
= proto_tree_add_item(megaco_tree_command_line
,hf_megaco_observedevents_descriptor
,tvb
,tvb_previous_offset
,tokenlen
, ENC_NA
);
2642 megaco_observedeventsdescriptor_tree
= proto_item_add_subtree(megaco_observedeventsdescriptor_ti
, ett_megaco_observedeventsdescriptor
);
2644 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '=');
2645 tvb_next_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '{');
2647 if ( tvb_current_offset
< tvb_RBRKT
&& tvb_current_offset
!= -1 ){
2649 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2650 tvb_help_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_next_offset
-1);
2652 tokenlen
= tvb_help_offset
- tvb_current_offset
;
2654 ti
= proto_tree_add_uint(megaco_observedeventsdescriptor_tree
, hf_megaco_requestid
, tvb
,
2655 tvb_current_offset
, 1,
2656 (uint32_t) strtoul(tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
), NULL
, 10));
2657 proto_item_set_len(ti
, tokenlen
);
2659 tvb_observedevents_end_offset
= tvb_RBRKT
;
2661 tvb_RBRKT
= tvb_next_offset
+1;
2662 tvb_LBRKT
= tvb_next_offset
+1;
2663 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_next_offset
+1);
2668 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
2669 tvb_observedevents_end_offset
, '}');
2670 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
,
2671 tvb_observedevents_end_offset
, '{');
2673 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
,
2674 tvb_observedevents_end_offset
, ',');
2676 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_observedevents_end_offset
){
2677 tvb_current_offset
= tvb_observedevents_end_offset
;
2681 /* Descriptor includes no parameters */
2683 if ( tvb_LBRKT
> tvb_current_offset
|| tvb_LBRKT
== -1 ){
2685 tvb_RBRKT
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1)-1;
2688 /* Descriptor includes Parameters */
2690 if ( (tvb_current_offset
> tvb_LBRKT
&& tvb_LBRKT
!= -1)){
2692 while ( tvb_LBRKT
!= -1 && tvb_RBRKT
> tvb_LBRKT
){
2694 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
+1,
2695 tvb_observedevents_end_offset
, '{');
2696 if ( tvb_LBRKT
< tvb_RBRKT
&& tvb_LBRKT
!= -1){
2697 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
2698 tvb_observedevents_end_offset
, '}');
2704 tvb_LBRKT
= tvb_help_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_observedevents_end_offset
, '{');
2706 /* if there are eventparameter */
2708 if ( tvb_help_offset
< tvb_RBRKT
&& tvb_help_offset
!= -1 ){
2710 requested_event_start_offset
= tvb_help_offset
;
2711 requested_event_end_offset
= tvb_RBRKT
;
2712 tvb_help_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_help_offset
-1);
2713 pkg_tokenlen
= tvb_help_offset
- tvb_previous_offset
;
2714 tokenlen
= tvb_LBRKT
+1 - tvb_previous_offset
;
2718 tokenlen
= pkg_tokenlen
= tvb_RBRKT
+1 - tvb_previous_offset
;
2721 megaco_observedevent_ti
= proto_tree_add_format_text(megaco_tree_command_line
, tvb
, tvb_previous_offset
, tokenlen
);
2723 megaco_observedevent_tree
= proto_item_add_subtree(megaco_observedevent_ti
, ett_megaco_observedevent
);
2725 proto_tree_add_item(megaco_observedevent_tree
,hf_megaco_pkgdname
,tvb
,tvb_previous_offset
,pkg_tokenlen
, ENC_UTF_8
);
2727 if ( tvb_help_offset
< tvb_RBRKT
&& tvb_help_offset
!= -1 ){
2729 requested_event_start_offset
= megaco_tvb_skip_wsp(tvb
, requested_event_start_offset
+1)-1;
2730 requested_event_end_offset
= megaco_tvb_skip_wsp_return(tvb
, requested_event_end_offset
-1);
2732 tvb_help_offset
= requested_event_start_offset
;
2735 param_start_offset
= megaco_tvb_skip_wsp(tvb
, tvb_help_offset
+1);
2737 tvb_help_offset
= tvb_find_uint8(tvb
, tvb_help_offset
+1,requested_event_end_offset
, ',');
2739 if ( tvb_help_offset
> requested_event_end_offset
|| tvb_help_offset
== -1){
2740 tvb_help_offset
= requested_event_end_offset
;
2743 param_end_offset
= megaco_tvb_skip_wsp(tvb
, tvb_help_offset
-1);
2745 tokenlen
= param_end_offset
- param_start_offset
+1;
2746 if(!tvb_strneql(tvb
, param_start_offset
, "h245", 4)){
2747 dissect_megaco_h245(tvb
, pinfo
, megaco_tree_command_line
, param_start_offset
, tokenlen
, top_tree
);
2749 proto_tree_add_format_text(megaco_tree_command_line
, tvb
, param_start_offset
, tokenlen
);
2753 } while ( tvb_help_offset
< requested_event_end_offset
);
2756 tvb_previous_offset
= tvb_current_offset
;
2757 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_RBRKT
,
2758 tvb_observedevents_end_offset
, ',');
2760 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_observedevents_end_offset
){
2761 tvb_current_offset
= tvb_observedevents_end_offset
;
2763 if (tvb_current_offset
< tvb_previous_offset
) {
2764 expert_add_info_format(pinfo
, megaco_observedevent_ti
, &ei_megaco_parse_error
, "Parse error: Invalid offset");
2768 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2770 tvb_LBRKT
= tvb_previous_offset
;
2771 tvb_RBRKT
= tvb_previous_offset
;
2772 /* Print the trailing '}' (raw formatting removed) */
2773 /* proto_tree_add_format_text(megaco_tree_command_line, tvb, tvb_observedevents_end_offset, 1); */
2775 } while ( tvb_current_offset
< tvb_observedevents_end_offset
);
2779 dissect_megaco_topologydescriptor(tvbuff_t
*tvb
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
)
2784 tokenlen
= (tvb_RBRKT
+1) - tvb_previous_offset
;
2785 proto_tree_add_item(megaco_tree_command_line
, hf_megaco_topology_descriptor
, tvb
,
2786 tvb_previous_offset
, tokenlen
, ENC_ASCII
);
2790 dissect_megaco_Packagesdescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_tree_command_line
, int tvb_RBRKT
, int tvb_previous_offset
)
2793 int tokenlen
, tvb_current_offset
, tvb_next_offset
, tvb_help_offset
;
2794 int tvb_packages_end_offset
, tvb_LBRKT
;
2795 proto_tree
*megaco_packagesdescriptor_tree
;
2796 proto_item
*megaco_packagesdescriptor_ti
, *ti
;
2798 tokenlen
= (tvb_RBRKT
+1) - tvb_previous_offset
;
2800 megaco_packagesdescriptor_ti
= proto_tree_add_item(megaco_tree_command_line
,hf_megaco_packages_descriptor
,tvb
,tvb_previous_offset
,tokenlen
, ENC_UTF_8
);
2801 megaco_packagesdescriptor_tree
= proto_item_add_subtree(megaco_packagesdescriptor_ti
, ett_megaco_packagesdescriptor
);
2803 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '=');
2804 tvb_next_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '{');
2806 if ( tvb_current_offset
< tvb_RBRKT
&& tvb_current_offset
!= -1 ){
2808 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2809 tvb_help_offset
= megaco_tvb_skip_wsp_return(tvb
, tvb_next_offset
-1);
2811 tokenlen
= tvb_help_offset
- tvb_current_offset
;
2813 ti
= proto_tree_add_uint(megaco_packagesdescriptor_tree
, hf_megaco_requestid
, tvb
,
2814 tvb_current_offset
, 1,
2815 (uint32_t) strtoul(tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
), NULL
, 10));
2816 proto_item_set_len(ti
, tokenlen
);
2818 tvb_packages_end_offset
= tvb_RBRKT
;
2820 tvb_RBRKT
= tvb_next_offset
+1;
2821 tvb_LBRKT
= tvb_next_offset
+1;
2822 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_next_offset
+1);
2827 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
2828 tvb_packages_end_offset
, '}');
2829 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
,
2830 tvb_packages_end_offset
, '{');
2832 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
,
2833 tvb_packages_end_offset
, ',');
2835 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_packages_end_offset
){
2836 tvb_current_offset
= tvb_packages_end_offset
;
2840 /* Descriptor includes no parameters */
2842 if ( tvb_LBRKT
> tvb_current_offset
|| tvb_LBRKT
== -1 ){
2844 tvb_RBRKT
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1)-1;
2847 /* Descriptor includes Parameters */
2849 if ( (tvb_current_offset
> tvb_LBRKT
&& tvb_LBRKT
!= -1)){
2851 while ( tvb_LBRKT
!= -1 && tvb_RBRKT
> tvb_LBRKT
){
2853 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
+1,
2854 tvb_packages_end_offset
, '{');
2855 if ( tvb_LBRKT
< tvb_RBRKT
&& tvb_LBRKT
!= -1)
2856 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
2857 tvb_packages_end_offset
, '}');
2862 tokenlen
= tvb_RBRKT
+1 - tvb_previous_offset
;
2864 proto_tree_add_format_text(megaco_packagesdescriptor_tree
, tvb
, tvb_previous_offset
, tokenlen
);
2866 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_RBRKT
,
2867 tvb_packages_end_offset
, ',');
2869 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_packages_end_offset
){
2870 tvb_current_offset
= tvb_packages_end_offset
;
2873 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2875 tvb_LBRKT
= tvb_previous_offset
;
2876 tvb_RBRKT
= tvb_previous_offset
;
2878 } while ( tvb_current_offset
< tvb_packages_end_offset
);
2882 /* The list of error code values is fetched from http://www.iana.org/assignments/megaco-h248 */
2885 static const value_string MEGACO_error_code_vals
[] = {
2887 {400, "Syntax error in message"},
2888 {401, "Protocol Error"},
2889 {402, "Unauthorized"},
2890 {403, "Syntax error in transaction request"},
2891 {406, "Version Not Supported"},
2892 {410, "Incorrect identifier"},
2893 {411, "The transaction refers to an unknown ContextId"},
2894 {412, "No ContextIDs available"},
2895 {421, "Unknown action or illegal combination of actions"},
2896 {422, "Syntax Error in Action"},
2897 {430, "Unknown TerminationID"},
2898 {431, "No TerminationID matched a wildcard"},
2899 {432, "Out of TerminationIDs or No TerminationID available"},
2900 {433, "TerminationID is already in a Context"},
2901 {434, "Max number of Terminations in a Context exceeded"},
2902 {435, "Termination ID is not in specified Context"},
2903 {440, "Unsupported or unknown Package"},
2904 {441, "Missing Remote or Local Descriptor"},
2905 {442, "Syntax Error in Command"},
2906 {443, "Unsupported or Unknown Command"},
2907 {444, "Unsupported or Unknown Descriptor"},
2908 {445, "Unsupported or Unknown Property"},
2909 {446, "Unsupported or Unknown Parameter"},
2910 {447, "Descriptor not legal in this command"},
2911 {448, "Descriptor appears twice in a command"},
2912 {450, "No such property in this package"},
2913 {451, "No such event in this package"},
2914 {452, "No such signal in this package"},
2915 {453, "No such statistic in this package"},
2916 {454, "No such parameter value in this package"},
2917 {455, "Property illegal in this Descriptor"},
2918 {456, "Property appears twice in this Descriptor"},
2919 {457, "Missing parameter in signal or event"},
2920 {458, "Unexpected Event/Request ID"},
2921 {459, "Unsupported or Unknown Profile"},
2922 {471, "Implied Add for Multiplex failure"},
2924 {500, "Internal software Failure in MG"},
2925 {501, "Not Implemented"},
2926 {502, "Not ready."},
2927 {503, "Service Unavailable"},
2928 {504, "Command Received from unauthorized entity"},
2929 {505, "Transaction Request Received before a Service Change Reply has been received"},
2930 {506, "Number of Transaction Pendings Exceeded"},
2931 {510, "Insufficient resources"},
2932 {512, "Media Gateway unequipped to detect requested Event"},
2933 {513, "Media Gateway unequipped to generate requested Signals"},
2934 {514, "Media Gateway cannot send the specified announcement"},
2935 {515, "Unsupported Media Type"},
2936 {517, "Unsupported or invalid mode"},
2937 {518, "Event buffer full"},
2938 {519, "Out of space to store digit map"},
2939 {520, "Digit Map undefined in the MG"},
2940 {521, "Termination is ServiceChanging"},
2941 {526, "Insufficient bandwidth"},
2942 {529, "Internal hardware failure in MG"},
2943 {530, "Temporary Network failure"},
2944 {531, "Permanent Network failure"},
2945 {532, "Audited Property, Statistic, Event or Signal does not exist"},
2946 {533, "Response exceeds maximum transport PDU size"},
2947 {534, "Illegal write or read only property"},
2948 {540, "Unexpected initial hook state"},
2949 {581, "Does Not Exist"},
2951 {600, "Illegal syntax within an announcement specification"},
2952 {601, "Variable type not supported"},
2953 {602, "Variable value out of range"},
2954 {603, "Category not supported"},
2955 {604, "Selector type not supported"},
2956 {605, "Selector value not supported"},
2957 {606, "Unknown segment ID"},
2958 {607, "Mismatch between play specification and provisioned data"},
2959 {608, "Provisioning error"},
2960 {609, "Invalid offset"},
2961 {610, "No free segment IDs"},
2962 {611, "Temporary segment not found"},
2963 {612, "Segment in use"},
2964 {613, "ISP port limit overrun"},
2965 {614, "No modems available"},
2966 {615, "Calling number unacceptable"},
2967 {616, "Called number unacceptable"},
2974 dissect_megaco_errordescriptor(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*megaco_tree_command_line
,
2975 int tvb_RBRKT
, int tvb_previous_offset
)
2981 int tvb_current_offset
;
2983 proto_tree
* error_tree
;
2984 bool error_code_valid
;
2986 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_RBRKT
, '=');
2987 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
2989 tokenlen
= (tvb_RBRKT
) - tvb_previous_offset
+1;
2991 item
= proto_tree_add_item(megaco_tree_command_line
, hf_megaco_error_descriptor
, tvb
,
2992 tvb_previous_offset
, tokenlen
, ENC_NA
);
2993 error_tree
= proto_item_add_subtree(item
, ett_megaco_error_descriptor
);
2995 /* Get the error code */
2996 tvb_get_raw_bytes_as_stringz(tvb
,tvb_current_offset
,4,error
);
2997 error_code_valid
= ws_strtoi32(error
, NULL
, &error_code
);
2998 item
= proto_tree_add_uint(error_tree
, hf_megaco_error_code
, tvb
, tvb_current_offset
, 3, error_code
);
2999 if (!error_code_valid
)
3000 expert_add_info(pinfo
, item
, &ei_megaco_error_code_invalid
);
3002 /* Get the error string (even though we have a value_string that should match) */
3003 tvb_previous_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_RBRKT
, '\"');
3004 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
+1, tvb_RBRKT
, '\"');
3006 tokenlen
= tvb_current_offset
- tvb_previous_offset
-1;
3007 proto_tree_add_item(error_tree
, hf_megaco_error_string
, tvb
, tvb_previous_offset
+1, tokenlen
, ENC_UTF_8
);
3010 dissect_megaco_TerminationStatedescriptor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*megaco_mediadescriptor_tree
, int tvb_next_offset
, int tvb_current_offset
)
3016 proto_tree
*megaco_TerminationState_tree
, *megaco_TerminationState_ti
;
3018 tvb_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_next_offset
, '=');
3020 tokenlen
= tvb_next_offset
- tvb_current_offset
;
3021 megaco_TerminationState_ti
= proto_tree_add_item(megaco_mediadescriptor_tree
,hf_megaco_TerminationState_descriptor
,tvb
,tvb_current_offset
,tokenlen
, ENC_NA
);
3022 megaco_TerminationState_tree
= proto_item_add_subtree(megaco_TerminationState_ti
, ett_megaco_TerminationState
);
3024 while ( tvb_offset
< tvb_next_offset
&& tvb_offset
!= -1 ){
3026 tempchar
= tvb_get_uint8(tvb
, tvb_current_offset
);
3027 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3028 if ( (tempchar
>= 'a')&& (tempchar
<= 'z'))
3029 tempchar
= tempchar
- 0x20;
3031 switch ( tempchar
){
3034 tvb_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_offset
, ',');
3035 if ( tvb_offset
== -1 || tvb_offset
> tvb_next_offset
){
3036 tvb_offset
= tvb_next_offset
;
3039 tokenlen
= tvb_offset
- tvb_current_offset
;
3041 proto_tree_add_string(megaco_TerminationState_tree
, hf_megaco_Service_State
, tvb
,
3042 tvb_current_offset
, tokenlen
,
3043 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
,
3050 tvb_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_offset
, ',');
3051 if ( tvb_offset
== -1 || tvb_offset
> tvb_next_offset
){
3052 tvb_offset
= tvb_next_offset
;
3055 tokenlen
= tvb_offset
- tvb_current_offset
;
3057 proto_tree_add_string(megaco_TerminationState_tree
, hf_megaco_Event_Buffer_Control
, tvb
,
3058 tvb_current_offset
, tokenlen
,
3059 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
,
3065 tvb_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_offset
, ',');
3066 if ( tvb_offset
== -1 || tvb_offset
> tvb_next_offset
){
3067 tvb_offset
= tvb_next_offset
;
3070 tokenlen
= tvb_offset
- tvb_current_offset
;
3072 proto_tree_add_string(megaco_TerminationState_tree
, hf_megaco_Event_Buffer_Control
, tvb
,
3073 tvb_current_offset
, tokenlen
,
3074 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
,
3080 tvb_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_offset
, ',');
3081 if ( tvb_offset
== -1 || tvb_offset
> tvb_next_offset
){
3082 tvb_offset
= tvb_next_offset
;
3085 tokenlen
= tvb_offset
- tvb_current_offset
;
3087 proto_tree_add_format_text(megaco_TerminationState_tree
, tvb
, tvb_current_offset
, tokenlen
);
3092 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3093 tvb_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_next_offset
, '=');
3096 /* (raw formatting removed)
3097 proto_tree_add_format_text(megaco_mediadescriptor_tree, tvb, tvb_next_offset, 1); */
3101 dissect_megaco_LocalRemotedescriptor(tvbuff_t
*tvb
, proto_tree
*megaco_mediadescriptor_tree
, packet_info
*pinfo
,
3102 int tvb_next_offset
, int tvb_current_offset
, uint32_t context
, bool is_local
)
3106 media_content_info_t content_info
= { MEDIA_CONTAINER_SIP_DATA
, NULL
, NULL
, NULL
};
3108 sdp_setup_info_t setup_info
;
3110 /* Only fill in the info when we have valid contex */
3111 if ((context
!= 0) && (context
< 0xfffffffe)) {
3112 setup_info
= (sdp_setup_info_t
){
3113 .hf_id
= hf_megaco_Context
,
3114 .hf_type
= SDP_TRACE_ID_HF_TYPE_UINT32
,
3115 .trace_id
.num
= context
,
3117 if (!sip_hide_generated_call_ids
) {
3118 setup_info
.add_hidden
= false;
3120 setup_info
.add_hidden
= prefs_get_bool_value(sip_hide_generated_call_ids
, pref_current
);
3122 content_info
.data
= &setup_info
;
3125 proto_tree
*megaco_localdescriptor_tree
;
3126 proto_item
*megaco_localdescriptor_item
;
3128 tokenlen
= tvb_next_offset
- tvb_current_offset
;
3131 megaco_localdescriptor_item
= proto_tree_add_item(megaco_mediadescriptor_tree
, hf_megaco_Local_descriptor
, tvb
, tvb_current_offset
, tokenlen
, ENC_NA
);
3132 megaco_localdescriptor_tree
= proto_item_add_subtree(megaco_localdescriptor_item
, ett_megaco_Localdescriptor
);
3134 megaco_localdescriptor_item
= proto_tree_add_item(megaco_mediadescriptor_tree
, hf_megaco_Remote_descriptor
, tvb
, tvb_current_offset
, tokenlen
, ENC_NA
);
3135 megaco_localdescriptor_tree
= proto_item_add_subtree(megaco_localdescriptor_item
, ett_megaco_Remotedescriptor
);
3138 if ( tokenlen
> 3 ){
3139 next_tvb
= tvb_new_subset_length(tvb
, tvb_current_offset
, tokenlen
);
3140 call_dissector_with_data(sdp_handle
, next_tvb
, pinfo
, megaco_localdescriptor_tree
, &content_info
);
3145 * localControlDescriptor = LocalControlToken LBRKT localParm
3146 * *(COMMA localParm) RBRKT
3147 * ; at-most-once per item
3148 * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
3151 #define MEGACO_MODETOKEN 1
3152 #define MEGACO_RESERVEDVALUETOKEN 2
3153 #define MEGACO_RESERVEDGROUPTOKEN 3
3154 #define MEGACO_H324_H223CAPR 4
3155 #define MEGACO_H324_MUXTBL_IN 5
3156 #define MEGACO_H324_MUXTBL_OUT 6
3157 #define MEGACO_DS_DSCP 7
3158 #define MEGACO_GM_SAF 8
3159 #define MEGACO_GM_SAM 9
3160 #define MEGACO_GM_SPF 10
3161 #define MEGACO_GM_SPR 11
3162 #define MEGACO_GM_ESAS 12
3163 #define MEGACO_GM_LSA 13
3164 #define MEGACO_GM_ESPS 14
3165 #define MEGACO_GM_LSP 15
3166 #define MEGACO_GM_RSB 16
3167 #define MEGACO_TMAN_POL 17
3168 #define MEGACO_TMAN_SDR 18
3169 #define MEGACO_TMAN_MBS 19
3170 #define MEGACO_TMAN_PDR 20
3171 #define MEGACO_TMAN_DVT 21
3172 #define MEGACO_IPDC_REALM 22
3174 static const megaco_tokens_t megaco_localParam_names
[] = {
3175 { "Unknown-token", NULL
}, /* 0 Pad so that the real headers start at index 1 */
3177 { "Mode", "MO" }, /* 1 */
3178 { "ReservedValue", "RV" }, /* 2 */
3179 { "ReservedGroup", "RG" }, /* 3 */
3180 /* propertyParm = pkgdName parmValue
3181 * Add more package names as needed.
3183 { "h324/h223capr", NULL
}, /* 4 */
3184 { "h324/muxtbl_in", NULL
}, /* 5 */
3185 { "h324/muxtbl_out", NULL
}, /* 6 */
3186 { "ds/dscp", NULL
}, /* 7 */
3187 { "gm/saf", NULL
}, /* 8 */
3188 { "gm/sam", NULL
}, /* 9 */
3189 { "gm/spf", NULL
}, /* 10 */
3190 { "gm/spr", NULL
}, /* 11 */
3191 { "gm/esas", NULL
}, /* 12 */
3192 { "gm/lsa", NULL
}, /* 13 */
3193 { "gm/esps", NULL
}, /* 14 */
3194 { "gm/lsp", NULL
}, /* 15 */
3195 { "gm/rsb", NULL
}, /* 16 */
3196 { "tman/pol", NULL
}, /* 17 */
3197 { "tman/sdr", NULL
}, /* 18 */
3198 { "tman/mbs", NULL
}, /* 19 */
3199 { "tman/pdr", NULL
}, /* 20 */
3200 { "tman/dvt", NULL
}, /* 21 */
3201 { "ipdc/realm", NULL
}, /* 22 */
3204 /* Returns index of megaco_tokens_t */
3205 static int find_megaco_localParam_names(tvbuff_t
*tvb
, int offset
, unsigned header_len
)
3209 for (i
= 1; i
< array_length(megaco_localParam_names
); i
++) {
3210 if (header_len
== strlen(megaco_localParam_names
[i
].name
) &&
3211 tvb_strncaseeql(tvb
, offset
, megaco_localParam_names
[i
].name
, header_len
) == 0)
3213 if (megaco_localParam_names
[i
].compact_name
!= NULL
&&
3214 header_len
== strlen(megaco_localParam_names
[i
].compact_name
) &&
3215 tvb_strncaseeql(tvb
, offset
, megaco_localParam_names
[i
].compact_name
, header_len
) == 0)
3223 dissect_megaco_LocalControldescriptor(tvbuff_t
*tvb
, proto_tree
*megaco_mediadescriptor_tree
, packet_info
*pinfo
, int tvb_next_offset
, int tvb_current_offset
, proto_tree
*top_tree
)
3226 unsigned token_name_len
;
3227 int tvb_offset
= 0,tvb_help_offset
;
3228 int token_index
= 0;
3231 uint8_t code_str
[3];
3233 proto_tree
*megaco_LocalControl_tree
;
3234 proto_item
*megaco_LocalControl_item
;
3236 tokenlen
= tvb_next_offset
- tvb_current_offset
;
3238 megaco_LocalControl_item
= proto_tree_add_item(megaco_mediadescriptor_tree
, hf_megaco_LocalControl_descriptor
, tvb
, tvb_current_offset
, tokenlen
, ENC_NA
);
3239 megaco_LocalControl_tree
= proto_item_add_subtree(megaco_LocalControl_item
, ett_megaco_LocalControldescriptor
);
3241 while ( tvb_offset
< tvb_next_offset
&& tvb_offset
!= -1 ){
3243 tvb_help_offset
= tvb_current_offset
;
3246 * Find local parameter name
3247 * localParm = ( streamMode / propertyParm / reservedValueMode / reservedGroupMode )
3248 * pkgdName = (PackageName SLASH ItemID) ;specific item
3249 * / (PackageName SLASH "*") ;all events in package
3250 * / ("*" SLASH "*") ; all events supported by the MG
3252 /* Find token length */
3253 for (tvb_offset
=tvb_current_offset
; tvb_offset
< tvb_next_offset
; tvb_offset
++){
3255 octet
= tvb_get_uint8(tvb
, tvb_offset
);
3256 if (!g_ascii_isalnum(octet
)){
3257 if ((octet
!='/')&&(octet
!='_')){
3262 token_name_len
= tvb_offset
- tvb_current_offset
;
3264 proto_tree_add_format_text(megaco_LocalControl_tree, tvb, tvb_current_offset, token_name_len);
3266 token_index
= find_megaco_localParam_names(tvb
, tvb_current_offset
, token_name_len
);
3267 /* Find start of parameter value */
3268 tvb_offset
= tvb_find_uint8(tvb
, tvb_offset
, tvb_next_offset
, '=');
3269 if (tvb_offset
== -1) {
3270 expert_add_info(pinfo
, megaco_LocalControl_item
, &ei_megaco_parse_error
);
3273 /* Start search after '=' in case there is no SP*/
3275 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
);
3277 /* find if there are more parameters or not */
3278 tvb_offset
= tvb_find_uint8(tvb
, tvb_current_offset
, tvb_offset
, ',');
3279 if ( tvb_offset
< 0 || tvb_offset
> tvb_next_offset
){
3280 tvb_offset
= tvb_next_offset
;
3283 tokenlen
= megaco_tvb_skip_wsp_return(tvb
,tvb_offset
-1) - tvb_current_offset
;
3285 proto_tree_add_format_text(megaco_LocalControl_tree, tvb, tvb_current_offset, tokenlen);
3287 switch ( token_index
){
3289 case MEGACO_MODETOKEN
: /* Mode */
3290 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_mode
, tvb
,
3291 tvb_help_offset
, tvb_offset
-tvb_help_offset
,
3292 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
,
3294 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (Mode:%s)",tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
,tokenlen
));
3295 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3298 case MEGACO_RESERVEDVALUETOKEN
: /* ReservedValue */
3299 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_reserve_value
, tvb
,
3300 tvb_help_offset
, tvb_offset
-tvb_help_offset
,
3301 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3303 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3305 case MEGACO_RESERVEDGROUPTOKEN
: /* ReservedGroup */
3306 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_reserve_group
, tvb
,
3307 tvb_help_offset
, tvb_offset
-tvb_help_offset
,
3308 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3309 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3312 case MEGACO_H324_H223CAPR
: /* h324/h223capr */
3313 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_h324_h223capr
, tvb
,
3314 tvb_help_offset
, tvb_offset
-tvb_help_offset
,
3315 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3317 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3318 tokenlen
= tvb_offset
- tvb_help_offset
;
3319 msg
=tvb_format_text(pinfo
->pool
, tvb
,tvb_help_offset
, tokenlen
);
3320 dissect_megaco_h324_h223caprn(tvb
, pinfo
, megaco_mediadescriptor_tree
, tvb_help_offset
, tokenlen
, msg
);
3324 case MEGACO_H324_MUXTBL_IN
: /* h324/muxtbl_in */
3326 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_h324_muxtbl_in
, tvb
,
3327 tvb_help_offset
, tvb_offset
-tvb_help_offset
,
3328 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3330 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3332 tokenlen
= tvb_offset
- tvb_help_offset
;
3333 /* Call the existing routine with tree = NULL to avoid an entry to the tree */
3334 dissect_megaco_h245(tvb
, pinfo
, NULL
, tvb_help_offset
, tokenlen
, top_tree
);
3338 case MEGACO_H324_MUXTBL_OUT
:
3340 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_h324_muxtbl_out
, tvb
,
3341 tvb_current_offset
, tokenlen
,
3342 tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
,
3345 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3347 tokenlen
= tvb_offset
- tvb_help_offset
;
3348 /* Call the existing routine with tree = NULL to avoid an entry to the tree */
3349 dissect_megaco_h245(tvb
, pinfo
, NULL
, tvb_help_offset
, tokenlen
, top_tree
);
3353 case MEGACO_DS_DSCP
:
3354 tvb_get_raw_bytes_as_stringz(tvb
,tvb_current_offset
,3,code_str
);
3355 item
= proto_tree_add_uint(megaco_LocalControl_tree
, hf_megaco_ds_dscp
, tvb
,
3356 tvb_help_offset
, 1, (uint32_t) strtoul(code_str
,NULL
,16));
3357 proto_item_set_len(item
, tvb_offset
-tvb_help_offset
);
3358 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3362 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_gm_saf
, tvb
,
3363 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3364 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3367 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_gm_sam
, tvb
,
3368 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3369 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3372 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_gm_spf
, tvb
,
3373 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3374 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3377 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_gm_spr
, tvb
,
3378 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3379 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3381 case MEGACO_GM_ESAS
:
3382 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_gm_esas
, tvb
,
3383 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3384 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3387 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_gm_rsb
, tvb
,
3388 tvb_help_offset
, tvb_offset
- tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3389 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+ 1);
3391 case MEGACO_TMAN_POL
:
3392 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_tman_pol
, tvb
,
3393 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3394 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3396 case MEGACO_TMAN_SDR
:
3402 sdr_valid
= ws_strtoi32(tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
), NULL
, &sdr
);
3403 pi
=proto_tree_add_int(megaco_LocalControl_tree
, hf_megaco_tman_sdr
, tvb
, tvb_help_offset
,
3404 tvb_offset
- tvb_help_offset
, sdr
);
3405 proto_item_append_text(pi
, " [%i b/s]", sdr
*8);
3407 expert_add_info(pinfo
, pi
, &ei_megaco_invalid_sdr
);
3409 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+ 1);
3412 case MEGACO_TMAN_MBS
:
3413 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_tman_mbs
, tvb
,
3414 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3415 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3417 case MEGACO_TMAN_PDR
:
3418 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_tman_pdr
, tvb
,
3419 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3420 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3422 case MEGACO_TMAN_DVT
:
3423 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_tman_dvt
, tvb
,
3424 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3425 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3427 case MEGACO_IPDC_REALM
:
3428 proto_tree_add_string(megaco_LocalControl_tree
, hf_megaco_ipdc_realm
, tvb
,
3429 tvb_help_offset
, tvb_offset
-tvb_help_offset
, tvb_format_text(pinfo
->pool
, tvb
, tvb_current_offset
, tokenlen
));
3430 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3434 tokenlen
= tvb_offset
- tvb_help_offset
;
3435 proto_tree_add_format_text(megaco_LocalControl_tree
, tvb
, tvb_help_offset
, tokenlen
);
3436 tvb_current_offset
= megaco_tvb_skip_wsp(tvb
, tvb_offset
+1);
3444 dissect_megaco_descriptors(tvbuff_t
*tvb
, proto_tree
*megaco_command_tree
, packet_info
*pinfo
, int tvb_descriptors_start_offset
,
3445 int tvb_descriptors_end_offset
, proto_tree
*top_tree
, uint32_t context
)
3447 int tvb_len
, token_index
, tvb_offset
, temp_offset
;
3448 int tvb_current_offset
,tvb_previous_offset
,save_offset
,tokenlen
;
3449 int tvb_RBRKT
, tvb_LBRKT
;
3450 proto_tree
* descriptor_tree
;
3451 proto_item
* descriptor_item
;
3453 tvb_len
= tvb_reported_length(tvb
);
3455 descriptor_tree
= proto_tree_add_subtree(megaco_command_tree
, tvb
, tvb_descriptors_start_offset
,
3456 tvb_descriptors_end_offset
-tvb_descriptors_start_offset
, ett_megaco_descriptors
, &descriptor_item
, "Descriptors");
3458 tvb_LBRKT
= megaco_tvb_skip_wsp(tvb
, tvb_descriptors_start_offset
+1);
3460 tvb_previous_offset
= tvb_LBRKT
;
3461 tvb_RBRKT
= tvb_descriptors_start_offset
;
3466 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,
3468 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
,
3471 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
,
3474 if (tvb_current_offset
== -1 || tvb_current_offset
> tvb_descriptors_end_offset
){
3475 tvb_current_offset
= tvb_descriptors_end_offset
;
3478 if (tvb_current_offset
<= tvb_previous_offset
) {
3479 expert_add_info_format(pinfo
, descriptor_item
, &ei_megaco_parse_error
, "Parse error: Invalid offset");
3483 /* Descriptor includes no parameters */
3485 if ( tvb_LBRKT
> tvb_current_offset
|| tvb_LBRKT
== -1 ){
3487 if ( tvb_current_offset
> tvb_RBRKT
){
3488 tvb_current_offset
= tvb_RBRKT
;
3491 tvb_RBRKT
= megaco_tvb_skip_wsp_return(tvb
, tvb_current_offset
-1)-1;
3494 /* Descriptor includes Parameters */
3495 if ( (tvb_current_offset
> tvb_LBRKT
&& tvb_LBRKT
!= -1)){
3497 while ( tvb_LBRKT
!= -1 && tvb_RBRKT
> tvb_LBRKT
){
3500 tvb_LBRKT
= tvb_find_uint8(tvb
, tvb_LBRKT
+1,
3502 if ( tvb_LBRKT
< tvb_RBRKT
&& tvb_LBRKT
!= -1)
3503 tvb_RBRKT
= tvb_find_uint8(tvb
, tvb_RBRKT
+1,tvb_len
, '}');
3508 /* Find token length */
3509 for (tvb_offset
=tvb_previous_offset
; tvb_offset
< tvb_descriptors_end_offset
-1; tvb_offset
++){
3510 if (!g_ascii_isalpha(tvb_get_uint8(tvb
, tvb_offset
))){
3514 tokenlen
= tvb_offset
- tvb_previous_offset
;
3515 token_index
= find_megaco_descriptors_names(tvb
, tvb_previous_offset
, tokenlen
);
3516 if (tvb_RBRKT
> tvb_descriptors_end_offset
)
3517 tvb_RBRKT
= tvb_descriptors_end_offset
;
3518 switch ( token_index
){
3519 case MEGACO_MODEM_TOKEN
:
3520 dissect_megaco_modemdescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
);
3522 case MEGACO_MUX_TOKEN
:
3523 dissect_megaco_multiplexdescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
);
3525 case MEGACO_MEDIA_TOKEN
:
3526 /*TODO: Move this to the top when all branches fixed !!!*/
3527 temp_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
,tvb_descriptors_end_offset
, '{');
3528 save_offset
= tvb_previous_offset
;
3530 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, temp_offset
+1);
3531 dissect_megaco_mediadescriptor(tvb
, descriptor_tree
, pinfo
, tvb_RBRKT
, tvb_previous_offset
, save_offset
, top_tree
, context
);
3533 case MEGACO_SIGNALS_TOKEN
:
3534 dissect_megaco_signaldescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
, top_tree
);
3536 case MEGACO_SERVICES_TOKEN
:
3537 dissect_megaco_servicechangedescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
);
3539 case MEGACO_STATS_TOKEN
:
3540 dissect_megaco_statisticsdescriptor(tvb
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
);
3542 case MEGACO_ERROR_TOKEN
:
3543 dissect_megaco_errordescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
);
3545 case MEGACO_EVENTS_TOKEN
:
3546 dissect_megaco_eventsdescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
, top_tree
);
3548 case MEGACO_AUDIT_TOKEN
:
3549 dissect_megaco_auditdescriptor(tvb
, descriptor_tree
, pinfo
, tvb_RBRKT
, tvb_previous_offset
, top_tree
, context
);
3551 case MEGACO_DIGITMAP_TOKEN
:
3552 dissect_megaco_digitmapdescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
);
3554 case MEGACO_OE_TOKEN
:
3555 /* ObservedEventsToken */
3556 dissect_megaco_observedeventsdescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
, top_tree
);
3558 case MEGACO_TOPOLOGY_TOKEN
:
3559 dissect_megaco_topologydescriptor(tvb
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
);
3561 case MEGACO_PACKAGES_TOKEN
:
3562 dissect_megaco_Packagesdescriptor(tvb
, pinfo
, descriptor_tree
, tvb_RBRKT
, tvb_previous_offset
);
3565 tokenlen
= (tvb_RBRKT
+1) - tvb_previous_offset
;
3566 proto_tree_add_expert(descriptor_tree
, pinfo
, &ei_megaco_no_descriptor
, tvb
, tvb_previous_offset
, tokenlen
);
3570 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_RBRKT
, tvb_len
, ',');
3571 if (tvb_current_offset
== -1 || tvb_descriptors_end_offset
< tvb_current_offset
){
3572 tvb_current_offset
= tvb_descriptors_end_offset
;
3574 tvb_previous_offset
= megaco_tvb_skip_wsp(tvb
, tvb_current_offset
+1);
3575 tvb_LBRKT
= tvb_previous_offset
;
3576 tvb_RBRKT
= tvb_previous_offset
;
3578 } while ( tvb_current_offset
< tvb_descriptors_end_offset
);
3582 /* Copied from MGCP dissector, prints whole message in raw text */
3584 static void tvb_raw_text_add(tvbuff_t
*tvb
, proto_tree
*tree
){
3586 int tvb_linebegin
,tvb_lineend
,linelen
;
3587 proto_tree
* text_tree
;
3592 text_tree
= proto_tree_add_subtree(tree
, tvb
, 0, -1, ett_megaco_raw_text
, NULL
, "-------------- (RAW text output) ---------------");
3595 linelen
= tvb_find_line_end(tvb
,tvb_linebegin
,-1,&tvb_lineend
,false);
3596 proto_tree_add_format_wsp_text(text_tree
, tvb
, tvb_linebegin
, linelen
);
3597 tvb_linebegin
= tvb_lineend
;
3598 } while (tvb_offset_exists(tvb
, tvb_lineend
) && linelen
> 0);
3603 * megaco_tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
3604 * character following offset or offset + maxlength -1 whichever
3608 * tvb - The tvbuff in which we are skipping whitespaces, tab and end_of_line characters.
3609 * offset - The offset in tvb from which we begin trying to skip whitespace.
3611 * Returns: The position in tvb of the first non-whitespace
3613 static int megaco_tvb_skip_wsp(tvbuff_t
* tvb
, int offset
){
3614 int counter
= offset
;
3615 int end
= tvb_reported_length(tvb
);
3617 for(counter
= offset
; counter
< end
&&
3618 (g_ascii_isspace(tvb_get_uint8(tvb
,counter
))); counter
++);
3622 static int megaco_tvb_skip_wsp_return(tvbuff_t
* tvb
, int offset
){
3623 int counter
= offset
;
3626 for(counter
= offset
; counter
> end
&&
3627 (g_ascii_isspace(tvb_get_uint8(tvb
,counter
))); counter
--);
3632 static int megaco_tvb_find_token(tvbuff_t
* tvb
, int offset
, int maxlength
){
3635 unsigned char needle
;
3638 pos
= tvb_ws_mempbrk_pattern_uint8(tvb
, pos
+ 1, maxlength
, &pbrk_braces
, &needle
);
3651 } while (counter
>0);
3656 pos
= megaco_tvb_skip_wsp(tvb
,pos
+1);
3662 megaco_fmt_content( char *result
, uint32_t context
)
3666 case CHOOSE_CONTEXT
:
3669 (void) g_strlcpy(result
, val_to_str_const(context
, megaco_context_vals
, "Unknown"), ITEM_LABEL_LENGTH
);
3672 snprintf( result
, ITEM_LABEL_LENGTH
, "%d", context
);
3677 proto_register_megaco(void)
3679 static hf_register_info hf
[] = {
3680 { &hf_megaco_audititem
,
3681 { "Audit Item", "megaco.audititem", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3682 "Identity of item to be audited", HFILL
}},
3683 { &hf_megaco_audit_descriptor
,
3684 { "Audit Descriptor", "megaco.audit", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3685 "Audit Descriptor of the megaco Command", HFILL
}},
3687 { &hf_megaco_command_line
,
3688 { "Command line", "megaco.command_line", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3689 "Commands of this message", HFILL
}},
3691 { &hf_megaco_command
,
3692 { "Command", "megaco.command", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3694 { &hf_megaco_command_optional
,
3695 { "Optional Command", "megaco.command_optional", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3697 { &hf_megaco_wildcard_response
,
3698 { "Wildcarded response to a command", "megaco.wildcard_response", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3701 { &hf_megaco_Context
,
3702 { "Context", "megaco.context", FT_UINT32
, BASE_CUSTOM
, CF_FUNC(megaco_fmt_content
), 0x0,
3703 "Context ID of this message", HFILL
}},
3704 { &hf_megaco_digitmap_descriptor
,
3705 { "DigitMap Descriptor", "megaco.digitmap", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3706 "DigitMap Descriptor of the megaco Command", HFILL
}},
3707 { &hf_megaco_error_descriptor
,
3708 { "ERROR Descriptor", "megaco.error", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3709 "Error Descriptor of the megaco Command", HFILL
}},
3710 { &hf_megaco_error_code
,
3711 { "ERROR Code", "megaco.error_code", FT_UINT32
, BASE_DEC
, VALS(MEGACO_error_code_vals
), 0x0,
3712 "Error Code of the megaco Command", HFILL
}},
3713 { &hf_megaco_error_string
,
3714 { "ERROR String", "megaco.error_string", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3715 "Error String of the megaco Command", HFILL
}},
3716 { &hf_megaco_Event_Buffer_Control
,
3717 { "Event Buffer Control", "megaco.eventbuffercontrol", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3718 "Event Buffer Control in Termination State Descriptor", HFILL
}},
3719 { &hf_megaco_events_descriptor
,
3720 { "Events Descriptor", "megaco.events", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3721 "Events Descriptor of the megaco Command", HFILL
}},
3722 { &hf_megaco_Local_descriptor
,
3723 { "Local Descriptor", "megaco.localdescriptor", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3724 "Local Descriptor in Media Descriptor", HFILL
}},
3725 { &hf_megaco_LocalControl_descriptor
,
3726 { "Local Control Descriptor", "megaco.localcontroldescriptor", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3727 "Local Control Descriptor in Media Descriptor", HFILL
}},
3728 { &hf_megaco_media_descriptor
,
3729 { "Media Descriptor", "megaco.media", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3730 "Media Descriptor of the megaco Command", HFILL
}},
3731 { &hf_megaco_modem_descriptor
,
3732 { "Modem Descriptor", "megaco.modem", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3733 "Modem Descriptor of the megaco Command", HFILL
}},
3735 { "Mode", "megaco.mode", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3736 "Mode sendonly/receiveonly/inactive/loopback", HFILL
}},
3737 { &hf_megaco_multiplex_descriptor
,
3738 { "Multiplex Descriptor", "megaco.multiplex", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3739 "Multiplex Descriptor of the megaco Command", HFILL
}},
3740 { &hf_megaco_observedevents_descriptor
,
3741 { "Observed Events Descriptor", "megaco.observedevents", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3742 "Observed Events Descriptor of the megaco Command", HFILL
}},
3743 { &hf_megaco_packages_descriptor
,
3744 { "Packages Descriptor", "megaco.packagesdescriptor", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3746 { &hf_megaco_pkgdname
,
3747 { "pkgdName", "megaco.pkgdname", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3748 "PackageName SLASH ItemID", HFILL
}},
3749 { &hf_megaco_Remote_descriptor
,
3750 { "Remote Descriptor", "megaco.remotedescriptor", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3751 "Remote Descriptor in Media Descriptor", HFILL
}},
3752 { &hf_megaco_reserve_group
,
3753 { "Reserve Group", "megaco.reservegroup", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3754 "Reserve Group on or off", HFILL
}},
3755 { &hf_megaco_h324_muxtbl_in
,
3756 { "h324/muxtbl_in", "megaco.h324_muxtbl_in", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3758 { &hf_megaco_h324_muxtbl_out
,
3759 { "h324/muxtbl_out", "megaco.h324_muxtbl_out", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3761 { &hf_megaco_ds_dscp
,
3762 { "Differentiated Services Code Point", "megaco.ds_dscp", FT_UINT32
, BASE_HEX
|BASE_EXT_STRING
, &dscp_vals_ext
, 0x0,
3764 { &hf_megaco_gm_saf
,
3765 { "Remote Source Address Filtering", "megaco.gm_saf", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3767 { &hf_megaco_gm_sam
,
3768 { "Remote Source Address Mask", "megaco.gm_sam", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3770 { &hf_megaco_gm_spf
,
3771 { "Remote Source Port Filtering", "megaco.gm_spf", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3773 { &hf_megaco_gm_spr
,
3774 { "Remote Source Port Range", "megaco.gm_spr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3776 { &hf_megaco_gm_esas
,
3777 { "Explicit Source Address Setting", "megaco.gm_esas", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3779 { &hf_megaco_tman_pol
,
3780 { "Policing", "megaco.tman_pol", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3782 { &hf_megaco_gm_rsb
,
3783 { "RTCP Allocation Specific Behaviour", "megaco.gm_rsb", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3785 { &hf_megaco_tman_sdr
,
3786 { "Sustainable Data Rate", "megaco.tman_sdr", FT_INT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytespsecond
), 0x0,
3788 { &hf_megaco_tman_mbs
,
3789 { "Maximum Burst Rate", "megaco.tman_mbs", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3791 { &hf_megaco_tman_pdr
,
3792 { "Peak Data Rate", "megaco.tman_pdr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3794 { &hf_megaco_tman_dvt
,
3795 { "Delay Variation Tolerance", "megaco.tman_dvt", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3797 { &hf_megaco_ipdc_realm
,
3798 { "IP Realm Identifier", "megaco.ipdc_realm", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3800 { &hf_megaco_h324_h223capr
,
3801 { "h324/h223capr", "megaco.h324_h223capr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3803 { &hf_megaco_reserve_value
,
3804 { "Reserve Value", "megaco.reservevalue", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3805 "Reserve Value on or off", HFILL
}},
3806 { &hf_megaco_requestid
,
3807 { "RequestID", "megaco.requestid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3808 "RequestID in Events or Observedevents Descriptor", HFILL
}},
3810 { &hf_megaco_servicechange_descriptor
,
3811 { "Service Change Descriptor", "megaco.servicechange", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3812 "Service Change Descriptor of the megaco Command", HFILL
}},
3814 { &hf_megaco_Service_State
,
3815 { "Service State", "megaco.servicestates", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3816 "Service States in Termination State Descriptor", HFILL
}},
3817 { &hf_megaco_signal_descriptor
,
3818 { "Signal Descriptor", "megaco.signal", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3819 "Signal Descriptor of the megaco Command", HFILL
}},
3820 { &hf_megaco_statistics_descriptor
,
3821 { "Statistics Descriptor", "megaco.statistics", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3822 "Statistics Descriptor of the megaco Command", HFILL
}},
3823 { &hf_megaco_streamid
,
3824 { "StreamID", "megaco.streamid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3825 "StreamID in the Media Descriptor", HFILL
}},
3826 { &hf_megaco_termid
,
3827 { "Termination ID", "megaco.termid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3828 "Termination ID of this Command", HFILL
}},
3829 { &hf_megaco_TerminationState_descriptor
,
3830 { "Termination State Descriptor", "megaco.terminationstate", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3831 "Termination State Descriptor in Media Descriptor", HFILL
}},
3832 { &hf_megaco_topology_descriptor
,
3833 { "Topology Descriptor", "megaco.topology", FT_STRING
, BASE_STR_WSP
, NULL
, 0x0,
3834 "Topology Descriptor of the megaco Command", HFILL
}},
3835 { &hf_megaco_transaction
,
3836 { "Transaction", "megaco.transaction", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3837 "Message Originator", HFILL
}},
3838 { &hf_megaco_transid
,
3839 { "Transaction ID", "megaco.transid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3840 "Transaction ID of this message", HFILL
}},
3842 { "MediagatewayID", "megaco.mId", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3843 "Mediagateway ID", HFILL
}},
3844 { &hf_megaco_version
,
3845 { "Version", "megaco.version", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3848 { "Start token", "megaco.start_token", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3851 { "h245", "megaco.h245", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3852 "Embedded H.245 message", HFILL
}},
3853 { &hf_megaco_h223Capability
,
3854 { "h223Capability", "megaco.h245.h223Capability", FT_NONE
, BASE_NONE
, NULL
, 0,
3855 "megaco.h245.H223Capability", HFILL
}},
3856 { &hf_megaco_priority
,
3857 { "Priority", "megaco.priority", FT_STRING
, BASE_NONE
, NULL
, 0,
3860 GCP_HF_ARR_ELEMS("megaco",megaco_ctx_ids
),
3862 /* Add more fields here */
3864 static int *ett
[] = {
3866 &ett_megaco_message
,
3867 &ett_megaco_message_body
,
3868 &ett_megaco_context
,
3869 &ett_megaco_command_line
,
3870 &ett_megaco_descriptors
,
3871 &ett_megaco_raw_text
,
3872 &ett_megaco_error_descriptor
,
3873 &ett_megaco_mediadescriptor
,
3874 &ett_megaco_TerminationState
,
3875 &ett_megaco_Remotedescriptor
,
3876 &ett_megaco_Localdescriptor
,
3877 &ett_megaco_LocalControldescriptor
,
3878 &ett_megaco_auditdescriptor
,
3879 &ett_megaco_eventsdescriptor
,
3880 &ett_megaco_statisticsdescriptor
,
3881 &ett_megaco_observedeventsdescriptor
,
3882 &ett_megaco_observedevent
,
3883 &ett_megaco_packagesdescriptor
,
3884 &ett_megaco_requestedevent
,
3885 &ett_megaco_signalsdescriptor
,
3886 &ett_megaco_requestedsignal
,
3888 GCP_ETT_ARR_ELEMS(megaco_ctx_ids
),
3891 static ei_register_info ei
[] = {
3892 { &ei_megaco_errored_command
, { "megaco.errored_command", PI_RESPONSE_CODE
, PI_WARN
, "Errored Command", EXPFILL
}},
3893 { &ei_megaco_parse_error
, { "megaco.parse_error", PI_MALFORMED
, PI_ERROR
, "Parse error", EXPFILL
}},
3894 { &ei_megaco_error_descriptor_transaction_list
, { "megaco.error_descriptor_transaction_list.invalid", PI_MALFORMED
, PI_ERROR
, "Sorry, can't understand errorDescriptor / transactionList", EXPFILL
}},
3895 { &ei_megaco_audit_descriptor
, { "megaco.audit.malformed", PI_MALFORMED
, PI_ERROR
, "Badly constructed audit descriptor (no { )", EXPFILL
}},
3896 { &ei_megaco_signal_descriptor
, { "megaco.signal_descriptor.empty", PI_PROTOCOL
, PI_NOTE
, "Empty Signal Descriptor", EXPFILL
}},
3897 { &ei_megaco_no_command
, { "megaco.no_command", PI_PROTOCOL
, PI_WARN
, "No Command detectable", EXPFILL
}},
3898 { &ei_megaco_no_descriptor
, { "megaco.no_descriptor", PI_PROTOCOL
, PI_WARN
, "No Descriptor detectable", EXPFILL
}},
3899 { &ei_megaco_reason_invalid
, { "megaco.change_reason.invalid", PI_MALFORMED
, PI_ERROR
, "Invalid Service Change Reason", EXPFILL
}},
3900 { &ei_megaco_error_code_invalid
,{ "megaco.error_code.invalid", PI_MALFORMED
, PI_ERROR
, "Invalid error code", EXPFILL
} },
3901 { &ei_megaco_invalid_sdr
, { "megaco.sdr.invalid", PI_MALFORMED
, PI_ERROR
, "Invalid Sustainable Data Rate", EXPFILL
}}
3904 module_t
*megaco_module
;
3905 expert_module_t
* expert_megaco
;
3907 proto_megaco
= proto_register_protocol("MEGACO", "MEGACO", "megaco");
3909 megaco_text_handle
= register_dissector("megaco", dissect_megaco_text
, proto_megaco
);
3911 proto_register_field_array(proto_megaco
, hf
, array_length(hf
));
3912 proto_register_subtree_array(ett
, array_length(ett
));
3913 expert_megaco
= expert_register_protocol(proto_megaco
);
3914 expert_register_field_array(expert_megaco
, ei
, array_length(ei
));
3916 /* Register our configuration options, particularly our ports */
3918 megaco_module
= prefs_register_protocol(proto_megaco
, NULL
);
3920 prefs_register_bool_preference(megaco_module
, "display_raw_text",
3921 "Display raw text for MEGACO message",
3922 "Specifies that the raw text of the "
3923 "MEGACO message should be displayed "
3924 "instead of (or in addition to) the "
3926 &global_megaco_raw_text
);
3928 prefs_register_bool_preference(megaco_module
, "display_dissect_tree",
3929 "Display tree dissection for MEGACO message",
3930 "Specifies that the dissection tree of the "
3931 "MEGACO message should be displayed "
3932 "instead of (or in addition to) the "
3934 &global_megaco_dissect_tree
);
3935 prefs_register_bool_preference(megaco_module
, "ctx_info",
3937 "Maintain relationships between transactions and contexts "
3938 "and display an extra tree showing context data",
3939 &keep_persistent_data
);
3941 megaco_tap
= register_tap("megaco");
3943 /* compile patterns */
3944 ws_mempbrk_compile(&pbrk_whitespace
, " \t\r\n");
3945 ws_mempbrk_compile(&pbrk_braces
, "{}");
3947 register_rtd_table(proto_megaco
, NULL
, 1, NUM_TIMESTATS
, megaco_message_type
, megacostat_packet
, megacostat_filtercheck
);
3950 /* Register all the bits needed with the filtering engine */
3951 /* The registration hand-off routine */
3953 proto_reg_handoff_megaco(void)
3955 dissector_handle_t megaco_text_tcp_handle
;
3957 sdp_handle
= find_dissector_add_dependency("sdp", proto_megaco
);
3958 h245_handle
= find_dissector_add_dependency("h245dg", proto_megaco
);
3959 h248_handle
= find_dissector_add_dependency("h248", proto_megaco
);
3960 h248_otp_handle
= find_dissector_add_dependency("h248_otp", proto_megaco
);
3961 data_handle
= find_dissector("data");
3963 megaco_text_tcp_handle
= create_dissector_handle(dissect_megaco_text_tcp
, proto_megaco
);
3965 dissector_add_uint_with_preference("tcp.port", PORT_MEGACO_TXT
, megaco_text_tcp_handle
);
3966 dissector_add_uint_with_preference("udp.port", PORT_MEGACO_TXT
, megaco_text_handle
);
3967 dissector_add_uint_with_preference("sctp.port", PORT_MEGACO_TXT
, megaco_text_handle
);
3968 dissector_add_uint("sctp.ppi", H248_PAYLOAD_PROTOCOL_ID
, megaco_text_handle
);
3970 exported_pdu_tap
= find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_7
);
3972 sip_hide_generated_call_ids
= prefs_find_preference(prefs_find_module("sip"), "hide_generated_call_id");
3977 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3982 * indent-tabs-mode: nil
3985 * vi: set shiftwidth=4 tabstop=8 expandtab:
3986 * :indentSize=4:tabSize=8:noTabs=true: