Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-mgcp.c
blob90f378b74a5288b2d5df47eaace88be85883d514
1 /* packet-mgcp.c
2 * Routines for mgcp packet disassembly
3 * RFC 2705
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
24 #define WS_LOG_DOMAIN "packet-mgcp"
26 #include "config.h"
27 #include <wireshark.h>
29 #include <stdlib.h>
31 #include <epan/packet.h>
32 #include <epan/exceptions.h>
33 #include <epan/prefs.h>
34 #include <epan/conversation.h>
35 #include <epan/tap.h>
36 #include <epan/strutil.h>
37 #include <epan/rtd_table.h>
38 #include <epan/expert.h>
39 #include "packet-media-type.h"
40 #include "packet-mgcp.h"
41 #include "packet-sdp.h"
43 #include <wsutil/strtoi.h>
45 #define TCP_PORT_MGCP_GATEWAY 2427
46 #define UDP_PORT_MGCP_GATEWAY 2427
47 #define TCP_PORT_MGCP_CALLAGENT 2727
48 #define UDP_PORT_MGCP_CALLAGENT 2727
51 /* Define the mgcp proto */
52 static int proto_mgcp;
54 /* Define many many headers for mgcp */
55 static int hf_mgcp_req;
56 static int hf_mgcp_req_verb;
57 static int hf_mgcp_req_endpoint;
58 static int hf_mgcp_req_frame;
59 static int hf_mgcp_rsp;
60 static int hf_mgcp_rsp_frame;
61 static int hf_mgcp_time;
62 static int hf_mgcp_transid;
63 static int hf_mgcp_version;
64 static int hf_mgcp_rsp_rspcode;
65 static int hf_mgcp_rsp_rspstring;
66 static int hf_mgcp_params;
67 static int hf_mgcp_param_rspack;
68 static int hf_mgcp_param_bearerinfo;
69 static int hf_mgcp_param_callid;
70 static int hf_mgcp_param_connectionid;
71 static int hf_mgcp_param_secondconnectionid;
72 static int hf_mgcp_param_notifiedentity;
73 static int hf_mgcp_param_requestid;
74 static int hf_mgcp_param_localconnoptions;
75 static int hf_mgcp_param_localconnoptions_p;
76 static int hf_mgcp_param_localconnoptions_a;
77 static int hf_mgcp_param_localconnoptions_s;
78 static int hf_mgcp_param_localconnoptions_e;
79 static int hf_mgcp_param_localconnoptions_scrtp;
80 static int hf_mgcp_param_localconnoptions_scrtcp;
81 static int hf_mgcp_param_localconnoptions_b;
82 static int hf_mgcp_param_localconnoptions_esccd;
83 static int hf_mgcp_param_localconnoptions_escci;
84 static int hf_mgcp_param_localconnoptions_dqgi;
85 static int hf_mgcp_param_localconnoptions_dqrd;
86 static int hf_mgcp_param_localconnoptions_dqri;
87 static int hf_mgcp_param_localconnoptions_dqrr;
88 static int hf_mgcp_param_localconnoptions_k;
89 static int hf_mgcp_param_localconnoptions_gc;
90 static int hf_mgcp_param_localconnoptions_fmtp;
91 static int hf_mgcp_param_localconnoptions_nt;
92 static int hf_mgcp_param_localconnoptions_ofmtp;
93 static int hf_mgcp_param_localconnoptions_r;
94 static int hf_mgcp_param_localconnoptions_t;
95 static int hf_mgcp_param_localconnoptions_rcnf;
96 static int hf_mgcp_param_localconnoptions_rdir;
97 static int hf_mgcp_param_localconnoptions_rsh;
98 static int hf_mgcp_param_localconnoptions_mp;
99 static int hf_mgcp_param_localconnoptions_fxr;
100 static int hf_mgcp_param_localvoicemetrics;
101 static int hf_mgcp_param_remotevoicemetrics;
102 static int hf_mgcp_param_voicemetrics_nlr;
103 static int hf_mgcp_param_voicemetrics_jdr;
104 static int hf_mgcp_param_voicemetrics_bld;
105 static int hf_mgcp_param_voicemetrics_gld;
106 static int hf_mgcp_param_voicemetrics_bd;
107 static int hf_mgcp_param_voicemetrics_gd;
108 static int hf_mgcp_param_voicemetrics_rtd;
109 static int hf_mgcp_param_voicemetrics_esd;
110 static int hf_mgcp_param_voicemetrics_sl;
111 static int hf_mgcp_param_voicemetrics_nl;
112 static int hf_mgcp_param_voicemetrics_rerl;
113 static int hf_mgcp_param_voicemetrics_gmn;
114 static int hf_mgcp_param_voicemetrics_nsr;
115 static int hf_mgcp_param_voicemetrics_xsr;
116 static int hf_mgcp_param_voicemetrics_mlq;
117 static int hf_mgcp_param_voicemetrics_mcq;
118 static int hf_mgcp_param_voicemetrics_plc;
119 static int hf_mgcp_param_voicemetrics_jba;
120 static int hf_mgcp_param_voicemetrics_jbr;
121 static int hf_mgcp_param_voicemetrics_jbn;
122 static int hf_mgcp_param_voicemetrics_jbm;
123 static int hf_mgcp_param_voicemetrics_jbs;
124 static int hf_mgcp_param_voicemetrics_iaj;
125 static int hf_mgcp_param_connectionmode;
126 static int hf_mgcp_param_reqevents;
127 static int hf_mgcp_param_restartmethod;
128 static int hf_mgcp_param_restartdelay;
129 static int hf_mgcp_param_signalreq;
130 static int hf_mgcp_param_digitmap;
131 static int hf_mgcp_param_observedevent;
132 static int hf_mgcp_param_connectionparam;
133 static int hf_mgcp_param_connectionparam_ps;
134 static int hf_mgcp_param_connectionparam_os;
135 static int hf_mgcp_param_connectionparam_pr;
136 static int hf_mgcp_param_connectionparam_or;
137 static int hf_mgcp_param_connectionparam_pl;
138 static int hf_mgcp_param_connectionparam_ji;
139 static int hf_mgcp_param_connectionparam_la;
140 static int hf_mgcp_param_connectionparam_pcrps;
141 static int hf_mgcp_param_connectionparam_pcros;
142 static int hf_mgcp_param_connectionparam_pcrpl;
143 static int hf_mgcp_param_connectionparam_pcrji;
144 static int hf_mgcp_param_connectionparam_x;
145 static int hf_mgcp_param_reasoncode;
146 static int hf_mgcp_param_eventstates;
147 static int hf_mgcp_param_specificendpoint;
148 static int hf_mgcp_param_secondendpointid;
149 static int hf_mgcp_param_reqinfo;
150 static int hf_mgcp_param_quarantinehandling;
151 static int hf_mgcp_param_detectedevents;
152 static int hf_mgcp_param_capabilities;
153 static int hf_mgcp_param_maxmgcpdatagram;
154 static int hf_mgcp_param_packagelist;
155 static int hf_mgcp_param_extension;
156 static int hf_mgcp_param_extension_critical;
157 static int hf_mgcp_param_resourceid;
158 static int hf_mgcp_param_invalid;
159 static int hf_mgcp_messagecount;
160 static int hf_mgcp_dup;
161 static int hf_mgcp_req_dup;
162 static int hf_mgcp_req_dup_frame;
163 static int hf_mgcp_rsp_dup;
164 static int hf_mgcp_rsp_dup_frame;
165 static int hf_mgcp_param_x_osmux;
166 static int hf_mgcp_unknown_parameter;
167 static int hf_mgcp_malformed_parameter;
169 static expert_field ei_mgcp_rsp_rspcode_invalid;
171 static const value_string mgcp_return_code_vals[] = {
172 {000, "Response Acknowledgement"},
173 {100, "The transaction is currently being executed. An actual completion message will follow on later."},
174 {101, "The transaction has been queued for execution. An actual completion message will follow later."},
175 {200, "The requested transaction was executed normally."},
176 {250, "The connection was deleted."},
177 {400, "The transaction could not be executed, due to a transient error."},
178 {401, "The phone is already off hook"},
179 {402, "The phone is already on hook"},
180 {403, "The transaction could not be executed, because the endpoint does not have sufficient resources at this time"},
181 {404, "Insufficient bandwidth at this time"},
182 {405, "The transaction could not be executed, because the endpoint is \"restarting\"."},
183 {406, "Transaction time-out. The transaction did not complete in a reasonable period of time and has been aborted."},
184 {407, "Transaction aborted. The transaction was aborted by some external action, e.g., a ModifyConnection command aborted by a DeleteConnection command."},
185 {409, "The transaction could not be executed because of internal overload."},
186 {410, "No endpoint available. A valid \"any of\" wildcard was used, however there was no endpoint available to satisfy the request."},
187 {500, "The transaction could not be executed, because the endpoint is unknown."},
188 {501, "The transaction could not be executed, because the endpoint is not ready."},
189 {502, "The transaction could not be executed, because the endpoint does not have sufficient resources"},
190 {503, "\"All of\" wildcard too complicated."},
191 {504, "Unknown or unsupported command."},
192 {505, "Unsupported RemoteConnectionDescriptor."},
193 {506, "Unable to satisfy both LocalConnectionOptions and RemoteConnectionDescriptor."},
194 {507, "Unsupported functionality."},
195 {508, "Unknown or unsupported quarantine handling."},
196 {509, "Error in RemoteConnectionDescriptor."},
197 {510, "The transaction could not be executed, because a protocol error was detected."},
198 {511, "The transaction could not be executed, because the command contained an unrecognized extension."},
199 {512, "The transaction could not be executed, because the gateway is not equipped to detect one of the requested events."},
200 {513, "The transaction could not be executed, because the gateway is not equipped to generate one of the requested signals."},
201 {514, "The transaction could not be executed, because the gateway cannot send the specified announcement."},
202 {515, "The transaction refers to an incorrect connection-id (may have been already deleted)"},
203 {516, "The transaction refers to an unknown call-id."},
204 {517, "Unsupported or invalid mode."},
205 {518, "Unsupported or unknown package."},
206 {519, "Endpoint does not have a digit map."},
207 {520, "The transaction could not be executed, because the endpoint is 'restarting'."},
208 {521, "Endpoint redirected to another Call Agent."},
209 {522, "No such event or signal."},
210 {523, "Unknown action or illegal combination of actions"},
211 {524, "Internal inconsistency in LocalConnectionOptions"},
212 {525, "Unknown extension in LocalConnectionOptions"},
213 {526, "Insufficient bandwidth"},
214 {527, "Missing RemoteConnectionDescriptor"},
215 {528, "Incompatible protocol version"},
216 {529, "Internal hardware failure"},
217 {530, "CAS signaling protocol error."},
218 {531, "failure of a grouping of trunks (e.g. facility failure)."},
219 {532, "Unsupported value(s) in LocalConnectionOptions."},
220 {533, "Response too large."},
221 {534, "Codec negotiation failure."},
222 {535, "Packetization period not supported"},
223 {536, "Unknown or unsupported RestartMethod"},
224 {537, "Unknown or unsupported digit map extension"},
225 {538, "Event/signal parameter error (e.g., missing, erroneous, unsupported, unknown, etc.)"},
226 {539, "Invalid or unsupported command parameter."},
227 {540, "Per endpoint connection limit exceeded."},
228 {541, "Invalid or unsupported LocalConnectionOptions"},
229 {0, NULL }
231 static value_string_ext mgcp_return_code_vals_ext = VALUE_STRING_EXT_INIT(mgcp_return_code_vals);
233 /* TODO: add/use when tested/have capture to test with */
235 static const value_string mgcp_reason_code_vals[] = {
236 {0, "Endpoint state is normal"},
237 {900, "Endpoint malfunctioning."},
238 {901, "Endpoint taken out-of-service."},
239 {902, "Loss of lower layer connectivity (e.g., downstream sync)."},
240 {903, "QoS resource reservation was lost."},
241 {904, "Manual intervention."},
242 {905, "Facility failure (e.g., DS-0 failure)."},
243 {0, NULL }
249 * Define the trees for mgcp
250 * We need one for MGCP itself, one for the MGCP paramters and one
251 * for each of the dissected parameters
253 static int ett_mgcp;
254 static int ett_mgcp_param;
255 static int ett_mgcp_param_connectionparam;
256 static int ett_mgcp_param_localconnectionoptions;
257 static int ett_mgcp_param_localvoicemetrics;
258 static int ett_mgcp_param_remotevoicemetrics;
261 * Define the tap for mgcp
263 static int mgcp_tap;
266 * Here are the global variables associated with
267 * the various user definable characteristics of the dissection
269 * MGCP has two kinds of "agents", gateways and callagents. Callagents
270 * control gateways in a master/slave sort of arrangement. Since gateways
271 * and callagents have different well known ports and could both
272 * operate under either udp or tcp we have rather a lot of port info to
273 * specify.
275 * global_mgcp_raw_text determines whether we are going to display
276 * the raw text of the mgcp message, much like the HTTP dissector does.
279 static unsigned global_mgcp_gateway_tcp_port = TCP_PORT_MGCP_GATEWAY;
280 static unsigned global_mgcp_gateway_udp_port = UDP_PORT_MGCP_GATEWAY;
281 static unsigned global_mgcp_callagent_tcp_port = TCP_PORT_MGCP_CALLAGENT;
282 static unsigned global_mgcp_callagent_udp_port = UDP_PORT_MGCP_CALLAGENT;
283 static bool global_mgcp_raw_text;
284 static bool global_mgcp_message_count;
286 /* Some basic utility functions that are specific to this dissector */
287 static bool is_mgcp_verb(tvbuff_t *tvb, int offset, int maxlength, const char **verb_name);
288 static bool is_mgcp_rspcode(tvbuff_t *tvb, int offset, int maxlength);
289 static int tvb_parse_param(tvbuff_t *tvb, int offset, int maxlength, int** hf, mgcp_info_t* mi);
292 * The various functions that either dissect some
293 * subpart of MGCP. These aren't really proto dissectors but they
294 * are written in the same style.
296 static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
297 proto_tree *mgcp_tree, proto_tree *ti);
298 static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mgcp_info_t* mi);
299 static void dissect_mgcp_params(tvbuff_t *tvb, proto_tree *tree, mgcp_info_t* mi);
300 static void dissect_mgcp_connectionparams(proto_tree *parent_tree, tvbuff_t *tvb,
301 int offset, int param_type_len,
302 int param_val_len);
303 static void dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, tvbuff_t *tvb,
304 int offset, int param_type_len,
305 int param_val_len);
306 static void dissect_mgcp_localvoicemetrics(proto_tree *parent_tree, tvbuff_t *tvb,
307 int offset, int param_type_len,
308 int param_val_len);
309 static void dissect_mgcp_remotevoicemetrics(proto_tree *parent_tree, tvbuff_t *tvb,
310 int offset, int param_type_len,
311 int param_val_len);
313 static void mgcp_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
315 #define NUM_TIMESTATS 11
317 static const value_string mgcp_message_type[] = {
318 { 0, "Overall"},
319 { 1, "EPCF "},
320 { 2, "CRCX "},
321 { 3, "MDCX "},
322 { 4, "DLCX "},
323 { 5, "RQNT "},
324 { 6, "NTFY "},
325 { 7, "AUEP "},
326 { 8, "AUCX "},
327 { 9, "RSIP "},
328 { 0, NULL}
331 static tap_packet_status
332 mgcpstat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pmi, tap_flags_t flags _U_)
334 rtd_data_t* rtd_data = (rtd_data_t*)pms;
335 rtd_stat_table* ms = &rtd_data->stat_table;
336 const mgcp_info_t *mi = (const mgcp_info_t *)pmi;
337 nstime_t delta;
338 tap_packet_status ret = TAP_PACKET_DONT_REDRAW;
340 switch (mi->mgcp_type) {
342 case MGCP_REQUEST:
343 if (mi->is_duplicate) {
344 /* Duplicate is ignored */
345 ms->time_stats[0].req_dup_num++;
347 else {
348 ms->time_stats[0].open_req_num++;
350 break;
352 case MGCP_RESPONSE:
353 if (mi->is_duplicate) {
354 /* Duplicate is ignored */
355 ms->time_stats[0].rsp_dup_num++;
357 else if (!mi->request_available) {
358 /* no request was seen */
359 ms->time_stats[0].disc_rsp_num++;
361 else {
362 ms->time_stats[0].open_req_num--;
363 /* calculate time delta between request and response */
364 nstime_delta(&delta, &pinfo->abs_ts, &mi->req_time);
366 time_stat_update(&(ms->time_stats[0].rtd[0]), &delta, pinfo);
368 if (g_ascii_strncasecmp(mi->code, "EPCF", 4) == 0 ) {
369 time_stat_update(&(ms->time_stats[0].rtd[1]), &delta, pinfo);
371 else if (g_ascii_strncasecmp(mi->code, "CRCX", 4) == 0 ) {
372 time_stat_update(&(ms->time_stats[0].rtd[2]), &delta, pinfo);
374 else if (g_ascii_strncasecmp(mi->code, "MDCX", 4) == 0 ) {
375 time_stat_update(&(ms->time_stats[0].rtd[3]), &delta, pinfo);
377 else if (g_ascii_strncasecmp(mi->code, "DLCX", 4) == 0 ) {
378 time_stat_update(&(ms->time_stats[0].rtd[4]), &delta, pinfo);
380 else if (g_ascii_strncasecmp(mi->code, "RQNT", 4) == 0 ) {
381 time_stat_update(&(ms->time_stats[0].rtd[5]), &delta, pinfo);
383 else if (g_ascii_strncasecmp(mi->code, "NTFY", 4) == 0 ) {
384 time_stat_update(&(ms->time_stats[0].rtd[6]), &delta, pinfo);
386 else if (g_ascii_strncasecmp(mi->code, "AUEP", 4) == 0 ) {
387 time_stat_update(&(ms->time_stats[0].rtd[7]), &delta, pinfo);
389 else if (g_ascii_strncasecmp(mi->code, "AUCX", 4) == 0 ) {
390 time_stat_update(&(ms->time_stats[0].rtd[8]), &delta, pinfo);
392 else if (g_ascii_strncasecmp(mi->code, "RSIP", 4) == 0 ) {
393 time_stat_update(&(ms->time_stats[0].rtd[9]), &delta, pinfo);
395 else {
396 time_stat_update(&(ms->time_stats[0].rtd[10]), &delta, pinfo);
399 ret = TAP_PACKET_REDRAW;
401 break;
403 default:
404 break;
407 return ret;
412 * Some functions which should be moved to a library
413 * as I think that people may find them of general usefulness.
415 static int tvb_find_null_line(tvbuff_t* tvb, int offset, int len, int* next_offset);
416 static int tvb_find_dot_line(tvbuff_t* tvb, int offset, int len, int* next_offset);
418 static dissector_handle_t sdp_handle;
419 static dissector_handle_t mgcp_handle;
420 extern void
421 dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
422 dissector_handle_t subdissector_handle);
423 extern uint16_t is_asciitpkt(tvbuff_t *tvb);
426 * Init Hash table stuff
429 typedef struct _mgcp_call_info_key
431 uint32_t transid;
432 conversation_t *conversation;
433 } mgcp_call_info_key;
435 static wmem_map_t *mgcp_calls;
437 /* Compare 2 keys */
438 static int mgcp_call_equal(const void *k1, const void *k2)
440 const mgcp_call_info_key* key1 = (const mgcp_call_info_key*) k1;
441 const mgcp_call_info_key* key2 = (const mgcp_call_info_key*) k2;
443 return (key1->transid == key2->transid &&
444 key1->conversation == key2->conversation);
447 /* Calculate a hash key */
448 static unsigned mgcp_call_hash(const void *k)
450 const mgcp_call_info_key* key = (const mgcp_call_info_key*) k;
452 return key->transid + key->conversation->conv_index;
456 /************************************************************************
457 * dissect_mgcp - The dissector for the Media Gateway Control Protocol
458 ************************************************************************/
459 static int dissect_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
461 int sectionlen;
462 uint32_t num_messages;
463 int tvb_sectionend, tvb_sectionbegin, tvb_len;
464 proto_tree *mgcp_tree = NULL;
465 proto_item *ti = NULL, *tii;
466 const char *verb_name = "";
468 /* Initialize variables */
469 tvb_sectionend = 0;
470 tvb_sectionbegin = tvb_sectionend;
471 tvb_len = tvb_reported_length(tvb);
472 num_messages = 0;
475 * Check to see whether we're really dealing with MGCP by looking
476 * for a valid MGCP verb or response code. This isn't infallible,
477 * but it's cheap and it's better than nothing.
479 if (!is_mgcp_verb(tvb, 0, tvb_len, &verb_name) && !is_mgcp_rspcode(tvb, 0, tvb_len))
480 return 0;
483 * Set the columns now, so that they'll be set correctly if we throw
484 * an exception. We can set them later as well....
486 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MGCP");
487 col_clear(pinfo->cinfo, COL_INFO);
490 * Loop through however many mgcp messages may be stuck in
491 * this packet using piggybacking
495 num_messages++;
497 /* Create our mgcp subtree */
498 ti = proto_tree_add_item(tree, proto_mgcp, tvb, 0, -1, ENC_NA);
499 mgcp_tree = proto_item_add_subtree(ti, ett_mgcp);
501 sectionlen = tvb_find_dot_line(tvb, tvb_sectionbegin, -1, &tvb_sectionend);
502 if (sectionlen != -1)
504 dissect_mgcp_message(tvb_new_subset_length_caplen(tvb, tvb_sectionbegin,
505 sectionlen, sectionlen),
506 pinfo, tree, mgcp_tree, ti);
507 tvb_sectionbegin = tvb_sectionend;
509 else
511 break;
513 } while (tvb_sectionend < tvb_len);
515 tii = proto_tree_add_uint(mgcp_tree, hf_mgcp_messagecount, tvb,
516 0 , 0 , num_messages);
517 proto_item_set_hidden(tii);
520 * Add our column information after dissecting SDP
521 * in order to prevent the column info changing to reflect the SDP
522 * (when showing message count)
524 tvb_sectionbegin = 0;
525 if (global_mgcp_message_count == true )
527 if (num_messages > 1)
529 col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MGCP (%i messages)", num_messages);
531 else
533 col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MGCP (%i message)", num_messages);
537 sectionlen = tvb_find_line_end(tvb, tvb_sectionbegin, -1,
538 &tvb_sectionend, false);
539 col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s",
540 tvb_format_text(pinfo->pool, tvb, tvb_sectionbegin, sectionlen));
542 return tvb_len;
545 /************************************************************************
546 * dissect_tpkt_mgcp - The dissector for the ASCII TPKT Media Gateway Control Protocol
547 ************************************************************************/
548 static int dissect_tpkt_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
550 uint16_t ascii_tpkt;
551 int offset = 0;
553 /* Check whether this looks like a ASCII TPKT-encapsulated
554 * MGCP packet.
556 ascii_tpkt = is_asciitpkt(tvb);
558 if (ascii_tpkt != 1 )
561 * It's not a ASCII TPKT packet
562 * in MGCP
564 offset = dissect_mgcp(tvb, pinfo, tree, NULL);
566 else
569 * Dissect ASCII TPKT header
571 dissect_asciitpkt(tvb, pinfo, tree, mgcp_handle);
572 offset = tvb_reported_length(tvb);
575 return offset;
578 /* Dissect an individual MGCP message */
579 static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
580 proto_tree *mgcp_tree, proto_tree *ti)
582 /* Declare variables */
583 int sectionlen;
584 int tvb_sectionend, tvb_sectionbegin, tvb_len;
585 tvbuff_t *next_tvb;
586 const char *verb_name = "";
587 mgcp_info_t* mi = wmem_new0(pinfo->pool, mgcp_info_t);
588 sdp_setup_info_t setup_info = { .hf_id = 0, .hf_type = SDP_TRACE_ID_HF_TYPE_UINT32 };
589 media_content_info_t content_info = { MEDIA_CONTAINER_SIP_DATA, NULL, NULL, &setup_info };
591 mi->mgcp_type = MGCP_OTHERS;
593 /* Initialize variables */
594 tvb_len = tvb_reported_length(tvb);
597 * Check to see whether we're really dealing with MGCP by looking
598 * for a valid MGCP verb or response code. This isn't infallible,
599 * but it's cheap and it's better than nothing.
601 if (is_mgcp_verb(tvb, 0, tvb_len, &verb_name) || is_mgcp_rspcode(tvb, 0, tvb_len))
603 /* dissect first line */
604 tvb_sectionbegin = 0;
605 tvb_sectionend = tvb_sectionbegin;
606 sectionlen = tvb_find_line_end(tvb, 0, -1, &tvb_sectionend, false);
607 if (sectionlen > 0)
609 dissect_mgcp_firstline(tvb_new_subset_length_caplen(tvb, tvb_sectionbegin,
610 sectionlen, sectionlen), pinfo,
611 mgcp_tree, mi);
613 tvb_sectionbegin = tvb_sectionend;
615 /* Dissect params */
616 if (tvb_sectionbegin < tvb_len)
618 sectionlen = tvb_find_null_line(tvb, tvb_sectionbegin, -1,
619 &tvb_sectionend);
620 if (sectionlen > 0)
622 dissect_mgcp_params(tvb_new_subset_length_caplen(tvb, tvb_sectionbegin, sectionlen, sectionlen),
623 mgcp_tree, mi);
627 /* Set the mgcp payload length correctly so we don't include any
628 encapsulated SDP */
629 sectionlen = tvb_sectionend;
630 proto_item_set_len(ti, sectionlen);
632 /* Display the raw text of the mgcp message if desired */
634 /* Do we want to display the raw text of our MGCP packet? */
635 if (global_mgcp_raw_text)
637 mgcp_raw_text_add(tvb, mgcp_tree);
640 /* Dissect sdp payload */
641 if (tvb_sectionend < tvb_len)
643 setup_info.is_osmux = mi->is_osmux;
644 next_tvb = tvb_new_subset_remaining(tvb, tvb_sectionend);
645 call_dissector_with_data(sdp_handle, next_tvb, pinfo, tree, &content_info);
652 * Add the raw text of the message to the dissect tree if appropriate
653 * preferences are specified.
655 static void mgcp_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
657 int tvb_linebegin, tvb_lineend, linelen;
659 tvb_linebegin = 0;
663 tvb_find_line_end(tvb, tvb_linebegin, -1, &tvb_lineend, false);
664 linelen = tvb_lineend - tvb_linebegin;
665 proto_tree_add_format_text(tree, tvb, tvb_linebegin, linelen);
666 tvb_linebegin = tvb_lineend;
667 } while (tvb_offset_exists(tvb, tvb_lineend));
671 * is_mgcp_verb - A function for determining whether there is a
672 * MGCP verb at offset in tvb
674 * Parameter:
675 * tvb - The tvbuff in which we are looking for an MGCP verb
676 * offset - The offset in tvb at which we are looking for a MGCP verb
677 * maxlength - The maximum distance from offset we may look for the
678 * characters that make up a MGCP verb.
679 * verb_name - The name for the verb code found (output)
681 * Return: true if there is an MGCP verb at offset in tvb, otherwise false
683 static bool is_mgcp_verb(tvbuff_t *tvb, int offset, int maxlength, const char **verb_name)
685 bool returnvalue = false;
686 char word[5];
688 /* This function is used for checking if a packet is actually an
689 mgcp packet. Make sure that we do not throw an exception
690 during such a check. If we did throw an exeption, we could
691 not refuse the packet and give other dissectors the chance to
692 look at it. */
693 if (tvb_captured_length_remaining(tvb, offset) < (int)sizeof(word))
694 return false;
696 /* Read the string into 'word' and see if it looks like the start of a verb */
697 if ((maxlength >= 4) && tvb_get_raw_bytes_as_string(tvb, offset, word, sizeof word))
699 if (((g_ascii_strncasecmp(word, "EPCF", 4) == 0) && (*verb_name = "EndpointConfiguration")) ||
700 ((g_ascii_strncasecmp(word, "CRCX", 4) == 0) && (*verb_name = "CreateConnection")) ||
701 ((g_ascii_strncasecmp(word, "MDCX", 4) == 0) && (*verb_name = "ModifyConnection")) ||
702 ((g_ascii_strncasecmp(word, "DLCX", 4) == 0) && (*verb_name = "DeleteConnection")) ||
703 ((g_ascii_strncasecmp(word, "RQNT", 4) == 0) && (*verb_name = "NotificationRequest")) ||
704 ((g_ascii_strncasecmp(word, "NTFY", 4) == 0) && (*verb_name = "Notify")) ||
705 ((g_ascii_strncasecmp(word, "AUEP", 4) == 0) && (*verb_name = "AuditEndpoint")) ||
706 ((g_ascii_strncasecmp(word, "AUCX", 4) == 0) && (*verb_name = "AuditConnection")) ||
707 ((g_ascii_strncasecmp(word, "RSIP", 4) == 0) && (*verb_name = "RestartInProgress")) ||
708 ((g_ascii_strncasecmp(word, "MESG", 4) == 0) && (*verb_name = "Message")) ||
709 (word[0] == 'X' && g_ascii_isalpha(word[1]) && g_ascii_isalpha(word[2]) &&
710 g_ascii_isalpha(word[3]) && (*verb_name = "*Experimental*")))
712 returnvalue = true;
716 /* May be whitespace after verb code - anything else is an error.. */
717 if (returnvalue && maxlength >= 5)
719 char next = tvb_get_uint8(tvb, 4);
720 if ((next != ' ') && (next != '\t'))
722 returnvalue = false;
726 return returnvalue;
730 * is_mgcp_rspcode - A function for determining whether something which
731 * looks roughly like a MGCP response code (3-digit number)
732 * is at 'offset' in tvb
734 * Parameters:
735 * tvb - The tvbuff in which we are looking for an MGCP response code
736 * offset - The offset in tvb at which we are looking for a MGCP response code
737 * maxlength - The maximum distance from offset we may look for the
738 * characters that make up a MGCP response code.
740 * Return: true if there is an MGCP response code at offset in tvb,
741 * otherwise false
743 static bool is_mgcp_rspcode(tvbuff_t *tvb, int offset, int maxlength)
745 bool returnvalue = false;
746 char word[4];
748 /* see the comment in is_mgcp_verb() */
749 if (tvb_captured_length_remaining(tvb, offset) < (int)sizeof(word))
750 return false;
752 /* Do 1st 3 characters look like digits? */
753 if (maxlength >= 3)
755 tvb_get_raw_bytes_as_string(tvb, offset, word, sizeof word);
756 if (g_ascii_isdigit(word[0]) && g_ascii_isdigit(word[1]) && g_ascii_isdigit(word[2]))
758 returnvalue = true;
762 /* Maybe some white space after the 3rd digit - anything else is an error */
763 if (returnvalue && maxlength >= 4)
765 char next = tvb_get_uint8(tvb, 3);
766 if ((next != ' ') && (next != '\t'))
768 returnvalue = false;
772 return returnvalue;
776 * tvb_parse_param - Parse the MGCP param into a type and a value.
778 * Parameters:
779 * tvb - The tvbuff containing the MGCP param we are to parse.
780 * offset - The offset in tvb at which we will begin looking for a
781 * MGCP parameter to parse.
782 * len - The maximum distance from offset in tvb that we can look for
783 * an MGCP parameter to parse.
784 * hf - The place to write a pointer to the integer representing the
785 * header field associated with the MGCP parameter parsed.
787 * Returns: The offset in tvb where the value of the MGCP parameter
788 * begins.
790 static int tvb_parse_param(tvbuff_t* tvb, int offset, int len, int** hf, mgcp_info_t* mi)
792 int returnvalue = -1, tvb_current_offset, ext_off;
793 uint8_t tempchar, plus_minus;
794 char **buf;
796 tvb_current_offset = offset;
797 *hf = NULL;
798 buf = NULL;
800 if (len > 0)
802 tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset));
804 switch (tempchar)
806 case 'K':
807 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
809 *hf = &hf_mgcp_param_invalid;
810 break;
812 *hf = &hf_mgcp_param_rspack;
813 break;
814 case 'B':
815 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
817 *hf = &hf_mgcp_param_invalid;
818 break;
820 *hf = &hf_mgcp_param_bearerinfo;
821 break;
822 case 'C':
823 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
825 *hf = &hf_mgcp_param_invalid;
826 break;
828 *hf = &hf_mgcp_param_callid;
829 break;
830 case 'I':
831 tvb_current_offset++;
832 if (len > (tvb_current_offset - offset) &&
833 (tempchar = tvb_get_uint8(tvb, tvb_current_offset)) == ':')
835 *hf = &hf_mgcp_param_connectionid;
836 tvb_current_offset--;
838 else
839 if (tempchar == '2')
841 *hf = &hf_mgcp_param_secondconnectionid;
843 break;
844 case 'N':
845 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
847 *hf = &hf_mgcp_param_invalid;
848 break;
850 *hf = &hf_mgcp_param_notifiedentity;
851 break;
852 case 'X':
853 /* Move past 'X' */
854 tvb_current_offset++;
856 /* X: is RequestIdentifier */
857 if (len > (tvb_current_offset - offset) &&
858 (tempchar = tvb_get_uint8(tvb, tvb_current_offset)) == ':')
860 *hf = &hf_mgcp_param_requestid;
861 tvb_current_offset--;
863 /* XRM/MCR */
864 else
865 if (len > (tvb_current_offset - offset) &&
866 ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb,tvb_current_offset))) == 'R')
868 /* Move past 'R' */
869 tvb_current_offset += 3;
870 if (len > (tvb_current_offset - offset) &&
871 ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb,tvb_current_offset))) == 'R')
873 *hf = &hf_mgcp_param_remotevoicemetrics;
875 else
876 if (len > (tvb_current_offset - offset) &&
877 ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb,tvb_current_offset))) == 'L')
879 *hf = &hf_mgcp_param_localvoicemetrics;
881 tvb_current_offset -= 4;
884 /* X+...: or X-....: are vendor extension parameters */
885 else
886 if (len > (tvb_current_offset - offset) &&
887 ((plus_minus = tvb_get_uint8(tvb, tvb_current_offset)) == '-' ||
888 (plus_minus == '+')))
890 /* Move past + or - */
891 tvb_current_offset++;
893 /* Keep going, through possible vendor param name */
894 /* We have a mempbrk; perhaps an equivalent of strspn
895 * for tvbs would be useful.
897 for (ext_off = 0; len > (ext_off + tvb_current_offset-offset); ext_off++) {
898 tempchar = tvb_get_uint8(tvb, tvb_current_offset + ext_off);
899 if (!g_ascii_isalpha(tempchar) && !g_ascii_isdigit(tempchar)) break;
902 if (tempchar == ':')
904 /* Looks like a valid vendor param name */
905 ws_debug("MGCP Extension: %s", tvb_get_string_enc(wmem_packet_scope(), tvb, tvb_current_offset, ext_off, ENC_ASCII));
906 switch (plus_minus)
908 case '+':
909 *hf = &hf_mgcp_param_extension_critical;
910 break;
911 case '-':
912 if (tvb_strncaseeql(tvb, tvb_current_offset, "OSMUX", ext_off) == 0) {
913 *hf = &hf_mgcp_param_x_osmux;
914 } else {
915 *hf = &hf_mgcp_param_extension;
917 break;
919 /* -1: Final generic path below expects us to point to char before the ':'. */
920 tvb_current_offset += ext_off - 1;
923 break;
924 case 'L':
925 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
927 *hf = &hf_mgcp_param_invalid;
928 break;
930 *hf = &hf_mgcp_param_localconnoptions;
931 break;
932 case 'M':
933 tvb_current_offset++;
934 if (len > (tvb_current_offset - offset) &&
935 (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
937 *hf = &hf_mgcp_param_connectionmode;
938 tvb_current_offset--;
940 else
941 if (tempchar == 'D')
943 *hf = &hf_mgcp_param_maxmgcpdatagram;
945 break;
946 case 'R':
947 tvb_current_offset++;
948 if (len > (tvb_current_offset - offset) &&
949 (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
951 *hf = &hf_mgcp_param_reqevents;
952 tvb_current_offset--;
954 else
955 if ( tempchar == 'M')
957 *hf = &hf_mgcp_param_restartmethod;
959 else
960 if (tempchar == 'D')
962 *hf = &hf_mgcp_param_restartdelay;
964 break;
965 case 'S':
966 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
968 *hf = &hf_mgcp_param_invalid;
969 break;
971 *hf = &hf_mgcp_param_signalreq;
972 buf = &(mi->signalReq);
973 break;
974 case 'D':
975 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
977 if (len > (tvb_current_offset + 5 - offset) &&
978 (g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset + 1) == 'Q')) &&
979 ( tvb_get_uint8(tvb, tvb_current_offset + 2) == '-' ) &&
980 (g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset + 3) == 'R')) &&
981 (g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset + 4) == 'I')) &&
982 ( tvb_get_uint8(tvb, tvb_current_offset + 5) == ':' )
984 tvb_current_offset+=4;
985 *hf = &hf_mgcp_param_resourceid;
986 break;
989 *hf = &hf_mgcp_param_invalid;
990 break;
992 *hf = &hf_mgcp_param_digitmap;
993 mi->hasDigitMap = true;
994 break;
995 case 'O':
996 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
998 *hf = &hf_mgcp_param_invalid;
999 break;
1001 *hf = &hf_mgcp_param_observedevent;
1002 buf = &(mi->observedEvents);
1003 break;
1004 case 'P':
1005 tvb_current_offset++;
1006 if (len > (tvb_current_offset - offset) &&
1007 (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
1009 *hf = &hf_mgcp_param_connectionparam;
1010 tvb_current_offset--;
1012 else
1013 if ( tempchar == 'L')
1015 *hf = &hf_mgcp_param_packagelist;
1017 break;
1018 case 'E':
1019 tvb_current_offset++;
1020 if (len > (tvb_current_offset - offset) &&
1021 (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
1023 *hf = &hf_mgcp_param_reasoncode;
1024 tvb_current_offset--;
1026 else
1027 if ( tempchar == 'S')
1029 *hf = &hf_mgcp_param_eventstates;
1031 break;
1032 case 'Z':
1033 tvb_current_offset++;
1034 if (len > (tvb_current_offset - offset) &&
1035 (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
1037 *hf = &hf_mgcp_param_specificendpoint;
1038 tvb_current_offset--;
1040 else
1041 if (tempchar == '2')
1043 *hf = &hf_mgcp_param_secondendpointid;
1045 break;
1046 case 'F':
1047 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
1049 *hf = &hf_mgcp_param_invalid;
1050 break;
1052 *hf = &hf_mgcp_param_reqinfo;
1053 break;
1054 case 'Q':
1055 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
1057 *hf = &hf_mgcp_param_invalid;
1058 break;
1060 *hf = &hf_mgcp_param_quarantinehandling;
1061 break;
1062 case 'T':
1063 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
1065 *hf = &hf_mgcp_param_invalid;
1066 break;
1068 *hf = &hf_mgcp_param_detectedevents;
1069 break;
1070 case 'A':
1071 if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
1073 *hf = &hf_mgcp_param_invalid;
1074 break;
1076 *hf = &hf_mgcp_param_capabilities;
1077 break;
1079 default:
1080 *hf = &hf_mgcp_param_invalid;
1081 break;
1084 /* Move to (hopefully) the colon */
1085 tvb_current_offset++;
1087 /* Add a recognised parameter type if we have one */
1088 if (*hf != NULL && len > (tvb_current_offset - offset) &&
1089 tvb_get_uint8(tvb, tvb_current_offset) == ':')
1091 tvb_current_offset++;
1092 tvb_current_offset = tvb_skip_wsp(tvb, tvb_current_offset, (len - tvb_current_offset + offset));
1093 returnvalue = tvb_current_offset;
1095 /* set the observedEvents or signalReq used in Voip Calls analysis */
1096 if (buf != NULL) {
1097 *buf = tvb_get_string_enc(wmem_packet_scope(), tvb, tvb_current_offset, (len - tvb_current_offset + offset), ENC_ASCII);
1101 else
1103 /* Was an empty line */
1104 *hf = &hf_mgcp_param_invalid;
1107 /* For these types, show the whole line */
1108 if ((*hf == &hf_mgcp_param_invalid) ||
1109 (*hf == &hf_mgcp_param_extension) || (*hf == &hf_mgcp_param_extension_critical) ||
1110 (*hf == &hf_mgcp_param_localvoicemetrics) || (*hf == &hf_mgcp_param_remotevoicemetrics))
1112 returnvalue = offset;
1115 return returnvalue;
1120 * dissect_mgcp_firstline - Dissects the firstline of an MGCP message.
1121 * Adds the appropriate headers fields to
1122 * tree for the dissection of the first line
1123 * of an MGCP message.
1125 * Parameters:
1126 * tvb - The tvb containing the first line of an MGCP message. This
1127 * tvb is presumed to ONLY contain the first line of the MGCP
1128 * message.
1129 * pinfo - The packet info for the packet. This is not really used
1130 * by this function but is passed through so as to retain the
1131 * style of a dissector.
1132 * tree - The tree from which to hang the structured information parsed
1133 * from the first line of the MGCP message.
1135 static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mgcp_info_t* mi)
1137 int tvb_current_offset, tvb_previous_offset, tvb_len, tvb_current_len;
1138 int tokennum, tokenlen;
1139 proto_item* hidden_item;
1140 char *transid = NULL;
1141 char *code = NULL;
1142 char *endpointId = NULL;
1143 mgcp_type_t mgcp_type = MGCP_OTHERS;
1144 conversation_t* conversation;
1145 mgcp_call_info_key mgcp_call_key;
1146 mgcp_call_info_key *new_mgcp_call_key = NULL;
1147 mgcp_call_t *mgcp_call = NULL;
1148 nstime_t delta;
1149 const char *verb_description = "";
1150 char code_with_verb[64] = ""; /* To fit "<4-letter-code> (<longest-verb>)" */
1151 proto_item* pi;
1153 static address null_address = ADDRESS_INIT_NONE;
1154 tvb_previous_offset = 0;
1155 tvb_len = tvb_reported_length(tvb);
1156 tvb_current_offset = tvb_previous_offset;
1157 mi->is_duplicate = false;
1158 mi->request_available = false;
1160 /* if (tree) */
1162 tokennum = 0;
1166 tvb_current_len = tvb_reported_length_remaining(tvb, tvb_previous_offset);
1167 tvb_current_offset = tvb_find_uint8(tvb, tvb_previous_offset, tvb_current_len, ' ');
1168 if (tvb_current_offset == -1)
1170 tvb_current_offset = tvb_len;
1171 tokenlen = tvb_current_len;
1173 else
1175 tokenlen = tvb_current_offset - tvb_previous_offset;
1177 if (tokennum == 0)
1179 if (tokenlen > 4)
1181 /* XXX - exception */
1182 return;
1185 code = tvb_format_text(pinfo->pool, tvb, tvb_previous_offset, tokenlen);
1186 (void) g_strlcpy(mi->code, code, 5);
1187 if (is_mgcp_verb(tvb, tvb_previous_offset, tvb_current_len, &verb_description))
1189 mgcp_type = MGCP_REQUEST;
1190 if (verb_description != NULL)
1192 /* Can show verb along with code if known */
1193 snprintf(code_with_verb, 64, "%s (%s)", code, verb_description);
1196 proto_tree_add_string_format(tree, hf_mgcp_req_verb, tvb,
1197 tvb_previous_offset, tokenlen,
1198 code, "%s",
1199 strlen(code_with_verb) ? code_with_verb : code);
1201 else
1202 if (is_mgcp_rspcode(tvb, tvb_previous_offset, tvb_current_len))
1204 bool rspcode_valid;
1205 mgcp_type = MGCP_RESPONSE;
1206 rspcode_valid = ws_strtou32(code, NULL, &mi->rspcode);
1207 pi = proto_tree_add_uint(tree, hf_mgcp_rsp_rspcode, tvb,
1208 tvb_previous_offset, tokenlen, mi->rspcode);
1209 if (!rspcode_valid)
1210 expert_add_info(pinfo, pi, &ei_mgcp_rsp_rspcode_invalid);
1212 else
1214 break;
1217 if (tokennum == 1)
1219 transid = tvb_format_text(pinfo->pool, tvb, tvb_previous_offset, tokenlen);
1220 /* XXX - what if this isn't a valid text string? */
1221 mi->transid = (uint32_t)strtoul(transid, NULL, 10);
1222 proto_tree_add_string(tree, hf_mgcp_transid, tvb,
1223 tvb_previous_offset, tokenlen, transid);
1225 if (tokennum == 2)
1227 if (mgcp_type == MGCP_REQUEST)
1229 endpointId = tvb_format_text(pinfo->pool, tvb, tvb_previous_offset, tokenlen);
1230 mi->endpointId = wmem_strdup(pinfo->pool, endpointId);
1231 proto_tree_add_string(tree, hf_mgcp_req_endpoint, tvb,
1232 tvb_previous_offset, tokenlen, endpointId);
1234 else
1235 if (mgcp_type == MGCP_RESPONSE)
1237 if (tvb_current_offset < tvb_len)
1239 tokenlen = tvb_find_line_end(tvb, tvb_previous_offset,
1240 -1, &tvb_current_offset, false);
1242 else
1244 tokenlen = tvb_current_len;
1246 proto_tree_add_string(tree, hf_mgcp_rsp_rspstring, tvb,
1247 tvb_previous_offset, tokenlen,
1248 tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
1249 tokenlen));
1250 break;
1254 if ((tokennum == 3 && mgcp_type == MGCP_REQUEST))
1256 if (tvb_current_offset < tvb_len )
1258 tokenlen = tvb_find_line_end(tvb, tvb_previous_offset,
1259 -1, &tvb_current_offset, false);
1261 else
1263 tokenlen = tvb_current_len;
1265 proto_tree_add_string(tree, hf_mgcp_version, tvb,
1266 tvb_previous_offset, tokenlen,
1267 tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
1268 tokenlen));
1269 break;
1271 if (tvb_current_offset < tvb_len)
1273 tvb_previous_offset = tvb_skip_wsp(tvb, tvb_current_offset,
1274 tvb_current_len);
1276 tokennum++;
1277 } while (tvb_current_offset < tvb_len && tvb_offset_exists(tvb, tvb_current_offset) && tvb_previous_offset < tvb_len && tokennum <= 3);
1279 switch (mgcp_type)
1281 case MGCP_RESPONSE:
1282 hidden_item = proto_tree_add_boolean(tree, hf_mgcp_rsp, tvb, 0, 0, true);
1283 proto_item_set_hidden(hidden_item);
1284 /* Check for MGCP response. A response must match a call that
1285 we've seen, and the response must be sent to the same
1286 port and address that the call came from, and must
1287 come from the port to which the call was sent.
1289 If the transport is connection-oriented (we check, for
1290 now, only for "pinfo->ptype" of PT_TCP), we take
1291 into account the address from which the call was sent
1292 and the address to which the call was sent, because
1293 the addresses of the two endpoints should be the same
1294 for all calls and replies.
1296 If the transport is connectionless, we don't worry
1297 about the address to which the call was sent and from
1298 which the reply was sent, because there's no
1299 guarantee that the reply will come from the address
1300 to which the call was sent. */
1301 if (pinfo->ptype == PT_TCP)
1303 conversation = find_conversation_pinfo(pinfo, 0);
1305 else
1307 /* XXX - can we just use NO_ADDR_B? Unfortunately,
1308 * you currently still have to pass a non-null
1309 * pointer for the second address argument even
1310 * if you do that.
1312 conversation = find_conversation(pinfo->num, &null_address,
1313 &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
1314 pinfo->destport, 0);
1316 if (conversation != NULL)
1318 /* Look only for matching request, if
1319 matching conversation is available. */
1320 mgcp_call_key.transid = mi->transid;
1321 mgcp_call_key.conversation = conversation;
1322 mgcp_call = (mgcp_call_t *)wmem_map_lookup(mgcp_calls, &mgcp_call_key);
1323 if (mgcp_call)
1325 /* Indicate the frame to which this is a reply. */
1326 if (mgcp_call->req_num)
1328 proto_item* item;
1329 mi->request_available = true;
1330 mgcp_call->responded = true;
1331 mi->req_num = mgcp_call->req_num;
1332 (void) g_strlcpy(mi->code, mgcp_call->code, 5);
1333 item = proto_tree_add_uint_format(tree, hf_mgcp_req_frame,
1334 tvb, 0, 0, mgcp_call->req_num,
1335 "This is a response to a request in frame %u",
1336 mgcp_call->req_num);
1337 proto_item_set_generated(item);
1338 nstime_delta(&delta, &pinfo->abs_ts, &mgcp_call->req_time);
1339 item = proto_tree_add_time(tree, hf_mgcp_time, tvb, 0, 0, &delta);
1340 proto_item_set_generated(item);
1343 if (mgcp_call->rsp_num == 0)
1345 /* We have not yet seen a response to that call, so
1346 this must be the first response; remember its
1347 frame number. */
1348 mgcp_call->rsp_num = pinfo->num;
1350 else
1352 /* We have seen a response to this call - but was it
1353 *this* response? (disregard provisional responses) */
1354 if ((mgcp_call->rsp_num != pinfo->num) &&
1355 (mi->rspcode >= 200) &&
1356 (mi->rspcode == mgcp_call->rspcode))
1358 proto_item* item;
1360 /* No, so it's a duplicate response. Mark it as such. */
1361 mi->is_duplicate = true;
1362 col_append_fstr(pinfo->cinfo, COL_INFO,
1363 ", Duplicate Response %u",
1364 mi->transid);
1366 item = proto_tree_add_uint(tree, hf_mgcp_dup, tvb, 0, 0, mi->transid);
1367 proto_item_set_hidden(item);
1368 item = proto_tree_add_uint(tree, hf_mgcp_rsp_dup,
1369 tvb, 0, 0, mi->transid);
1370 proto_item_set_generated(item);
1371 item = proto_tree_add_uint(tree, hf_mgcp_rsp_dup_frame,
1372 tvb, 0, 0, mgcp_call->rsp_num);
1373 proto_item_set_generated(item);
1376 /* Now store the response code (after comparison above) */
1377 mgcp_call->rspcode = mi->rspcode;
1380 break;
1381 case MGCP_REQUEST:
1382 hidden_item = proto_tree_add_boolean(tree, hf_mgcp_req, tvb, 0, 0, true);
1383 proto_item_set_hidden(hidden_item);
1384 /* Keep track of the address and port whence the call came,
1385 * and the port to which the call is being sent, so that
1386 * we can match up calls with replies.
1388 * If the transport is connection-oriented (we check, for
1389 * now, only for "pinfo->ptype" of PT_TCP), we take
1390 * into account the address from which the call was sent
1391 * and the address to which the call was sent, because
1392 * the addresses of the two endpoints should be the same
1393 * for all calls and replies.
1395 * If the transport is connectionless, we don't worry
1396 * about the address to which the call was sent and from
1397 * which the reply was sent, because there's no
1398 * guarantee that the reply will come from the address
1399 * to which the call was sent.
1401 if (pinfo->ptype == PT_TCP)
1403 conversation = find_conversation_pinfo(pinfo, 0);
1405 else
1408 * XXX - can we just use NO_ADDR_B? Unfortunately,
1409 * you currently still have to pass a non-null
1410 * pointer for the second address argument even
1411 * if you do that.
1413 conversation = find_conversation(pinfo->num, &pinfo->src,
1414 &null_address, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
1415 pinfo->destport, 0);
1417 if (conversation == NULL)
1419 /* It's not part of any conversation - create a new one. */
1420 if (pinfo->ptype == PT_TCP)
1422 conversation = conversation_new(pinfo->num, &pinfo->src,
1423 &pinfo->dst, CONVERSATION_TCP, pinfo->srcport,
1424 pinfo->destport, 0);
1426 else
1428 conversation = conversation_new(pinfo->num, &pinfo->src,
1429 &null_address, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
1430 pinfo->destport, 0);
1434 /* Prepare the key data */
1435 mgcp_call_key.transid = mi->transid;
1436 mgcp_call_key.conversation = conversation;
1438 /* Look up the request */
1439 mgcp_call = (mgcp_call_t *)wmem_map_lookup(mgcp_calls, &mgcp_call_key);
1440 if (mgcp_call != NULL)
1442 /* We've seen a request with this TRANSID, with the same
1443 source and destination, before - but was it
1444 *this* request? */
1445 if (pinfo->num != mgcp_call->req_num)
1447 /* No, so it's a duplicate request. Mark it as such. */
1448 mi->is_duplicate = true;
1449 mi->req_num = mgcp_call->req_num;
1450 col_append_fstr(pinfo->cinfo, COL_INFO,
1451 ", Duplicate Request %u",
1452 mi->transid);
1453 if (tree)
1455 proto_item* item;
1456 item = proto_tree_add_uint(tree, hf_mgcp_dup, tvb, 0, 0, mi->transid);
1457 proto_item_set_hidden(item);
1458 item = proto_tree_add_uint(tree, hf_mgcp_req_dup, tvb, 0, 0, mi->transid);
1459 proto_item_set_generated(item);
1460 item = proto_tree_add_uint(tree, hf_mgcp_req_dup_frame, tvb, 0, 0, mi->req_num);
1461 proto_item_set_generated(item);
1465 else
1467 /* Prepare the value data.
1468 "req_num" and "rsp_num" are frame numbers;
1469 frame numbers are 1-origin, so we use 0
1470 to mean "we don't yet know in which frame
1471 the reply for this call appears". */
1472 new_mgcp_call_key = (mgcp_call_info_key *)wmem_alloc(wmem_file_scope(), sizeof(*new_mgcp_call_key));
1473 *new_mgcp_call_key = mgcp_call_key;
1474 mgcp_call = (mgcp_call_t *)wmem_alloc(wmem_file_scope(), sizeof(*mgcp_call));
1475 mgcp_call->req_num = pinfo->num;
1476 mgcp_call->rsp_num = 0;
1477 mgcp_call->transid = mi->transid;
1478 mgcp_call->responded = false;
1479 mgcp_call->req_time=pinfo->abs_ts;
1480 (void) g_strlcpy(mgcp_call->code, mi->code, 5);
1482 /* Store it */
1483 wmem_map_insert(mgcp_calls, new_mgcp_call_key, mgcp_call);
1485 if (mgcp_call->rsp_num)
1487 proto_item* item = proto_tree_add_uint_format(tree, hf_mgcp_rsp_frame,
1488 tvb, 0, 0, mgcp_call->rsp_num,
1489 "The response to this request is in frame %u",
1490 mgcp_call->rsp_num);
1491 proto_item_set_generated(item);
1493 break;
1494 default:
1495 break;
1498 mi->mgcp_type = mgcp_type;
1499 if (mgcp_call)
1501 mi->req_time.secs=mgcp_call->req_time.secs;
1502 mi->req_time.nsecs=mgcp_call->req_time.nsecs;
1506 tap_queue_packet(mgcp_tap, pinfo, mi);
1510 * dissect_mgcp_params - Dissects the parameters of an MGCP message.
1511 * Adds the appropriate headers fields to
1512 * tree for the dissection of the parameters
1513 * of an MGCP message.
1515 * Parameters:
1516 * tvb - The tvb containing the parameters of an MGCP message. This
1517 * tvb is presumed to ONLY contain the part of the MGCP
1518 * message which contains the MGCP parameters.
1519 * tree - The tree from which to hang the structured information parsed
1520 * from the parameters of the MGCP message.
1522 static void dissect_mgcp_params(tvbuff_t *tvb, proto_tree *tree, mgcp_info_t* mi)
1524 int linelen, tokenlen, *my_param;
1525 int tvb_lineend, tvb_linebegin, tvb_len, old_lineend;
1526 int tvb_tokenbegin;
1527 proto_tree *mgcp_param_ti, *mgcp_param_tree;
1529 tvb_len = tvb_reported_length(tvb);
1530 tvb_linebegin = 0;
1531 tvb_lineend = tvb_linebegin;
1533 mgcp_param_ti = proto_tree_add_item(tree, hf_mgcp_params, tvb,
1534 tvb_linebegin, tvb_len, ENC_NA);
1535 proto_item_set_text(mgcp_param_ti, "Parameters");
1536 mgcp_param_tree = proto_item_add_subtree(mgcp_param_ti, ett_mgcp_param);
1538 /* Parse the parameters */
1539 while (tvb_offset_exists(tvb, tvb_lineend))
1541 old_lineend = tvb_lineend;
1542 linelen = tvb_find_line_end(tvb, tvb_linebegin, -1, &tvb_lineend, false);
1543 tvb_tokenbegin = tvb_parse_param(tvb, tvb_linebegin, linelen, &my_param, mi);
1545 if (my_param)
1547 tokenlen = tvb_find_line_end(tvb, tvb_tokenbegin, -1, &tvb_lineend, false);
1548 if (*my_param == hf_mgcp_param_connectionparam) {
1549 dissect_mgcp_connectionparams(mgcp_param_tree, tvb, tvb_linebegin,
1550 tvb_tokenbegin - tvb_linebegin, tokenlen);
1551 } else if (*my_param == hf_mgcp_param_localconnoptions) {
1552 dissect_mgcp_localconnectionoptions(mgcp_param_tree, tvb, tvb_linebegin,
1553 tvb_tokenbegin - tvb_linebegin, tokenlen);
1554 } else if (*my_param == hf_mgcp_param_localvoicemetrics) {
1555 dissect_mgcp_localvoicemetrics(mgcp_param_tree, tvb, tvb_linebegin,
1556 tvb_tokenbegin - tvb_linebegin, tokenlen);
1557 } else if (*my_param == hf_mgcp_param_remotevoicemetrics) {
1558 dissect_mgcp_remotevoicemetrics(mgcp_param_tree, tvb, tvb_linebegin,
1559 tvb_tokenbegin - tvb_linebegin, tokenlen);
1560 } else if (*my_param == hf_mgcp_param_x_osmux) {
1561 proto_tree_add_string(mgcp_param_tree, *my_param, tvb,
1562 tvb_linebegin, linelen,
1563 tvb_format_text(wmem_packet_scope(),
1564 tvb, tvb_tokenbegin, tokenlen));
1565 /* Mark that Osmux is used, so that packet-sdp.c doesn't call
1566 * srtp_add_address() and decodes it as RTP. */
1567 mi->is_osmux = true;
1568 } else {
1569 proto_tree_add_string(mgcp_param_tree, *my_param, tvb,
1570 tvb_linebegin, linelen,
1571 tvb_format_text(wmem_packet_scope(),
1572 tvb, tvb_tokenbegin, tokenlen));
1576 tvb_linebegin = tvb_lineend;
1577 /* Its a infinite loop if we didn't advance (or went backwards) */
1578 if (old_lineend >= tvb_lineend)
1580 /* XXX - exception */
1581 break;
1586 /* Dissect the connection params */
1587 static void
1588 dissect_mgcp_connectionparams(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int param_type_len, int param_val_len)
1590 proto_tree *tree;
1591 proto_item *item;
1593 char *tokenline;
1594 char **tokens;
1595 unsigned i;
1597 item = proto_tree_add_item(parent_tree, hf_mgcp_param_connectionparam, tvb, offset, param_type_len+param_val_len, ENC_ASCII);
1598 tree = proto_item_add_subtree(item, ett_mgcp_param_connectionparam);
1600 /* The P: line */
1601 offset += param_type_len; /* skip the P: */
1602 tokenline = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, param_val_len, ENC_ASCII);
1604 /* Split into type=value pairs separated by comma */
1605 tokens = wmem_strsplit(wmem_packet_scope(), tokenline, ",", -1);
1607 for (i = 0; tokens[i] != NULL; i++)
1609 char **typval;
1610 unsigned tokenlen;
1611 int hf_uint = 0;
1612 int hf_string = 0;
1614 tokenlen = (int)strlen(tokens[i]);
1615 typval = wmem_strsplit(wmem_packet_scope(), tokens[i], "=", 2);
1616 if ((typval[0] != NULL) && (typval[1] != NULL))
1618 if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PS"))
1620 hf_uint = hf_mgcp_param_connectionparam_ps;
1622 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "OS"))
1624 hf_uint = hf_mgcp_param_connectionparam_os;
1626 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PR"))
1628 hf_uint = hf_mgcp_param_connectionparam_pr;
1630 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "OR"))
1632 hf_uint = hf_mgcp_param_connectionparam_or;
1634 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PL"))
1636 hf_uint = hf_mgcp_param_connectionparam_pl;
1638 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JI"))
1640 hf_uint = hf_mgcp_param_connectionparam_ji;
1642 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "LA"))
1644 hf_uint = hf_mgcp_param_connectionparam_la;
1646 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PC/RPS"))
1648 hf_uint = hf_mgcp_param_connectionparam_pcrps;
1649 } else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PC/ROS"))
1651 hf_uint = hf_mgcp_param_connectionparam_pcros;
1653 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PC/RPL"))
1655 hf_uint = hf_mgcp_param_connectionparam_pcrpl;
1657 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PC/RJI"))
1659 hf_uint = hf_mgcp_param_connectionparam_pcrji;
1661 else if (!g_ascii_strncasecmp(g_strstrip(typval[0]), "X-", 2))
1663 hf_string = hf_mgcp_param_connectionparam_x;
1666 if (hf_uint > 0)
1668 proto_tree_add_uint(tree, hf_uint, tvb, offset, tokenlen, (uint32_t)strtoul(typval[1], NULL, 10));
1670 else if (hf_string > 0)
1672 proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
1674 else
1676 proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
1679 else
1681 proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
1683 offset += tokenlen + 1; /* 1 extra for the delimiter */
1688 /* Dissect the local connection option */
1689 static void
1690 dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int param_type_len, int param_val_len)
1692 proto_tree *tree;
1693 proto_item *item;
1695 char *tokenline;
1696 char **tokens;
1697 unsigned i;
1699 item = proto_tree_add_item(parent_tree, hf_mgcp_param_localconnoptions, tvb, offset, param_type_len+param_val_len, ENC_ASCII);
1700 tree = proto_item_add_subtree(item, ett_mgcp_param_localconnectionoptions);
1702 /* The L: line */
1703 offset += param_type_len; /* skip the L: */
1704 tokenline = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, param_val_len, ENC_ASCII);
1706 /* Split into type=value pairs separated by comma */
1707 tokens = wmem_strsplit(wmem_packet_scope(), tokenline, ",", -1);
1708 for (i = 0; tokens[i] != NULL; i++)
1710 char **typval;
1711 unsigned tokenlen;
1712 int hf_uint;
1713 int hf_string;
1715 hf_uint = -1;
1716 hf_string = -1;
1718 tokenlen = (int)strlen(tokens[i]);
1719 typval = wmem_strsplit(wmem_packet_scope(), tokens[i], ":", 2);
1720 if ((typval[0] != NULL) && (typval[1] != NULL))
1722 if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "p"))
1724 hf_uint = hf_mgcp_param_localconnoptions_p;
1726 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "a"))
1728 hf_string = hf_mgcp_param_localconnoptions_a;
1730 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "s"))
1732 hf_string = hf_mgcp_param_localconnoptions_s;
1734 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "e"))
1736 hf_string = hf_mgcp_param_localconnoptions_e;
1738 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "sc-rtp"))
1740 hf_string = hf_mgcp_param_localconnoptions_scrtp;
1742 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "sc-rtcp"))
1744 hf_string = hf_mgcp_param_localconnoptions_scrtcp;
1746 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "b"))
1748 hf_string = hf_mgcp_param_localconnoptions_b;
1750 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "es-ccd"))
1752 hf_string = hf_mgcp_param_localconnoptions_esccd;
1754 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "es-cci"))
1756 hf_string = hf_mgcp_param_localconnoptions_escci;
1758 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "dq-gi"))
1760 hf_string = hf_mgcp_param_localconnoptions_dqgi;
1762 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "dq-rd"))
1764 hf_string = hf_mgcp_param_localconnoptions_dqrd;
1766 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "dq-ri"))
1768 hf_string = hf_mgcp_param_localconnoptions_dqri;
1770 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "dq-rr"))
1772 hf_string = hf_mgcp_param_localconnoptions_dqrr;
1774 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "k"))
1776 hf_string = hf_mgcp_param_localconnoptions_k;
1778 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "gc"))
1780 hf_uint = hf_mgcp_param_localconnoptions_gc;
1782 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "fmtp"))
1784 hf_string = hf_mgcp_param_localconnoptions_fmtp;
1786 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "nt"))
1788 hf_string = hf_mgcp_param_localconnoptions_nt;
1790 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "o-fmtp"))
1792 hf_string = hf_mgcp_param_localconnoptions_ofmtp;
1794 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "r"))
1796 hf_string = hf_mgcp_param_localconnoptions_r;
1798 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "t"))
1800 hf_string = hf_mgcp_param_localconnoptions_t;
1802 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "r-cnf"))
1804 hf_string = hf_mgcp_param_localconnoptions_rcnf;
1806 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "r-dir"))
1808 hf_string = hf_mgcp_param_localconnoptions_rdir;
1810 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "r-sh"))
1812 hf_string = hf_mgcp_param_localconnoptions_rsh;
1814 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "mp"))
1816 hf_string = hf_mgcp_param_localconnoptions_mp;
1818 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "fxr/fx"))
1820 hf_string = hf_mgcp_param_localconnoptions_fxr;
1822 else
1824 hf_uint = -1;
1825 hf_string = -1;
1828 /* Add item */
1829 if (hf_uint > 0)
1831 proto_tree_add_uint(tree, hf_uint, tvb, offset, tokenlen, (uint32_t)strtoul(typval[1], NULL, 10));
1833 else if (hf_string > 0)
1835 proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
1837 else
1839 proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
1845 /* Dissect the Local Voice Metrics option */
1846 static void
1847 dissect_mgcp_localvoicemetrics(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int param_type_len, int param_val_len)
1849 proto_tree *tree = parent_tree;
1850 proto_item *item = NULL;
1852 char *tokenline = NULL;
1853 char **tokens = NULL;
1854 char **typval = NULL;
1855 unsigned i = 0;
1856 unsigned tokenlen = 0;
1857 int hf_string = -1;
1859 if (parent_tree)
1861 item = proto_tree_add_item(parent_tree, hf_mgcp_param_localvoicemetrics, tvb, offset, param_type_len+param_val_len, ENC_ASCII);
1862 tree = proto_item_add_subtree(item, ett_mgcp_param_localvoicemetrics);
1865 /* The XRM/LVM: line */
1866 offset += 9; /* skip the XRM/LVM: */
1867 tokenline = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, param_val_len - 9, ENC_ASCII);
1869 /* Split into type=value pairs separated by comma and WSP */
1870 tokens = wmem_strsplit(wmem_packet_scope(), tokenline, ",", -1);
1871 for (i = 0; tokens[i] != NULL; i++)
1874 tokenlen = (int)strlen(tokens[i]);
1875 typval = wmem_strsplit(wmem_packet_scope(), tokens[i], "=", 2);
1876 if ((typval[0] != NULL) && (typval[1] != NULL))
1878 if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NLR"))
1880 hf_string = hf_mgcp_param_voicemetrics_nlr;
1882 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JDR"))
1884 hf_string = hf_mgcp_param_voicemetrics_jdr;
1886 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BLD"))
1888 hf_string = hf_mgcp_param_voicemetrics_bld;
1890 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GLD"))
1892 hf_string = hf_mgcp_param_voicemetrics_gld;
1894 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BD"))
1896 hf_string = hf_mgcp_param_voicemetrics_bd;
1898 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GD"))
1900 hf_string = hf_mgcp_param_voicemetrics_gd;
1902 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RTD"))
1904 hf_string = hf_mgcp_param_voicemetrics_rtd;
1906 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "ESD"))
1908 hf_string = hf_mgcp_param_voicemetrics_esd;
1910 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "SL"))
1912 hf_string = hf_mgcp_param_voicemetrics_sl;
1914 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NL"))
1916 hf_string = hf_mgcp_param_voicemetrics_nl;
1918 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RERL"))
1920 hf_string = hf_mgcp_param_voicemetrics_rerl;
1922 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GMN"))
1924 hf_string = hf_mgcp_param_voicemetrics_gmn;
1926 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NSR"))
1928 hf_string = hf_mgcp_param_voicemetrics_nsr;
1930 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "XSR"))
1932 hf_string = hf_mgcp_param_voicemetrics_xsr;
1934 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MLQ"))
1936 hf_string = hf_mgcp_param_voicemetrics_mlq;
1938 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MCQ"))
1940 hf_string = hf_mgcp_param_voicemetrics_mcq;
1942 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PLC"))
1944 hf_string = hf_mgcp_param_voicemetrics_plc;
1946 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBA"))
1948 hf_string = hf_mgcp_param_voicemetrics_jba;
1950 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBR"))
1952 hf_string = hf_mgcp_param_voicemetrics_jbr;
1954 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBN"))
1956 hf_string = hf_mgcp_param_voicemetrics_jbn;
1958 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBM"))
1960 hf_string = hf_mgcp_param_voicemetrics_jbm;
1962 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBS"))
1964 hf_string = hf_mgcp_param_voicemetrics_jbs;
1966 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "IAJ"))
1968 hf_string = hf_mgcp_param_voicemetrics_iaj;
1970 else
1972 hf_string = -1;
1975 /* Add item */
1976 if (tree)
1978 if (hf_string > 0)
1980 proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
1982 else
1984 proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
1988 else if (tree)
1990 proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
1992 offset += tokenlen + 1; /* 1 extra for the delimiter */
1996 /* Dissect the Remote Voice Metrics option */
1997 static void
1998 dissect_mgcp_remotevoicemetrics(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int param_type_len, int param_val_len)
2000 proto_tree *tree = parent_tree;
2001 proto_item *item = NULL;
2003 char *tokenline = NULL;
2004 char **tokens = NULL;
2005 char **typval = NULL;
2006 unsigned i = 0;
2007 unsigned tokenlen = 0;
2008 int hf_string = -1;
2010 if (parent_tree)
2012 item = proto_tree_add_item(parent_tree, hf_mgcp_param_remotevoicemetrics, tvb, offset, param_type_len+param_val_len, ENC_ASCII);
2013 tree = proto_item_add_subtree(item, ett_mgcp_param_remotevoicemetrics);
2016 /* The XRM/RVM: line */
2017 offset += 9; /* skip the XRM/RVM: */
2018 tokenline = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, param_val_len - 9, ENC_ASCII);
2020 /* Split into type=value pairs separated by comma and WSP */
2021 tokens = wmem_strsplit(wmem_packet_scope(), tokenline, ",", -1);
2022 for (i = 0; tokens[i] != NULL; i++)
2024 tokenlen = (int)strlen(tokens[i]);
2025 typval = wmem_strsplit(wmem_packet_scope(), tokens[i], "=", 2);
2026 if ((typval[0] != NULL) && (typval[1] != NULL))
2028 if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NLR"))
2030 hf_string = hf_mgcp_param_voicemetrics_nlr;
2032 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JDR"))
2034 hf_string = hf_mgcp_param_voicemetrics_jdr;
2036 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BLD"))
2038 hf_string = hf_mgcp_param_voicemetrics_bld;
2040 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GLD"))
2042 hf_string = hf_mgcp_param_voicemetrics_gld;
2044 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BD"))
2046 hf_string = hf_mgcp_param_voicemetrics_bd;
2048 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GD"))
2050 hf_string = hf_mgcp_param_voicemetrics_gd;
2052 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RTD"))
2054 hf_string = hf_mgcp_param_voicemetrics_rtd;
2056 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "ESD"))
2058 hf_string = hf_mgcp_param_voicemetrics_esd;
2060 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "SL"))
2062 hf_string = hf_mgcp_param_voicemetrics_sl;
2064 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NL"))
2066 hf_string = hf_mgcp_param_voicemetrics_nl;
2068 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RERL"))
2070 hf_string = hf_mgcp_param_voicemetrics_rerl;
2072 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GMN"))
2074 hf_string = hf_mgcp_param_voicemetrics_gmn;
2076 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NSR"))
2078 hf_string = hf_mgcp_param_voicemetrics_nsr;
2080 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "XSR"))
2082 hf_string = hf_mgcp_param_voicemetrics_xsr;
2084 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MLQ"))
2086 hf_string = hf_mgcp_param_voicemetrics_mlq;
2088 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MCQ"))
2090 hf_string = hf_mgcp_param_voicemetrics_mcq;
2092 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PLC"))
2094 hf_string = hf_mgcp_param_voicemetrics_plc;
2096 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBA"))
2098 hf_string = hf_mgcp_param_voicemetrics_jba;
2100 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBR"))
2102 hf_string = hf_mgcp_param_voicemetrics_jbr;
2104 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBN"))
2106 hf_string = hf_mgcp_param_voicemetrics_jbn;
2108 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBM"))
2110 hf_string = hf_mgcp_param_voicemetrics_jbm;
2112 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBS"))
2114 hf_string = hf_mgcp_param_voicemetrics_jbs;
2116 else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "IAJ"))
2118 hf_string = hf_mgcp_param_voicemetrics_iaj;
2120 else
2122 hf_string = -1;
2125 /* Add item */
2126 if (tree)
2128 if (hf_string > 0)
2130 proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
2132 else
2134 proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
2138 else if (tree)
2140 proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
2142 offset += tokenlen + 1; /* 1 extra for the delimiter */
2147 * tvb_find_null_line - Returns the length from offset to the first null
2148 * line found (a null line is a line that begins
2149 * with a CR or LF. The offset to the first character
2150 * after the null line is written into the int pointed
2151 * to by next_offset.
2153 * Parameters:
2154 * tvb - The tvbuff in which we are looking for a null line.
2155 * offset - The offset in tvb at which we will begin looking for
2156 * a null line.
2157 * len - The maximum distance from offset in tvb that we will look for
2158 * a null line. If it is -1 we will look to the end of the buffer.
2160 * next_offset - The location to write the offset of first character
2161 * FOLLOWING the null line.
2163 * Returns: The length from offset to the first character BEFORE
2164 * the null line..
2166 static int tvb_find_null_line(tvbuff_t* tvb, int offset, int len, int* next_offset)
2168 int tvb_lineend, tvb_current_len, tvb_linebegin, maxoffset;
2169 unsigned tempchar;
2171 tvb_linebegin = offset;
2172 tvb_lineend = tvb_linebegin;
2174 /* Simple setup to allow for the traditional -1 search to the end of the tvbuff */
2175 if (len != -1)
2177 tvb_current_len = len;
2179 else
2181 tvb_current_len = tvb_reported_length_remaining(tvb, offset);
2184 maxoffset = (tvb_current_len - 1) + offset;
2186 /* Loop around until we either find a line beginning with a carriage return
2187 or newline character or until we hit the end of the tvbuff. */
2190 tvb_linebegin = tvb_lineend;
2191 tvb_current_len = tvb_reported_length_remaining(tvb, tvb_linebegin);
2192 tvb_find_line_end(tvb, tvb_linebegin, tvb_current_len, &tvb_lineend, false);
2193 tempchar = tvb_get_uint8(tvb, tvb_linebegin);
2194 } while (tempchar != '\r' && tempchar != '\n' && tvb_lineend <= maxoffset && tvb_offset_exists(tvb, tvb_lineend));
2197 *next_offset = tvb_lineend;
2199 if (tvb_lineend <= maxoffset)
2201 tvb_current_len = tvb_linebegin - offset;
2203 else
2205 tvb_current_len = tvb_reported_length_remaining(tvb, offset);
2208 return tvb_current_len;
2212 * tvb_find_dot_line - Returns the length from offset to the first line
2213 * containing only a dot (.) character. A line
2214 * containing only a dot is used to indicate a
2215 * separation between multiple MGCP messages
2216 * piggybacked in the same UDP packet.
2218 * Parameters:
2219 * tvb - The tvbuff in which we are looking for a dot line.
2220 * offset - The offset in tvb at which we will begin looking for
2221 * a dot line.
2222 * len - The maximum distance from offset in tvb that we will look for
2223 * a dot line. If it is -1 we will look to the end of the buffer.
2225 * next_offset - The location to write the offset of first character
2226 * FOLLOWING the dot line.
2228 * Returns: The length from offset to the first character BEFORE
2229 * the dot line or -1 if the character at offset is a .
2230 * followed by a newline or a carriage return.
2232 static int tvb_find_dot_line(tvbuff_t* tvb, int offset, int len, int* next_offset)
2234 int tvb_current_offset, tvb_current_len, maxoffset, tvb_len;
2235 uint8_t tempchar;
2236 tvb_current_len = len;
2237 tvb_len = tvb_reported_length(tvb);
2239 if (len == -1)
2241 maxoffset = tvb_len - 1;
2243 else
2245 maxoffset = (len - 1) + offset;
2247 tvb_current_offset = offset -1;
2251 tvb_current_offset = tvb_find_uint8(tvb, tvb_current_offset+1,
2252 tvb_current_len, '.');
2253 tvb_current_len = maxoffset - tvb_current_offset + 1;
2255 /* If we didn't find a . then break out of the loop */
2256 if (tvb_current_offset == -1)
2258 break;
2261 /* Do we have and characters following the . ? */
2262 if (tvb_current_offset < maxoffset)
2264 tempchar = tvb_get_uint8(tvb, tvb_current_offset+1);
2265 /* Are the characters that follow the dot a newline or carriage return ? */
2266 if (tempchar == '\r' || tempchar == '\n')
2268 /* Do we have any characters that proceed the . ? */
2269 if (tvb_current_offset == 0)
2271 break;
2273 else
2275 tempchar = tvb_get_uint8(tvb, tvb_current_offset-1);
2277 /* Are the characters that follow the dot a newline or a
2278 carriage return ? */
2279 if (tempchar == '\r' || tempchar == '\n')
2281 break;
2286 else
2287 if (tvb_current_offset == maxoffset)
2289 if (tvb_current_offset == 0)
2291 break;
2293 else
2295 tempchar = tvb_get_uint8(tvb, tvb_current_offset-1);
2296 if (tempchar == '\r' || tempchar == '\n')
2298 break;
2302 } while (tvb_current_offset < maxoffset);
2306 * So now we either have the tvb_current_offset of a . in a dot line
2307 * or a tvb_current_offset of -1
2309 if (tvb_current_offset == -1)
2311 tvb_current_offset = maxoffset +1;
2312 *next_offset = maxoffset + 1;
2314 else
2316 tvb_find_line_end(tvb, tvb_current_offset, tvb_current_len, next_offset, false);
2319 if (tvb_current_offset == offset)
2321 tvb_current_len = -1;
2323 else
2325 tvb_current_len = tvb_current_offset - offset;
2328 return tvb_current_len;
2331 /* Register all the bits needed with the filtering engine */
2333 void proto_register_mgcp(void);
2334 void proto_reg_handoff_mgcp(void);
2336 void proto_register_mgcp(void)
2338 expert_module_t* expert_mgcp;
2340 static hf_register_info hf[] =
2342 { &hf_mgcp_req,
2343 { "Request", "mgcp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2344 "True if MGCP request", HFILL }},
2345 { &hf_mgcp_rsp,
2346 { "Response", "mgcp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2347 "true if MGCP response", HFILL }},
2348 { &hf_mgcp_req_frame,
2349 { "Request Frame", "mgcp.reqframe", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0,
2350 NULL, HFILL }},
2351 { &hf_mgcp_rsp_frame,
2352 { "Response Frame", "mgcp.rspframe", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0,
2353 NULL, HFILL }},
2354 { &hf_mgcp_time,
2355 { "Time from request", "mgcp.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
2356 "Timedelta between Request and Response", HFILL }},
2357 { &hf_mgcp_req_verb,
2358 { "Verb", "mgcp.req.verb", FT_STRING, BASE_NONE, NULL, 0x0,
2359 "Name of the verb", HFILL }},
2360 { &hf_mgcp_req_endpoint,
2361 { "Endpoint", "mgcp.req.endpoint", FT_STRING, BASE_NONE, NULL, 0x0,
2362 "Endpoint referenced by the message", HFILL }},
2363 { &hf_mgcp_transid,
2364 { "Transaction ID", "mgcp.transid", FT_STRING, BASE_NONE, NULL, 0x0,
2365 "Transaction ID of this message", HFILL }},
2366 { &hf_mgcp_version,
2367 { "Version", "mgcp.version", FT_STRING, BASE_NONE, NULL, 0x0,
2368 "MGCP Version", HFILL }},
2369 { &hf_mgcp_rsp_rspcode,
2370 { "Response Code", "mgcp.rsp.rspcode", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &mgcp_return_code_vals_ext, 0x0,
2371 NULL, HFILL }},
2372 { &hf_mgcp_rsp_rspstring,
2373 { "Response String", "mgcp.rsp.rspstring", FT_STRING, BASE_NONE, NULL, 0x0,
2374 NULL, HFILL }},
2375 { &hf_mgcp_params,
2376 { "Parameters", "mgcp.params", FT_NONE, BASE_NONE, NULL, 0x0,
2377 "MGCP parameters", HFILL }},
2378 { &hf_mgcp_param_rspack,
2379 { "ResponseAck (K)", "mgcp.param.rspack", FT_STRING, BASE_NONE, NULL, 0x0,
2380 "Response Ack", HFILL }},
2381 { &hf_mgcp_param_bearerinfo,
2382 { "BearerInformation (B)", "mgcp.param.bearerinfo", FT_STRING, BASE_NONE, NULL, 0x0,
2383 "Bearer Information", HFILL }},
2384 { &hf_mgcp_param_callid,
2385 { "CallId (C)", "mgcp.param.callid", FT_STRING, BASE_NONE, NULL, 0x0,
2386 "Call Id", HFILL }},
2387 { &hf_mgcp_param_connectionid,
2388 {"ConnectionIdentifier (I)", "mgcp.param.connectionid", FT_STRING, BASE_NONE, NULL, 0x0,
2389 "Connection Identifier", HFILL }},
2390 { &hf_mgcp_param_secondconnectionid,
2391 { "SecondConnectionID (I2)", "mgcp.param.secondconnectionid", FT_STRING, BASE_NONE, NULL, 0x0,
2392 "Second Connection Identifier", HFILL }},
2393 { &hf_mgcp_param_notifiedentity,
2394 { "NotifiedEntity (N)", "mgcp.param.notifiedentity", FT_STRING, BASE_NONE, NULL, 0x0,
2395 "Notified Entity", HFILL }},
2396 { &hf_mgcp_param_requestid,
2397 { "RequestIdentifier (X)", "mgcp.param.requestid", FT_STRING, BASE_NONE, NULL, 0x0,
2398 "Request Identifier", HFILL }},
2399 { &hf_mgcp_param_localconnoptions,
2400 { "LocalConnectionOptions (L)", "mgcp.param.localconnectionoptions", FT_STRING, BASE_NONE, NULL, 0x0,
2401 "Local Connection Options", HFILL }},
2402 { &hf_mgcp_param_localconnoptions_p,
2403 { "Packetization period (p)", "mgcp.param.localconnectionoptions.p", FT_UINT32, BASE_DEC, NULL, 0x0,
2404 NULL, HFILL }},
2405 { &hf_mgcp_param_localconnoptions_a,
2406 { "Codecs (a)", "mgcp.param.localconnectionoptions.a", FT_STRING, BASE_NONE, NULL, 0x0,
2407 NULL, HFILL }},
2408 { &hf_mgcp_param_localconnoptions_s,
2409 { "Silence Suppression (s)", "mgcp.param.localconnectionoptions.s", FT_STRING, BASE_NONE, NULL, 0x0,
2410 NULL, HFILL }},
2411 { &hf_mgcp_param_localconnoptions_e,
2412 { "Echo Cancellation (e)", "mgcp.param.localconnectionoptions.e", FT_STRING, BASE_NONE, NULL, 0x0,
2413 NULL, HFILL }},
2414 { &hf_mgcp_param_localconnoptions_scrtp,
2415 { "RTP ciphersuite (sc-rtp)", "mgcp.param.localconnectionoptions.scrtp", FT_STRING, BASE_NONE, NULL, 0x0,
2416 NULL, HFILL }},
2417 { &hf_mgcp_param_localconnoptions_scrtcp,
2418 { "RTCP ciphersuite (sc-rtcp)", "mgcp.param.localconnectionoptions.scrtcp", FT_STRING, BASE_NONE, NULL, 0x0,
2419 NULL, HFILL }},
2420 { &hf_mgcp_param_localconnoptions_b,
2421 { "Bandwidth (b)", "mgcp.param.localconnectionoptions.b", FT_STRING, BASE_NONE, NULL, 0x0,
2422 NULL, HFILL }},
2423 { &hf_mgcp_param_localconnoptions_esccd,
2424 { "Content Destination (es-ccd)", "mgcp.param.localconnectionoptions.esccd", FT_STRING, BASE_NONE, NULL, 0x0,
2425 NULL, HFILL }},
2426 { &hf_mgcp_param_localconnoptions_escci,
2427 { "Content Identifier (es-cci)", "mgcp.param.localconnectionoptions.escci", FT_STRING, BASE_NONE, NULL, 0x0,
2428 NULL, HFILL }},
2429 { &hf_mgcp_param_localconnoptions_dqgi,
2430 { "D-QoS GateID (dq-gi)", "mgcp.param.localconnectionoptions.dqgi", FT_STRING, BASE_NONE, NULL, 0x0,
2431 NULL, HFILL }},
2432 { &hf_mgcp_param_localconnoptions_dqrd,
2433 { "D-QoS Reserve Destination (dq-rd)", "mgcp.param.localconnectionoptions.dqrd", FT_STRING, BASE_NONE, NULL, 0x0,
2434 NULL, HFILL }},
2435 { &hf_mgcp_param_localconnoptions_dqri,
2436 { "D-QoS Resource ID (dq-ri)", "mgcp.param.localconnectionoptions.dqri", FT_STRING, BASE_NONE, NULL, 0x0,
2437 NULL, HFILL }},
2438 { &hf_mgcp_param_localconnoptions_dqrr,
2439 { "D-QoS Resource Reservation (dq-rr)", "mgcp.param.localconnectionoptions.dqrr", FT_STRING, BASE_NONE, NULL, 0x0,
2440 NULL, HFILL }},
2441 { &hf_mgcp_param_localconnoptions_k,
2442 { "Encryption Key (k)", "mgcp.param.localconnectionoptions.k", FT_STRING, BASE_NONE, NULL, 0x0,
2443 NULL, HFILL }},
2444 { &hf_mgcp_param_localconnoptions_gc,
2445 { "Gain Control (gc)", "mgcp.param.localconnectionoptions.gc", FT_UINT32, BASE_DEC, NULL, 0x0,
2446 NULL, HFILL }},
2447 { &hf_mgcp_param_localconnoptions_fmtp,
2448 { "Media Format (fmtp)", "mgcp.param.localconnectionoptions.fmtp", FT_STRING, BASE_NONE, NULL, 0x0,
2449 NULL, HFILL }},
2450 { &hf_mgcp_param_localconnoptions_nt,
2451 { "Network Type (nt)", "mgcp.param.localconnectionoptions.nt", FT_STRING, BASE_NONE, NULL, 0x0,
2452 NULL, HFILL }},
2453 { &hf_mgcp_param_localconnoptions_ofmtp,
2454 { "Optional Media Format (o-fmtp)", "mgcp.param.localconnectionoptions.ofmtp", FT_STRING, BASE_NONE, NULL, 0x0,
2455 NULL, HFILL }},
2456 { &hf_mgcp_param_localconnoptions_r,
2457 { "Resource Reservation (r)", "mgcp.param.localconnectionoptions.r", FT_STRING, BASE_NONE, NULL, 0x0,
2458 NULL, HFILL }},
2459 { &hf_mgcp_param_localconnoptions_t,
2460 { "Type of Service (r)", "mgcp.param.localconnectionoptions.t", FT_STRING, BASE_NONE, NULL, 0x0,
2461 NULL, HFILL }},
2462 { &hf_mgcp_param_localconnoptions_rcnf,
2463 { "Reservation Confirmation (r-cnf)", "mgcp.param.localconnectionoptions.rcnf", FT_STRING, BASE_NONE, NULL, 0x0,
2464 NULL, HFILL }},
2465 { &hf_mgcp_param_localconnoptions_rdir,
2466 { "Reservation Direction (r-dir)", "mgcp.param.localconnectionoptions.rdir", FT_STRING, BASE_NONE, NULL, 0x0,
2467 NULL, HFILL }},
2468 { &hf_mgcp_param_localconnoptions_rsh,
2469 { "Resource Sharing (r-sh)", "mgcp.param.localconnectionoptions.rsh", FT_STRING, BASE_NONE, NULL, 0x0,
2470 NULL, HFILL }},
2471 { &hf_mgcp_param_localconnoptions_mp,
2472 { "Multiple Packetization period (mp)", "mgcp.param.localconnectionoptions.mp", FT_STRING, BASE_NONE, NULL, 0x0,
2473 NULL, HFILL }},
2474 { &hf_mgcp_param_localconnoptions_fxr,
2475 { "FXR (fxr/fx)", "mgcp.param.localconnectionoptions.fxr", FT_STRING, BASE_NONE, NULL, 0x0,
2476 NULL, HFILL }},
2477 { &hf_mgcp_param_localvoicemetrics,
2478 { "LocalVoiceMetrics (XRM/LVM)", "mgcp.param.localvoicemetrics", FT_STRING, BASE_NONE, NULL, 0x0,
2479 NULL, HFILL }},
2480 { &hf_mgcp_param_remotevoicemetrics,
2481 { "RemoteVoiceMetrics (XRM/RVM)", "mgcp.param.remotevoicemetrics", FT_STRING, BASE_NONE, NULL, 0x0,
2482 NULL, HFILL }},
2483 { &hf_mgcp_param_voicemetrics_nlr,
2484 { "Network packet loss rate(NLR)", "mgcp.param.voicemetrics.nlr", FT_STRING, BASE_NONE, NULL, 0x0,
2485 "Voice Metrics NLR", HFILL }},
2486 { &hf_mgcp_param_voicemetrics_jdr,
2487 { "Jitter buffer discard rate(JDR)", "mgcp.param.voicemetrics.jdr", FT_STRING, BASE_NONE, NULL, 0x0,
2488 "Voice Metrics JDR", HFILL }},
2489 { &hf_mgcp_param_voicemetrics_bld,
2490 { "Burst loss density(BLD)", "mgcp.param.voicemetrics.bld", FT_STRING, BASE_NONE, NULL, 0x0,
2491 "Voice Metrics BLD", HFILL }},
2492 { &hf_mgcp_param_voicemetrics_gld,
2493 { "Gap loss density(GLD)", "mgcp.param.voicemetrics.gld", FT_STRING, BASE_NONE, NULL, 0x0,
2494 "Voice Metrics GLD", HFILL }},
2495 { &hf_mgcp_param_voicemetrics_bd,
2496 { "Burst duration(BD)", "mgcp.param.voicemetrics.bd", FT_STRING, BASE_NONE, NULL, 0x0,
2497 "Voice Metrics BD", HFILL }},
2498 { &hf_mgcp_param_voicemetrics_gd,
2499 { "Gap duration(GD)", "mgcp.param.voicemetrics.gd", FT_STRING, BASE_NONE, NULL, 0x0,
2500 "Voice Metrics GD", HFILL }},
2501 { &hf_mgcp_param_voicemetrics_rtd,
2502 { "Round trip network delay(RTD)", "mgcp.param.voicemetrics.rtd", FT_STRING, BASE_NONE, NULL, 0x0,
2503 "Voice Metrics RTD", HFILL }},
2504 { &hf_mgcp_param_voicemetrics_esd,
2505 { "End system delay(ESD)", "mgcp.param.voicemetrics.esd", FT_STRING, BASE_NONE, NULL, 0x0,
2506 "Voice Metrics ESD", HFILL }},
2507 { &hf_mgcp_param_voicemetrics_sl,
2508 { "Signal level(SL)", "mgcp.param.voicemetrics.sl", FT_STRING, BASE_NONE, NULL, 0x0,
2509 "Voice Metrics SL", HFILL }},
2510 { &hf_mgcp_param_voicemetrics_nl,
2511 { "Noise level(NL)", "mgcp.param.voicemetrics.nl", FT_STRING, BASE_NONE, NULL, 0x0,
2512 "Voice Metricsx NL", HFILL }},
2513 { &hf_mgcp_param_voicemetrics_rerl,
2514 { "Residual echo return loss(RERL)", "mgcp.param.voicemetrics.rerl", FT_STRING, BASE_NONE, NULL, 0x0,
2515 "Voice Metrics ERL", HFILL }},
2516 { &hf_mgcp_param_voicemetrics_gmn,
2517 { "Minimum gap threshold(GMN)", "mgcp.param.voicemetrics.gmn", FT_STRING, BASE_NONE, NULL, 0x0,
2518 "Voice Metrics GMN", HFILL }},
2519 { &hf_mgcp_param_voicemetrics_nsr,
2520 { "R factor(NSR)", "mgcp.param.voicemetrics.nsr", FT_STRING, BASE_NONE, NULL, 0x0,
2521 "Voice Metrics NSR", HFILL }},
2522 { &hf_mgcp_param_voicemetrics_xsr,
2523 { "External R factor(XSR)", "mgcp.param.voicemetrics.xsr", FT_STRING, BASE_NONE, NULL, 0x0,
2524 "Voice Metrics XSR", HFILL }},
2525 { &hf_mgcp_param_voicemetrics_mlq,
2526 { "Estimated MOS-LQ(MLQ)", "mgcp.param.voicemetrics.mlq", FT_STRING, BASE_NONE, NULL, 0x0,
2527 "Voice Metrics MLQ", HFILL }},
2528 { &hf_mgcp_param_voicemetrics_mcq,
2529 { "Estimated MOS-CQ(MCQ)", "mgcp.param.voicemetrics.mcq", FT_STRING, BASE_NONE, NULL, 0x0,
2530 "Voice Metrics MCQ", HFILL }},
2531 { &hf_mgcp_param_voicemetrics_plc,
2532 { "Packet loss concealment type(PLC)", "mgcp.param.voicemetrics.plc", FT_STRING, BASE_NONE, NULL, 0x0,
2533 "Voice Metrics PLC", HFILL }},
2534 { &hf_mgcp_param_voicemetrics_jba,
2535 { "Jitter Buffer Adaptive(JBA)", "mgcp.param.voicemetrics.jba", FT_STRING, BASE_NONE, NULL, 0x0,
2536 "Voice Metrics JBA", HFILL }},
2537 { &hf_mgcp_param_voicemetrics_jbr,
2538 { "Jitter Buffer Rate(JBR)", "mgcp.param.voicemetrics.jbr", FT_STRING, BASE_NONE, NULL, 0x0,
2539 "Voice Metrics JBR", HFILL }},
2540 { &hf_mgcp_param_voicemetrics_jbn,
2541 { "Nominal jitter buffer delay(JBN)", "mgcp.param.voicemetrics.jbn", FT_STRING, BASE_NONE, NULL, 0x0,
2542 "Voice Metrics JBN", HFILL }},
2543 { &hf_mgcp_param_voicemetrics_jbm,
2544 { "Maximum jitter buffer delay(JBM)", "mgcp.param.voicemetrics.jbm", FT_STRING, BASE_NONE, NULL, 0x0,
2545 "Voice Metrics JBM", HFILL }},
2546 { &hf_mgcp_param_voicemetrics_jbs,
2547 { "Absolute maximum jitter buffer delay(JBS)", "mgcp.param.voicemetrics.jbs", FT_STRING, BASE_NONE, NULL, 0x0,
2548 "Voice Metrics JBS", HFILL }},
2549 { &hf_mgcp_param_voicemetrics_iaj,
2550 { "Inter-arrival Jitter(IAJ)", "mgcp.param.voicemetrics.iaj", FT_STRING, BASE_NONE, NULL, 0x0,
2551 "Voice Metrics IAJ", HFILL }},
2552 { &hf_mgcp_param_connectionmode,
2553 { "ConnectionMode (M)", "mgcp.param.connectionmode", FT_STRING, BASE_NONE, NULL, 0x0,
2554 "Connection Mode", HFILL }},
2555 { &hf_mgcp_param_reqevents,
2556 { "RequestedEvents (R)", "mgcp.param.reqevents", FT_STRING, BASE_NONE, NULL, 0x0,
2557 "Requested Events", HFILL }},
2558 { &hf_mgcp_param_signalreq,
2559 { "SignalRequests (S)", "mgcp.param.signalreq", FT_STRING, BASE_NONE, NULL, 0x0,
2560 "Signal Request", HFILL }},
2561 { &hf_mgcp_param_restartmethod,
2562 { "RestartMethod (RM)", "mgcp.param.restartmethod", FT_STRING, BASE_NONE, NULL, 0x0,
2563 "Restart Method", HFILL }},
2564 { &hf_mgcp_param_restartdelay,
2565 { "RestartDelay (RD)", "mgcp.param.restartdelay", FT_STRING, BASE_NONE, NULL, 0x0,
2566 "Restart Delay", HFILL }},
2567 { &hf_mgcp_param_digitmap,
2568 { "DigitMap (D)", "mgcp.param.digitmap", FT_STRING, BASE_NONE, NULL, 0x0,
2569 "Digit Map", HFILL }},
2570 { &hf_mgcp_param_observedevent,
2571 { "ObservedEvents (O)", "mgcp.param.observedevents", FT_STRING, BASE_NONE, NULL, 0x0,
2572 "Observed Events", HFILL }},
2573 { &hf_mgcp_param_connectionparam,
2574 { "ConnectionParameters (P)", "mgcp.param.connectionparam", FT_STRING, BASE_NONE, NULL, 0x0,
2575 "Connection Parameters", HFILL }},
2576 { &hf_mgcp_param_connectionparam_ps,
2577 { "Packets sent (PS)", "mgcp.param.connectionparam.ps", FT_UINT32, BASE_DEC, NULL, 0x0,
2578 "Packets sent (P:PS)", HFILL }},
2579 { &hf_mgcp_param_connectionparam_os,
2580 { "Octets sent (OS)", "mgcp.param.connectionparam.os", FT_UINT32, BASE_DEC, NULL, 0x0,
2581 "Octets sent (P:OS)", HFILL }},
2582 { &hf_mgcp_param_connectionparam_pr,
2583 { "Packets received (PR)", "mgcp.param.connectionparam.pr", FT_UINT32, BASE_DEC, NULL, 0x0,
2584 "Packets received (P:PR)", HFILL }},
2585 { &hf_mgcp_param_connectionparam_or,
2586 { "Octets received (OR)", "mgcp.param.connectionparam.or", FT_UINT32, BASE_DEC, NULL, 0x0,
2587 "Octets received (P:OR)", HFILL }},
2588 { &hf_mgcp_param_connectionparam_pl,
2589 { "Packets lost (PL)", "mgcp.param.connectionparam.pl", FT_UINT32, BASE_DEC, NULL, 0x0,
2590 "Packets lost (P:PL)", HFILL }},
2591 { &hf_mgcp_param_connectionparam_ji,
2592 { "Jitter (JI)", "mgcp.param.connectionparam.ji", FT_UINT32, BASE_DEC, NULL, 0x0,
2593 "Average inter-packet arrival jitter in milliseconds (P:JI)", HFILL }},
2594 { &hf_mgcp_param_connectionparam_la,
2595 { "Latency (LA)", "mgcp.param.connectionparam.la", FT_UINT32, BASE_DEC, NULL, 0x0,
2596 "Average latency in milliseconds (P:LA)", HFILL }},
2597 { &hf_mgcp_param_connectionparam_pcrps,
2598 { "Remote Packets sent (PC/RPS)", "mgcp.param.connectionparam.pcrps", FT_UINT32, BASE_DEC, NULL, 0x0,
2599 "Remote Packets sent (P:PC/RPS)", HFILL }},
2600 { &hf_mgcp_param_connectionparam_pcros,
2601 { "Remote Octets sent (PC/ROS)", "mgcp.param.connectionparam.pcros", FT_UINT32, BASE_DEC, NULL, 0x0,
2602 "Remote Octets sent (P:PC/ROS)", HFILL }},
2603 { &hf_mgcp_param_connectionparam_pcrpl,
2604 { "Remote Packets lost (PC/RPL)", "mgcp.param.connectionparam.pcrpl", FT_UINT32, BASE_DEC, NULL, 0x0,
2605 "Remote Packets lost (P:PC/RPL)", HFILL }},
2606 { &hf_mgcp_param_connectionparam_pcrji,
2607 { "Remote Jitter (PC/RJI)", "mgcp.param.connectionparam.pcrji", FT_UINT32, BASE_DEC, NULL, 0x0,
2608 "Remote Jitter (P:PC/RJI)", HFILL }},
2609 { &hf_mgcp_param_connectionparam_x,
2610 { "Vendor Extension", "mgcp.param.connectionparam.x", FT_STRING, BASE_NONE, NULL, 0x0,
2611 "Vendor Extension (P:X-*)", HFILL }},
2612 { &hf_mgcp_param_reasoncode,
2613 { "ReasonCode (E)", "mgcp.param.reasoncode", FT_STRING, BASE_NONE, NULL, 0x0,
2614 "Reason Code", HFILL }},
2615 { &hf_mgcp_param_eventstates,
2616 { "EventStates (ES)", "mgcp.param.eventstates", FT_STRING, BASE_NONE, NULL, 0x0,
2617 "Event States", HFILL }},
2618 { &hf_mgcp_param_specificendpoint,
2619 { "SpecificEndpointID (Z)", "mgcp.param.specificendpointid", FT_STRING, BASE_NONE, NULL, 0x0,
2620 "Specific Endpoint ID", HFILL }},
2621 { &hf_mgcp_param_secondendpointid,
2622 { "SecondEndpointID (Z2)", "mgcp.param.secondendpointid", FT_STRING, BASE_NONE, NULL, 0x0,
2623 "Second Endpoint ID", HFILL }},
2624 { &hf_mgcp_param_reqinfo,
2625 { "RequestedInfo (F)", "mgcp.param.reqinfo", FT_STRING, BASE_NONE, NULL, 0x0,
2626 "Requested Info", HFILL }},
2627 { &hf_mgcp_param_quarantinehandling,
2628 { "QuarantineHandling (Q)", "mgcp.param.quarantinehandling", FT_STRING, BASE_NONE, NULL, 0x0,
2629 "Quarantine Handling", HFILL }},
2630 { &hf_mgcp_param_detectedevents,
2631 { "DetectedEvents (T)", "mgcp.param.detectedevents", FT_STRING, BASE_NONE, NULL, 0x0,
2632 "Detected Events", HFILL }},
2633 { &hf_mgcp_param_capabilities,
2634 { "Capabilities (A)", "mgcp.param.capabilities", FT_STRING, BASE_NONE, NULL, 0x0,
2635 NULL, HFILL }},
2636 { &hf_mgcp_param_maxmgcpdatagram,
2637 {"MaxMGCPDatagram (MD)", "mgcp.param.maxmgcpdatagram", FT_STRING, BASE_NONE, NULL, 0x0,
2638 "Maximum MGCP Datagram size", HFILL }},
2639 { &hf_mgcp_param_packagelist,
2640 {"PackageList (PL)", "mgcp.param.packagelist", FT_STRING, BASE_NONE, NULL, 0x0,
2641 "Package List", HFILL }},
2642 { &hf_mgcp_param_extension,
2643 { "Extension Parameter (non-critical)", "mgcp.param.extension", FT_STRING, BASE_NONE, NULL, 0x0,
2644 NULL, HFILL }},
2645 { &hf_mgcp_param_extension_critical,
2646 { "Extension Parameter (critical)", "mgcp.param.extensioncritical", FT_STRING, BASE_NONE, NULL, 0x0,
2647 "Critical Extension Parameter", HFILL }},
2648 { &hf_mgcp_param_resourceid,
2649 { "ResourceIdentifier (DQ-RI)", "mgcp.param.resourceid", FT_STRING, BASE_NONE, NULL, 0x0,
2650 "Resource Identifier", HFILL }},
2651 { &hf_mgcp_param_invalid,
2652 { "Invalid Parameter", "mgcp.param.invalid", FT_STRING, BASE_NONE, NULL, 0x0,
2653 NULL, HFILL }},
2654 { &hf_mgcp_messagecount,
2655 { "MGCP Message Count", "mgcp.messagecount", FT_UINT32, BASE_DEC, NULL, 0x0,
2656 "Number of MGCP message in a packet", HFILL }},
2657 { &hf_mgcp_dup,
2658 { "Duplicate Message", "mgcp.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
2659 NULL, HFILL }},
2660 { &hf_mgcp_req_dup,
2661 { "Duplicate Request", "mgcp.req.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
2662 NULL, HFILL }},
2663 { &hf_mgcp_req_dup_frame,
2664 { "Original Request Frame", "mgcp.req.dup.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2665 "Frame containing original request", HFILL }},
2666 { &hf_mgcp_rsp_dup,
2667 { "Duplicate Response", "mgcp.rsp.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
2668 NULL, HFILL }},
2669 { &hf_mgcp_rsp_dup_frame,
2670 { "Original Response Frame", "mgcp.rsp.dup.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2671 "Frame containing original response", HFILL }},
2672 { &hf_mgcp_param_x_osmux,
2673 { "X-Osmux", "mgcp.param.x_osmux", FT_STRING, BASE_NONE, NULL, 0x0,
2674 "Osmux CID", HFILL }},
2675 { &hf_mgcp_unknown_parameter,
2676 { "Unknown parameter", "mgcp.unknown_parameter", FT_STRING, BASE_NONE, NULL, 0x0,
2677 NULL, HFILL }},
2678 { &hf_mgcp_malformed_parameter,
2679 { "Malformed parameter", "mgcp.rsp.malformed_parameter", FT_STRING, BASE_NONE, NULL, 0x0,
2680 NULL, HFILL }},
2683 static int *ett[] =
2685 &ett_mgcp,
2686 &ett_mgcp_param,
2687 &ett_mgcp_param_connectionparam,
2688 &ett_mgcp_param_localconnectionoptions,
2689 &ett_mgcp_param_localvoicemetrics,
2690 &ett_mgcp_param_remotevoicemetrics
2693 static ei_register_info ei[] = {
2694 { &ei_mgcp_rsp_rspcode_invalid, { "mgcp.rsp.rspcode.invalid", PI_MALFORMED, PI_ERROR,
2695 "RSP code must be a string containing an integer", EXPFILL }}
2698 module_t *mgcp_module;
2700 /* Register protocol */
2701 proto_mgcp = proto_register_protocol("Media Gateway Control Protocol", "MGCP", "mgcp");
2702 proto_register_field_array(proto_mgcp, hf, array_length(hf));
2703 proto_register_subtree_array(ett, array_length(ett));
2705 mgcp_calls = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), mgcp_call_hash, mgcp_call_equal);
2707 mgcp_handle = register_dissector("mgcp", dissect_mgcp, proto_mgcp);
2709 /* Register our configuration options */
2710 mgcp_module = prefs_register_protocol(proto_mgcp, proto_reg_handoff_mgcp);
2712 prefs_register_uint_preference(mgcp_module, "tcp.gateway_port",
2713 "MGCP Gateway TCP Port",
2714 "Set the UDP port for gateway messages "
2715 "(if other than the default of 2427)",
2716 10, &global_mgcp_gateway_tcp_port);
2718 prefs_register_uint_preference(mgcp_module, "udp.gateway_port",
2719 "MGCP Gateway UDP Port",
2720 "Set the TCP port for gateway messages "
2721 "(if other than the default of 2427)",
2722 10, &global_mgcp_gateway_udp_port);
2724 prefs_register_uint_preference(mgcp_module, "tcp.callagent_port",
2725 "MGCP Callagent TCP Port",
2726 "Set the TCP port for callagent messages "
2727 "(if other than the default of 2727)",
2728 10, &global_mgcp_callagent_tcp_port);
2730 prefs_register_uint_preference(mgcp_module, "udp.callagent_port",
2731 "MGCP Callagent UDP Port",
2732 "Set the UDP port for callagent messages "
2733 "(if other than the default of 2727)",
2734 10, &global_mgcp_callagent_udp_port);
2737 prefs_register_bool_preference(mgcp_module, "display_raw_text",
2738 "Display raw text for MGCP message",
2739 "Specifies that the raw text of the "
2740 "MGCP message should be displayed "
2741 "instead of (or in addition to) the "
2742 "dissection tree",
2743 &global_mgcp_raw_text);
2745 prefs_register_obsolete_preference(mgcp_module, "display_dissect_tree");
2747 prefs_register_bool_preference(mgcp_module, "display_mgcp_message_count",
2748 "Display the number of MGCP messages",
2749 "Display the number of MGCP messages "
2750 "found in a packet in the protocol column.",
2751 &global_mgcp_message_count);
2753 mgcp_tap = register_tap("mgcp");
2755 register_rtd_table(proto_mgcp, NULL, 1, NUM_TIMESTATS, mgcp_message_type, mgcpstat_packet, NULL);
2757 expert_mgcp = expert_register_protocol(proto_mgcp);
2758 expert_register_field_array(expert_mgcp, ei, array_length(ei));
2762 /* The registration hand-off routine */
2763 void proto_reg_handoff_mgcp(void)
2765 static bool mgcp_prefs_initialized = false;
2766 static dissector_handle_t mgcp_tpkt_handle;
2768 * Variables to allow for proper deletion of dissector registration when
2769 * the user changes port from the gui.
2771 static unsigned gateway_tcp_port;
2772 static unsigned gateway_udp_port;
2773 static unsigned callagent_tcp_port;
2774 static unsigned callagent_udp_port;
2776 if (!mgcp_prefs_initialized)
2778 /* Get a handle for the SDP dissector. */
2779 sdp_handle = find_dissector_add_dependency("sdp", proto_mgcp);
2780 mgcp_tpkt_handle = create_dissector_handle(dissect_tpkt_mgcp, proto_mgcp);
2781 mgcp_prefs_initialized = true;
2783 else
2785 dissector_delete_uint("tcp.port", gateway_tcp_port, mgcp_tpkt_handle);
2786 dissector_delete_uint("udp.port", gateway_udp_port, mgcp_handle);
2787 dissector_delete_uint("tcp.port", callagent_tcp_port, mgcp_tpkt_handle);
2788 dissector_delete_uint("udp.port", callagent_udp_port, mgcp_handle);
2791 /* Set our port number for future use */
2792 gateway_tcp_port = global_mgcp_gateway_tcp_port;
2793 gateway_udp_port = global_mgcp_gateway_udp_port;
2795 callagent_tcp_port = global_mgcp_callagent_tcp_port;
2796 callagent_udp_port = global_mgcp_callagent_udp_port;
2798 /* Names of port preferences too specific to add "auto" preference here */
2799 dissector_add_uint("tcp.port", global_mgcp_gateway_tcp_port, mgcp_tpkt_handle);
2800 dissector_add_uint("udp.port", global_mgcp_gateway_udp_port, mgcp_handle);
2801 dissector_add_uint("tcp.port", global_mgcp_callagent_tcp_port, mgcp_tpkt_handle);
2802 dissector_add_uint("udp.port", global_mgcp_callagent_udp_port, mgcp_handle);
2806 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2808 * Local variables:
2809 * c-basic-offset: 8
2810 * tab-width: 8
2811 * indent-tabs-mode: t
2812 * End:
2814 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2815 * :indentSize=8:tabSize=8:noTabs=false: