2 * Routines for mgcp packet disassembly
4 * RFC 3435 (obsoletes 2705): Media Gateway Control Protocol (MGCP) Version 1.0
5 * RFC 3660: Basic MGCP Packages
6 * RFC 3661: MGCP Return Code Usage
7 * NCS 1.0: PacketCable Network-Based Call Signaling Protocol Specification,
8 * PKT-SP-EC-MGCP-I09-040113, January 13, 2004, Cable Television
9 * Laboratories, Inc., http://www.PacketCable.com/
10 * NCS 1.5: PKT-SP-NCS1.5-I04-120412, April 12, 2012 Cable Television
11 * Laboratories, Inc., http://www.PacketCable.com/
12 * www.iana.org/assignments/mgcp-localconnectionoptions
14 * Copyright (c) 2000 by Ed Warnicke <hagbard@physics.rutgers.edu>
15 * Copyright (c) 2004 by Thomas Anders <thomas.anders [AT] blue-cable.de>
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1999 Gerald Combs
21 * SPDX-License-Identifier: GPL-2.0-or-later
28 #include <epan/packet.h>
29 #include <epan/exceptions.h>
30 #include <epan/prefs.h>
31 #include <epan/conversation.h>
33 #include <epan/strutil.h>
34 #include <epan/rtd_table.h>
35 #include <epan/expert.h>
36 #include "packet-media-type.h"
37 #include "packet-mgcp.h"
38 #include "packet-sdp.h"
40 #include <wsutil/strtoi.h>
42 #define TCP_PORT_MGCP_GATEWAY 2427
43 #define UDP_PORT_MGCP_GATEWAY 2427
44 #define TCP_PORT_MGCP_CALLAGENT 2727
45 #define UDP_PORT_MGCP_CALLAGENT 2727
48 /* Define the mgcp proto */
49 static int proto_mgcp
;
51 /* Define many many headers for mgcp */
52 static int hf_mgcp_req
;
53 static int hf_mgcp_req_verb
;
54 static int hf_mgcp_req_endpoint
;
55 static int hf_mgcp_req_frame
;
56 static int hf_mgcp_rsp
;
57 static int hf_mgcp_rsp_frame
;
58 static int hf_mgcp_time
;
59 static int hf_mgcp_transid
;
60 static int hf_mgcp_version
;
61 static int hf_mgcp_rsp_rspcode
;
62 static int hf_mgcp_rsp_rspstring
;
63 static int hf_mgcp_params
;
64 static int hf_mgcp_param_rspack
;
65 static int hf_mgcp_param_bearerinfo
;
66 static int hf_mgcp_param_callid
;
67 static int hf_mgcp_param_connectionid
;
68 static int hf_mgcp_param_secondconnectionid
;
69 static int hf_mgcp_param_notifiedentity
;
70 static int hf_mgcp_param_requestid
;
71 static int hf_mgcp_param_localconnoptions
;
72 static int hf_mgcp_param_localconnoptions_p
;
73 static int hf_mgcp_param_localconnoptions_a
;
74 static int hf_mgcp_param_localconnoptions_s
;
75 static int hf_mgcp_param_localconnoptions_e
;
76 static int hf_mgcp_param_localconnoptions_scrtp
;
77 static int hf_mgcp_param_localconnoptions_scrtcp
;
78 static int hf_mgcp_param_localconnoptions_b
;
79 static int hf_mgcp_param_localconnoptions_esccd
;
80 static int hf_mgcp_param_localconnoptions_escci
;
81 static int hf_mgcp_param_localconnoptions_dqgi
;
82 static int hf_mgcp_param_localconnoptions_dqrd
;
83 static int hf_mgcp_param_localconnoptions_dqri
;
84 static int hf_mgcp_param_localconnoptions_dqrr
;
85 static int hf_mgcp_param_localconnoptions_k
;
86 static int hf_mgcp_param_localconnoptions_gc
;
87 static int hf_mgcp_param_localconnoptions_fmtp
;
88 static int hf_mgcp_param_localconnoptions_nt
;
89 static int hf_mgcp_param_localconnoptions_ofmtp
;
90 static int hf_mgcp_param_localconnoptions_r
;
91 static int hf_mgcp_param_localconnoptions_t
;
92 static int hf_mgcp_param_localconnoptions_rcnf
;
93 static int hf_mgcp_param_localconnoptions_rdir
;
94 static int hf_mgcp_param_localconnoptions_rsh
;
95 static int hf_mgcp_param_localconnoptions_mp
;
96 static int hf_mgcp_param_localconnoptions_fxr
;
97 static int hf_mgcp_param_localvoicemetrics
;
98 static int hf_mgcp_param_remotevoicemetrics
;
99 static int hf_mgcp_param_voicemetrics_nlr
;
100 static int hf_mgcp_param_voicemetrics_jdr
;
101 static int hf_mgcp_param_voicemetrics_bld
;
102 static int hf_mgcp_param_voicemetrics_gld
;
103 static int hf_mgcp_param_voicemetrics_bd
;
104 static int hf_mgcp_param_voicemetrics_gd
;
105 static int hf_mgcp_param_voicemetrics_rtd
;
106 static int hf_mgcp_param_voicemetrics_esd
;
107 static int hf_mgcp_param_voicemetrics_sl
;
108 static int hf_mgcp_param_voicemetrics_nl
;
109 static int hf_mgcp_param_voicemetrics_rerl
;
110 static int hf_mgcp_param_voicemetrics_gmn
;
111 static int hf_mgcp_param_voicemetrics_nsr
;
112 static int hf_mgcp_param_voicemetrics_xsr
;
113 static int hf_mgcp_param_voicemetrics_mlq
;
114 static int hf_mgcp_param_voicemetrics_mcq
;
115 static int hf_mgcp_param_voicemetrics_plc
;
116 static int hf_mgcp_param_voicemetrics_jba
;
117 static int hf_mgcp_param_voicemetrics_jbr
;
118 static int hf_mgcp_param_voicemetrics_jbn
;
119 static int hf_mgcp_param_voicemetrics_jbm
;
120 static int hf_mgcp_param_voicemetrics_jbs
;
121 static int hf_mgcp_param_voicemetrics_iaj
;
122 static int hf_mgcp_param_connectionmode
;
123 static int hf_mgcp_param_reqevents
;
124 static int hf_mgcp_param_restartmethod
;
125 static int hf_mgcp_param_restartdelay
;
126 static int hf_mgcp_param_signalreq
;
127 static int hf_mgcp_param_digitmap
;
128 static int hf_mgcp_param_observedevent
;
129 static int hf_mgcp_param_connectionparam
;
130 static int hf_mgcp_param_connectionparam_ps
;
131 static int hf_mgcp_param_connectionparam_os
;
132 static int hf_mgcp_param_connectionparam_pr
;
133 static int hf_mgcp_param_connectionparam_or
;
134 static int hf_mgcp_param_connectionparam_pl
;
135 static int hf_mgcp_param_connectionparam_ji
;
136 static int hf_mgcp_param_connectionparam_la
;
137 static int hf_mgcp_param_connectionparam_pcrps
;
138 static int hf_mgcp_param_connectionparam_pcros
;
139 static int hf_mgcp_param_connectionparam_pcrpl
;
140 static int hf_mgcp_param_connectionparam_pcrji
;
141 static int hf_mgcp_param_connectionparam_x
;
142 static int hf_mgcp_param_reasoncode
;
143 static int hf_mgcp_param_eventstates
;
144 static int hf_mgcp_param_specificendpoint
;
145 static int hf_mgcp_param_secondendpointid
;
146 static int hf_mgcp_param_reqinfo
;
147 static int hf_mgcp_param_quarantinehandling
;
148 static int hf_mgcp_param_detectedevents
;
149 static int hf_mgcp_param_capabilities
;
150 static int hf_mgcp_param_maxmgcpdatagram
;
151 static int hf_mgcp_param_packagelist
;
152 static int hf_mgcp_param_extension
;
153 static int hf_mgcp_param_extension_critical
;
154 static int hf_mgcp_param_resourceid
;
155 static int hf_mgcp_param_invalid
;
156 static int hf_mgcp_messagecount
;
157 static int hf_mgcp_dup
;
158 static int hf_mgcp_req_dup
;
159 static int hf_mgcp_req_dup_frame
;
160 static int hf_mgcp_rsp_dup
;
161 static int hf_mgcp_rsp_dup_frame
;
162 static int hf_mgcp_param_x_osmux
;
163 static int hf_mgcp_unknown_parameter
;
164 static int hf_mgcp_malformed_parameter
;
166 static expert_field ei_mgcp_rsp_rspcode_invalid
;
168 static const value_string mgcp_return_code_vals
[] = {
169 {000, "Response Acknowledgement"},
170 {100, "The transaction is currently being executed. An actual completion message will follow on later."},
171 {101, "The transaction has been queued for execution. An actual completion message will follow later."},
172 {200, "The requested transaction was executed normally."},
173 {250, "The connection was deleted."},
174 {400, "The transaction could not be executed, due to a transient error."},
175 {401, "The phone is already off hook"},
176 {402, "The phone is already on hook"},
177 {403, "The transaction could not be executed, because the endpoint does not have sufficient resources at this time"},
178 {404, "Insufficient bandwidth at this time"},
179 {405, "The transaction could not be executed, because the endpoint is \"restarting\"."},
180 {406, "Transaction time-out. The transaction did not complete in a reasonable period of time and has been aborted."},
181 {407, "Transaction aborted. The transaction was aborted by some external action, e.g., a ModifyConnection command aborted by a DeleteConnection command."},
182 {409, "The transaction could not be executed because of internal overload."},
183 {410, "No endpoint available. A valid \"any of\" wildcard was used, however there was no endpoint available to satisfy the request."},
184 {500, "The transaction could not be executed, because the endpoint is unknown."},
185 {501, "The transaction could not be executed, because the endpoint is not ready."},
186 {502, "The transaction could not be executed, because the endpoint does not have sufficient resources"},
187 {503, "\"All of\" wildcard too complicated."},
188 {504, "Unknown or unsupported command."},
189 {505, "Unsupported RemoteConnectionDescriptor."},
190 {506, "Unable to satisfy both LocalConnectionOptions and RemoteConnectionDescriptor."},
191 {507, "Unsupported functionality."},
192 {508, "Unknown or unsupported quarantine handling."},
193 {509, "Error in RemoteConnectionDescriptor."},
194 {510, "The transaction could not be executed, because a protocol error was detected."},
195 {511, "The transaction could not be executed, because the command contained an unrecognized extension."},
196 {512, "The transaction could not be executed, because the gateway is not equipped to detect one of the requested events."},
197 {513, "The transaction could not be executed, because the gateway is not equipped to generate one of the requested signals."},
198 {514, "The transaction could not be executed, because the gateway cannot send the specified announcement."},
199 {515, "The transaction refers to an incorrect connection-id (may have been already deleted)"},
200 {516, "The transaction refers to an unknown call-id."},
201 {517, "Unsupported or invalid mode."},
202 {518, "Unsupported or unknown package."},
203 {519, "Endpoint does not have a digit map."},
204 {520, "The transaction could not be executed, because the endpoint is 'restarting'."},
205 {521, "Endpoint redirected to another Call Agent."},
206 {522, "No such event or signal."},
207 {523, "Unknown action or illegal combination of actions"},
208 {524, "Internal inconsistency in LocalConnectionOptions"},
209 {525, "Unknown extension in LocalConnectionOptions"},
210 {526, "Insufficient bandwidth"},
211 {527, "Missing RemoteConnectionDescriptor"},
212 {528, "Incompatible protocol version"},
213 {529, "Internal hardware failure"},
214 {530, "CAS signaling protocol error."},
215 {531, "failure of a grouping of trunks (e.g. facility failure)."},
216 {532, "Unsupported value(s) in LocalConnectionOptions."},
217 {533, "Response too large."},
218 {534, "Codec negotiation failure."},
219 {535, "Packetization period not supported"},
220 {536, "Unknown or unsupported RestartMethod"},
221 {537, "Unknown or unsupported digit map extension"},
222 {538, "Event/signal parameter error (e.g., missing, erroneous, unsupported, unknown, etc.)"},
223 {539, "Invalid or unsupported command parameter."},
224 {540, "Per endpoint connection limit exceeded."},
225 {541, "Invalid or unsupported LocalConnectionOptions"},
228 static value_string_ext mgcp_return_code_vals_ext
= VALUE_STRING_EXT_INIT(mgcp_return_code_vals
);
230 /* TODO: add/use when tested/have capture to test with */
232 static const value_string mgcp_reason_code_vals[] = {
233 {0, "Endpoint state is normal"},
234 {900, "Endpoint malfunctioning."},
235 {901, "Endpoint taken out-of-service."},
236 {902, "Loss of lower layer connectivity (e.g., downstream sync)."},
237 {903, "QoS resource reservation was lost."},
238 {904, "Manual intervention."},
239 {905, "Facility failure (e.g., DS-0 failure)."},
246 * Define the trees for mgcp
247 * We need one for MGCP itself, one for the MGCP paramters and one
248 * for each of the dissected parameters
251 static int ett_mgcp_param
;
252 static int ett_mgcp_param_connectionparam
;
253 static int ett_mgcp_param_localconnectionoptions
;
254 static int ett_mgcp_param_localvoicemetrics
;
255 static int ett_mgcp_param_remotevoicemetrics
;
258 * Define the tap for mgcp
263 * Here are the global variables associated with
264 * the various user definable characteristics of the dissection
266 * MGCP has two kinds of "agents", gateways and callagents. Callagents
267 * control gateways in a master/slave sort of arrangement. Since gateways
268 * and callagents have different well known ports and could both
269 * operate under either udp or tcp we have rather a lot of port info to
272 * global_mgcp_raw_text determines whether we are going to display
273 * the raw text of the mgcp message, much like the HTTP dissector does.
276 static unsigned global_mgcp_gateway_tcp_port
= TCP_PORT_MGCP_GATEWAY
;
277 static unsigned global_mgcp_gateway_udp_port
= UDP_PORT_MGCP_GATEWAY
;
278 static unsigned global_mgcp_callagent_tcp_port
= TCP_PORT_MGCP_CALLAGENT
;
279 static unsigned global_mgcp_callagent_udp_port
= UDP_PORT_MGCP_CALLAGENT
;
280 static bool global_mgcp_raw_text
;
281 static bool global_mgcp_message_count
;
283 /* Some basic utility functions that are specific to this dissector */
284 static bool is_mgcp_verb(tvbuff_t
*tvb
, int offset
, int maxlength
, const char **verb_name
);
285 static bool is_mgcp_rspcode(tvbuff_t
*tvb
, int offset
, int maxlength
);
286 static int tvb_parse_param(tvbuff_t
*tvb
, int offset
, int maxlength
, int** hf
, mgcp_info_t
* mi
);
289 * The various functions that either dissect some
290 * subpart of MGCP. These aren't really proto dissectors but they
291 * are written in the same style.
293 static void dissect_mgcp_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
294 proto_tree
*mgcp_tree
, proto_tree
*ti
);
295 static void dissect_mgcp_firstline(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, mgcp_info_t
* mi
);
296 static void dissect_mgcp_params(tvbuff_t
*tvb
, proto_tree
*tree
, mgcp_info_t
* mi
);
297 static void dissect_mgcp_connectionparams(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
298 int offset
, int param_type_len
,
300 static void dissect_mgcp_localconnectionoptions(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
301 int offset
, int param_type_len
,
303 static void dissect_mgcp_localvoicemetrics(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
304 int offset
, int param_type_len
,
306 static void dissect_mgcp_remotevoicemetrics(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
307 int offset
, int param_type_len
,
310 static void mgcp_raw_text_add(tvbuff_t
*tvb
, proto_tree
*tree
);
312 #define NUM_TIMESTATS 11
314 static const value_string mgcp_message_type
[] = {
328 static tap_packet_status
329 mgcpstat_packet(void *pms
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *pmi
, tap_flags_t flags _U_
)
331 rtd_data_t
* rtd_data
= (rtd_data_t
*)pms
;
332 rtd_stat_table
* ms
= &rtd_data
->stat_table
;
333 const mgcp_info_t
*mi
= (const mgcp_info_t
*)pmi
;
335 tap_packet_status ret
= TAP_PACKET_DONT_REDRAW
;
337 switch (mi
->mgcp_type
) {
340 if (mi
->is_duplicate
) {
341 /* Duplicate is ignored */
342 ms
->time_stats
[0].req_dup_num
++;
345 ms
->time_stats
[0].open_req_num
++;
350 if (mi
->is_duplicate
) {
351 /* Duplicate is ignored */
352 ms
->time_stats
[0].rsp_dup_num
++;
354 else if (!mi
->request_available
) {
355 /* no request was seen */
356 ms
->time_stats
[0].disc_rsp_num
++;
359 ms
->time_stats
[0].open_req_num
--;
360 /* calculate time delta between request and response */
361 nstime_delta(&delta
, &pinfo
->abs_ts
, &mi
->req_time
);
363 time_stat_update(&(ms
->time_stats
[0].rtd
[0]), &delta
, pinfo
);
365 if (g_ascii_strncasecmp(mi
->code
, "EPCF", 4) == 0 ) {
366 time_stat_update(&(ms
->time_stats
[0].rtd
[1]), &delta
, pinfo
);
368 else if (g_ascii_strncasecmp(mi
->code
, "CRCX", 4) == 0 ) {
369 time_stat_update(&(ms
->time_stats
[0].rtd
[2]), &delta
, pinfo
);
371 else if (g_ascii_strncasecmp(mi
->code
, "MDCX", 4) == 0 ) {
372 time_stat_update(&(ms
->time_stats
[0].rtd
[3]), &delta
, pinfo
);
374 else if (g_ascii_strncasecmp(mi
->code
, "DLCX", 4) == 0 ) {
375 time_stat_update(&(ms
->time_stats
[0].rtd
[4]), &delta
, pinfo
);
377 else if (g_ascii_strncasecmp(mi
->code
, "RQNT", 4) == 0 ) {
378 time_stat_update(&(ms
->time_stats
[0].rtd
[5]), &delta
, pinfo
);
380 else if (g_ascii_strncasecmp(mi
->code
, "NTFY", 4) == 0 ) {
381 time_stat_update(&(ms
->time_stats
[0].rtd
[6]), &delta
, pinfo
);
383 else if (g_ascii_strncasecmp(mi
->code
, "AUEP", 4) == 0 ) {
384 time_stat_update(&(ms
->time_stats
[0].rtd
[7]), &delta
, pinfo
);
386 else if (g_ascii_strncasecmp(mi
->code
, "AUCX", 4) == 0 ) {
387 time_stat_update(&(ms
->time_stats
[0].rtd
[8]), &delta
, pinfo
);
389 else if (g_ascii_strncasecmp(mi
->code
, "RSIP", 4) == 0 ) {
390 time_stat_update(&(ms
->time_stats
[0].rtd
[9]), &delta
, pinfo
);
393 time_stat_update(&(ms
->time_stats
[0].rtd
[10]), &delta
, pinfo
);
396 ret
= TAP_PACKET_REDRAW
;
409 * Some functions which should be moved to a library
410 * as I think that people may find them of general usefulness.
412 static int tvb_find_null_line(tvbuff_t
* tvb
, int offset
, int len
, int* next_offset
);
413 static int tvb_find_dot_line(tvbuff_t
* tvb
, int offset
, int len
, int* next_offset
);
415 static dissector_handle_t sdp_handle
;
416 static dissector_handle_t mgcp_handle
;
418 dissect_asciitpkt(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
419 dissector_handle_t subdissector_handle
);
420 extern uint16_t is_asciitpkt(tvbuff_t
*tvb
);
423 * Init Hash table stuff
426 typedef struct _mgcp_call_info_key
429 conversation_t
*conversation
;
430 } mgcp_call_info_key
;
432 static wmem_map_t
*mgcp_calls
;
435 static int mgcp_call_equal(const void *k1
, const void *k2
)
437 const mgcp_call_info_key
* key1
= (const mgcp_call_info_key
*) k1
;
438 const mgcp_call_info_key
* key2
= (const mgcp_call_info_key
*) k2
;
440 return (key1
->transid
== key2
->transid
&&
441 key1
->conversation
== key2
->conversation
);
444 /* Calculate a hash key */
445 static unsigned mgcp_call_hash(const void *k
)
447 const mgcp_call_info_key
* key
= (const mgcp_call_info_key
*) k
;
449 return key
->transid
+ key
->conversation
->conv_index
;
453 /************************************************************************
454 * dissect_mgcp - The dissector for the Media Gateway Control Protocol
455 ************************************************************************/
456 static int dissect_mgcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
459 uint32_t num_messages
;
460 int tvb_sectionend
, tvb_sectionbegin
, tvb_len
;
461 proto_tree
*mgcp_tree
= NULL
;
462 proto_item
*ti
= NULL
, *tii
;
463 const char *verb_name
= "";
465 /* Initialize variables */
467 tvb_sectionbegin
= tvb_sectionend
;
468 tvb_len
= tvb_reported_length(tvb
);
472 * Check to see whether we're really dealing with MGCP by looking
473 * for a valid MGCP verb or response code. This isn't infallible,
474 * but it's cheap and it's better than nothing.
476 if (!is_mgcp_verb(tvb
, 0, tvb_len
, &verb_name
) && !is_mgcp_rspcode(tvb
, 0, tvb_len
))
480 * Set the columns now, so that they'll be set correctly if we throw
481 * an exception. We can set them later as well....
483 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MGCP");
484 col_clear(pinfo
->cinfo
, COL_INFO
);
487 * Loop through however many mgcp messages may be stuck in
488 * this packet using piggybacking
494 /* Create our mgcp subtree */
495 ti
= proto_tree_add_item(tree
, proto_mgcp
, tvb
, 0, -1, ENC_NA
);
496 mgcp_tree
= proto_item_add_subtree(ti
, ett_mgcp
);
498 sectionlen
= tvb_find_dot_line(tvb
, tvb_sectionbegin
, -1, &tvb_sectionend
);
499 if (sectionlen
!= -1)
501 dissect_mgcp_message(tvb_new_subset_length_caplen(tvb
, tvb_sectionbegin
,
502 sectionlen
, sectionlen
),
503 pinfo
, tree
, mgcp_tree
, ti
);
504 tvb_sectionbegin
= tvb_sectionend
;
510 } while (tvb_sectionend
< tvb_len
);
512 tii
= proto_tree_add_uint(mgcp_tree
, hf_mgcp_messagecount
, tvb
,
513 0 , 0 , num_messages
);
514 proto_item_set_hidden(tii
);
517 * Add our column information after dissecting SDP
518 * in order to prevent the column info changing to reflect the SDP
519 * (when showing message count)
521 tvb_sectionbegin
= 0;
522 if (global_mgcp_message_count
== true )
524 if (num_messages
> 1)
526 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
, "MGCP (%i messages)", num_messages
);
530 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
, "MGCP (%i message)", num_messages
);
534 sectionlen
= tvb_find_line_end(tvb
, tvb_sectionbegin
, -1,
535 &tvb_sectionend
, false);
536 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "%s",
537 tvb_format_text(pinfo
->pool
, tvb
, tvb_sectionbegin
, sectionlen
));
542 /************************************************************************
543 * dissect_tpkt_mgcp - The dissector for the ASCII TPKT Media Gateway Control Protocol
544 ************************************************************************/
545 static int dissect_tpkt_mgcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
550 /* Check whether this looks like a ASCII TPKT-encapsulated
553 ascii_tpkt
= is_asciitpkt(tvb
);
555 if (ascii_tpkt
!= 1 )
558 * It's not a ASCII TPKT packet
561 offset
= dissect_mgcp(tvb
, pinfo
, tree
, NULL
);
566 * Dissect ASCII TPKT header
568 dissect_asciitpkt(tvb
, pinfo
, tree
, mgcp_handle
);
569 offset
= tvb_reported_length(tvb
);
575 /* Dissect an individual MGCP message */
576 static void dissect_mgcp_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
577 proto_tree
*mgcp_tree
, proto_tree
*ti
)
579 /* Declare variables */
581 int tvb_sectionend
, tvb_sectionbegin
, tvb_len
;
583 const char *verb_name
= "";
584 mgcp_info_t
* mi
= wmem_new0(pinfo
->pool
, mgcp_info_t
);
585 sdp_setup_info_t setup_info
= { .hf_id
= 0, .hf_type
= SDP_TRACE_ID_HF_TYPE_UINT32
};
586 media_content_info_t content_info
= { MEDIA_CONTAINER_SIP_DATA
, NULL
, NULL
, &setup_info
};
588 mi
->mgcp_type
= MGCP_OTHERS
;
590 /* Initialize variables */
591 tvb_len
= tvb_reported_length(tvb
);
594 * Check to see whether we're really dealing with MGCP by looking
595 * for a valid MGCP verb or response code. This isn't infallible,
596 * but it's cheap and it's better than nothing.
598 if (is_mgcp_verb(tvb
, 0, tvb_len
, &verb_name
) || is_mgcp_rspcode(tvb
, 0, tvb_len
))
600 /* dissect first line */
601 tvb_sectionbegin
= 0;
602 tvb_sectionend
= tvb_sectionbegin
;
603 sectionlen
= tvb_find_line_end(tvb
, 0, -1, &tvb_sectionend
, false);
606 dissect_mgcp_firstline(tvb_new_subset_length_caplen(tvb
, tvb_sectionbegin
,
607 sectionlen
, sectionlen
), pinfo
,
610 tvb_sectionbegin
= tvb_sectionend
;
613 if (tvb_sectionbegin
< tvb_len
)
615 sectionlen
= tvb_find_null_line(tvb
, tvb_sectionbegin
, -1,
619 dissect_mgcp_params(tvb_new_subset_length_caplen(tvb
, tvb_sectionbegin
, sectionlen
, sectionlen
),
624 /* Set the mgcp payload length correctly so we don't include any
626 sectionlen
= tvb_sectionend
;
627 proto_item_set_len(ti
, sectionlen
);
629 /* Display the raw text of the mgcp message if desired */
631 /* Do we want to display the raw text of our MGCP packet? */
632 if (global_mgcp_raw_text
)
634 mgcp_raw_text_add(tvb
, mgcp_tree
);
637 /* Dissect sdp payload */
638 if (tvb_sectionend
< tvb_len
)
640 setup_info
.is_osmux
= mi
->is_osmux
;
641 next_tvb
= tvb_new_subset_remaining(tvb
, tvb_sectionend
);
642 call_dissector_with_data(sdp_handle
, next_tvb
, pinfo
, tree
, &content_info
);
649 * Add the raw text of the message to the dissect tree if appropriate
650 * preferences are specified.
652 static void mgcp_raw_text_add(tvbuff_t
*tvb
, proto_tree
*tree
)
654 int tvb_linebegin
, tvb_lineend
, linelen
;
660 tvb_find_line_end(tvb
, tvb_linebegin
, -1, &tvb_lineend
, false);
661 linelen
= tvb_lineend
- tvb_linebegin
;
662 proto_tree_add_format_text(tree
, tvb
, tvb_linebegin
, linelen
);
663 tvb_linebegin
= tvb_lineend
;
664 } while (tvb_offset_exists(tvb
, tvb_lineend
));
668 * is_mgcp_verb - A function for determining whether there is a
669 * MGCP verb at offset in tvb
672 * tvb - The tvbuff in which we are looking for an MGCP verb
673 * offset - The offset in tvb at which we are looking for a MGCP verb
674 * maxlength - The maximum distance from offset we may look for the
675 * characters that make up a MGCP verb.
676 * verb_name - The name for the verb code found (output)
678 * Return: true if there is an MGCP verb at offset in tvb, otherwise false
680 static bool is_mgcp_verb(tvbuff_t
*tvb
, int offset
, int maxlength
, const char **verb_name
)
682 bool returnvalue
= false;
685 /* This function is used for checking if a packet is actually an
686 mgcp packet. Make sure that we do not throw an exception
687 during such a check. If we did throw an exeption, we could
688 not refuse the packet and give other dissectors the chance to
690 if (tvb_captured_length_remaining(tvb
, offset
) < (int)sizeof(word
))
693 /* Read the string into 'word' and see if it looks like the start of a verb */
694 if ((maxlength
>= 4) && tvb_get_raw_bytes_as_string(tvb
, offset
, word
, sizeof word
))
696 if (((g_ascii_strncasecmp(word
, "EPCF", 4) == 0) && (*verb_name
= "EndpointConfiguration")) ||
697 ((g_ascii_strncasecmp(word
, "CRCX", 4) == 0) && (*verb_name
= "CreateConnection")) ||
698 ((g_ascii_strncasecmp(word
, "MDCX", 4) == 0) && (*verb_name
= "ModifyConnection")) ||
699 ((g_ascii_strncasecmp(word
, "DLCX", 4) == 0) && (*verb_name
= "DeleteConnection")) ||
700 ((g_ascii_strncasecmp(word
, "RQNT", 4) == 0) && (*verb_name
= "NotificationRequest")) ||
701 ((g_ascii_strncasecmp(word
, "NTFY", 4) == 0) && (*verb_name
= "Notify")) ||
702 ((g_ascii_strncasecmp(word
, "AUEP", 4) == 0) && (*verb_name
= "AuditEndpoint")) ||
703 ((g_ascii_strncasecmp(word
, "AUCX", 4) == 0) && (*verb_name
= "AuditConnection")) ||
704 ((g_ascii_strncasecmp(word
, "RSIP", 4) == 0) && (*verb_name
= "RestartInProgress")) ||
705 ((g_ascii_strncasecmp(word
, "MESG", 4) == 0) && (*verb_name
= "Message")) ||
706 (word
[0] == 'X' && g_ascii_isalpha(word
[1]) && g_ascii_isalpha(word
[2]) &&
707 g_ascii_isalpha(word
[3]) && (*verb_name
= "*Experimental*")))
713 /* May be whitespace after verb code - anything else is an error.. */
714 if (returnvalue
&& maxlength
>= 5)
716 char next
= tvb_get_uint8(tvb
, 4);
717 if ((next
!= ' ') && (next
!= '\t'))
727 * is_mgcp_rspcode - A function for determining whether something which
728 * looks roughly like a MGCP response code (3-digit number)
729 * is at 'offset' in tvb
732 * tvb - The tvbuff in which we are looking for an MGCP response code
733 * offset - The offset in tvb at which we are looking for a MGCP response code
734 * maxlength - The maximum distance from offset we may look for the
735 * characters that make up a MGCP response code.
737 * Return: true if there is an MGCP response code at offset in tvb,
740 static bool is_mgcp_rspcode(tvbuff_t
*tvb
, int offset
, int maxlength
)
742 bool returnvalue
= false;
745 /* see the comment in is_mgcp_verb() */
746 if (tvb_captured_length_remaining(tvb
, offset
) < (int)sizeof(word
))
749 /* Do 1st 3 characters look like digits? */
752 tvb_get_raw_bytes_as_string(tvb
, offset
, word
, sizeof word
);
753 if (g_ascii_isdigit(word
[0]) && g_ascii_isdigit(word
[1]) && g_ascii_isdigit(word
[2]))
759 /* Maybe some white space after the 3rd digit - anything else is an error */
760 if (returnvalue
&& maxlength
>= 4)
762 char next
= tvb_get_uint8(tvb
, 3);
763 if ((next
!= ' ') && (next
!= '\t'))
773 * tvb_parse_param - Parse the MGCP param into a type and a value.
776 * tvb - The tvbuff containing the MGCP param we are to parse.
777 * offset - The offset in tvb at which we will begin looking for a
778 * MGCP parameter to parse.
779 * len - The maximum distance from offset in tvb that we can look for
780 * an MGCP parameter to parse.
781 * hf - The place to write a pointer to the integer representing the
782 * header field associated with the MGCP parameter parsed.
784 * Returns: The offset in tvb where the value of the MGCP parameter
787 static int tvb_parse_param(tvbuff_t
* tvb
, int offset
, int len
, int** hf
, mgcp_info_t
* mi
)
789 int returnvalue
= -1, tvb_current_offset
, ext_off
;
790 uint8_t tempchar
, plus_minus
;
793 tvb_current_offset
= offset
;
799 tempchar
= (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
));
804 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
806 *hf
= &hf_mgcp_param_invalid
;
809 *hf
= &hf_mgcp_param_rspack
;
812 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
814 *hf
= &hf_mgcp_param_invalid
;
817 *hf
= &hf_mgcp_param_bearerinfo
;
820 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
822 *hf
= &hf_mgcp_param_invalid
;
825 *hf
= &hf_mgcp_param_callid
;
828 tvb_current_offset
++;
829 if (len
> (tvb_current_offset
- offset
) &&
830 (tempchar
= tvb_get_uint8(tvb
, tvb_current_offset
)) == ':')
832 *hf
= &hf_mgcp_param_connectionid
;
833 tvb_current_offset
--;
838 *hf
= &hf_mgcp_param_secondconnectionid
;
842 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
844 *hf
= &hf_mgcp_param_invalid
;
847 *hf
= &hf_mgcp_param_notifiedentity
;
851 tvb_current_offset
++;
853 /* X: is RequestIdentifier */
854 if (len
> (tvb_current_offset
- offset
) &&
855 (tempchar
= tvb_get_uint8(tvb
, tvb_current_offset
)) == ':')
857 *hf
= &hf_mgcp_param_requestid
;
858 tvb_current_offset
--;
862 if (len
> (tvb_current_offset
- offset
) &&
863 ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
,tvb_current_offset
))) == 'R')
866 tvb_current_offset
+= 3;
867 if (len
> (tvb_current_offset
- offset
) &&
868 ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
,tvb_current_offset
))) == 'R')
870 *hf
= &hf_mgcp_param_remotevoicemetrics
;
873 if (len
> (tvb_current_offset
- offset
) &&
874 ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
,tvb_current_offset
))) == 'L')
876 *hf
= &hf_mgcp_param_localvoicemetrics
;
878 tvb_current_offset
-= 4;
881 /* X+...: or X-....: are vendor extension parameters */
883 if (len
> (tvb_current_offset
- offset
) &&
884 ((plus_minus
= tvb_get_uint8(tvb
, tvb_current_offset
)) == '-' ||
885 (plus_minus
== '+')))
887 /* Move past + or - */
888 tvb_current_offset
++;
890 /* Keep going, through possible vendor param name */
891 /* We have a mempbrk; perhaps an equivalent of strspn
892 * for tvbs would be useful.
894 for (ext_off
= 0; len
> (ext_off
+ tvb_current_offset
-offset
); ext_off
++) {
895 tempchar
= tvb_get_uint8(tvb
, tvb_current_offset
+ ext_off
);
896 if (!g_ascii_isalpha(tempchar
) && !g_ascii_isdigit(tempchar
)) break;
901 /* Looks like a valid vendor param name */
902 //fprintf(stderr, "MGCP Extension: %s\n", tvb_get_string_enc(wmem_packet_scope(), tvb, tvb_current_offset, ext_off, ENC_ASCII));
906 *hf
= &hf_mgcp_param_extension_critical
;
909 if (tvb_strncaseeql(tvb
, tvb_current_offset
, "OSMUX", ext_off
) == 0) {
910 *hf
= &hf_mgcp_param_x_osmux
;
912 *hf
= &hf_mgcp_param_extension
;
916 /* -1: Final generic path below expects us to point to char before the ':'. */
917 tvb_current_offset
+= ext_off
- 1;
922 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
924 *hf
= &hf_mgcp_param_invalid
;
927 *hf
= &hf_mgcp_param_localconnoptions
;
930 tvb_current_offset
++;
931 if (len
> (tvb_current_offset
- offset
) &&
932 (tempchar
= (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
))) == ':')
934 *hf
= &hf_mgcp_param_connectionmode
;
935 tvb_current_offset
--;
940 *hf
= &hf_mgcp_param_maxmgcpdatagram
;
944 tvb_current_offset
++;
945 if (len
> (tvb_current_offset
- offset
) &&
946 (tempchar
= (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
))) == ':')
948 *hf
= &hf_mgcp_param_reqevents
;
949 tvb_current_offset
--;
952 if ( tempchar
== 'M')
954 *hf
= &hf_mgcp_param_restartmethod
;
959 *hf
= &hf_mgcp_param_restartdelay
;
963 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
965 *hf
= &hf_mgcp_param_invalid
;
968 *hf
= &hf_mgcp_param_signalreq
;
969 buf
= &(mi
->signalReq
);
972 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
974 if (len
> (tvb_current_offset
+ 5 - offset
) &&
975 (g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
+ 1) == 'Q')) &&
976 ( tvb_get_uint8(tvb
, tvb_current_offset
+ 2) == '-' ) &&
977 (g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
+ 3) == 'R')) &&
978 (g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
+ 4) == 'I')) &&
979 ( tvb_get_uint8(tvb
, tvb_current_offset
+ 5) == ':' )
981 tvb_current_offset
+=4;
982 *hf
= &hf_mgcp_param_resourceid
;
986 *hf
= &hf_mgcp_param_invalid
;
989 *hf
= &hf_mgcp_param_digitmap
;
990 mi
->hasDigitMap
= true;
993 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
995 *hf
= &hf_mgcp_param_invalid
;
998 *hf
= &hf_mgcp_param_observedevent
;
999 buf
= &(mi
->observedEvents
);
1002 tvb_current_offset
++;
1003 if (len
> (tvb_current_offset
- offset
) &&
1004 (tempchar
= (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
))) == ':')
1006 *hf
= &hf_mgcp_param_connectionparam
;
1007 tvb_current_offset
--;
1010 if ( tempchar
== 'L')
1012 *hf
= &hf_mgcp_param_packagelist
;
1016 tvb_current_offset
++;
1017 if (len
> (tvb_current_offset
- offset
) &&
1018 (tempchar
= (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
))) == ':')
1020 *hf
= &hf_mgcp_param_reasoncode
;
1021 tvb_current_offset
--;
1024 if ( tempchar
== 'S')
1026 *hf
= &hf_mgcp_param_eventstates
;
1030 tvb_current_offset
++;
1031 if (len
> (tvb_current_offset
- offset
) &&
1032 (tempchar
= (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb
, tvb_current_offset
))) == ':')
1034 *hf
= &hf_mgcp_param_specificendpoint
;
1035 tvb_current_offset
--;
1038 if (tempchar
== '2')
1040 *hf
= &hf_mgcp_param_secondendpointid
;
1044 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
1046 *hf
= &hf_mgcp_param_invalid
;
1049 *hf
= &hf_mgcp_param_reqinfo
;
1052 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
1054 *hf
= &hf_mgcp_param_invalid
;
1057 *hf
= &hf_mgcp_param_quarantinehandling
;
1060 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
1062 *hf
= &hf_mgcp_param_invalid
;
1065 *hf
= &hf_mgcp_param_detectedevents
;
1068 if (tvb_get_uint8(tvb
, tvb_current_offset
+1) != ':')
1070 *hf
= &hf_mgcp_param_invalid
;
1073 *hf
= &hf_mgcp_param_capabilities
;
1077 *hf
= &hf_mgcp_param_invalid
;
1081 /* Move to (hopefully) the colon */
1082 tvb_current_offset
++;
1084 /* Add a recognised parameter type if we have one */
1085 if (*hf
!= NULL
&& len
> (tvb_current_offset
- offset
) &&
1086 tvb_get_uint8(tvb
, tvb_current_offset
) == ':')
1088 tvb_current_offset
++;
1089 tvb_current_offset
= tvb_skip_wsp(tvb
, tvb_current_offset
, (len
- tvb_current_offset
+ offset
));
1090 returnvalue
= tvb_current_offset
;
1092 /* set the observedEvents or signalReq used in Voip Calls analysis */
1094 *buf
= tvb_get_string_enc(wmem_packet_scope(), tvb
, tvb_current_offset
, (len
- tvb_current_offset
+ offset
), ENC_ASCII
);
1100 /* Was an empty line */
1101 *hf
= &hf_mgcp_param_invalid
;
1104 /* For these types, show the whole line */
1105 if ((*hf
== &hf_mgcp_param_invalid
) ||
1106 (*hf
== &hf_mgcp_param_extension
) || (*hf
== &hf_mgcp_param_extension_critical
) ||
1107 (*hf
== &hf_mgcp_param_localvoicemetrics
) || (*hf
== &hf_mgcp_param_remotevoicemetrics
))
1109 returnvalue
= offset
;
1117 * dissect_mgcp_firstline - Dissects the firstline of an MGCP message.
1118 * Adds the appropriate headers fields to
1119 * tree for the dissection of the first line
1120 * of an MGCP message.
1123 * tvb - The tvb containing the first line of an MGCP message. This
1124 * tvb is presumed to ONLY contain the first line of the MGCP
1126 * pinfo - The packet info for the packet. This is not really used
1127 * by this function but is passed through so as to retain the
1128 * style of a dissector.
1129 * tree - The tree from which to hang the structured information parsed
1130 * from the first line of the MGCP message.
1132 static void dissect_mgcp_firstline(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, mgcp_info_t
* mi
)
1134 int tvb_current_offset
, tvb_previous_offset
, tvb_len
, tvb_current_len
;
1135 int tokennum
, tokenlen
;
1136 proto_item
* hidden_item
;
1137 char *transid
= NULL
;
1139 char *endpointId
= NULL
;
1140 mgcp_type_t mgcp_type
= MGCP_OTHERS
;
1141 conversation_t
* conversation
;
1142 mgcp_call_info_key mgcp_call_key
;
1143 mgcp_call_info_key
*new_mgcp_call_key
= NULL
;
1144 mgcp_call_t
*mgcp_call
= NULL
;
1146 const char *verb_description
= "";
1147 char code_with_verb
[64] = ""; /* To fit "<4-letter-code> (<longest-verb>)" */
1150 static address null_address
= ADDRESS_INIT_NONE
;
1151 tvb_previous_offset
= 0;
1152 tvb_len
= tvb_reported_length(tvb
);
1153 tvb_current_offset
= tvb_previous_offset
;
1154 mi
->is_duplicate
= false;
1155 mi
->request_available
= false;
1163 tvb_current_len
= tvb_reported_length_remaining(tvb
, tvb_previous_offset
);
1164 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_previous_offset
, tvb_current_len
, ' ');
1165 if (tvb_current_offset
== -1)
1167 tvb_current_offset
= tvb_len
;
1168 tokenlen
= tvb_current_len
;
1172 tokenlen
= tvb_current_offset
- tvb_previous_offset
;
1178 /* XXX - exception */
1182 code
= tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
, tokenlen
);
1183 (void) g_strlcpy(mi
->code
, code
, 5);
1184 if (is_mgcp_verb(tvb
, tvb_previous_offset
, tvb_current_len
, &verb_description
))
1186 mgcp_type
= MGCP_REQUEST
;
1187 if (verb_description
!= NULL
)
1189 /* Can show verb along with code if known */
1190 snprintf(code_with_verb
, 64, "%s (%s)", code
, verb_description
);
1193 proto_tree_add_string_format(tree
, hf_mgcp_req_verb
, tvb
,
1194 tvb_previous_offset
, tokenlen
,
1196 strlen(code_with_verb
) ? code_with_verb
: code
);
1199 if (is_mgcp_rspcode(tvb
, tvb_previous_offset
, tvb_current_len
))
1202 mgcp_type
= MGCP_RESPONSE
;
1203 rspcode_valid
= ws_strtou32(code
, NULL
, &mi
->rspcode
);
1204 pi
= proto_tree_add_uint(tree
, hf_mgcp_rsp_rspcode
, tvb
,
1205 tvb_previous_offset
, tokenlen
, mi
->rspcode
);
1207 expert_add_info(pinfo
, pi
, &ei_mgcp_rsp_rspcode_invalid
);
1216 transid
= tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
, tokenlen
);
1217 /* XXX - what if this isn't a valid text string? */
1218 mi
->transid
= (uint32_t)strtoul(transid
, NULL
, 10);
1219 proto_tree_add_string(tree
, hf_mgcp_transid
, tvb
,
1220 tvb_previous_offset
, tokenlen
, transid
);
1224 if (mgcp_type
== MGCP_REQUEST
)
1226 endpointId
= tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
, tokenlen
);
1227 mi
->endpointId
= wmem_strdup(pinfo
->pool
, endpointId
);
1228 proto_tree_add_string(tree
, hf_mgcp_req_endpoint
, tvb
,
1229 tvb_previous_offset
, tokenlen
, endpointId
);
1232 if (mgcp_type
== MGCP_RESPONSE
)
1234 if (tvb_current_offset
< tvb_len
)
1236 tokenlen
= tvb_find_line_end(tvb
, tvb_previous_offset
,
1237 -1, &tvb_current_offset
, false);
1241 tokenlen
= tvb_current_len
;
1243 proto_tree_add_string(tree
, hf_mgcp_rsp_rspstring
, tvb
,
1244 tvb_previous_offset
, tokenlen
,
1245 tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
,
1251 if ((tokennum
== 3 && mgcp_type
== MGCP_REQUEST
))
1253 if (tvb_current_offset
< tvb_len
)
1255 tokenlen
= tvb_find_line_end(tvb
, tvb_previous_offset
,
1256 -1, &tvb_current_offset
, false);
1260 tokenlen
= tvb_current_len
;
1262 proto_tree_add_string(tree
, hf_mgcp_version
, tvb
,
1263 tvb_previous_offset
, tokenlen
,
1264 tvb_format_text(pinfo
->pool
, tvb
, tvb_previous_offset
,
1268 if (tvb_current_offset
< tvb_len
)
1270 tvb_previous_offset
= tvb_skip_wsp(tvb
, tvb_current_offset
,
1274 } while (tvb_current_offset
< tvb_len
&& tvb_offset_exists(tvb
, tvb_current_offset
) && tvb_previous_offset
< tvb_len
&& tokennum
<= 3);
1279 hidden_item
= proto_tree_add_boolean(tree
, hf_mgcp_rsp
, tvb
, 0, 0, true);
1280 proto_item_set_hidden(hidden_item
);
1281 /* Check for MGCP response. A response must match a call that
1282 we've seen, and the response must be sent to the same
1283 port and address that the call came from, and must
1284 come from the port to which the call was sent.
1286 If the transport is connection-oriented (we check, for
1287 now, only for "pinfo->ptype" of PT_TCP), we take
1288 into account the address from which the call was sent
1289 and the address to which the call was sent, because
1290 the addresses of the two endpoints should be the same
1291 for all calls and replies.
1293 If the transport is connectionless, we don't worry
1294 about the address to which the call was sent and from
1295 which the reply was sent, because there's no
1296 guarantee that the reply will come from the address
1297 to which the call was sent. */
1298 if (pinfo
->ptype
== PT_TCP
)
1300 conversation
= find_conversation_pinfo(pinfo
, 0);
1304 /* XXX - can we just use NO_ADDR_B? Unfortunately,
1305 * you currently still have to pass a non-null
1306 * pointer for the second address argument even
1309 conversation
= find_conversation(pinfo
->num
, &null_address
,
1310 &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
), pinfo
->srcport
,
1311 pinfo
->destport
, 0);
1313 if (conversation
!= NULL
)
1315 /* Look only for matching request, if
1316 matching conversation is available. */
1317 mgcp_call_key
.transid
= mi
->transid
;
1318 mgcp_call_key
.conversation
= conversation
;
1319 mgcp_call
= (mgcp_call_t
*)wmem_map_lookup(mgcp_calls
, &mgcp_call_key
);
1322 /* Indicate the frame to which this is a reply. */
1323 if (mgcp_call
->req_num
)
1326 mi
->request_available
= true;
1327 mgcp_call
->responded
= true;
1328 mi
->req_num
= mgcp_call
->req_num
;
1329 (void) g_strlcpy(mi
->code
, mgcp_call
->code
, 5);
1330 item
= proto_tree_add_uint_format(tree
, hf_mgcp_req_frame
,
1331 tvb
, 0, 0, mgcp_call
->req_num
,
1332 "This is a response to a request in frame %u",
1333 mgcp_call
->req_num
);
1334 proto_item_set_generated(item
);
1335 nstime_delta(&delta
, &pinfo
->abs_ts
, &mgcp_call
->req_time
);
1336 item
= proto_tree_add_time(tree
, hf_mgcp_time
, tvb
, 0, 0, &delta
);
1337 proto_item_set_generated(item
);
1340 if (mgcp_call
->rsp_num
== 0)
1342 /* We have not yet seen a response to that call, so
1343 this must be the first response; remember its
1345 mgcp_call
->rsp_num
= pinfo
->num
;
1349 /* We have seen a response to this call - but was it
1350 *this* response? (disregard provisional responses) */
1351 if ((mgcp_call
->rsp_num
!= pinfo
->num
) &&
1352 (mi
->rspcode
>= 200) &&
1353 (mi
->rspcode
== mgcp_call
->rspcode
))
1357 /* No, so it's a duplicate response. Mark it as such. */
1358 mi
->is_duplicate
= true;
1359 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
1360 ", Duplicate Response %u",
1363 item
= proto_tree_add_uint(tree
, hf_mgcp_dup
, tvb
, 0, 0, mi
->transid
);
1364 proto_item_set_hidden(item
);
1365 item
= proto_tree_add_uint(tree
, hf_mgcp_rsp_dup
,
1366 tvb
, 0, 0, mi
->transid
);
1367 proto_item_set_generated(item
);
1368 item
= proto_tree_add_uint(tree
, hf_mgcp_rsp_dup_frame
,
1369 tvb
, 0, 0, mgcp_call
->rsp_num
);
1370 proto_item_set_generated(item
);
1373 /* Now store the response code (after comparison above) */
1374 mgcp_call
->rspcode
= mi
->rspcode
;
1379 hidden_item
= proto_tree_add_boolean(tree
, hf_mgcp_req
, tvb
, 0, 0, true);
1380 proto_item_set_hidden(hidden_item
);
1381 /* Keep track of the address and port whence the call came,
1382 * and the port to which the call is being sent, so that
1383 * we can match up calls with replies.
1385 * If the transport is connection-oriented (we check, for
1386 * now, only for "pinfo->ptype" of PT_TCP), we take
1387 * into account the address from which the call was sent
1388 * and the address to which the call was sent, because
1389 * the addresses of the two endpoints should be the same
1390 * for all calls and replies.
1392 * If the transport is connectionless, we don't worry
1393 * about the address to which the call was sent and from
1394 * which the reply was sent, because there's no
1395 * guarantee that the reply will come from the address
1396 * to which the call was sent.
1398 if (pinfo
->ptype
== PT_TCP
)
1400 conversation
= find_conversation_pinfo(pinfo
, 0);
1405 * XXX - can we just use NO_ADDR_B? Unfortunately,
1406 * you currently still have to pass a non-null
1407 * pointer for the second address argument even
1410 conversation
= find_conversation(pinfo
->num
, &pinfo
->src
,
1411 &null_address
, conversation_pt_to_conversation_type(pinfo
->ptype
), pinfo
->srcport
,
1412 pinfo
->destport
, 0);
1414 if (conversation
== NULL
)
1416 /* It's not part of any conversation - create a new one. */
1417 if (pinfo
->ptype
== PT_TCP
)
1419 conversation
= conversation_new(pinfo
->num
, &pinfo
->src
,
1420 &pinfo
->dst
, CONVERSATION_TCP
, pinfo
->srcport
,
1421 pinfo
->destport
, 0);
1425 conversation
= conversation_new(pinfo
->num
, &pinfo
->src
,
1426 &null_address
, conversation_pt_to_conversation_type(pinfo
->ptype
), pinfo
->srcport
,
1427 pinfo
->destport
, 0);
1431 /* Prepare the key data */
1432 mgcp_call_key
.transid
= mi
->transid
;
1433 mgcp_call_key
.conversation
= conversation
;
1435 /* Look up the request */
1436 mgcp_call
= (mgcp_call_t
*)wmem_map_lookup(mgcp_calls
, &mgcp_call_key
);
1437 if (mgcp_call
!= NULL
)
1439 /* We've seen a request with this TRANSID, with the same
1440 source and destination, before - but was it
1442 if (pinfo
->num
!= mgcp_call
->req_num
)
1444 /* No, so it's a duplicate request. Mark it as such. */
1445 mi
->is_duplicate
= true;
1446 mi
->req_num
= mgcp_call
->req_num
;
1447 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
1448 ", Duplicate Request %u",
1453 item
= proto_tree_add_uint(tree
, hf_mgcp_dup
, tvb
, 0, 0, mi
->transid
);
1454 proto_item_set_hidden(item
);
1455 item
= proto_tree_add_uint(tree
, hf_mgcp_req_dup
, tvb
, 0, 0, mi
->transid
);
1456 proto_item_set_generated(item
);
1457 item
= proto_tree_add_uint(tree
, hf_mgcp_req_dup_frame
, tvb
, 0, 0, mi
->req_num
);
1458 proto_item_set_generated(item
);
1464 /* Prepare the value data.
1465 "req_num" and "rsp_num" are frame numbers;
1466 frame numbers are 1-origin, so we use 0
1467 to mean "we don't yet know in which frame
1468 the reply for this call appears". */
1469 new_mgcp_call_key
= (mgcp_call_info_key
*)wmem_alloc(wmem_file_scope(), sizeof(*new_mgcp_call_key
));
1470 *new_mgcp_call_key
= mgcp_call_key
;
1471 mgcp_call
= (mgcp_call_t
*)wmem_alloc(wmem_file_scope(), sizeof(*mgcp_call
));
1472 mgcp_call
->req_num
= pinfo
->num
;
1473 mgcp_call
->rsp_num
= 0;
1474 mgcp_call
->transid
= mi
->transid
;
1475 mgcp_call
->responded
= false;
1476 mgcp_call
->req_time
=pinfo
->abs_ts
;
1477 (void) g_strlcpy(mgcp_call
->code
, mi
->code
, 5);
1480 wmem_map_insert(mgcp_calls
, new_mgcp_call_key
, mgcp_call
);
1482 if (mgcp_call
->rsp_num
)
1484 proto_item
* item
= proto_tree_add_uint_format(tree
, hf_mgcp_rsp_frame
,
1485 tvb
, 0, 0, mgcp_call
->rsp_num
,
1486 "The response to this request is in frame %u",
1487 mgcp_call
->rsp_num
);
1488 proto_item_set_generated(item
);
1495 mi
->mgcp_type
= mgcp_type
;
1498 mi
->req_time
.secs
=mgcp_call
->req_time
.secs
;
1499 mi
->req_time
.nsecs
=mgcp_call
->req_time
.nsecs
;
1503 tap_queue_packet(mgcp_tap
, pinfo
, mi
);
1507 * dissect_mgcp_params - Dissects the parameters of an MGCP message.
1508 * Adds the appropriate headers fields to
1509 * tree for the dissection of the parameters
1510 * of an MGCP message.
1513 * tvb - The tvb containing the parameters of an MGCP message. This
1514 * tvb is presumed to ONLY contain the part of the MGCP
1515 * message which contains the MGCP parameters.
1516 * tree - The tree from which to hang the structured information parsed
1517 * from the parameters of the MGCP message.
1519 static void dissect_mgcp_params(tvbuff_t
*tvb
, proto_tree
*tree
, mgcp_info_t
* mi
)
1521 int linelen
, tokenlen
, *my_param
;
1522 int tvb_lineend
, tvb_linebegin
, tvb_len
, old_lineend
;
1524 proto_tree
*mgcp_param_ti
, *mgcp_param_tree
;
1526 tvb_len
= tvb_reported_length(tvb
);
1528 tvb_lineend
= tvb_linebegin
;
1530 mgcp_param_ti
= proto_tree_add_item(tree
, hf_mgcp_params
, tvb
,
1531 tvb_linebegin
, tvb_len
, ENC_NA
);
1532 proto_item_set_text(mgcp_param_ti
, "Parameters");
1533 mgcp_param_tree
= proto_item_add_subtree(mgcp_param_ti
, ett_mgcp_param
);
1535 /* Parse the parameters */
1536 while (tvb_offset_exists(tvb
, tvb_lineend
))
1538 old_lineend
= tvb_lineend
;
1539 linelen
= tvb_find_line_end(tvb
, tvb_linebegin
, -1, &tvb_lineend
, false);
1540 tvb_tokenbegin
= tvb_parse_param(tvb
, tvb_linebegin
, linelen
, &my_param
, mi
);
1544 tokenlen
= tvb_find_line_end(tvb
, tvb_tokenbegin
, -1, &tvb_lineend
, false);
1545 if (*my_param
== hf_mgcp_param_connectionparam
) {
1546 dissect_mgcp_connectionparams(mgcp_param_tree
, tvb
, tvb_linebegin
,
1547 tvb_tokenbegin
- tvb_linebegin
, tokenlen
);
1548 } else if (*my_param
== hf_mgcp_param_localconnoptions
) {
1549 dissect_mgcp_localconnectionoptions(mgcp_param_tree
, tvb
, tvb_linebegin
,
1550 tvb_tokenbegin
- tvb_linebegin
, tokenlen
);
1551 } else if (*my_param
== hf_mgcp_param_localvoicemetrics
) {
1552 dissect_mgcp_localvoicemetrics(mgcp_param_tree
, tvb
, tvb_linebegin
,
1553 tvb_tokenbegin
- tvb_linebegin
, tokenlen
);
1554 } else if (*my_param
== hf_mgcp_param_remotevoicemetrics
) {
1555 dissect_mgcp_remotevoicemetrics(mgcp_param_tree
, tvb
, tvb_linebegin
,
1556 tvb_tokenbegin
- tvb_linebegin
, tokenlen
);
1557 } else if (*my_param
== hf_mgcp_param_x_osmux
) {
1558 proto_tree_add_string(mgcp_param_tree
, *my_param
, tvb
,
1559 tvb_linebegin
, linelen
,
1560 tvb_format_text(wmem_packet_scope(),
1561 tvb
, tvb_tokenbegin
, tokenlen
));
1562 /* Mark that Osmux is used, so that packet-sdp.c doesn't call
1563 * srtp_add_address() and decodes it as RTP. */
1564 mi
->is_osmux
= true;
1566 proto_tree_add_string(mgcp_param_tree
, *my_param
, tvb
,
1567 tvb_linebegin
, linelen
,
1568 tvb_format_text(wmem_packet_scope(),
1569 tvb
, tvb_tokenbegin
, tokenlen
));
1573 tvb_linebegin
= tvb_lineend
;
1574 /* Its a infinite loop if we didn't advance (or went backwards) */
1575 if (old_lineend
>= tvb_lineend
)
1577 /* XXX - exception */
1583 /* Dissect the connection params */
1585 dissect_mgcp_connectionparams(proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int param_type_len
, int param_val_len
)
1594 item
= proto_tree_add_item(parent_tree
, hf_mgcp_param_connectionparam
, tvb
, offset
, param_type_len
+param_val_len
, ENC_ASCII
);
1595 tree
= proto_item_add_subtree(item
, ett_mgcp_param_connectionparam
);
1598 offset
+= param_type_len
; /* skip the P: */
1599 tokenline
= tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
, param_val_len
, ENC_ASCII
);
1601 /* Split into type=value pairs separated by comma */
1602 tokens
= wmem_strsplit(wmem_packet_scope(), tokenline
, ",", -1);
1604 for (i
= 0; tokens
[i
] != NULL
; i
++)
1611 tokenlen
= (int)strlen(tokens
[i
]);
1612 typval
= wmem_strsplit(wmem_packet_scope(), tokens
[i
], "=", 2);
1613 if ((typval
[0] != NULL
) && (typval
[1] != NULL
))
1615 if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PS"))
1617 hf_uint
= hf_mgcp_param_connectionparam_ps
;
1619 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "OS"))
1621 hf_uint
= hf_mgcp_param_connectionparam_os
;
1623 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PR"))
1625 hf_uint
= hf_mgcp_param_connectionparam_pr
;
1627 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "OR"))
1629 hf_uint
= hf_mgcp_param_connectionparam_or
;
1631 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PL"))
1633 hf_uint
= hf_mgcp_param_connectionparam_pl
;
1635 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JI"))
1637 hf_uint
= hf_mgcp_param_connectionparam_ji
;
1639 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "LA"))
1641 hf_uint
= hf_mgcp_param_connectionparam_la
;
1643 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PC/RPS"))
1645 hf_uint
= hf_mgcp_param_connectionparam_pcrps
;
1646 } else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PC/ROS"))
1648 hf_uint
= hf_mgcp_param_connectionparam_pcros
;
1650 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PC/RPL"))
1652 hf_uint
= hf_mgcp_param_connectionparam_pcrpl
;
1654 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PC/RJI"))
1656 hf_uint
= hf_mgcp_param_connectionparam_pcrji
;
1658 else if (!g_ascii_strncasecmp(g_strstrip(typval
[0]), "X-", 2))
1660 hf_string
= hf_mgcp_param_connectionparam_x
;
1665 proto_tree_add_uint(tree
, hf_uint
, tvb
, offset
, tokenlen
, (uint32_t)strtoul(typval
[1], NULL
, 10));
1667 else if (hf_string
> 0)
1669 proto_tree_add_string(tree
, hf_string
, tvb
, offset
, tokenlen
, g_strstrip(typval
[1]));
1673 proto_tree_add_string(tree
, hf_mgcp_unknown_parameter
, tvb
, offset
, tokenlen
, tokens
[i
]);
1678 proto_tree_add_string(tree
, hf_mgcp_malformed_parameter
, tvb
, offset
, tokenlen
, tokens
[i
]);
1680 offset
+= tokenlen
+ 1; /* 1 extra for the delimiter */
1685 /* Dissect the local connection option */
1687 dissect_mgcp_localconnectionoptions(proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int param_type_len
, int param_val_len
)
1696 item
= proto_tree_add_item(parent_tree
, hf_mgcp_param_localconnoptions
, tvb
, offset
, param_type_len
+param_val_len
, ENC_ASCII
);
1697 tree
= proto_item_add_subtree(item
, ett_mgcp_param_localconnectionoptions
);
1700 offset
+= param_type_len
; /* skip the L: */
1701 tokenline
= tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
, param_val_len
, ENC_ASCII
);
1703 /* Split into type=value pairs separated by comma */
1704 tokens
= wmem_strsplit(wmem_packet_scope(), tokenline
, ",", -1);
1705 for (i
= 0; tokens
[i
] != NULL
; i
++)
1715 tokenlen
= (int)strlen(tokens
[i
]);
1716 typval
= wmem_strsplit(wmem_packet_scope(), tokens
[i
], ":", 2);
1717 if ((typval
[0] != NULL
) && (typval
[1] != NULL
))
1719 if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "p"))
1721 hf_uint
= hf_mgcp_param_localconnoptions_p
;
1723 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "a"))
1725 hf_string
= hf_mgcp_param_localconnoptions_a
;
1727 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "s"))
1729 hf_string
= hf_mgcp_param_localconnoptions_s
;
1731 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "e"))
1733 hf_string
= hf_mgcp_param_localconnoptions_e
;
1735 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "sc-rtp"))
1737 hf_string
= hf_mgcp_param_localconnoptions_scrtp
;
1739 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "sc-rtcp"))
1741 hf_string
= hf_mgcp_param_localconnoptions_scrtcp
;
1743 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "b"))
1745 hf_string
= hf_mgcp_param_localconnoptions_b
;
1747 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "es-ccd"))
1749 hf_string
= hf_mgcp_param_localconnoptions_esccd
;
1751 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "es-cci"))
1753 hf_string
= hf_mgcp_param_localconnoptions_escci
;
1755 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "dq-gi"))
1757 hf_string
= hf_mgcp_param_localconnoptions_dqgi
;
1759 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "dq-rd"))
1761 hf_string
= hf_mgcp_param_localconnoptions_dqrd
;
1763 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "dq-ri"))
1765 hf_string
= hf_mgcp_param_localconnoptions_dqri
;
1767 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "dq-rr"))
1769 hf_string
= hf_mgcp_param_localconnoptions_dqrr
;
1771 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "k"))
1773 hf_string
= hf_mgcp_param_localconnoptions_k
;
1775 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "gc"))
1777 hf_uint
= hf_mgcp_param_localconnoptions_gc
;
1779 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "fmtp"))
1781 hf_string
= hf_mgcp_param_localconnoptions_fmtp
;
1783 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "nt"))
1785 hf_string
= hf_mgcp_param_localconnoptions_nt
;
1787 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "o-fmtp"))
1789 hf_string
= hf_mgcp_param_localconnoptions_ofmtp
;
1791 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "r"))
1793 hf_string
= hf_mgcp_param_localconnoptions_r
;
1795 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "t"))
1797 hf_string
= hf_mgcp_param_localconnoptions_t
;
1799 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "r-cnf"))
1801 hf_string
= hf_mgcp_param_localconnoptions_rcnf
;
1803 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "r-dir"))
1805 hf_string
= hf_mgcp_param_localconnoptions_rdir
;
1807 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "r-sh"))
1809 hf_string
= hf_mgcp_param_localconnoptions_rsh
;
1811 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "mp"))
1813 hf_string
= hf_mgcp_param_localconnoptions_mp
;
1815 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "fxr/fx"))
1817 hf_string
= hf_mgcp_param_localconnoptions_fxr
;
1828 proto_tree_add_uint(tree
, hf_uint
, tvb
, offset
, tokenlen
, (uint32_t)strtoul(typval
[1], NULL
, 10));
1830 else if (hf_string
> 0)
1832 proto_tree_add_string(tree
, hf_string
, tvb
, offset
, tokenlen
, g_strstrip(typval
[1]));
1836 proto_tree_add_string(tree
, hf_mgcp_unknown_parameter
, tvb
, offset
, tokenlen
, tokens
[i
]);
1842 /* Dissect the Local Voice Metrics option */
1844 dissect_mgcp_localvoicemetrics(proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int param_type_len
, int param_val_len
)
1846 proto_tree
*tree
= parent_tree
;
1847 proto_item
*item
= NULL
;
1849 char *tokenline
= NULL
;
1850 char **tokens
= NULL
;
1851 char **typval
= NULL
;
1853 unsigned tokenlen
= 0;
1858 item
= proto_tree_add_item(parent_tree
, hf_mgcp_param_localvoicemetrics
, tvb
, offset
, param_type_len
+param_val_len
, ENC_ASCII
);
1859 tree
= proto_item_add_subtree(item
, ett_mgcp_param_localvoicemetrics
);
1862 /* The XRM/LVM: line */
1863 offset
+= 9; /* skip the XRM/LVM: */
1864 tokenline
= tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
, param_val_len
- 9, ENC_ASCII
);
1866 /* Split into type=value pairs separated by comma and WSP */
1867 tokens
= wmem_strsplit(wmem_packet_scope(), tokenline
, ",", -1);
1868 for (i
= 0; tokens
[i
] != NULL
; i
++)
1871 tokenlen
= (int)strlen(tokens
[i
]);
1872 typval
= wmem_strsplit(wmem_packet_scope(), tokens
[i
], "=", 2);
1873 if ((typval
[0] != NULL
) && (typval
[1] != NULL
))
1875 if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "NLR"))
1877 hf_string
= hf_mgcp_param_voicemetrics_nlr
;
1879 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JDR"))
1881 hf_string
= hf_mgcp_param_voicemetrics_jdr
;
1883 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "BLD"))
1885 hf_string
= hf_mgcp_param_voicemetrics_bld
;
1887 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "GLD"))
1889 hf_string
= hf_mgcp_param_voicemetrics_gld
;
1891 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "BD"))
1893 hf_string
= hf_mgcp_param_voicemetrics_bd
;
1895 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "GD"))
1897 hf_string
= hf_mgcp_param_voicemetrics_gd
;
1899 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "RTD"))
1901 hf_string
= hf_mgcp_param_voicemetrics_rtd
;
1903 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "ESD"))
1905 hf_string
= hf_mgcp_param_voicemetrics_esd
;
1907 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "SL"))
1909 hf_string
= hf_mgcp_param_voicemetrics_sl
;
1911 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "NL"))
1913 hf_string
= hf_mgcp_param_voicemetrics_nl
;
1915 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "RERL"))
1917 hf_string
= hf_mgcp_param_voicemetrics_rerl
;
1919 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "GMN"))
1921 hf_string
= hf_mgcp_param_voicemetrics_gmn
;
1923 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "NSR"))
1925 hf_string
= hf_mgcp_param_voicemetrics_nsr
;
1927 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "XSR"))
1929 hf_string
= hf_mgcp_param_voicemetrics_xsr
;
1931 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "MLQ"))
1933 hf_string
= hf_mgcp_param_voicemetrics_mlq
;
1935 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "MCQ"))
1937 hf_string
= hf_mgcp_param_voicemetrics_mcq
;
1939 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PLC"))
1941 hf_string
= hf_mgcp_param_voicemetrics_plc
;
1943 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBA"))
1945 hf_string
= hf_mgcp_param_voicemetrics_jba
;
1947 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBR"))
1949 hf_string
= hf_mgcp_param_voicemetrics_jbr
;
1951 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBN"))
1953 hf_string
= hf_mgcp_param_voicemetrics_jbn
;
1955 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBM"))
1957 hf_string
= hf_mgcp_param_voicemetrics_jbm
;
1959 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBS"))
1961 hf_string
= hf_mgcp_param_voicemetrics_jbs
;
1963 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "IAJ"))
1965 hf_string
= hf_mgcp_param_voicemetrics_iaj
;
1977 proto_tree_add_string(tree
, hf_string
, tvb
, offset
, tokenlen
, g_strstrip(typval
[1]));
1981 proto_tree_add_string(tree
, hf_mgcp_unknown_parameter
, tvb
, offset
, tokenlen
, tokens
[i
]);
1987 proto_tree_add_string(tree
, hf_mgcp_malformed_parameter
, tvb
, offset
, tokenlen
, tokens
[i
]);
1989 offset
+= tokenlen
+ 1; /* 1 extra for the delimiter */
1993 /* Dissect the Remote Voice Metrics option */
1995 dissect_mgcp_remotevoicemetrics(proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int param_type_len
, int param_val_len
)
1997 proto_tree
*tree
= parent_tree
;
1998 proto_item
*item
= NULL
;
2000 char *tokenline
= NULL
;
2001 char **tokens
= NULL
;
2002 char **typval
= NULL
;
2004 unsigned tokenlen
= 0;
2009 item
= proto_tree_add_item(parent_tree
, hf_mgcp_param_remotevoicemetrics
, tvb
, offset
, param_type_len
+param_val_len
, ENC_ASCII
);
2010 tree
= proto_item_add_subtree(item
, ett_mgcp_param_remotevoicemetrics
);
2013 /* The XRM/RVM: line */
2014 offset
+= 9; /* skip the XRM/RVM: */
2015 tokenline
= tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
, param_val_len
- 9, ENC_ASCII
);
2017 /* Split into type=value pairs separated by comma and WSP */
2018 tokens
= wmem_strsplit(wmem_packet_scope(), tokenline
, ",", -1);
2019 for (i
= 0; tokens
[i
] != NULL
; i
++)
2021 tokenlen
= (int)strlen(tokens
[i
]);
2022 typval
= wmem_strsplit(wmem_packet_scope(), tokens
[i
], "=", 2);
2023 if ((typval
[0] != NULL
) && (typval
[1] != NULL
))
2025 if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "NLR"))
2027 hf_string
= hf_mgcp_param_voicemetrics_nlr
;
2029 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JDR"))
2031 hf_string
= hf_mgcp_param_voicemetrics_jdr
;
2033 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "BLD"))
2035 hf_string
= hf_mgcp_param_voicemetrics_bld
;
2037 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "GLD"))
2039 hf_string
= hf_mgcp_param_voicemetrics_gld
;
2041 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "BD"))
2043 hf_string
= hf_mgcp_param_voicemetrics_bd
;
2045 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "GD"))
2047 hf_string
= hf_mgcp_param_voicemetrics_gd
;
2049 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "RTD"))
2051 hf_string
= hf_mgcp_param_voicemetrics_rtd
;
2053 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "ESD"))
2055 hf_string
= hf_mgcp_param_voicemetrics_esd
;
2057 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "SL"))
2059 hf_string
= hf_mgcp_param_voicemetrics_sl
;
2061 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "NL"))
2063 hf_string
= hf_mgcp_param_voicemetrics_nl
;
2065 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "RERL"))
2067 hf_string
= hf_mgcp_param_voicemetrics_rerl
;
2069 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "GMN"))
2071 hf_string
= hf_mgcp_param_voicemetrics_gmn
;
2073 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "NSR"))
2075 hf_string
= hf_mgcp_param_voicemetrics_nsr
;
2077 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "XSR"))
2079 hf_string
= hf_mgcp_param_voicemetrics_xsr
;
2081 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "MLQ"))
2083 hf_string
= hf_mgcp_param_voicemetrics_mlq
;
2085 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "MCQ"))
2087 hf_string
= hf_mgcp_param_voicemetrics_mcq
;
2089 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "PLC"))
2091 hf_string
= hf_mgcp_param_voicemetrics_plc
;
2093 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBA"))
2095 hf_string
= hf_mgcp_param_voicemetrics_jba
;
2097 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBR"))
2099 hf_string
= hf_mgcp_param_voicemetrics_jbr
;
2101 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBN"))
2103 hf_string
= hf_mgcp_param_voicemetrics_jbn
;
2105 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBM"))
2107 hf_string
= hf_mgcp_param_voicemetrics_jbm
;
2109 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "JBS"))
2111 hf_string
= hf_mgcp_param_voicemetrics_jbs
;
2113 else if (!g_ascii_strcasecmp(g_strstrip(typval
[0]), "IAJ"))
2115 hf_string
= hf_mgcp_param_voicemetrics_iaj
;
2127 proto_tree_add_string(tree
, hf_string
, tvb
, offset
, tokenlen
, g_strstrip(typval
[1]));
2131 proto_tree_add_string(tree
, hf_mgcp_unknown_parameter
, tvb
, offset
, tokenlen
, tokens
[i
]);
2137 proto_tree_add_string(tree
, hf_mgcp_malformed_parameter
, tvb
, offset
, tokenlen
, tokens
[i
]);
2139 offset
+= tokenlen
+ 1; /* 1 extra for the delimiter */
2144 * tvb_find_null_line - Returns the length from offset to the first null
2145 * line found (a null line is a line that begins
2146 * with a CR or LF. The offset to the first character
2147 * after the null line is written into the int pointed
2148 * to by next_offset.
2151 * tvb - The tvbuff in which we are looking for a null line.
2152 * offset - The offset in tvb at which we will begin looking for
2154 * len - The maximum distance from offset in tvb that we will look for
2155 * a null line. If it is -1 we will look to the end of the buffer.
2157 * next_offset - The location to write the offset of first character
2158 * FOLLOWING the null line.
2160 * Returns: The length from offset to the first character BEFORE
2163 static int tvb_find_null_line(tvbuff_t
* tvb
, int offset
, int len
, int* next_offset
)
2165 int tvb_lineend
, tvb_current_len
, tvb_linebegin
, maxoffset
;
2168 tvb_linebegin
= offset
;
2169 tvb_lineend
= tvb_linebegin
;
2171 /* Simple setup to allow for the traditional -1 search to the end of the tvbuff */
2174 tvb_current_len
= len
;
2178 tvb_current_len
= tvb_reported_length_remaining(tvb
, offset
);
2181 maxoffset
= (tvb_current_len
- 1) + offset
;
2183 /* Loop around until we either find a line beginning with a carriage return
2184 or newline character or until we hit the end of the tvbuff. */
2187 tvb_linebegin
= tvb_lineend
;
2188 tvb_current_len
= tvb_reported_length_remaining(tvb
, tvb_linebegin
);
2189 tvb_find_line_end(tvb
, tvb_linebegin
, tvb_current_len
, &tvb_lineend
, false);
2190 tempchar
= tvb_get_uint8(tvb
, tvb_linebegin
);
2191 } while (tempchar
!= '\r' && tempchar
!= '\n' && tvb_lineend
<= maxoffset
&& tvb_offset_exists(tvb
, tvb_lineend
));
2194 *next_offset
= tvb_lineend
;
2196 if (tvb_lineend
<= maxoffset
)
2198 tvb_current_len
= tvb_linebegin
- offset
;
2202 tvb_current_len
= tvb_reported_length_remaining(tvb
, offset
);
2205 return tvb_current_len
;
2209 * tvb_find_dot_line - Returns the length from offset to the first line
2210 * containing only a dot (.) character. A line
2211 * containing only a dot is used to indicate a
2212 * separation between multiple MGCP messages
2213 * piggybacked in the same UDP packet.
2216 * tvb - The tvbuff in which we are looking for a dot line.
2217 * offset - The offset in tvb at which we will begin looking for
2219 * len - The maximum distance from offset in tvb that we will look for
2220 * a dot line. If it is -1 we will look to the end of the buffer.
2222 * next_offset - The location to write the offset of first character
2223 * FOLLOWING the dot line.
2225 * Returns: The length from offset to the first character BEFORE
2226 * the dot line or -1 if the character at offset is a .
2227 * followed by a newline or a carriage return.
2229 static int tvb_find_dot_line(tvbuff_t
* tvb
, int offset
, int len
, int* next_offset
)
2231 int tvb_current_offset
, tvb_current_len
, maxoffset
, tvb_len
;
2233 tvb_current_len
= len
;
2234 tvb_len
= tvb_reported_length(tvb
);
2238 maxoffset
= tvb_len
- 1;
2242 maxoffset
= (len
- 1) + offset
;
2244 tvb_current_offset
= offset
-1;
2248 tvb_current_offset
= tvb_find_uint8(tvb
, tvb_current_offset
+1,
2249 tvb_current_len
, '.');
2250 tvb_current_len
= maxoffset
- tvb_current_offset
+ 1;
2252 /* If we didn't find a . then break out of the loop */
2253 if (tvb_current_offset
== -1)
2258 /* Do we have and characters following the . ? */
2259 if (tvb_current_offset
< maxoffset
)
2261 tempchar
= tvb_get_uint8(tvb
, tvb_current_offset
+1);
2262 /* Are the characters that follow the dot a newline or carriage return ? */
2263 if (tempchar
== '\r' || tempchar
== '\n')
2265 /* Do we have any characters that proceed the . ? */
2266 if (tvb_current_offset
== 0)
2272 tempchar
= tvb_get_uint8(tvb
, tvb_current_offset
-1);
2274 /* Are the characters that follow the dot a newline or a
2275 carriage return ? */
2276 if (tempchar
== '\r' || tempchar
== '\n')
2284 if (tvb_current_offset
== maxoffset
)
2286 if (tvb_current_offset
== 0)
2292 tempchar
= tvb_get_uint8(tvb
, tvb_current_offset
-1);
2293 if (tempchar
== '\r' || tempchar
== '\n')
2299 } while (tvb_current_offset
< maxoffset
);
2303 * So now we either have the tvb_current_offset of a . in a dot line
2304 * or a tvb_current_offset of -1
2306 if (tvb_current_offset
== -1)
2308 tvb_current_offset
= maxoffset
+1;
2309 *next_offset
= maxoffset
+ 1;
2313 tvb_find_line_end(tvb
, tvb_current_offset
, tvb_current_len
, next_offset
, false);
2316 if (tvb_current_offset
== offset
)
2318 tvb_current_len
= -1;
2322 tvb_current_len
= tvb_current_offset
- offset
;
2325 return tvb_current_len
;
2328 /* Register all the bits needed with the filtering engine */
2330 void proto_register_mgcp(void);
2331 void proto_reg_handoff_mgcp(void);
2333 void proto_register_mgcp(void)
2335 expert_module_t
* expert_mgcp
;
2337 static hf_register_info hf
[] =
2340 { "Request", "mgcp.req", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2341 "True if MGCP request", HFILL
}},
2343 { "Response", "mgcp.rsp", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2344 "true if MGCP response", HFILL
}},
2345 { &hf_mgcp_req_frame
,
2346 { "Request Frame", "mgcp.reqframe", FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0,
2348 { &hf_mgcp_rsp_frame
,
2349 { "Response Frame", "mgcp.rspframe", FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0,
2352 { "Time from request", "mgcp.time", FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0,
2353 "Timedelta between Request and Response", HFILL
}},
2354 { &hf_mgcp_req_verb
,
2355 { "Verb", "mgcp.req.verb", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2356 "Name of the verb", HFILL
}},
2357 { &hf_mgcp_req_endpoint
,
2358 { "Endpoint", "mgcp.req.endpoint", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2359 "Endpoint referenced by the message", HFILL
}},
2361 { "Transaction ID", "mgcp.transid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2362 "Transaction ID of this message", HFILL
}},
2364 { "Version", "mgcp.version", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2365 "MGCP Version", HFILL
}},
2366 { &hf_mgcp_rsp_rspcode
,
2367 { "Response Code", "mgcp.rsp.rspcode", FT_UINT32
, BASE_DEC
|BASE_EXT_STRING
, &mgcp_return_code_vals_ext
, 0x0,
2369 { &hf_mgcp_rsp_rspstring
,
2370 { "Response String", "mgcp.rsp.rspstring", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2373 { "Parameters", "mgcp.params", FT_NONE
, BASE_NONE
, NULL
, 0x0,
2374 "MGCP parameters", HFILL
}},
2375 { &hf_mgcp_param_rspack
,
2376 { "ResponseAck (K)", "mgcp.param.rspack", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2377 "Response Ack", HFILL
}},
2378 { &hf_mgcp_param_bearerinfo
,
2379 { "BearerInformation (B)", "mgcp.param.bearerinfo", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2380 "Bearer Information", HFILL
}},
2381 { &hf_mgcp_param_callid
,
2382 { "CallId (C)", "mgcp.param.callid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2383 "Call Id", HFILL
}},
2384 { &hf_mgcp_param_connectionid
,
2385 {"ConnectionIdentifier (I)", "mgcp.param.connectionid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2386 "Connection Identifier", HFILL
}},
2387 { &hf_mgcp_param_secondconnectionid
,
2388 { "SecondConnectionID (I2)", "mgcp.param.secondconnectionid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2389 "Second Connection Identifier", HFILL
}},
2390 { &hf_mgcp_param_notifiedentity
,
2391 { "NotifiedEntity (N)", "mgcp.param.notifiedentity", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2392 "Notified Entity", HFILL
}},
2393 { &hf_mgcp_param_requestid
,
2394 { "RequestIdentifier (X)", "mgcp.param.requestid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2395 "Request Identifier", HFILL
}},
2396 { &hf_mgcp_param_localconnoptions
,
2397 { "LocalConnectionOptions (L)", "mgcp.param.localconnectionoptions", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2398 "Local Connection Options", HFILL
}},
2399 { &hf_mgcp_param_localconnoptions_p
,
2400 { "Packetization period (p)", "mgcp.param.localconnectionoptions.p", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2402 { &hf_mgcp_param_localconnoptions_a
,
2403 { "Codecs (a)", "mgcp.param.localconnectionoptions.a", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2405 { &hf_mgcp_param_localconnoptions_s
,
2406 { "Silence Suppression (s)", "mgcp.param.localconnectionoptions.s", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2408 { &hf_mgcp_param_localconnoptions_e
,
2409 { "Echo Cancellation (e)", "mgcp.param.localconnectionoptions.e", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2411 { &hf_mgcp_param_localconnoptions_scrtp
,
2412 { "RTP ciphersuite (sc-rtp)", "mgcp.param.localconnectionoptions.scrtp", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2414 { &hf_mgcp_param_localconnoptions_scrtcp
,
2415 { "RTCP ciphersuite (sc-rtcp)", "mgcp.param.localconnectionoptions.scrtcp", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2417 { &hf_mgcp_param_localconnoptions_b
,
2418 { "Bandwidth (b)", "mgcp.param.localconnectionoptions.b", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2420 { &hf_mgcp_param_localconnoptions_esccd
,
2421 { "Content Destination (es-ccd)", "mgcp.param.localconnectionoptions.esccd", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2423 { &hf_mgcp_param_localconnoptions_escci
,
2424 { "Content Identifier (es-cci)", "mgcp.param.localconnectionoptions.escci", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2426 { &hf_mgcp_param_localconnoptions_dqgi
,
2427 { "D-QoS GateID (dq-gi)", "mgcp.param.localconnectionoptions.dqgi", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2429 { &hf_mgcp_param_localconnoptions_dqrd
,
2430 { "D-QoS Reserve Destination (dq-rd)", "mgcp.param.localconnectionoptions.dqrd", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2432 { &hf_mgcp_param_localconnoptions_dqri
,
2433 { "D-QoS Resource ID (dq-ri)", "mgcp.param.localconnectionoptions.dqri", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2435 { &hf_mgcp_param_localconnoptions_dqrr
,
2436 { "D-QoS Resource Reservation (dq-rr)", "mgcp.param.localconnectionoptions.dqrr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2438 { &hf_mgcp_param_localconnoptions_k
,
2439 { "Encryption Key (k)", "mgcp.param.localconnectionoptions.k", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2441 { &hf_mgcp_param_localconnoptions_gc
,
2442 { "Gain Control (gc)", "mgcp.param.localconnectionoptions.gc", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2444 { &hf_mgcp_param_localconnoptions_fmtp
,
2445 { "Media Format (fmtp)", "mgcp.param.localconnectionoptions.fmtp", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2447 { &hf_mgcp_param_localconnoptions_nt
,
2448 { "Network Type (nt)", "mgcp.param.localconnectionoptions.nt", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2450 { &hf_mgcp_param_localconnoptions_ofmtp
,
2451 { "Optional Media Format (o-fmtp)", "mgcp.param.localconnectionoptions.ofmtp", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2453 { &hf_mgcp_param_localconnoptions_r
,
2454 { "Resource Reservation (r)", "mgcp.param.localconnectionoptions.r", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2456 { &hf_mgcp_param_localconnoptions_t
,
2457 { "Type of Service (r)", "mgcp.param.localconnectionoptions.t", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2459 { &hf_mgcp_param_localconnoptions_rcnf
,
2460 { "Reservation Confirmation (r-cnf)", "mgcp.param.localconnectionoptions.rcnf", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2462 { &hf_mgcp_param_localconnoptions_rdir
,
2463 { "Reservation Direction (r-dir)", "mgcp.param.localconnectionoptions.rdir", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2465 { &hf_mgcp_param_localconnoptions_rsh
,
2466 { "Resource Sharing (r-sh)", "mgcp.param.localconnectionoptions.rsh", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2468 { &hf_mgcp_param_localconnoptions_mp
,
2469 { "Multiple Packetization period (mp)", "mgcp.param.localconnectionoptions.mp", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2471 { &hf_mgcp_param_localconnoptions_fxr
,
2472 { "FXR (fxr/fx)", "mgcp.param.localconnectionoptions.fxr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2474 { &hf_mgcp_param_localvoicemetrics
,
2475 { "LocalVoiceMetrics (XRM/LVM)", "mgcp.param.localvoicemetrics", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2477 { &hf_mgcp_param_remotevoicemetrics
,
2478 { "RemoteVoiceMetrics (XRM/RVM)", "mgcp.param.remotevoicemetrics", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2480 { &hf_mgcp_param_voicemetrics_nlr
,
2481 { "Network packet loss rate(NLR)", "mgcp.param.voicemetrics.nlr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2482 "Voice Metrics NLR", HFILL
}},
2483 { &hf_mgcp_param_voicemetrics_jdr
,
2484 { "Jitter buffer discard rate(JDR)", "mgcp.param.voicemetrics.jdr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2485 "Voice Metrics JDR", HFILL
}},
2486 { &hf_mgcp_param_voicemetrics_bld
,
2487 { "Burst loss density(BLD)", "mgcp.param.voicemetrics.bld", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2488 "Voice Metrics BLD", HFILL
}},
2489 { &hf_mgcp_param_voicemetrics_gld
,
2490 { "Gap loss density(GLD)", "mgcp.param.voicemetrics.gld", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2491 "Voice Metrics GLD", HFILL
}},
2492 { &hf_mgcp_param_voicemetrics_bd
,
2493 { "Burst duration(BD)", "mgcp.param.voicemetrics.bd", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2494 "Voice Metrics BD", HFILL
}},
2495 { &hf_mgcp_param_voicemetrics_gd
,
2496 { "Gap duration(GD)", "mgcp.param.voicemetrics.gd", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2497 "Voice Metrics GD", HFILL
}},
2498 { &hf_mgcp_param_voicemetrics_rtd
,
2499 { "Round trip network delay(RTD)", "mgcp.param.voicemetrics.rtd", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2500 "Voice Metrics RTD", HFILL
}},
2501 { &hf_mgcp_param_voicemetrics_esd
,
2502 { "End system delay(ESD)", "mgcp.param.voicemetrics.esd", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2503 "Voice Metrics ESD", HFILL
}},
2504 { &hf_mgcp_param_voicemetrics_sl
,
2505 { "Signal level(SL)", "mgcp.param.voicemetrics.sl", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2506 "Voice Metrics SL", HFILL
}},
2507 { &hf_mgcp_param_voicemetrics_nl
,
2508 { "Noise level(NL)", "mgcp.param.voicemetrics.nl", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2509 "Voice Metricsx NL", HFILL
}},
2510 { &hf_mgcp_param_voicemetrics_rerl
,
2511 { "Residual echo return loss(RERL)", "mgcp.param.voicemetrics.rerl", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2512 "Voice Metrics ERL", HFILL
}},
2513 { &hf_mgcp_param_voicemetrics_gmn
,
2514 { "Minimum gap threshold(GMN)", "mgcp.param.voicemetrics.gmn", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2515 "Voice Metrics GMN", HFILL
}},
2516 { &hf_mgcp_param_voicemetrics_nsr
,
2517 { "R factor(NSR)", "mgcp.param.voicemetrics.nsr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2518 "Voice Metrics NSR", HFILL
}},
2519 { &hf_mgcp_param_voicemetrics_xsr
,
2520 { "External R factor(XSR)", "mgcp.param.voicemetrics.xsr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2521 "Voice Metrics XSR", HFILL
}},
2522 { &hf_mgcp_param_voicemetrics_mlq
,
2523 { "Estimated MOS-LQ(MLQ)", "mgcp.param.voicemetrics.mlq", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2524 "Voice Metrics MLQ", HFILL
}},
2525 { &hf_mgcp_param_voicemetrics_mcq
,
2526 { "Estimated MOS-CQ(MCQ)", "mgcp.param.voicemetrics.mcq", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2527 "Voice Metrics MCQ", HFILL
}},
2528 { &hf_mgcp_param_voicemetrics_plc
,
2529 { "Packet loss concealment type(PLC)", "mgcp.param.voicemetrics.plc", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2530 "Voice Metrics PLC", HFILL
}},
2531 { &hf_mgcp_param_voicemetrics_jba
,
2532 { "Jitter Buffer Adaptive(JBA)", "mgcp.param.voicemetrics.jba", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2533 "Voice Metrics JBA", HFILL
}},
2534 { &hf_mgcp_param_voicemetrics_jbr
,
2535 { "Jitter Buffer Rate(JBR)", "mgcp.param.voicemetrics.jbr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2536 "Voice Metrics JBR", HFILL
}},
2537 { &hf_mgcp_param_voicemetrics_jbn
,
2538 { "Nominal jitter buffer delay(JBN)", "mgcp.param.voicemetrics.jbn", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2539 "Voice Metrics JBN", HFILL
}},
2540 { &hf_mgcp_param_voicemetrics_jbm
,
2541 { "Maximum jitter buffer delay(JBM)", "mgcp.param.voicemetrics.jbm", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2542 "Voice Metrics JBM", HFILL
}},
2543 { &hf_mgcp_param_voicemetrics_jbs
,
2544 { "Absolute maximum jitter buffer delay(JBS)", "mgcp.param.voicemetrics.jbs", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2545 "Voice Metrics JBS", HFILL
}},
2546 { &hf_mgcp_param_voicemetrics_iaj
,
2547 { "Inter-arrival Jitter(IAJ)", "mgcp.param.voicemetrics.iaj", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2548 "Voice Metrics IAJ", HFILL
}},
2549 { &hf_mgcp_param_connectionmode
,
2550 { "ConnectionMode (M)", "mgcp.param.connectionmode", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2551 "Connection Mode", HFILL
}},
2552 { &hf_mgcp_param_reqevents
,
2553 { "RequestedEvents (R)", "mgcp.param.reqevents", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2554 "Requested Events", HFILL
}},
2555 { &hf_mgcp_param_signalreq
,
2556 { "SignalRequests (S)", "mgcp.param.signalreq", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2557 "Signal Request", HFILL
}},
2558 { &hf_mgcp_param_restartmethod
,
2559 { "RestartMethod (RM)", "mgcp.param.restartmethod", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2560 "Restart Method", HFILL
}},
2561 { &hf_mgcp_param_restartdelay
,
2562 { "RestartDelay (RD)", "mgcp.param.restartdelay", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2563 "Restart Delay", HFILL
}},
2564 { &hf_mgcp_param_digitmap
,
2565 { "DigitMap (D)", "mgcp.param.digitmap", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2566 "Digit Map", HFILL
}},
2567 { &hf_mgcp_param_observedevent
,
2568 { "ObservedEvents (O)", "mgcp.param.observedevents", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2569 "Observed Events", HFILL
}},
2570 { &hf_mgcp_param_connectionparam
,
2571 { "ConnectionParameters (P)", "mgcp.param.connectionparam", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2572 "Connection Parameters", HFILL
}},
2573 { &hf_mgcp_param_connectionparam_ps
,
2574 { "Packets sent (PS)", "mgcp.param.connectionparam.ps", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2575 "Packets sent (P:PS)", HFILL
}},
2576 { &hf_mgcp_param_connectionparam_os
,
2577 { "Octets sent (OS)", "mgcp.param.connectionparam.os", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2578 "Octets sent (P:OS)", HFILL
}},
2579 { &hf_mgcp_param_connectionparam_pr
,
2580 { "Packets received (PR)", "mgcp.param.connectionparam.pr", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2581 "Packets received (P:PR)", HFILL
}},
2582 { &hf_mgcp_param_connectionparam_or
,
2583 { "Octets received (OR)", "mgcp.param.connectionparam.or", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2584 "Octets received (P:OR)", HFILL
}},
2585 { &hf_mgcp_param_connectionparam_pl
,
2586 { "Packets lost (PL)", "mgcp.param.connectionparam.pl", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2587 "Packets lost (P:PL)", HFILL
}},
2588 { &hf_mgcp_param_connectionparam_ji
,
2589 { "Jitter (JI)", "mgcp.param.connectionparam.ji", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2590 "Average inter-packet arrival jitter in milliseconds (P:JI)", HFILL
}},
2591 { &hf_mgcp_param_connectionparam_la
,
2592 { "Latency (LA)", "mgcp.param.connectionparam.la", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2593 "Average latency in milliseconds (P:LA)", HFILL
}},
2594 { &hf_mgcp_param_connectionparam_pcrps
,
2595 { "Remote Packets sent (PC/RPS)", "mgcp.param.connectionparam.pcrps", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2596 "Remote Packets sent (P:PC/RPS)", HFILL
}},
2597 { &hf_mgcp_param_connectionparam_pcros
,
2598 { "Remote Octets sent (PC/ROS)", "mgcp.param.connectionparam.pcros", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2599 "Remote Octets sent (P:PC/ROS)", HFILL
}},
2600 { &hf_mgcp_param_connectionparam_pcrpl
,
2601 { "Remote Packets lost (PC/RPL)", "mgcp.param.connectionparam.pcrpl", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2602 "Remote Packets lost (P:PC/RPL)", HFILL
}},
2603 { &hf_mgcp_param_connectionparam_pcrji
,
2604 { "Remote Jitter (PC/RJI)", "mgcp.param.connectionparam.pcrji", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2605 "Remote Jitter (P:PC/RJI)", HFILL
}},
2606 { &hf_mgcp_param_connectionparam_x
,
2607 { "Vendor Extension", "mgcp.param.connectionparam.x", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2608 "Vendor Extension (P:X-*)", HFILL
}},
2609 { &hf_mgcp_param_reasoncode
,
2610 { "ReasonCode (E)", "mgcp.param.reasoncode", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2611 "Reason Code", HFILL
}},
2612 { &hf_mgcp_param_eventstates
,
2613 { "EventStates (ES)", "mgcp.param.eventstates", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2614 "Event States", HFILL
}},
2615 { &hf_mgcp_param_specificendpoint
,
2616 { "SpecificEndpointID (Z)", "mgcp.param.specificendpointid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2617 "Specific Endpoint ID", HFILL
}},
2618 { &hf_mgcp_param_secondendpointid
,
2619 { "SecondEndpointID (Z2)", "mgcp.param.secondendpointid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2620 "Second Endpoint ID", HFILL
}},
2621 { &hf_mgcp_param_reqinfo
,
2622 { "RequestedInfo (F)", "mgcp.param.reqinfo", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2623 "Requested Info", HFILL
}},
2624 { &hf_mgcp_param_quarantinehandling
,
2625 { "QuarantineHandling (Q)", "mgcp.param.quarantinehandling", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2626 "Quarantine Handling", HFILL
}},
2627 { &hf_mgcp_param_detectedevents
,
2628 { "DetectedEvents (T)", "mgcp.param.detectedevents", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2629 "Detected Events", HFILL
}},
2630 { &hf_mgcp_param_capabilities
,
2631 { "Capabilities (A)", "mgcp.param.capabilities", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2633 { &hf_mgcp_param_maxmgcpdatagram
,
2634 {"MaxMGCPDatagram (MD)", "mgcp.param.maxmgcpdatagram", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2635 "Maximum MGCP Datagram size", HFILL
}},
2636 { &hf_mgcp_param_packagelist
,
2637 {"PackageList (PL)", "mgcp.param.packagelist", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2638 "Package List", HFILL
}},
2639 { &hf_mgcp_param_extension
,
2640 { "Extension Parameter (non-critical)", "mgcp.param.extension", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2642 { &hf_mgcp_param_extension_critical
,
2643 { "Extension Parameter (critical)", "mgcp.param.extensioncritical", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2644 "Critical Extension Parameter", HFILL
}},
2645 { &hf_mgcp_param_resourceid
,
2646 { "ResourceIdentifier (DQ-RI)", "mgcp.param.resourceid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2647 "Resource Identifier", HFILL
}},
2648 { &hf_mgcp_param_invalid
,
2649 { "Invalid Parameter", "mgcp.param.invalid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2651 { &hf_mgcp_messagecount
,
2652 { "MGCP Message Count", "mgcp.messagecount", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2653 "Number of MGCP message in a packet", HFILL
}},
2655 { "Duplicate Message", "mgcp.dup", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2658 { "Duplicate Request", "mgcp.req.dup", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2660 { &hf_mgcp_req_dup_frame
,
2661 { "Original Request Frame", "mgcp.req.dup.frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
2662 "Frame containing original request", HFILL
}},
2664 { "Duplicate Response", "mgcp.rsp.dup", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2666 { &hf_mgcp_rsp_dup_frame
,
2667 { "Original Response Frame", "mgcp.rsp.dup.frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
2668 "Frame containing original response", HFILL
}},
2669 { &hf_mgcp_param_x_osmux
,
2670 { "X-Osmux", "mgcp.param.x_osmux", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2671 "Osmux CID", HFILL
}},
2672 { &hf_mgcp_unknown_parameter
,
2673 { "Unknown parameter", "mgcp.unknown_parameter", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2675 { &hf_mgcp_malformed_parameter
,
2676 { "Malformed parameter", "mgcp.rsp.malformed_parameter", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2684 &ett_mgcp_param_connectionparam
,
2685 &ett_mgcp_param_localconnectionoptions
,
2686 &ett_mgcp_param_localvoicemetrics
,
2687 &ett_mgcp_param_remotevoicemetrics
2690 static ei_register_info ei
[] = {
2691 { &ei_mgcp_rsp_rspcode_invalid
, { "mgcp.rsp.rspcode.invalid", PI_MALFORMED
, PI_ERROR
,
2692 "RSP code must be a string containing an integer", EXPFILL
}}
2695 module_t
*mgcp_module
;
2697 /* Register protocol */
2698 proto_mgcp
= proto_register_protocol("Media Gateway Control Protocol", "MGCP", "mgcp");
2699 proto_register_field_array(proto_mgcp
, hf
, array_length(hf
));
2700 proto_register_subtree_array(ett
, array_length(ett
));
2702 mgcp_calls
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), mgcp_call_hash
, mgcp_call_equal
);
2704 mgcp_handle
= register_dissector("mgcp", dissect_mgcp
, proto_mgcp
);
2706 /* Register our configuration options */
2707 mgcp_module
= prefs_register_protocol(proto_mgcp
, proto_reg_handoff_mgcp
);
2709 prefs_register_uint_preference(mgcp_module
, "tcp.gateway_port",
2710 "MGCP Gateway TCP Port",
2711 "Set the UDP port for gateway messages "
2712 "(if other than the default of 2427)",
2713 10, &global_mgcp_gateway_tcp_port
);
2715 prefs_register_uint_preference(mgcp_module
, "udp.gateway_port",
2716 "MGCP Gateway UDP Port",
2717 "Set the TCP port for gateway messages "
2718 "(if other than the default of 2427)",
2719 10, &global_mgcp_gateway_udp_port
);
2721 prefs_register_uint_preference(mgcp_module
, "tcp.callagent_port",
2722 "MGCP Callagent TCP Port",
2723 "Set the TCP port for callagent messages "
2724 "(if other than the default of 2727)",
2725 10, &global_mgcp_callagent_tcp_port
);
2727 prefs_register_uint_preference(mgcp_module
, "udp.callagent_port",
2728 "MGCP Callagent UDP Port",
2729 "Set the UDP port for callagent messages "
2730 "(if other than the default of 2727)",
2731 10, &global_mgcp_callagent_udp_port
);
2734 prefs_register_bool_preference(mgcp_module
, "display_raw_text",
2735 "Display raw text for MGCP message",
2736 "Specifies that the raw text of the "
2737 "MGCP message should be displayed "
2738 "instead of (or in addition to) the "
2740 &global_mgcp_raw_text
);
2742 prefs_register_obsolete_preference(mgcp_module
, "display_dissect_tree");
2744 prefs_register_bool_preference(mgcp_module
, "display_mgcp_message_count",
2745 "Display the number of MGCP messages",
2746 "Display the number of MGCP messages "
2747 "found in a packet in the protocol column.",
2748 &global_mgcp_message_count
);
2750 mgcp_tap
= register_tap("mgcp");
2752 register_rtd_table(proto_mgcp
, NULL
, 1, NUM_TIMESTATS
, mgcp_message_type
, mgcpstat_packet
, NULL
);
2754 expert_mgcp
= expert_register_protocol(proto_mgcp
);
2755 expert_register_field_array(expert_mgcp
, ei
, array_length(ei
));
2759 /* The registration hand-off routine */
2760 void proto_reg_handoff_mgcp(void)
2762 static bool mgcp_prefs_initialized
= false;
2763 static dissector_handle_t mgcp_tpkt_handle
;
2765 * Variables to allow for proper deletion of dissector registration when
2766 * the user changes port from the gui.
2768 static unsigned gateway_tcp_port
;
2769 static unsigned gateway_udp_port
;
2770 static unsigned callagent_tcp_port
;
2771 static unsigned callagent_udp_port
;
2773 if (!mgcp_prefs_initialized
)
2775 /* Get a handle for the SDP dissector. */
2776 sdp_handle
= find_dissector_add_dependency("sdp", proto_mgcp
);
2777 mgcp_tpkt_handle
= create_dissector_handle(dissect_tpkt_mgcp
, proto_mgcp
);
2778 mgcp_prefs_initialized
= true;
2782 dissector_delete_uint("tcp.port", gateway_tcp_port
, mgcp_tpkt_handle
);
2783 dissector_delete_uint("udp.port", gateway_udp_port
, mgcp_handle
);
2784 dissector_delete_uint("tcp.port", callagent_tcp_port
, mgcp_tpkt_handle
);
2785 dissector_delete_uint("udp.port", callagent_udp_port
, mgcp_handle
);
2788 /* Set our port number for future use */
2789 gateway_tcp_port
= global_mgcp_gateway_tcp_port
;
2790 gateway_udp_port
= global_mgcp_gateway_udp_port
;
2792 callagent_tcp_port
= global_mgcp_callagent_tcp_port
;
2793 callagent_udp_port
= global_mgcp_callagent_udp_port
;
2795 /* Names of port preferences too specific to add "auto" preference here */
2796 dissector_add_uint("tcp.port", global_mgcp_gateway_tcp_port
, mgcp_tpkt_handle
);
2797 dissector_add_uint("udp.port", global_mgcp_gateway_udp_port
, mgcp_handle
);
2798 dissector_add_uint("tcp.port", global_mgcp_callagent_tcp_port
, mgcp_tpkt_handle
);
2799 dissector_add_uint("udp.port", global_mgcp_callagent_udp_port
, mgcp_handle
);
2803 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2808 * indent-tabs-mode: t
2811 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2812 * :indentSize=8:tabSize=8:noTabs=false: