Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-mgcp.c
Line
Count
Source
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
13
 *
14
 * Copyright (c) 2000 by Ed Warnicke <hagbard@physics.rutgers.edu>
15
 * Copyright (c) 2004 by Thomas Anders <thomas.anders [AT] blue-cable.de>
16
 *
17
 * Wireshark - Network traffic analyzer
18
 * By Gerald Combs <gerald@wireshark.org>
19
 * Copyright 1999 Gerald Combs
20
 *
21
 * SPDX-License-Identifier: GPL-2.0-or-later
22
 */
23
24
0
#define WS_LOG_DOMAIN "packet-mgcp"
25
26
#include "config.h"
27
#include <wireshark.h>
28
29
#include <stdlib.h>
30
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"
42
43
#include <wsutil/strtoi.h>
44
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
49
50
51
/* Define the mgcp proto */
52
static int proto_mgcp;
53
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;
168
169
static expert_field ei_mgcp_rsp_rspcode_invalid;
170
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 }
230
};
231
static value_string_ext mgcp_return_code_vals_ext = VALUE_STRING_EXT_INIT(mgcp_return_code_vals);
232
233
/* TODO: add/use when tested/have capture to test with */
234
/*
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 }
244
};
245
*/
246
247
248
/*
249
 * Define the trees for mgcp
250
 * We need one for MGCP itself, one for the MGCP parameters and one
251
 * for each of the dissected parameters
252
 */
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;
259
260
/*
261
 * Define the tap for mgcp
262
 */
263
static int mgcp_tap;
264
265
/*
266
 * Here are the global variables associated with
267
 * the various user definable characteristics of the dissection
268
 *
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.
274
 *
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.
277
 *
278
 */
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;
285
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
290
/*
291
 * The various functions that either dissect some
292
 * subpart of MGCP.  These aren't really proto dissectors but they
293
 * are written in the same style.
294
 */
295
static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
296
         proto_tree *mgcp_tree, proto_tree *ti);
297
static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mgcp_info_t* mi);
298
static void dissect_mgcp_params(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, mgcp_info_t* mi);
299
static void dissect_mgcp_connectionparams(proto_tree *parent_tree, packet_info* pinfo, tvbuff_t *tvb,
300
            int offset, int param_type_len,
301
            int param_val_len);
302
static void dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, packet_info* pinfo, tvbuff_t *tvb,
303
            int offset, int param_type_len,
304
            int param_val_len);
305
static void dissect_mgcp_localvoicemetrics(proto_tree *parent_tree, packet_info* pinfo, tvbuff_t *tvb,
306
            int offset, int param_type_len,
307
            int param_val_len);
308
static void dissect_mgcp_remotevoicemetrics(proto_tree *parent_tree, packet_info* pinfo, tvbuff_t *tvb,
309
            int offset, int param_type_len,
310
            int param_val_len);
311
312
static void mgcp_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
313
314
14
#define NUM_TIMESTATS 11
315
316
static const value_string mgcp_message_type[] = {
317
  {  0, "Overall"},
318
  {  1, "EPCF   "},
319
  {  2, "CRCX   "},
320
  {  3, "MDCX   "},
321
  {  4, "DLCX   "},
322
  {  5, "RQNT   "},
323
  {  6, "NTFY   "},
324
  {  7, "AUEP   "},
325
  {  8, "AUCX   "},
326
  {  9, "RSIP   "},
327
  {  0, NULL}
328
};
329
330
static tap_packet_status
331
mgcpstat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pmi, tap_flags_t flags _U_)
332
0
{
333
0
  rtd_data_t* rtd_data = (rtd_data_t*)pms;
334
0
  rtd_stat_table* ms = &rtd_data->stat_table;
335
0
  const mgcp_info_t *mi = (const mgcp_info_t *)pmi;
336
0
  nstime_t delta;
337
0
  tap_packet_status ret = TAP_PACKET_DONT_REDRAW;
338
339
0
  switch (mi->mgcp_type) {
340
341
0
  case MGCP_REQUEST:
342
0
    if (mi->is_duplicate) {
343
      /* Duplicate is ignored */
344
0
      ms->time_stats[0].req_dup_num++;
345
0
    }
346
0
    else {
347
0
      ms->time_stats[0].open_req_num++;
348
0
    }
349
0
    break;
350
351
0
  case MGCP_RESPONSE:
352
0
    if (mi->is_duplicate) {
353
      /* Duplicate is ignored */
354
0
      ms->time_stats[0].rsp_dup_num++;
355
0
    }
356
0
    else if (!mi->request_available) {
357
      /* no request was seen */
358
0
      ms->time_stats[0].disc_rsp_num++;
359
0
    }
360
0
    else {
361
0
      ms->time_stats[0].open_req_num--;
362
      /* calculate time delta between request and response */
363
0
      nstime_delta(&delta, &pinfo->abs_ts, &mi->req_time);
364
365
0
      time_stat_update(&(ms->time_stats[0].rtd[0]), &delta, pinfo);
366
367
0
      if (g_ascii_strncasecmp(mi->code, "EPCF", 4) == 0 ) {
368
0
        time_stat_update(&(ms->time_stats[0].rtd[1]), &delta, pinfo);
369
0
      }
370
0
      else if (g_ascii_strncasecmp(mi->code, "CRCX", 4) == 0 ) {
371
0
        time_stat_update(&(ms->time_stats[0].rtd[2]), &delta, pinfo);
372
0
      }
373
0
      else if (g_ascii_strncasecmp(mi->code, "MDCX", 4) == 0 ) {
374
0
        time_stat_update(&(ms->time_stats[0].rtd[3]), &delta, pinfo);
375
0
      }
376
0
      else if (g_ascii_strncasecmp(mi->code, "DLCX", 4) == 0 ) {
377
0
        time_stat_update(&(ms->time_stats[0].rtd[4]), &delta, pinfo);
378
0
      }
379
0
      else if (g_ascii_strncasecmp(mi->code, "RQNT", 4) == 0 ) {
380
0
        time_stat_update(&(ms->time_stats[0].rtd[5]), &delta, pinfo);
381
0
      }
382
0
      else if (g_ascii_strncasecmp(mi->code, "NTFY", 4) == 0 ) {
383
0
        time_stat_update(&(ms->time_stats[0].rtd[6]), &delta, pinfo);
384
0
      }
385
0
      else if (g_ascii_strncasecmp(mi->code, "AUEP", 4) == 0 ) {
386
0
        time_stat_update(&(ms->time_stats[0].rtd[7]), &delta, pinfo);
387
0
      }
388
0
      else if (g_ascii_strncasecmp(mi->code, "AUCX", 4) == 0 ) {
389
0
        time_stat_update(&(ms->time_stats[0].rtd[8]), &delta, pinfo);
390
0
      }
391
0
      else if (g_ascii_strncasecmp(mi->code, "RSIP", 4) == 0 ) {
392
0
        time_stat_update(&(ms->time_stats[0].rtd[9]), &delta, pinfo);
393
0
      }
394
0
      else {
395
0
        time_stat_update(&(ms->time_stats[0].rtd[10]), &delta, pinfo);
396
0
      }
397
398
0
      ret = TAP_PACKET_REDRAW;
399
0
    }
400
0
    break;
401
402
0
  default:
403
0
    break;
404
0
  }
405
406
0
  return ret;
407
0
}
408
409
410
/*
411
 * Some functions which should be moved to a library
412
 * as I think that people may find them of general usefulness.
413
 */
414
static int tvb_find_null_line(tvbuff_t* tvb, int offset, int len, int* next_offset);
415
static int tvb_find_dot_line(tvbuff_t* tvb, int offset, int len, int* next_offset);
416
417
static dissector_handle_t sdp_handle;
418
static dissector_handle_t mgcp_handle;
419
extern void
420
dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
421
      dissector_handle_t subdissector_handle);
422
extern uint16_t is_asciitpkt(tvbuff_t *tvb);
423
424
/*
425
 * Init Hash table stuff
426
 */
427
428
typedef struct _mgcp_call_info_key
429
{
430
  uint32_t transid;
431
  conversation_t *conversation;
432
} mgcp_call_info_key;
433
434
static wmem_map_t *mgcp_calls;
435
436
/* Compare 2 keys */
437
static int mgcp_call_equal(const void *k1, const void *k2)
438
297
{
439
297
  const mgcp_call_info_key* key1 = (const mgcp_call_info_key*) k1;
440
297
  const mgcp_call_info_key* key2 = (const mgcp_call_info_key*) k2;
441
442
297
  return (key1->transid == key2->transid &&
443
297
          key1->conversation == key2->conversation);
444
297
}
445
446
/* Calculate a hash key */
447
static unsigned mgcp_call_hash(const void *k)
448
362
{
449
362
  const mgcp_call_info_key* key = (const mgcp_call_info_key*) k;
450
451
362
  return key->transid  + key->conversation->conv_index;
452
362
}
453
454
455
/************************************************************************
456
 * dissect_mgcp - The dissector for the Media Gateway Control Protocol
457
 ************************************************************************/
458
static int dissect_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
459
485
{
460
485
  int sectionlen;
461
485
  uint32_t num_messages;
462
485
  int tvb_sectionend, tvb_sectionbegin, tvb_len;
463
485
  proto_tree *mgcp_tree = NULL;
464
485
  proto_item *ti = NULL, *tii;
465
485
  const char *verb_name = "";
466
467
  /* Initialize variables */
468
485
  tvb_sectionend = 0;
469
485
  tvb_sectionbegin = tvb_sectionend;
470
485
  tvb_len = tvb_reported_length(tvb);
471
485
  num_messages = 0;
472
473
  /*
474
   * Check to see whether we're really dealing with MGCP by looking
475
   * for a valid MGCP verb or response code.  This isn't infallible,
476
   * but it's cheap and it's better than nothing.
477
   */
478
485
  if (!is_mgcp_verb(tvb, 0, tvb_len, &verb_name) && !is_mgcp_rspcode(tvb, 0, tvb_len))
479
252
    return 0;
480
481
  /*
482
   * Set the columns now, so that they'll be set correctly if we throw
483
   * an exception.  We can set them later as well....
484
   */
485
233
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "MGCP");
486
233
  col_clear(pinfo->cinfo, COL_INFO);
487
488
  /*
489
   * Loop through however many mgcp messages may be stuck in
490
   * this packet using piggybacking
491
   */
492
233
  do
493
1.07k
  {
494
1.07k
    num_messages++;
495
496
    /* Create our mgcp subtree */
497
1.07k
    ti = proto_tree_add_item(tree, proto_mgcp, tvb, 0, -1, ENC_NA);
498
1.07k
    mgcp_tree = proto_item_add_subtree(ti, ett_mgcp);
499
500
1.07k
    sectionlen = tvb_find_dot_line(tvb, tvb_sectionbegin, -1, &tvb_sectionend);
501
1.07k
    if (sectionlen != -1)
502
1.07k
    {
503
1.07k
      dissect_mgcp_message(tvb_new_subset_length(tvb, tvb_sectionbegin, sectionlen),
504
1.07k
          pinfo, tree, mgcp_tree, ti);
505
1.07k
      tvb_sectionbegin = tvb_sectionend;
506
1.07k
    }
507
1
    else
508
1
    {
509
1
      break;
510
1
    }
511
1.07k
  } while (tvb_sectionend < tvb_len);
512
513
233
  tii = proto_tree_add_uint(mgcp_tree, hf_mgcp_messagecount, tvb,
514
233
      0 , 0 , num_messages);
515
233
  proto_item_set_hidden(tii);
516
517
  /*
518
   * Add our column information after dissecting SDP
519
   * in order to prevent the column info changing to reflect the SDP
520
   * (when showing message count)
521
   */
522
233
  tvb_sectionbegin = 0;
523
233
  if (global_mgcp_message_count == true )
524
0
  {
525
0
    if (num_messages > 1)
526
0
    {
527
0
      col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MGCP (%i messages)", num_messages);
528
0
    }
529
0
    else
530
0
    {
531
0
      col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MGCP (%i message)", num_messages);
532
0
    }
533
0
  }
534
535
233
  sectionlen = tvb_find_line_end(tvb, tvb_sectionbegin, -1,
536
233
      &tvb_sectionend, false);
537
233
  col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s",
538
233
      tvb_format_text(pinfo->pool, tvb, tvb_sectionbegin, sectionlen));
539
540
233
  return tvb_len;
541
485
}
542
543
/************************************************************************
544
 * dissect_tpkt_mgcp - The dissector for the ASCII TPKT Media Gateway Control Protocol
545
 ************************************************************************/
546
static int dissect_tpkt_mgcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
547
194
{
548
194
  uint16_t ascii_tpkt;
549
194
  int     offset = 0;
550
551
  /* Check whether this looks like a ASCII TPKT-encapsulated
552
   *  MGCP packet.
553
   */
554
194
  ascii_tpkt = is_asciitpkt(tvb);
555
556
194
  if (ascii_tpkt != 1 )
557
158
  {
558
    /*
559
     * It's not a ASCII TPKT packet
560
     * in MGCP
561
     */
562
158
    offset = dissect_mgcp(tvb, pinfo, tree, NULL);
563
158
  }
564
36
  else
565
36
  {
566
    /*
567
     * Dissect ASCII TPKT header
568
     */
569
36
    dissect_asciitpkt(tvb, pinfo, tree, mgcp_handle);
570
36
    offset = tvb_reported_length(tvb);
571
36
  }
572
573
194
  return offset;
574
194
}
575
576
/* Dissect an individual MGCP message */
577
static void dissect_mgcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
578
         proto_tree *mgcp_tree, proto_tree *ti)
579
1.07k
{
580
  /* Declare variables */
581
1.07k
  int sectionlen;
582
1.07k
  int tvb_sectionend, tvb_sectionbegin, tvb_len;
583
1.07k
  tvbuff_t *next_tvb;
584
1.07k
  const char *verb_name = "";
585
1.07k
  mgcp_info_t* mi = wmem_new0(pinfo->pool, mgcp_info_t);
586
1.07k
  sdp_setup_info_t setup_info = { .hf_id = 0, .hf_type = SDP_TRACE_ID_HF_TYPE_UINT32 };
587
1.07k
  media_content_info_t content_info = { MEDIA_CONTAINER_SIP_DATA, NULL, NULL, &setup_info };
588
589
1.07k
  mi->mgcp_type = MGCP_OTHERS;
590
591
  /* Initialize variables */
592
1.07k
  tvb_len = tvb_reported_length(tvb);
593
594
  /*
595
   * Check to see whether we're really dealing with MGCP by looking
596
   * for a valid MGCP verb or response code.  This isn't infallible,
597
   * but it's cheap and it's better than nothing.
598
   */
599
1.07k
  if (is_mgcp_verb(tvb, 0, tvb_len, &verb_name) || is_mgcp_rspcode(tvb, 0, tvb_len))
600
760
  {
601
    /* dissect first line */
602
760
    tvb_sectionbegin = 0;
603
760
    tvb_sectionend = tvb_sectionbegin;
604
760
    sectionlen = tvb_find_line_end(tvb, 0, -1, &tvb_sectionend, false);
605
760
    if (sectionlen > 0)
606
760
    {
607
760
      dissect_mgcp_firstline(tvb_new_subset_length(tvb, tvb_sectionbegin,
608
760
                             sectionlen), pinfo,
609
760
                             mgcp_tree, mi);
610
760
    }
611
760
    tvb_sectionbegin = tvb_sectionend;
612
613
    /* Dissect params */
614
760
    if (tvb_sectionbegin < tvb_len)
615
568
    {
616
568
      sectionlen = tvb_find_null_line(tvb, tvb_sectionbegin, -1,
617
568
                                      &tvb_sectionend);
618
568
      if (sectionlen > 0)
619
534
      {
620
534
        dissect_mgcp_params(tvb_new_subset_length(tvb, tvb_sectionbegin, sectionlen),
621
534
                                           pinfo, mgcp_tree, mi);
622
534
      }
623
568
    }
624
625
    /* Set the mgcp payload length correctly so we don't include any
626
       encapsulated SDP */
627
760
    sectionlen = tvb_sectionend;
628
760
    proto_item_set_len(ti, sectionlen);
629
630
    /* Display the raw text of the mgcp message if desired */
631
632
    /* Do we want to display the raw text of our MGCP packet? */
633
760
    if (global_mgcp_raw_text)
634
0
    {
635
0
      mgcp_raw_text_add(tvb, mgcp_tree);
636
0
    }
637
638
    /* Dissect sdp payload */
639
760
    if (tvb_sectionend < tvb_len)
640
63
    {
641
63
      setup_info.is_osmux = mi->is_osmux;
642
63
      next_tvb = tvb_new_subset_remaining(tvb, tvb_sectionend);
643
63
      call_dissector_with_data(sdp_handle, next_tvb, pinfo, tree, &content_info);
644
63
    }
645
760
  }
646
1.07k
}
647
648
649
/*
650
 * Add the raw text of the message to the dissect tree if appropriate
651
 * preferences are specified.
652
 */
653
static void mgcp_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
654
0
{
655
0
  int tvb_linebegin, tvb_lineend, linelen;
656
657
0
  tvb_linebegin = 0;
658
659
0
  do
660
0
  {
661
0
    tvb_find_line_end(tvb, tvb_linebegin, -1, &tvb_lineend, false);
662
0
    linelen = tvb_lineend - tvb_linebegin;
663
0
    proto_tree_add_format_text(tree, tvb, tvb_linebegin, linelen);
664
0
    tvb_linebegin = tvb_lineend;
665
0
  } while (tvb_offset_exists(tvb, tvb_lineend));
666
0
}
667
668
/*
669
 * is_mgcp_verb - A function for determining whether there is a
670
 *                MGCP verb at offset in tvb
671
 *
672
 * Parameter:
673
 * tvb - The tvbuff in which we are looking for an MGCP verb
674
 * offset - The offset in tvb at which we are looking for a MGCP verb
675
 * maxlength - The maximum distance from offset we may look for the
676
 *             characters that make up a MGCP verb.
677
 * verb_name - The name for the verb code found (output)
678
 *
679
 * Return: true if there is an MGCP verb at offset in tvb, otherwise false
680
 */
681
static bool is_mgcp_verb(tvbuff_t *tvb, int offset, int maxlength, const char **verb_name)
682
2.30k
{
683
2.30k
  bool returnvalue = false;
684
2.30k
  char word[5];
685
686
  /* This function is used for checking if a packet is actually an
687
     mgcp packet. Make sure that we do not throw an exception
688
     during such a check. If we did throw an exception, we could
689
     not refuse the packet and give other dissectors the chance to
690
     look at it. */
691
2.30k
  if (tvb_captured_length_remaining(tvb, offset) < (int)sizeof(word))
692
166
    return false;
693
694
  /* Read the string into 'word' and see if it looks like the start of a verb */
695
2.13k
  if ((maxlength >= 4) && tvb_get_raw_bytes_as_string(tvb, offset, word, sizeof word))
696
2.13k
  {
697
2.13k
    if (((g_ascii_strncasecmp(word, "EPCF", 4) == 0) && (*verb_name = "EndpointConfiguration")) ||
698
2.13k
        ((g_ascii_strncasecmp(word, "CRCX", 4) == 0) && (*verb_name = "CreateConnection")) ||
699
2.13k
        ((g_ascii_strncasecmp(word, "MDCX", 4) == 0) && (*verb_name = "ModifyConnection")) ||
700
2.13k
        ((g_ascii_strncasecmp(word, "DLCX", 4) == 0) && (*verb_name = "DeleteConnection")) ||
701
2.13k
        ((g_ascii_strncasecmp(word, "RQNT", 4) == 0) && (*verb_name = "NotificationRequest")) ||
702
2.13k
        ((g_ascii_strncasecmp(word, "NTFY", 4) == 0) && (*verb_name = "Notify")) ||
703
2.13k
        ((g_ascii_strncasecmp(word, "AUEP", 4) == 0) && (*verb_name = "AuditEndpoint")) ||
704
2.13k
        ((g_ascii_strncasecmp(word, "AUCX", 4) == 0) && (*verb_name = "AuditConnection")) ||
705
2.13k
        ((g_ascii_strncasecmp(word, "RSIP", 4) == 0) && (*verb_name = "RestartInProgress")) ||
706
2.13k
        ((g_ascii_strncasecmp(word, "MESG", 4) == 0) && (*verb_name = "Message")) ||
707
2.13k
        (word[0] == 'X' && g_ascii_isalpha(word[1]) && g_ascii_isalpha(word[2]) &&
708
2.13k
                           g_ascii_isalpha(word[3]) && (*verb_name = "*Experimental*")))
709
415
    {
710
415
      returnvalue = true;
711
415
    }
712
2.13k
  }
713
714
  /* May be whitespace after verb code - anything else is an error.. */
715
2.13k
  if (returnvalue && maxlength >= 5)
716
415
  {
717
415
    char next = tvb_get_uint8(tvb, 4);
718
415
    if ((next != ' ') && (next != '\t'))
719
3
    {
720
3
      returnvalue = false;
721
3
    }
722
415
  }
723
724
2.13k
  return returnvalue;
725
2.30k
}
726
727
/*
728
 * is_mgcp_rspcode - A function for determining whether something which
729
 *                   looks roughly like a MGCP response code (3-digit number)
730
 *                   is at 'offset' in tvb
731
 *
732
 * Parameters:
733
 * tvb - The tvbuff in which we are looking for an MGCP response code
734
 * offset - The offset in tvb at which we are looking for a MGCP response code
735
 * maxlength - The maximum distance from offset we may look for the
736
 *             characters that make up a MGCP response code.
737
 *
738
 * Return: true if there is an MGCP response code at offset in tvb,
739
 *         otherwise false
740
 */
741
static bool is_mgcp_rspcode(tvbuff_t *tvb, int offset, int maxlength)
742
1.89k
{
743
1.89k
  bool returnvalue = false;
744
1.89k
  char word[4];
745
746
  /* see the comment in is_mgcp_verb() */
747
1.89k
  if (tvb_captured_length_remaining(tvb, offset) < (int)sizeof(word))
748
160
    return false;
749
750
  /* Do 1st 3 characters look like digits? */
751
1.73k
  if (maxlength >= 3)
752
1.73k
  {
753
1.73k
    tvb_get_raw_bytes_as_string(tvb, offset, word, sizeof word);
754
1.73k
    if (g_ascii_isdigit(word[0]) && g_ascii_isdigit(word[1]) && g_ascii_isdigit(word[2]))
755
1.35k
    {
756
1.35k
      returnvalue = true;
757
1.35k
    }
758
1.73k
  }
759
760
  /* Maybe some white space after the 3rd digit - anything else is an error */
761
1.73k
  if (returnvalue && maxlength >= 4)
762
1.35k
  {
763
1.35k
    char next = tvb_get_uint8(tvb, 3);
764
1.35k
    if ((next != ' ') && (next != '\t'))
765
35
    {
766
35
      returnvalue = false;
767
35
    }
768
1.35k
  }
769
770
1.73k
  return returnvalue;
771
1.89k
}
772
773
/*
774
 * tvb_parse_param - Parse the MGCP param into a type and a value.
775
 *
776
 * Parameters:
777
 * tvb - The tvbuff containing the MGCP param we are to parse.
778
 * offset - The offset in tvb at which we will begin looking for a
779
 *          MGCP parameter to parse.
780
 * len - The maximum distance from offset in tvb that we can look for
781
 *       an MGCP parameter to parse.
782
 * hf - The place to write a pointer to the integer representing the
783
 *      header field associated with the MGCP parameter parsed.
784
 *
785
 * Returns: The offset in tvb where the value of the MGCP parameter
786
 *          begins.
787
 */
788
static int tvb_parse_param(tvbuff_t* tvb, packet_info* pinfo, int offset, int len, int** hf, mgcp_info_t* mi)
789
2.30k
{
790
2.30k
  int returnvalue = -1, tvb_current_offset, ext_off;
791
2.30k
  uint8_t tempchar, plus_minus;
792
2.30k
  char **buf;
793
794
2.30k
  tvb_current_offset = offset;
795
2.30k
  *hf = NULL;
796
2.30k
  buf = NULL;
797
798
2.30k
  if (len > 0)
799
2.28k
  {
800
2.28k
    tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset));
801
802
2.28k
    switch (tempchar)
803
2.28k
    {
804
62
      case 'K':
805
62
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
806
61
        {
807
61
          *hf = &hf_mgcp_param_invalid;
808
61
          break;
809
61
        }
810
1
        *hf = &hf_mgcp_param_rspack;
811
1
        break;
812
7
      case 'B':
813
7
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
814
7
        {
815
7
          *hf = &hf_mgcp_param_invalid;
816
7
          break;
817
7
        }
818
0
        *hf = &hf_mgcp_param_bearerinfo;
819
0
        break;
820
42
      case 'C':
821
42
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
822
42
        {
823
42
          *hf = &hf_mgcp_param_invalid;
824
42
          break;
825
42
        }
826
0
        *hf = &hf_mgcp_param_callid;
827
0
        break;
828
42
      case 'I':
829
42
        tvb_current_offset++;
830
42
        if (len > (tvb_current_offset - offset) &&
831
28
           (tempchar = tvb_get_uint8(tvb, tvb_current_offset)) == ':')
832
0
        {
833
0
          *hf = &hf_mgcp_param_connectionid;
834
0
          tvb_current_offset--;
835
0
        }
836
42
        else
837
42
          if (tempchar == '2')
838
0
        {
839
0
          *hf = &hf_mgcp_param_secondconnectionid;
840
0
        }
841
42
        break;
842
7
      case 'N':
843
7
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
844
7
        {
845
7
          *hf = &hf_mgcp_param_invalid;
846
7
          break;
847
7
        }
848
0
        *hf = &hf_mgcp_param_notifiedentity;
849
0
        break;
850
78
      case 'X':
851
        /* Move past 'X' */
852
78
        tvb_current_offset++;
853
854
        /* X: is RequestIdentifier */
855
78
        if (len > (tvb_current_offset - offset) &&
856
77
           (tempchar = tvb_get_uint8(tvb, tvb_current_offset)) == ':')
857
0
        {
858
0
          *hf = &hf_mgcp_param_requestid;
859
0
          tvb_current_offset--;
860
0
        }
861
        /* XRM/MCR */
862
78
        else
863
78
        if (len > (tvb_current_offset - offset) &&
864
77
           ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb,tvb_current_offset))) == 'R')
865
0
        {
866
          /* Move past 'R' */
867
0
          tvb_current_offset += 3;
868
0
          if (len > (tvb_current_offset - offset) &&
869
0
            ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb,tvb_current_offset))) == 'R')
870
0
          {
871
0
            *hf = &hf_mgcp_param_remotevoicemetrics;
872
0
          }
873
0
          else
874
0
          if (len > (tvb_current_offset - offset) &&
875
0
             ((uint8_t)g_ascii_toupper(tvb_get_uint8(tvb,tvb_current_offset))) == 'L')
876
0
          {
877
0
            *hf = &hf_mgcp_param_localvoicemetrics;
878
0
          }
879
0
          tvb_current_offset -= 4;
880
0
        }
881
882
        /* X+...: or X-....: are vendor extension parameters */
883
78
        else
884
78
        if (len > (tvb_current_offset - offset) &&
885
77
            ((plus_minus = tvb_get_uint8(tvb, tvb_current_offset)) == '-' ||
886
77
             (plus_minus == '+')))
887
0
        {
888
          /* Move past + or - */
889
0
          tvb_current_offset++;
890
891
          /* Keep going, through possible vendor param name */
892
          /* We have a mempbrk; perhaps an equivalent of strspn
893
           * for tvbs would be useful.
894
           */
895
0
          for (ext_off = 0; len > (ext_off + tvb_current_offset-offset); ext_off++) {
896
0
            tempchar = tvb_get_uint8(tvb, tvb_current_offset + ext_off);
897
0
            if (!g_ascii_isalpha(tempchar) && !g_ascii_isdigit(tempchar)) break;
898
0
          }
899
900
0
          if (tempchar == ':')
901
0
          {
902
            /* Looks like a valid vendor param name */
903
0
            ws_debug("MGCP Extension: %s", tvb_get_string_enc(pinfo->pool, tvb, tvb_current_offset, ext_off, ENC_ASCII));
904
0
            switch (plus_minus)
905
0
            {
906
0
              case '+':
907
0
                *hf = &hf_mgcp_param_extension_critical;
908
0
                break;
909
0
              case '-':
910
0
                if (tvb_strncaseeql(tvb, tvb_current_offset, "OSMUX", ext_off) == 0) {
911
0
                  *hf = &hf_mgcp_param_x_osmux;
912
0
                } else {
913
0
                  *hf = &hf_mgcp_param_extension;
914
0
                }
915
0
                break;
916
0
            }
917
            /* -1: Final generic path below expects us to point to char before the ':'. */
918
0
            tvb_current_offset += ext_off - 1;
919
0
          }
920
0
        }
921
78
        break;
922
78
      case 'L':
923
14
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
924
13
        {
925
13
          *hf = &hf_mgcp_param_invalid;
926
13
          break;
927
13
        }
928
1
        *hf = &hf_mgcp_param_localconnoptions;
929
1
        break;
930
9
      case 'M':
931
9
        tvb_current_offset++;
932
9
        if (len > (tvb_current_offset - offset) &&
933
7
           (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
934
1
        {
935
1
          *hf = &hf_mgcp_param_connectionmode;
936
1
          tvb_current_offset--;
937
1
        }
938
8
        else
939
8
        if (tempchar == 'D')
940
0
        {
941
0
          *hf = &hf_mgcp_param_maxmgcpdatagram;
942
0
        }
943
9
        break;
944
1
      case 'R':
945
1
        tvb_current_offset++;
946
1
        if (len > (tvb_current_offset - offset) &&
947
1
            (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
948
0
        {
949
0
          *hf = &hf_mgcp_param_reqevents;
950
0
          tvb_current_offset--;
951
0
        }
952
1
        else
953
1
        if ( tempchar == 'M')
954
0
        {
955
0
          *hf = &hf_mgcp_param_restartmethod;
956
0
        }
957
1
        else
958
1
        if (tempchar == 'D')
959
0
        {
960
0
          *hf = &hf_mgcp_param_restartdelay;
961
0
        }
962
1
        break;
963
238
      case 'S':
964
238
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
965
231
        {
966
231
          *hf = &hf_mgcp_param_invalid;
967
231
          break;
968
231
        }
969
7
        *hf = &hf_mgcp_param_signalreq;
970
7
        buf = &(mi->signalReq);
971
7
        break;
972
14
      case 'D':
973
14
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
974
14
        {
975
14
          if (len > (tvb_current_offset + 5 - offset) &&
976
5
            (g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset + 1) == 'Q')) &&
977
0
            (                tvb_get_uint8(tvb, tvb_current_offset + 2) == '-' ) &&
978
0
            (g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset + 3) == 'R')) &&
979
0
            (g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset + 4) == 'I')) &&
980
0
            (                tvb_get_uint8(tvb, tvb_current_offset + 5) == ':' )
981
14
          ) {
982
0
            tvb_current_offset+=4;
983
0
            *hf = &hf_mgcp_param_resourceid;
984
0
            break;
985
0
          }
986
987
14
          *hf = &hf_mgcp_param_invalid;
988
14
          break;
989
14
        }
990
0
        *hf = &hf_mgcp_param_digitmap;
991
0
        mi->hasDigitMap = true;
992
0
        break;
993
119
      case 'O':
994
119
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
995
95
        {
996
95
          *hf = &hf_mgcp_param_invalid;
997
95
          break;
998
95
        }
999
24
        *hf = &hf_mgcp_param_observedevent;
1000
24
        buf = &(mi->observedEvents);
1001
24
        break;
1002
29
      case 'P':
1003
29
        tvb_current_offset++;
1004
29
        if (len > (tvb_current_offset - offset) &&
1005
29
            (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
1006
0
        {
1007
0
          *hf = &hf_mgcp_param_connectionparam;
1008
0
          tvb_current_offset--;
1009
0
        }
1010
29
        else
1011
29
        if ( tempchar == 'L')
1012
0
        {
1013
0
          *hf = &hf_mgcp_param_packagelist;
1014
0
        }
1015
29
        break;
1016
37
      case 'E':
1017
37
        tvb_current_offset++;
1018
37
        if (len > (tvb_current_offset - offset) &&
1019
29
            (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
1020
0
        {
1021
0
          *hf = &hf_mgcp_param_reasoncode;
1022
0
          tvb_current_offset--;
1023
0
        }
1024
37
        else
1025
37
        if ( tempchar == 'S')
1026
0
        {
1027
0
          *hf = &hf_mgcp_param_eventstates;
1028
0
        }
1029
37
        break;
1030
10
      case 'Z':
1031
10
        tvb_current_offset++;
1032
10
        if (len > (tvb_current_offset - offset) &&
1033
9
            (tempchar = (uint8_t)g_ascii_toupper(tvb_get_uint8(tvb, tvb_current_offset))) == ':')
1034
0
        {
1035
0
          *hf = &hf_mgcp_param_specificendpoint;
1036
0
          tvb_current_offset--;
1037
0
        }
1038
10
        else
1039
10
        if (tempchar == '2')
1040
0
        {
1041
0
          *hf = &hf_mgcp_param_secondendpointid;
1042
0
        }
1043
10
        break;
1044
26
      case 'F':
1045
26
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
1046
26
        {
1047
26
          *hf = &hf_mgcp_param_invalid;
1048
26
          break;
1049
26
        }
1050
0
        *hf = &hf_mgcp_param_reqinfo;
1051
0
        break;
1052
21
      case 'Q':
1053
21
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
1054
21
        {
1055
21
          *hf = &hf_mgcp_param_invalid;
1056
21
          break;
1057
21
        }
1058
0
        *hf = &hf_mgcp_param_quarantinehandling;
1059
0
        break;
1060
59
      case 'T':
1061
59
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
1062
59
        {
1063
59
          *hf = &hf_mgcp_param_invalid;
1064
59
          break;
1065
59
        }
1066
0
        *hf = &hf_mgcp_param_detectedevents;
1067
0
        break;
1068
10
      case 'A':
1069
10
        if (tvb_get_uint8(tvb, tvb_current_offset+1) != ':')
1070
10
        {
1071
10
          *hf = &hf_mgcp_param_invalid;
1072
10
          break;
1073
10
        }
1074
0
        *hf = &hf_mgcp_param_capabilities;
1075
0
        break;
1076
1077
1.46k
      default:
1078
1.46k
        *hf = &hf_mgcp_param_invalid;
1079
1.46k
        break;
1080
2.28k
    }
1081
1082
    /* Move to (hopefully) the colon */
1083
2.28k
    tvb_current_offset++;
1084
1085
    /* Add a recognised parameter type if we have one */
1086
2.28k
    if (*hf != NULL && len > (tvb_current_offset - offset) &&
1087
1.91k
        tvb_get_uint8(tvb, tvb_current_offset) == ':')
1088
56
    {
1089
56
      tvb_current_offset++;
1090
56
      tvb_current_offset = tvb_skip_wsp(tvb, tvb_current_offset, (len - tvb_current_offset + offset));
1091
56
      returnvalue = tvb_current_offset;
1092
1093
      /* set the observedEvents or signalReq used in Voip Calls analysis */
1094
56
      if (buf != NULL) {
1095
31
        *buf = (char*)tvb_get_string_enc(pinfo->pool, tvb, tvb_current_offset, (len - tvb_current_offset + offset), ENC_ASCII);
1096
31
      }
1097
56
    }
1098
2.28k
  }
1099
20
  else
1100
20
  {
1101
    /* Was an empty line */
1102
20
    *hf = &hf_mgcp_param_invalid;
1103
20
  }
1104
1105
  /* For these types, show the whole line */
1106
2.30k
  if ((*hf == &hf_mgcp_param_invalid) ||
1107
239
      (*hf == &hf_mgcp_param_extension) || (*hf == &hf_mgcp_param_extension_critical) ||
1108
239
      (*hf == &hf_mgcp_param_localvoicemetrics) || (*hf == &hf_mgcp_param_remotevoicemetrics))
1109
2.06k
  {
1110
2.06k
    returnvalue = offset;
1111
2.06k
  }
1112
1113
2.30k
  return returnvalue;
1114
2.30k
}
1115
1116
1117
/*
1118
 * dissect_mgcp_firstline - Dissects the firstline of an MGCP message.
1119
 *                          Adds the appropriate headers fields to
1120
 *                          tree for the dissection of the first line
1121
 *                          of an MGCP message.
1122
 *
1123
 * Parameters:
1124
 * tvb - The tvb containing the first line of an MGCP message.  This
1125
 *       tvb is presumed to ONLY contain the first line of the MGCP
1126
 *       message.
1127
 * pinfo - The packet info for the packet.  This is not really used
1128
 *         by this function but is passed through so as to retain the
1129
 *         style of a dissector.
1130
 * tree - The tree from which to hang the structured information parsed
1131
 *        from the first line of the MGCP message.
1132
 */
1133
static void dissect_mgcp_firstline(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mgcp_info_t* mi)
1134
760
{
1135
760
  int tvb_current_offset, tvb_previous_offset, tvb_len, tvb_current_len;
1136
760
  int tokennum, tokenlen;
1137
760
  proto_item* hidden_item;
1138
760
  char *transid = NULL;
1139
760
  char *code = NULL;
1140
760
  char *endpointId = NULL;
1141
760
  mgcp_type_t mgcp_type = MGCP_OTHERS;
1142
760
  conversation_t* conversation;
1143
760
  mgcp_call_info_key mgcp_call_key;
1144
760
  mgcp_call_info_key *new_mgcp_call_key = NULL;
1145
760
  mgcp_call_t *mgcp_call = NULL;
1146
760
  nstime_t delta;
1147
760
  const char *verb_description = "";
1148
760
  char code_with_verb[64] = "";  /* To fit "<4-letter-code> (<longest-verb>)" */
1149
760
  proto_item* pi;
1150
1151
760
  static address null_address = ADDRESS_INIT_NONE;
1152
760
  tvb_previous_offset = 0;
1153
760
  tvb_len = tvb_reported_length(tvb);
1154
760
  tvb_current_offset = tvb_previous_offset;
1155
760
  mi->is_duplicate = false;
1156
760
  mi->request_available = false;
1157
1158
  /* if (tree) */
1159
760
  {
1160
760
    tokennum = 0;
1161
1162
760
    do
1163
1.83k
    {
1164
1.83k
      tvb_current_len = tvb_reported_length_remaining(tvb, tvb_previous_offset);
1165
1.83k
      tvb_current_offset = tvb_find_uint8(tvb, tvb_previous_offset, tvb_current_len, ' ');
1166
1.83k
      if (tvb_current_offset == -1)
1167
692
      {
1168
692
        tvb_current_offset = tvb_len;
1169
692
        tokenlen = tvb_current_len;
1170
692
      }
1171
1.14k
      else
1172
1.14k
      {
1173
1.14k
        tokenlen = tvb_current_offset - tvb_previous_offset;
1174
1.14k
      }
1175
1.83k
      if (tokennum == 0)
1176
760
      {
1177
760
        if (tokenlen > 4)
1178
17
        {
1179
          /* XXX - exception */
1180
17
          return;
1181
17
        }
1182
1183
743
        code = tvb_format_text(pinfo->pool, tvb, tvb_previous_offset, tokenlen);
1184
743
        (void) g_strlcpy(mi->code, code, 5);
1185
743
        if (is_mgcp_verb(tvb, tvb_previous_offset, tvb_current_len, &verb_description))
1186
134
        {
1187
134
          mgcp_type = MGCP_REQUEST;
1188
134
          if (verb_description != NULL)
1189
134
          {
1190
            /* Can show verb along with code if known */
1191
134
            snprintf(code_with_verb, 64, "%s (%s)", code, verb_description);
1192
134
          }
1193
1194
134
          proto_tree_add_string_format(tree, hf_mgcp_req_verb, tvb,
1195
134
                                       tvb_previous_offset, tokenlen,
1196
134
                                       code, "%s",
1197
134
                                       strlen(code_with_verb) ? code_with_verb : code);
1198
134
        }
1199
609
        else
1200
609
        if (is_mgcp_rspcode(tvb, tvb_previous_offset, tvb_current_len))
1201
609
        {
1202
609
          bool rspcode_valid;
1203
609
          mgcp_type = MGCP_RESPONSE;
1204
609
          rspcode_valid = ws_strtou32(code, NULL, &mi->rspcode);
1205
609
          pi = proto_tree_add_uint(tree, hf_mgcp_rsp_rspcode, tvb,
1206
609
                              tvb_previous_offset, tokenlen, mi->rspcode);
1207
609
          if (!rspcode_valid)
1208
0
            expert_add_info(pinfo, pi, &ei_mgcp_rsp_rspcode_invalid);
1209
609
        }
1210
0
        else
1211
0
        {
1212
0
          break;
1213
0
        }
1214
743
      }
1215
1.81k
      if (tokennum == 1)
1216
741
      {
1217
741
        transid = tvb_format_text(pinfo->pool, tvb, tvb_previous_offset, tokenlen);
1218
        /* XXX - what if this isn't a valid text string? */
1219
741
        mi->transid = (uint32_t)strtoul(transid, NULL, 10);
1220
741
        proto_tree_add_string(tree, hf_mgcp_transid, tvb,
1221
741
                              tvb_previous_offset, tokenlen, transid);
1222
741
      }
1223
1.81k
      if (tokennum == 2)
1224
318
      {
1225
318
        if (mgcp_type == MGCP_REQUEST)
1226
81
        {
1227
81
          endpointId = tvb_format_text(pinfo->pool, tvb, tvb_previous_offset, tokenlen);
1228
81
          mi->endpointId = wmem_strdup(pinfo->pool, endpointId);
1229
81
          proto_tree_add_string(tree, hf_mgcp_req_endpoint, tvb,
1230
81
                                tvb_previous_offset, tokenlen, endpointId);
1231
81
        }
1232
237
        else
1233
237
        if (mgcp_type == MGCP_RESPONSE)
1234
237
        {
1235
237
          if (tvb_current_offset < tvb_len)
1236
31
          {
1237
31
            tokenlen = tvb_find_line_end(tvb, tvb_previous_offset,
1238
31
                                         -1, &tvb_current_offset, false);
1239
31
          }
1240
206
          else
1241
206
          {
1242
206
            tokenlen = tvb_current_len;
1243
206
          }
1244
237
          proto_tree_add_string(tree, hf_mgcp_rsp_rspstring, tvb,
1245
237
                                tvb_previous_offset, tokenlen,
1246
237
                                tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
1247
237
                                tokenlen));
1248
237
          break;
1249
237
        }
1250
318
      }
1251
1252
1.57k
      if ((tokennum == 3 && mgcp_type == MGCP_REQUEST))
1253
13
      {
1254
13
        if (tvb_current_offset < tvb_len )
1255
5
        {
1256
5
          tokenlen = tvb_find_line_end(tvb, tvb_previous_offset,
1257
5
                                       -1, &tvb_current_offset, false);
1258
5
        }
1259
8
        else
1260
8
        {
1261
8
          tokenlen = tvb_current_len;
1262
8
        }
1263
13
        proto_tree_add_string(tree, hf_mgcp_version, tvb,
1264
13
                              tvb_previous_offset, tokenlen,
1265
13
                              tvb_format_text(pinfo->pool, tvb, tvb_previous_offset,
1266
13
                              tokenlen));
1267
13
        break;
1268
13
      }
1269
1.56k
      if (tvb_current_offset < tvb_len)
1270
1.10k
      {
1271
1.10k
        tvb_previous_offset = tvb_skip_wsp(tvb, tvb_current_offset,
1272
1.10k
                                           tvb_current_len);
1273
1.10k
      }
1274
1.56k
      tokennum++;
1275
1.56k
    } while (tvb_current_offset < tvb_len && tvb_offset_exists(tvb, tvb_current_offset) && tvb_previous_offset < tvb_len && tokennum <= 3);
1276
1277
743
    switch (mgcp_type)
1278
743
    {
1279
609
      case MGCP_RESPONSE:
1280
609
        hidden_item = proto_tree_add_boolean(tree, hf_mgcp_rsp, tvb, 0, 0, true);
1281
609
        proto_item_set_hidden(hidden_item);
1282
        /* Check for MGCP response.  A response must match a call that
1283
           we've seen, and the response must be sent to the same
1284
           port and address that the call came from, and must
1285
           come from the port to which the call was sent.
1286
1287
           If the transport is connection-oriented (we check, for
1288
           now, only for "pinfo->ptype" of PT_TCP), we take
1289
           into account the address from which the call was sent
1290
           and the address to which the call was sent, because
1291
           the addresses of the two endpoints should be the same
1292
           for all calls and replies.
1293
1294
           If the transport is connectionless, we don't worry
1295
           about the address to which the call was sent and from
1296
           which the reply was sent, because there's no
1297
           guarantee that the reply will come from the address
1298
           to which the call was sent. */
1299
609
        if (pinfo->ptype == PT_TCP)
1300
391
        {
1301
391
          conversation = find_conversation_pinfo(pinfo, 0);
1302
391
        }
1303
218
        else
1304
218
        {
1305
          /* XXX - can we just use NO_ADDR_B?  Unfortunately,
1306
           * you currently still have to pass a non-null
1307
           * pointer for the second address argument even
1308
           * if you do that.
1309
           */
1310
218
          conversation = find_conversation(pinfo->num, &null_address,
1311
218
                                           &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
1312
218
                                           pinfo->destport, 0);
1313
218
        }
1314
609
        if (conversation != NULL)
1315
609
        {
1316
          /* Look only for matching request, if
1317
             matching conversation is available. */
1318
609
          mgcp_call_key.transid = mi->transid;
1319
609
          mgcp_call_key.conversation = conversation;
1320
609
          mgcp_call = (mgcp_call_t *)wmem_map_lookup(mgcp_calls, &mgcp_call_key);
1321
609
          if (mgcp_call)
1322
174
          {
1323
            /* Indicate the frame to which this is a reply. */
1324
174
            if (mgcp_call->req_num)
1325
174
            {
1326
174
              proto_item* item;
1327
174
              mi->request_available = true;
1328
174
              mgcp_call->responded = true;
1329
174
              mi->req_num = mgcp_call->req_num;
1330
174
              (void) g_strlcpy(mi->code, mgcp_call->code, 5);
1331
174
              item = proto_tree_add_uint_format(tree, hf_mgcp_req_frame,
1332
174
                                                tvb, 0, 0, mgcp_call->req_num,
1333
174
                                                "This is a response to a request in frame %u",
1334
174
                                                mgcp_call->req_num);
1335
174
              proto_item_set_generated(item);
1336
174
              nstime_delta(&delta, &pinfo->abs_ts, &mgcp_call->req_time);
1337
174
              item = proto_tree_add_time(tree, hf_mgcp_time, tvb, 0, 0, &delta);
1338
174
              proto_item_set_generated(item);
1339
174
            }
1340
1341
174
            if (mgcp_call->rsp_num == 0)
1342
2
            {
1343
              /* We have not yet seen a response to that call, so
1344
                 this must be the first response; remember its
1345
                 frame number. */
1346
2
              mgcp_call->rsp_num = pinfo->num;
1347
2
            }
1348
172
            else
1349
172
            {
1350
              /* We have seen a response to this call - but was it
1351
                 *this* response? (disregard provisional responses) */
1352
172
              if ((mgcp_call->rsp_num != pinfo->num) &&
1353
163
                  (mi->rspcode >= 200) &&
1354
160
                  (mi->rspcode == mgcp_call->rspcode))
1355
70
              {
1356
70
                proto_item* item;
1357
1358
                /* No, so it's a duplicate response. Mark it as such. */
1359
70
                mi->is_duplicate = true;
1360
70
                col_append_fstr(pinfo->cinfo, COL_INFO,
1361
70
                    ", Duplicate Response %u",
1362
70
                    mi->transid);
1363
1364
70
                item = proto_tree_add_uint(tree, hf_mgcp_dup, tvb, 0, 0, mi->transid);
1365
70
                proto_item_set_hidden(item);
1366
70
                item = proto_tree_add_uint(tree, hf_mgcp_rsp_dup,
1367
70
                    tvb, 0, 0, mi->transid);
1368
70
                proto_item_set_generated(item);
1369
70
                item = proto_tree_add_uint(tree, hf_mgcp_rsp_dup_frame,
1370
70
                    tvb, 0, 0, mgcp_call->rsp_num);
1371
70
                proto_item_set_generated(item);
1372
70
              }
1373
172
            }
1374
            /* Now store the response code (after comparison above) */
1375
174
            mgcp_call->rspcode = mi->rspcode;
1376
174
          }
1377
609
        }
1378
609
        break;
1379
134
      case MGCP_REQUEST:
1380
134
        hidden_item = proto_tree_add_boolean(tree, hf_mgcp_req, tvb, 0, 0, true);
1381
134
        proto_item_set_hidden(hidden_item);
1382
        /* Keep track of the address and port whence the call came,
1383
         * and the port to which the call is being sent, so that
1384
         * we can match up calls with replies.
1385
         *
1386
         * If the transport is connection-oriented (we check, for
1387
         * now, only for "pinfo->ptype" of PT_TCP), we take
1388
         * into account the address from which the call was sent
1389
         * and the address to which the call was sent, because
1390
         * the addresses of the two endpoints should be the same
1391
         * for all calls and replies.
1392
         *
1393
         * If the transport is connectionless, we don't worry
1394
         * about the address to which the call was sent and from
1395
         * which the reply was sent, because there's no
1396
         * guarantee that the reply will come from the address
1397
         * to which the call was sent.
1398
         */
1399
134
        if (pinfo->ptype == PT_TCP)
1400
0
        {
1401
0
          conversation = find_conversation_pinfo(pinfo, 0);
1402
0
        }
1403
134
        else
1404
134
        {
1405
          /*
1406
           * XXX - can we just use NO_ADDR_B?  Unfortunately,
1407
           * you currently still have to pass a non-null
1408
           * pointer for the second address argument even
1409
           * if you do that.
1410
           */
1411
134
          conversation = find_conversation(pinfo->num, &pinfo->src,
1412
134
                                           &null_address, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
1413
134
                                           pinfo->destport, 0);
1414
134
        }
1415
134
        if (conversation == NULL)
1416
0
        {
1417
          /* It's not part of any conversation - create a new one. */
1418
0
          if (pinfo->ptype == PT_TCP)
1419
0
          {
1420
0
            conversation = conversation_new(pinfo->num, &pinfo->src,
1421
0
                                            &pinfo->dst, CONVERSATION_TCP, pinfo->srcport,
1422
0
                                            pinfo->destport, 0);
1423
0
          }
1424
0
          else
1425
0
          {
1426
0
            conversation = conversation_new(pinfo->num, &pinfo->src,
1427
0
                                            &null_address, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
1428
0
                                            pinfo->destport, 0);
1429
0
          }
1430
0
        }
1431
1432
        /* Prepare the key data */
1433
134
        mgcp_call_key.transid = mi->transid;
1434
134
        mgcp_call_key.conversation = conversation;
1435
1436
        /* Look up the request */
1437
134
        mgcp_call = (mgcp_call_t *)wmem_map_lookup(mgcp_calls, &mgcp_call_key);
1438
134
        if (mgcp_call != NULL)
1439
123
        {
1440
          /* We've seen a request with this TRANSID, with the same
1441
             source and destination, before - but was it
1442
             *this* request? */
1443
123
          if (pinfo->num != mgcp_call->req_num)
1444
121
          {
1445
            /* No, so it's a duplicate request. Mark it as such. */
1446
121
            mi->is_duplicate = true;
1447
121
            mi->req_num = mgcp_call->req_num;
1448
121
            col_append_fstr(pinfo->cinfo, COL_INFO,
1449
121
                            ", Duplicate Request %u",
1450
121
                            mi->transid);
1451
121
            if (tree)
1452
121
            {
1453
121
              proto_item* item;
1454
121
              item = proto_tree_add_uint(tree, hf_mgcp_dup, tvb, 0, 0, mi->transid);
1455
121
              proto_item_set_hidden(item);
1456
121
              item = proto_tree_add_uint(tree, hf_mgcp_req_dup, tvb, 0, 0, mi->transid);
1457
121
              proto_item_set_generated(item);
1458
121
              item = proto_tree_add_uint(tree, hf_mgcp_req_dup_frame, tvb, 0, 0, mi->req_num);
1459
121
              proto_item_set_generated(item);
1460
121
            }
1461
121
          }
1462
123
        }
1463
11
        else
1464
11
        {
1465
          /* Prepare the value data.
1466
             "req_num" and "rsp_num" are frame numbers;
1467
             frame numbers are 1-origin, so we use 0
1468
             to mean "we don't yet know in which frame
1469
             the reply for this call appears". */
1470
11
          new_mgcp_call_key    = (mgcp_call_info_key *)wmem_alloc(wmem_file_scope(), sizeof(*new_mgcp_call_key));
1471
11
          *new_mgcp_call_key   = mgcp_call_key;
1472
11
          mgcp_call            = (mgcp_call_t *)wmem_alloc(wmem_file_scope(), sizeof(*mgcp_call));
1473
11
          mgcp_call->req_num   = pinfo->num;
1474
11
          mgcp_call->rsp_num   = 0;
1475
11
          mgcp_call->transid   = mi->transid;
1476
11
          mgcp_call->responded = false;
1477
11
          mgcp_call->req_time=pinfo->abs_ts;
1478
11
          (void) g_strlcpy(mgcp_call->code, mi->code, 5);
1479
1480
          /* Store it */
1481
11
          wmem_map_insert(mgcp_calls, new_mgcp_call_key, mgcp_call);
1482
11
        }
1483
134
        if (mgcp_call->rsp_num)
1484
87
        {
1485
87
          proto_item* item = proto_tree_add_uint_format(tree, hf_mgcp_rsp_frame,
1486
87
                                                        tvb, 0, 0, mgcp_call->rsp_num,
1487
87
                                                        "The response to this request is in frame %u",
1488
87
                                                        mgcp_call->rsp_num);
1489
87
          proto_item_set_generated(item);
1490
87
        }
1491
134
        break;
1492
0
      default:
1493
0
        break;
1494
743
    }
1495
1496
743
    mi->mgcp_type = mgcp_type;
1497
743
    if (mgcp_call)
1498
308
    {
1499
308
      mi->req_time.secs=mgcp_call->req_time.secs;
1500
308
      mi->req_time.nsecs=mgcp_call->req_time.nsecs;
1501
308
    }
1502
743
  }
1503
1504
0
  tap_queue_packet(mgcp_tap, pinfo, mi);
1505
743
}
1506
1507
/*
1508
 * dissect_mgcp_params - Dissects the parameters of an MGCP message.
1509
 *                       Adds the appropriate headers fields to
1510
 *                       tree for the dissection of the parameters
1511
 *                       of an MGCP message.
1512
 *
1513
 * Parameters:
1514
 * tvb - The tvb containing the parameters of an MGCP message.  This
1515
 *       tvb is presumed to ONLY contain the part of the MGCP
1516
 *       message which contains the MGCP parameters.
1517
 * tree - The tree from which to hang the structured information parsed
1518
 *        from the parameters of the MGCP message.
1519
 */
1520
static void dissect_mgcp_params(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, mgcp_info_t* mi)
1521
534
{
1522
534
  int linelen, tokenlen, *my_param;
1523
534
  int tvb_lineend, tvb_linebegin, tvb_len, old_lineend;
1524
534
  int tvb_tokenbegin;
1525
534
  proto_tree *mgcp_param_ti, *mgcp_param_tree;
1526
1527
534
  tvb_len = tvb_reported_length(tvb);
1528
534
  tvb_linebegin = 0;
1529
534
  tvb_lineend = tvb_linebegin;
1530
1531
534
  mgcp_param_ti = proto_tree_add_item(tree, hf_mgcp_params, tvb,
1532
534
      tvb_linebegin, tvb_len, ENC_NA);
1533
534
  proto_item_set_text(mgcp_param_ti, "Parameters");
1534
534
  mgcp_param_tree = proto_item_add_subtree(mgcp_param_ti, ett_mgcp_param);
1535
1536
  /* Parse the parameters */
1537
2.84k
  while (tvb_offset_exists(tvb, tvb_lineend))
1538
2.30k
  {
1539
2.30k
    old_lineend = tvb_lineend;
1540
2.30k
    linelen = tvb_find_line_end(tvb, tvb_linebegin, -1, &tvb_lineend, false);
1541
2.30k
    tvb_tokenbegin = tvb_parse_param(tvb, pinfo, tvb_linebegin, linelen, &my_param, mi);
1542
1543
2.30k
    if (my_param)
1544
2.10k
    {
1545
2.10k
      tokenlen = tvb_find_line_end(tvb, tvb_tokenbegin, -1, &tvb_lineend, false);
1546
2.10k
      if (*my_param == hf_mgcp_param_connectionparam) {
1547
0
        dissect_mgcp_connectionparams(mgcp_param_tree, pinfo, tvb, tvb_linebegin,
1548
0
                    tvb_tokenbegin - tvb_linebegin, tokenlen);
1549
2.10k
      } else if (*my_param == hf_mgcp_param_localconnoptions) {
1550
1
        dissect_mgcp_localconnectionoptions(mgcp_param_tree, pinfo, tvb, tvb_linebegin,
1551
1
                    tvb_tokenbegin - tvb_linebegin, tokenlen);
1552
2.10k
      } else if (*my_param == hf_mgcp_param_localvoicemetrics) {
1553
0
        dissect_mgcp_localvoicemetrics(mgcp_param_tree, pinfo, tvb, tvb_linebegin,
1554
0
                     tvb_tokenbegin - tvb_linebegin, tokenlen);
1555
2.10k
      } else if (*my_param == hf_mgcp_param_remotevoicemetrics) {
1556
0
        dissect_mgcp_remotevoicemetrics(mgcp_param_tree, pinfo, tvb, tvb_linebegin,
1557
0
                tvb_tokenbegin - tvb_linebegin, tokenlen);
1558
2.10k
      } else if (*my_param == hf_mgcp_param_x_osmux) {
1559
0
          proto_tree_add_string(mgcp_param_tree, *my_param, tvb,
1560
0
                    tvb_linebegin, linelen,
1561
0
                    tvb_format_text(pinfo->pool,
1562
0
                        tvb, tvb_tokenbegin, tokenlen));
1563
          /* Mark that Osmux is used, so that packet-sdp.c doesn't call
1564
           * srtp_add_address() and decodes it as RTP. */
1565
0
          mi->is_osmux = true;
1566
2.10k
      } else {
1567
2.10k
        proto_tree_add_string(mgcp_param_tree, *my_param, tvb,
1568
2.10k
                  tvb_linebegin, linelen,
1569
2.10k
                  tvb_format_text(pinfo->pool,
1570
2.10k
                      tvb, tvb_tokenbegin, tokenlen));
1571
2.10k
      }
1572
2.10k
    }
1573
1574
2.30k
    tvb_linebegin = tvb_lineend;
1575
    /* Its a infinite loop if we didn't advance (or went backwards) */
1576
2.30k
    if (old_lineend >= tvb_lineend)
1577
0
    {
1578
      /* XXX - exception */
1579
0
      break;
1580
0
    }
1581
2.30k
  }
1582
534
}
1583
1584
/* Dissect the connection params */
1585
static void
1586
dissect_mgcp_connectionparams(proto_tree *parent_tree, packet_info* pinfo, tvbuff_t *tvb, int offset, int param_type_len, int param_val_len)
1587
0
{
1588
0
  proto_tree *tree;
1589
0
  proto_item *item;
1590
1591
0
  char *tokenline;
1592
0
  char **tokens;
1593
0
  unsigned i;
1594
1595
0
  item = proto_tree_add_item(parent_tree, hf_mgcp_param_connectionparam, tvb, offset, param_type_len+param_val_len, ENC_ASCII);
1596
0
  tree = proto_item_add_subtree(item, ett_mgcp_param_connectionparam);
1597
1598
  /* The P: line */
1599
0
  offset += param_type_len; /* skip the P: */
1600
0
  tokenline = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, param_val_len, ENC_ASCII);
1601
1602
  /* Split into type=value pairs separated by comma */
1603
0
  tokens = wmem_strsplit(pinfo->pool, tokenline, ",", -1);
1604
1605
0
  for (i = 0; tokens[i] != NULL; i++)
1606
0
  {
1607
0
    char **typval;
1608
0
    unsigned tokenlen;
1609
0
    int hf_uint = 0;
1610
0
    int hf_string = 0;
1611
1612
0
    tokenlen = (int)strlen(tokens[i]);
1613
0
    typval = wmem_strsplit(pinfo->pool, tokens[i], "=", 2);
1614
0
    if ((typval[0] != NULL) && (typval[1] != NULL))
1615
0
    {
1616
0
      if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PS"))
1617
0
      {
1618
0
        hf_uint = hf_mgcp_param_connectionparam_ps;
1619
0
      }
1620
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "OS"))
1621
0
      {
1622
0
        hf_uint = hf_mgcp_param_connectionparam_os;
1623
0
      }
1624
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PR"))
1625
0
      {
1626
0
        hf_uint = hf_mgcp_param_connectionparam_pr;
1627
0
      }
1628
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "OR"))
1629
0
      {
1630
0
        hf_uint = hf_mgcp_param_connectionparam_or;
1631
0
      }
1632
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PL"))
1633
0
      {
1634
0
        hf_uint = hf_mgcp_param_connectionparam_pl;
1635
0
      }
1636
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JI"))
1637
0
      {
1638
0
        hf_uint = hf_mgcp_param_connectionparam_ji;
1639
0
      }
1640
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "LA"))
1641
0
      {
1642
0
        hf_uint = hf_mgcp_param_connectionparam_la;
1643
0
      }
1644
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PC/RPS"))
1645
0
      {
1646
0
        hf_uint = hf_mgcp_param_connectionparam_pcrps;
1647
0
      } else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PC/ROS"))
1648
0
      {
1649
0
        hf_uint = hf_mgcp_param_connectionparam_pcros;
1650
0
      }
1651
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PC/RPL"))
1652
0
      {
1653
0
        hf_uint = hf_mgcp_param_connectionparam_pcrpl;
1654
0
      }
1655
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PC/RJI"))
1656
0
      {
1657
0
        hf_uint = hf_mgcp_param_connectionparam_pcrji;
1658
0
      }
1659
0
      else if (!g_ascii_strncasecmp(g_strstrip(typval[0]), "X-", 2))
1660
0
      {
1661
0
        hf_string = hf_mgcp_param_connectionparam_x;
1662
0
      }
1663
1664
0
      if (hf_uint > 0)
1665
0
      {
1666
0
        proto_tree_add_uint(tree, hf_uint, tvb, offset, tokenlen, (uint32_t)strtoul(typval[1], NULL, 10));
1667
0
      }
1668
0
      else if (hf_string > 0)
1669
0
      {
1670
0
        proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
1671
0
      }
1672
0
      else
1673
0
      {
1674
0
        proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
1675
0
      }
1676
0
    }
1677
0
    else
1678
0
    {
1679
0
      proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
1680
0
    }
1681
0
    offset += tokenlen + 1; /* 1 extra for the delimiter */
1682
0
  }
1683
1684
0
}
1685
1686
/* Dissect the local connection option */
1687
static void
1688
dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, packet_info* pinfo, tvbuff_t *tvb, int offset, int param_type_len, int param_val_len)
1689
1
{
1690
1
  proto_tree *tree;
1691
1
  proto_item *item;
1692
1693
1
  char *tokenline;
1694
1
  char **tokens;
1695
1
  unsigned i;
1696
1697
1
  item = proto_tree_add_item(parent_tree, hf_mgcp_param_localconnoptions, tvb, offset, param_type_len+param_val_len, ENC_ASCII);
1698
1
  tree = proto_item_add_subtree(item, ett_mgcp_param_localconnectionoptions);
1699
1700
  /* The L: line */
1701
1
  offset += param_type_len; /* skip the L: */
1702
1
  tokenline = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, param_val_len, ENC_ASCII);
1703
1704
  /* Split into type=value pairs separated by comma */
1705
1
  tokens = wmem_strsplit(pinfo->pool, tokenline, ",", -1);
1706
2
  for (i = 0; tokens[i] != NULL; i++)
1707
1
  {
1708
1
    char **typval;
1709
1
    unsigned tokenlen;
1710
1
    int hf_uint;
1711
1
    int hf_string;
1712
1713
1
    hf_uint = -1;
1714
1
    hf_string = -1;
1715
1716
1
    tokenlen = (int)strlen(tokens[i]);
1717
1
    typval = wmem_strsplit(pinfo->pool, tokens[i], ":", 2);
1718
1
    if ((typval[0] != NULL) && (typval[1] != NULL))
1719
0
    {
1720
0
      if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "p"))
1721
0
      {
1722
0
        hf_uint = hf_mgcp_param_localconnoptions_p;
1723
0
      }
1724
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "a"))
1725
0
      {
1726
0
        hf_string = hf_mgcp_param_localconnoptions_a;
1727
0
      }
1728
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "s"))
1729
0
      {
1730
0
        hf_string = hf_mgcp_param_localconnoptions_s;
1731
0
      }
1732
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "e"))
1733
0
      {
1734
0
        hf_string = hf_mgcp_param_localconnoptions_e;
1735
0
      }
1736
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "sc-rtp"))
1737
0
      {
1738
0
        hf_string = hf_mgcp_param_localconnoptions_scrtp;
1739
0
      }
1740
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "sc-rtcp"))
1741
0
      {
1742
0
        hf_string = hf_mgcp_param_localconnoptions_scrtcp;
1743
0
      }
1744
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "b"))
1745
0
      {
1746
0
        hf_string = hf_mgcp_param_localconnoptions_b;
1747
0
      }
1748
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "es-ccd"))
1749
0
      {
1750
0
        hf_string = hf_mgcp_param_localconnoptions_esccd;
1751
0
      }
1752
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "es-cci"))
1753
0
      {
1754
0
        hf_string = hf_mgcp_param_localconnoptions_escci;
1755
0
      }
1756
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "dq-gi"))
1757
0
      {
1758
0
        hf_string = hf_mgcp_param_localconnoptions_dqgi;
1759
0
      }
1760
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "dq-rd"))
1761
0
      {
1762
0
        hf_string = hf_mgcp_param_localconnoptions_dqrd;
1763
0
      }
1764
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "dq-ri"))
1765
0
      {
1766
0
        hf_string = hf_mgcp_param_localconnoptions_dqri;
1767
0
      }
1768
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "dq-rr"))
1769
0
      {
1770
0
        hf_string = hf_mgcp_param_localconnoptions_dqrr;
1771
0
      }
1772
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "k"))
1773
0
      {
1774
0
        hf_string = hf_mgcp_param_localconnoptions_k;
1775
0
      }
1776
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "gc"))
1777
0
      {
1778
0
        hf_uint = hf_mgcp_param_localconnoptions_gc;
1779
0
      }
1780
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "fmtp"))
1781
0
      {
1782
0
        hf_string = hf_mgcp_param_localconnoptions_fmtp;
1783
0
      }
1784
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "nt"))
1785
0
      {
1786
0
        hf_string = hf_mgcp_param_localconnoptions_nt;
1787
0
      }
1788
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "o-fmtp"))
1789
0
      {
1790
0
        hf_string = hf_mgcp_param_localconnoptions_ofmtp;
1791
0
      }
1792
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "r"))
1793
0
      {
1794
0
        hf_string = hf_mgcp_param_localconnoptions_r;
1795
0
      }
1796
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "t"))
1797
0
      {
1798
0
        hf_string = hf_mgcp_param_localconnoptions_t;
1799
0
      }
1800
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "r-cnf"))
1801
0
      {
1802
0
        hf_string = hf_mgcp_param_localconnoptions_rcnf;
1803
0
      }
1804
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "r-dir"))
1805
0
      {
1806
0
        hf_string = hf_mgcp_param_localconnoptions_rdir;
1807
0
      }
1808
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "r-sh"))
1809
0
      {
1810
0
        hf_string = hf_mgcp_param_localconnoptions_rsh;
1811
0
      }
1812
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "mp"))
1813
0
      {
1814
0
        hf_string = hf_mgcp_param_localconnoptions_mp;
1815
0
      }
1816
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "fxr/fx"))
1817
0
      {
1818
0
        hf_string = hf_mgcp_param_localconnoptions_fxr;
1819
0
      }
1820
0
      else
1821
0
      {
1822
0
        hf_uint = -1;
1823
0
        hf_string = -1;
1824
0
      }
1825
1826
      /* Add item */
1827
0
      if (hf_uint > 0)
1828
0
      {
1829
0
        proto_tree_add_uint(tree, hf_uint, tvb, offset, tokenlen, (uint32_t)strtoul(typval[1], NULL, 10));
1830
0
      }
1831
0
      else if (hf_string > 0)
1832
0
      {
1833
0
        proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
1834
0
      }
1835
0
      else
1836
0
      {
1837
0
        proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
1838
0
      }
1839
0
    }
1840
1
  }
1841
1
}
1842
1843
/* Dissect the Local Voice Metrics option */
1844
static void
1845
dissect_mgcp_localvoicemetrics(proto_tree *parent_tree, packet_info* pinfo, tvbuff_t *tvb, int offset, int param_type_len, int param_val_len)
1846
0
{
1847
0
  proto_tree *tree = parent_tree;
1848
0
  proto_item *item = NULL;
1849
1850
0
  char *tokenline = NULL;
1851
0
  char **tokens = NULL;
1852
0
  char **typval = NULL;
1853
0
  unsigned i = 0;
1854
0
  unsigned tokenlen = 0;
1855
0
  int hf_string = -1;
1856
1857
0
  if (parent_tree)
1858
0
  {
1859
0
  item = proto_tree_add_item(parent_tree, hf_mgcp_param_localvoicemetrics, tvb, offset, param_type_len+param_val_len, ENC_ASCII);
1860
0
    tree = proto_item_add_subtree(item, ett_mgcp_param_localvoicemetrics);
1861
0
  }
1862
1863
  /* The XRM/LVM: line */
1864
0
  offset += 9; /* skip the XRM/LVM: */
1865
0
  tokenline = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, param_val_len - 9, ENC_ASCII);
1866
1867
  /* Split into type=value pairs separated by comma and WSP */
1868
0
  tokens = wmem_strsplit(pinfo->pool, tokenline, ",", -1);
1869
0
  for (i = 0; tokens[i] != NULL; i++)
1870
0
  {
1871
1872
0
    tokenlen = (int)strlen(tokens[i]);
1873
0
    typval = wmem_strsplit(pinfo->pool, tokens[i], "=", 2);
1874
0
    if ((typval[0] != NULL) && (typval[1] != NULL))
1875
0
    {
1876
0
      if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NLR"))
1877
0
      {
1878
0
        hf_string = hf_mgcp_param_voicemetrics_nlr;
1879
0
      }
1880
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JDR"))
1881
0
      {
1882
0
        hf_string = hf_mgcp_param_voicemetrics_jdr;
1883
0
      }
1884
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BLD"))
1885
0
      {
1886
0
        hf_string = hf_mgcp_param_voicemetrics_bld;
1887
0
      }
1888
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GLD"))
1889
0
      {
1890
0
        hf_string = hf_mgcp_param_voicemetrics_gld;
1891
0
      }
1892
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BD"))
1893
0
      {
1894
0
        hf_string = hf_mgcp_param_voicemetrics_bd;
1895
0
      }
1896
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GD"))
1897
0
      {
1898
0
        hf_string = hf_mgcp_param_voicemetrics_gd;
1899
0
      }
1900
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RTD"))
1901
0
      {
1902
0
        hf_string = hf_mgcp_param_voicemetrics_rtd;
1903
0
      }
1904
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "ESD"))
1905
0
      {
1906
0
        hf_string = hf_mgcp_param_voicemetrics_esd;
1907
0
      }
1908
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "SL"))
1909
0
      {
1910
0
        hf_string = hf_mgcp_param_voicemetrics_sl;
1911
0
      }
1912
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NL"))
1913
0
      {
1914
0
        hf_string = hf_mgcp_param_voicemetrics_nl;
1915
0
      }
1916
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RERL"))
1917
0
      {
1918
0
        hf_string = hf_mgcp_param_voicemetrics_rerl;
1919
0
      }
1920
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GMN"))
1921
0
      {
1922
0
        hf_string = hf_mgcp_param_voicemetrics_gmn;
1923
0
      }
1924
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NSR"))
1925
0
      {
1926
0
        hf_string = hf_mgcp_param_voicemetrics_nsr;
1927
0
      }
1928
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "XSR"))
1929
0
      {
1930
0
        hf_string = hf_mgcp_param_voicemetrics_xsr;
1931
0
      }
1932
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MLQ"))
1933
0
      {
1934
0
        hf_string = hf_mgcp_param_voicemetrics_mlq;
1935
0
      }
1936
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MCQ"))
1937
0
      {
1938
0
        hf_string = hf_mgcp_param_voicemetrics_mcq;
1939
0
      }
1940
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PLC"))
1941
0
      {
1942
0
        hf_string = hf_mgcp_param_voicemetrics_plc;
1943
0
      }
1944
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBA"))
1945
0
      {
1946
0
        hf_string = hf_mgcp_param_voicemetrics_jba;
1947
0
      }
1948
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBR"))
1949
0
      {
1950
0
        hf_string = hf_mgcp_param_voicemetrics_jbr;
1951
0
      }
1952
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBN"))
1953
0
      {
1954
0
        hf_string = hf_mgcp_param_voicemetrics_jbn;
1955
0
      }
1956
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBM"))
1957
0
      {
1958
0
        hf_string = hf_mgcp_param_voicemetrics_jbm;
1959
0
      }
1960
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBS"))
1961
0
      {
1962
0
        hf_string = hf_mgcp_param_voicemetrics_jbs;
1963
0
      }
1964
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "IAJ"))
1965
0
      {
1966
0
        hf_string = hf_mgcp_param_voicemetrics_iaj;
1967
0
      }
1968
0
      else
1969
0
      {
1970
0
        hf_string = -1;
1971
0
      }
1972
1973
      /* Add item */
1974
0
      if (tree)
1975
0
      {
1976
0
        if (hf_string > 0)
1977
0
        {
1978
0
          proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
1979
0
        }
1980
0
        else
1981
0
        {
1982
0
          proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
1983
0
        }
1984
0
      }
1985
0
    }
1986
0
    else if (tree)
1987
0
    {
1988
0
      proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
1989
0
    }
1990
0
    offset += tokenlen + 1; /* 1 extra for the delimiter */
1991
0
  }
1992
0
}
1993
1994
/* Dissect the Remote Voice Metrics option */
1995
static void
1996
dissect_mgcp_remotevoicemetrics(proto_tree *parent_tree, packet_info* pinfo, tvbuff_t *tvb, int offset, int param_type_len, int param_val_len)
1997
0
{
1998
0
  proto_tree *tree = parent_tree;
1999
0
  proto_item *item = NULL;
2000
2001
0
  char *tokenline = NULL;
2002
0
  char **tokens = NULL;
2003
0
  char **typval = NULL;
2004
0
  unsigned i = 0;
2005
0
  unsigned tokenlen = 0;
2006
0
  int hf_string = -1;
2007
2008
0
  if (parent_tree)
2009
0
  {
2010
0
  item = proto_tree_add_item(parent_tree, hf_mgcp_param_remotevoicemetrics, tvb, offset, param_type_len+param_val_len, ENC_ASCII);
2011
0
    tree = proto_item_add_subtree(item, ett_mgcp_param_remotevoicemetrics);
2012
0
  }
2013
2014
  /* The XRM/RVM: line */
2015
0
  offset += 9; /* skip the XRM/RVM: */
2016
0
  tokenline = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, param_val_len - 9, ENC_ASCII);
2017
2018
  /* Split into type=value pairs separated by comma and WSP */
2019
0
  tokens = wmem_strsplit(pinfo->pool, tokenline, ",", -1);
2020
0
  for (i = 0; tokens[i] != NULL; i++)
2021
0
  {
2022
0
    tokenlen = (int)strlen(tokens[i]);
2023
0
    typval = wmem_strsplit(pinfo->pool, tokens[i], "=", 2);
2024
0
    if ((typval[0] != NULL) && (typval[1] != NULL))
2025
0
    {
2026
0
      if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NLR"))
2027
0
      {
2028
0
        hf_string = hf_mgcp_param_voicemetrics_nlr;
2029
0
      }
2030
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JDR"))
2031
0
      {
2032
0
        hf_string = hf_mgcp_param_voicemetrics_jdr;
2033
0
      }
2034
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BLD"))
2035
0
      {
2036
0
        hf_string = hf_mgcp_param_voicemetrics_bld;
2037
0
      }
2038
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GLD"))
2039
0
      {
2040
0
        hf_string = hf_mgcp_param_voicemetrics_gld;
2041
0
      }
2042
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "BD"))
2043
0
      {
2044
0
        hf_string = hf_mgcp_param_voicemetrics_bd;
2045
0
      }
2046
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GD"))
2047
0
      {
2048
0
        hf_string = hf_mgcp_param_voicemetrics_gd;
2049
0
      }
2050
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RTD"))
2051
0
      {
2052
0
        hf_string = hf_mgcp_param_voicemetrics_rtd;
2053
0
      }
2054
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "ESD"))
2055
0
      {
2056
0
        hf_string = hf_mgcp_param_voicemetrics_esd;
2057
0
      }
2058
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "SL"))
2059
0
      {
2060
0
        hf_string = hf_mgcp_param_voicemetrics_sl;
2061
0
      }
2062
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NL"))
2063
0
      {
2064
0
        hf_string = hf_mgcp_param_voicemetrics_nl;
2065
0
      }
2066
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "RERL"))
2067
0
      {
2068
0
        hf_string = hf_mgcp_param_voicemetrics_rerl;
2069
0
      }
2070
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "GMN"))
2071
0
      {
2072
0
        hf_string = hf_mgcp_param_voicemetrics_gmn;
2073
0
      }
2074
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "NSR"))
2075
0
      {
2076
0
        hf_string = hf_mgcp_param_voicemetrics_nsr;
2077
0
      }
2078
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "XSR"))
2079
0
      {
2080
0
        hf_string = hf_mgcp_param_voicemetrics_xsr;
2081
0
      }
2082
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MLQ"))
2083
0
      {
2084
0
        hf_string = hf_mgcp_param_voicemetrics_mlq;
2085
0
      }
2086
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "MCQ"))
2087
0
      {
2088
0
        hf_string = hf_mgcp_param_voicemetrics_mcq;
2089
0
      }
2090
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "PLC"))
2091
0
      {
2092
0
        hf_string = hf_mgcp_param_voicemetrics_plc;
2093
0
      }
2094
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBA"))
2095
0
      {
2096
0
        hf_string = hf_mgcp_param_voicemetrics_jba;
2097
0
      }
2098
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBR"))
2099
0
      {
2100
0
        hf_string = hf_mgcp_param_voicemetrics_jbr;
2101
0
      }
2102
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBN"))
2103
0
      {
2104
0
        hf_string = hf_mgcp_param_voicemetrics_jbn;
2105
0
      }
2106
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBM"))
2107
0
      {
2108
0
        hf_string = hf_mgcp_param_voicemetrics_jbm;
2109
0
      }
2110
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "JBS"))
2111
0
      {
2112
0
        hf_string = hf_mgcp_param_voicemetrics_jbs;
2113
0
      }
2114
0
      else if (!g_ascii_strcasecmp(g_strstrip(typval[0]), "IAJ"))
2115
0
      {
2116
0
        hf_string = hf_mgcp_param_voicemetrics_iaj;
2117
0
      }
2118
0
      else
2119
0
      {
2120
0
        hf_string = -1;
2121
0
      }
2122
2123
      /* Add item */
2124
0
      if (tree)
2125
0
      {
2126
0
        if (hf_string > 0)
2127
0
        {
2128
0
          proto_tree_add_string(tree, hf_string, tvb, offset, tokenlen, g_strstrip(typval[1]));
2129
0
        }
2130
0
        else
2131
0
        {
2132
0
          proto_tree_add_string(tree, hf_mgcp_unknown_parameter, tvb, offset, tokenlen, tokens[i]);
2133
0
        }
2134
0
      }
2135
0
    }
2136
0
    else if (tree)
2137
0
    {
2138
0
      proto_tree_add_string(tree, hf_mgcp_malformed_parameter, tvb, offset, tokenlen, tokens[i]);
2139
0
    }
2140
0
    offset += tokenlen + 1; /* 1 extra for the delimiter */
2141
0
  }
2142
0
}
2143
2144
/*
2145
 * tvb_find_null_line - Returns the length from offset to the first null
2146
 *                      line found (a null line is a line that begins
2147
 *                      with a CR or LF.  The offset to the first character
2148
 *                      after the null line is written into the int pointed
2149
 *                      to by next_offset.
2150
 *
2151
 * Parameters:
2152
 * tvb - The tvbuff in which we are looking for a null line.
2153
 * offset - The offset in tvb at which we will begin looking for
2154
 *          a null line.
2155
 * len - The maximum distance from offset in tvb that we will look for
2156
 *       a null line.  If it is -1 we will look to the end of the buffer.
2157
 *
2158
 * next_offset - The location to write the offset of first character
2159
 *               FOLLOWING the null line.
2160
 *
2161
 * Returns: The length from offset to the first character BEFORE
2162
 *          the null line..
2163
 */
2164
static int tvb_find_null_line(tvbuff_t* tvb, int offset, int len, int* next_offset)
2165
568
{
2166
568
  int tvb_lineend, tvb_current_len, tvb_linebegin, maxoffset;
2167
568
  unsigned tempchar;
2168
2169
568
  tvb_linebegin = offset;
2170
568
  tvb_lineend = tvb_linebegin;
2171
2172
  /* Simple setup to allow for the traditional -1 search to the end of the tvbuff */
2173
568
  if (len != -1)
2174
0
  {
2175
0
    tvb_current_len = len;
2176
0
  }
2177
568
  else
2178
568
  {
2179
568
    tvb_current_len = tvb_reported_length_remaining(tvb, offset);
2180
568
  }
2181
2182
568
  maxoffset = (tvb_current_len - 1) + offset;
2183
2184
  /* Loop around until we either find a line beginning with a carriage return
2185
     or newline character or until we hit the end of the tvbuff. */
2186
568
  do
2187
2.37k
  {
2188
2.37k
    tvb_linebegin = tvb_lineend;
2189
2.37k
    tvb_current_len = tvb_reported_length_remaining(tvb, tvb_linebegin);
2190
2.37k
    tvb_find_line_end(tvb, tvb_linebegin, tvb_current_len, &tvb_lineend, false);
2191
2.37k
    tempchar = tvb_get_uint8(tvb, tvb_linebegin);
2192
2.37k
  } while (tempchar != '\r' && tempchar != '\n' && tvb_lineend <= maxoffset && tvb_offset_exists(tvb, tvb_lineend));
2193
2194
2195
568
  *next_offset = tvb_lineend;
2196
2197
568
  if (tvb_lineend <= maxoffset)
2198
63
  {
2199
63
    tvb_current_len = tvb_linebegin - offset;
2200
63
  }
2201
505
  else
2202
505
  {
2203
505
    tvb_current_len = tvb_reported_length_remaining(tvb, offset);
2204
505
  }
2205
2206
568
  return tvb_current_len;
2207
568
}
2208
2209
/*
2210
 * tvb_find_dot_line -  Returns the length from offset to the first line
2211
 *                      containing only a dot (.) character.  A line
2212
 *                      containing only a dot is used to indicate a
2213
 *                      separation between multiple MGCP messages
2214
 *                      piggybacked in the same UDP packet.
2215
 *
2216
 * Parameters:
2217
 * tvb - The tvbuff in which we are looking for a dot line.
2218
 * offset - The offset in tvb at which we will begin looking for
2219
 *          a dot line.
2220
 * len - The maximum distance from offset in tvb that we will look for
2221
 *       a dot line.  If it is -1 we will look to the end of the buffer.
2222
 *
2223
 * next_offset - The location to write the offset of first character
2224
 *               FOLLOWING the dot line.
2225
 *
2226
 * Returns: The length from offset to the first character BEFORE
2227
 *          the dot line or -1 if the character at offset is a .
2228
 *          followed by a newline or a carriage return.
2229
 */
2230
static int tvb_find_dot_line(tvbuff_t* tvb, int offset, int len, int* next_offset)
2231
1.07k
{
2232
1.07k
  int tvb_current_offset, tvb_current_len, maxoffset, tvb_len;
2233
1.07k
  uint8_t tempchar;
2234
1.07k
  tvb_current_len = len;
2235
1.07k
  tvb_len = tvb_reported_length(tvb);
2236
2237
1.07k
  if (len == -1)
2238
1.07k
  {
2239
1.07k
    maxoffset = tvb_len - 1;
2240
1.07k
  }
2241
0
  else
2242
0
  {
2243
0
    maxoffset = (len - 1) + offset;
2244
0
  }
2245
1.07k
  tvb_current_offset = offset -1;
2246
2247
1.07k
  do
2248
1.94k
  {
2249
1.94k
    tvb_current_offset = tvb_find_uint8(tvb, tvb_current_offset+1,
2250
1.94k
                                         tvb_current_len, '.');
2251
1.94k
    tvb_current_len = maxoffset - tvb_current_offset + 1;
2252
2253
    /* If we didn't find a . then break out of the loop */
2254
1.94k
    if (tvb_current_offset == -1)
2255
219
    {
2256
219
      break;
2257
219
    }
2258
2259
    /* Do we have and characters following the . ? */
2260
1.72k
    if (tvb_current_offset < maxoffset)
2261
1.70k
    {
2262
1.70k
      tempchar = tvb_get_uint8(tvb, tvb_current_offset+1);
2263
      /* Are the characters that follow the dot a newline or carriage return ? */
2264
1.70k
      if (tempchar == '\r' || tempchar == '\n')
2265
1.22k
      {
2266
        /* Do we have any characters that precede the . ? */
2267
1.22k
        if (tvb_current_offset == 0)
2268
0
        {
2269
0
          break;
2270
0
        }
2271
1.22k
        else
2272
1.22k
        {
2273
1.22k
          tempchar = tvb_get_uint8(tvb, tvb_current_offset-1);
2274
2275
          /* Are the characters that precede the dot a newline or a
2276
             carriage return ? */
2277
1.22k
          if (tempchar == '\r' || tempchar == '\n')
2278
844
          {
2279
844
            break;
2280
844
          }
2281
1.22k
        }
2282
1.22k
      }
2283
1.70k
    }
2284
13
    else
2285
13
    if (tvb_current_offset == maxoffset)
2286
13
    {
2287
13
      if (tvb_current_offset == 0)
2288
0
      {
2289
0
        break;
2290
0
      }
2291
13
      else
2292
13
      {
2293
13
        tempchar = tvb_get_uint8(tvb, tvb_current_offset-1);
2294
13
        if (tempchar == '\r' || tempchar == '\n')
2295
7
        {
2296
7
          break;
2297
7
        }
2298
13
      }
2299
13
    }
2300
1.72k
  } while (tvb_current_offset < maxoffset);
2301
2302
2303
  /*
2304
   * So now we either have the tvb_current_offset of a . in a dot line
2305
   * or a tvb_current_offset of -1
2306
   */
2307
1.07k
  if (tvb_current_offset == -1)
2308
219
  {
2309
219
    tvb_current_offset = maxoffset +1;
2310
219
    *next_offset = maxoffset + 1;
2311
219
  }
2312
857
  else
2313
857
  {
2314
857
    tvb_find_line_end(tvb, tvb_current_offset, tvb_current_len, next_offset, false);
2315
857
  }
2316
2317
1.07k
  if (tvb_current_offset == offset)
2318
1
  {
2319
1
    tvb_current_len = -1;
2320
1
  }
2321
1.07k
  else
2322
1.07k
  {
2323
1.07k
    tvb_current_len = tvb_current_offset - offset;
2324
1.07k
  }
2325
2326
1.07k
  return tvb_current_len;
2327
1.07k
}
2328
2329
/* Register all the bits needed with the filtering engine */
2330
2331
void proto_register_mgcp(void);
2332
void proto_reg_handoff_mgcp(void);
2333
2334
void proto_register_mgcp(void)
2335
14
{
2336
14
  expert_module_t* expert_mgcp;
2337
2338
14
  static hf_register_info hf[] =
2339
14
    {
2340
14
      { &hf_mgcp_req,
2341
14
        { "Request", "mgcp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2342
14
          "True if MGCP request", HFILL }},
2343
14
      { &hf_mgcp_rsp,
2344
14
        { "Response", "mgcp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2345
14
          "true if MGCP response", HFILL }},
2346
14
      { &hf_mgcp_req_frame,
2347
14
        { "Request Frame", "mgcp.reqframe", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0,
2348
14
          NULL, HFILL }},
2349
14
      { &hf_mgcp_rsp_frame,
2350
14
        { "Response Frame", "mgcp.rspframe", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0,
2351
14
          NULL, HFILL }},
2352
14
      { &hf_mgcp_time,
2353
14
        { "Time from request", "mgcp.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
2354
14
          "Timedelta between Request and Response", HFILL }},
2355
14
      { &hf_mgcp_req_verb,
2356
14
        { "Verb", "mgcp.req.verb", FT_STRING, BASE_NONE, NULL, 0x0,
2357
14
          "Name of the verb", HFILL }},
2358
14
      { &hf_mgcp_req_endpoint,
2359
14
        { "Endpoint", "mgcp.req.endpoint", FT_STRING, BASE_NONE, NULL, 0x0,
2360
14
          "Endpoint referenced by the message", HFILL }},
2361
14
      { &hf_mgcp_transid,
2362
14
        { "Transaction ID", "mgcp.transid", FT_STRING, BASE_NONE, NULL, 0x0,
2363
14
          "Transaction ID of this message", HFILL }},
2364
14
      { &hf_mgcp_version,
2365
14
        { "Version", "mgcp.version", FT_STRING, BASE_NONE, NULL, 0x0,
2366
14
          "MGCP Version", HFILL }},
2367
14
      { &hf_mgcp_rsp_rspcode,
2368
14
        { "Response Code", "mgcp.rsp.rspcode", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &mgcp_return_code_vals_ext, 0x0,
2369
14
          NULL, HFILL }},
2370
14
      { &hf_mgcp_rsp_rspstring,
2371
14
        { "Response String", "mgcp.rsp.rspstring", FT_STRING, BASE_NONE, NULL, 0x0,
2372
14
          NULL, HFILL }},
2373
14
      { &hf_mgcp_params,
2374
14
        { "Parameters", "mgcp.params", FT_NONE, BASE_NONE, NULL, 0x0,
2375
14
          "MGCP parameters", HFILL }},
2376
14
      { &hf_mgcp_param_rspack,
2377
14
        { "ResponseAck (K)", "mgcp.param.rspack", FT_STRING, BASE_NONE, NULL, 0x0,
2378
14
          "Response Ack", HFILL }},
2379
14
      { &hf_mgcp_param_bearerinfo,
2380
14
        { "BearerInformation (B)", "mgcp.param.bearerinfo", FT_STRING, BASE_NONE, NULL, 0x0,
2381
14
          "Bearer Information", HFILL }},
2382
14
      { &hf_mgcp_param_callid,
2383
14
        { "CallId (C)", "mgcp.param.callid", FT_STRING, BASE_NONE, NULL, 0x0,
2384
14
          "Call Id", HFILL }},
2385
14
      { &hf_mgcp_param_connectionid,
2386
14
        {"ConnectionIdentifier (I)", "mgcp.param.connectionid", FT_STRING, BASE_NONE, NULL, 0x0,
2387
14
         "Connection Identifier", HFILL }},
2388
14
      { &hf_mgcp_param_secondconnectionid,
2389
14
        { "SecondConnectionID (I2)", "mgcp.param.secondconnectionid", FT_STRING, BASE_NONE, NULL, 0x0,
2390
14
          "Second Connection Identifier", HFILL }},
2391
14
      { &hf_mgcp_param_notifiedentity,
2392
14
        { "NotifiedEntity (N)", "mgcp.param.notifiedentity", FT_STRING, BASE_NONE, NULL, 0x0,
2393
14
          "Notified Entity", HFILL }},
2394
14
      { &hf_mgcp_param_requestid,
2395
14
        { "RequestIdentifier (X)", "mgcp.param.requestid", FT_STRING, BASE_NONE, NULL, 0x0,
2396
14
          "Request Identifier", HFILL }},
2397
14
      { &hf_mgcp_param_localconnoptions,
2398
14
        { "LocalConnectionOptions (L)", "mgcp.param.localconnectionoptions", FT_STRING, BASE_NONE, NULL, 0x0,
2399
14
          "Local Connection Options", HFILL }},
2400
14
      { &hf_mgcp_param_localconnoptions_p,
2401
14
        { "Packetization period (p)", "mgcp.param.localconnectionoptions.p", FT_UINT32, BASE_DEC, NULL, 0x0,
2402
14
          NULL, HFILL }},
2403
14
      { &hf_mgcp_param_localconnoptions_a,
2404
14
        { "Codecs (a)", "mgcp.param.localconnectionoptions.a", FT_STRING, BASE_NONE, NULL, 0x0,
2405
14
          NULL, HFILL }},
2406
14
      { &hf_mgcp_param_localconnoptions_s,
2407
14
        { "Silence Suppression (s)", "mgcp.param.localconnectionoptions.s", FT_STRING, BASE_NONE, NULL, 0x0,
2408
14
          NULL, HFILL }},
2409
14
      { &hf_mgcp_param_localconnoptions_e,
2410
14
        { "Echo Cancellation (e)", "mgcp.param.localconnectionoptions.e", FT_STRING, BASE_NONE, NULL, 0x0,
2411
14
          NULL, HFILL }},
2412
14
      { &hf_mgcp_param_localconnoptions_scrtp,
2413
14
        { "RTP ciphersuite (sc-rtp)", "mgcp.param.localconnectionoptions.scrtp", FT_STRING, BASE_NONE, NULL, 0x0,
2414
14
          NULL, HFILL }},
2415
14
      { &hf_mgcp_param_localconnoptions_scrtcp,
2416
14
        { "RTCP ciphersuite (sc-rtcp)", "mgcp.param.localconnectionoptions.scrtcp", FT_STRING, BASE_NONE, NULL, 0x0,
2417
14
          NULL, HFILL }},
2418
14
      { &hf_mgcp_param_localconnoptions_b,
2419
14
        { "Bandwidth (b)", "mgcp.param.localconnectionoptions.b", FT_STRING, BASE_NONE, NULL, 0x0,
2420
14
          NULL, HFILL }},
2421
14
      { &hf_mgcp_param_localconnoptions_esccd,
2422
14
        { "Content Destination (es-ccd)", "mgcp.param.localconnectionoptions.esccd", FT_STRING, BASE_NONE, NULL, 0x0,
2423
14
          NULL, HFILL }},
2424
14
      { &hf_mgcp_param_localconnoptions_escci,
2425
14
        { "Content Identifier (es-cci)", "mgcp.param.localconnectionoptions.escci", FT_STRING, BASE_NONE, NULL, 0x0,
2426
14
          NULL, HFILL }},
2427
14
      { &hf_mgcp_param_localconnoptions_dqgi,
2428
14
        { "D-QoS GateID (dq-gi)", "mgcp.param.localconnectionoptions.dqgi", FT_STRING, BASE_NONE, NULL, 0x0,
2429
14
          NULL, HFILL }},
2430
14
      { &hf_mgcp_param_localconnoptions_dqrd,
2431
14
        { "D-QoS Reserve Destination (dq-rd)", "mgcp.param.localconnectionoptions.dqrd", FT_STRING, BASE_NONE, NULL, 0x0,
2432
14
          NULL, HFILL }},
2433
14
      { &hf_mgcp_param_localconnoptions_dqri,
2434
14
        { "D-QoS Resource ID (dq-ri)", "mgcp.param.localconnectionoptions.dqri", FT_STRING, BASE_NONE, NULL, 0x0,
2435
14
          NULL, HFILL }},
2436
14
      { &hf_mgcp_param_localconnoptions_dqrr,
2437
14
        { "D-QoS Resource Reservation (dq-rr)", "mgcp.param.localconnectionoptions.dqrr", FT_STRING, BASE_NONE, NULL, 0x0,
2438
14
          NULL, HFILL }},
2439
14
      { &hf_mgcp_param_localconnoptions_k,
2440
14
        { "Encryption Key (k)", "mgcp.param.localconnectionoptions.k", FT_STRING, BASE_NONE, NULL, 0x0,
2441
14
          NULL, HFILL }},
2442
14
      { &hf_mgcp_param_localconnoptions_gc,
2443
14
        { "Gain Control (gc)", "mgcp.param.localconnectionoptions.gc", FT_UINT32, BASE_DEC, NULL, 0x0,
2444
14
          NULL, HFILL }},
2445
14
      { &hf_mgcp_param_localconnoptions_fmtp,
2446
14
        { "Media Format (fmtp)", "mgcp.param.localconnectionoptions.fmtp", FT_STRING, BASE_NONE, NULL, 0x0,
2447
14
          NULL, HFILL }},
2448
14
      { &hf_mgcp_param_localconnoptions_nt,
2449
14
        { "Network Type (nt)", "mgcp.param.localconnectionoptions.nt", FT_STRING, BASE_NONE, NULL, 0x0,
2450
14
          NULL, HFILL }},
2451
14
      { &hf_mgcp_param_localconnoptions_ofmtp,
2452
14
        { "Optional Media Format (o-fmtp)", "mgcp.param.localconnectionoptions.ofmtp", FT_STRING, BASE_NONE, NULL, 0x0,
2453
14
          NULL, HFILL }},
2454
14
      { &hf_mgcp_param_localconnoptions_r,
2455
14
        { "Resource Reservation (r)", "mgcp.param.localconnectionoptions.r", FT_STRING, BASE_NONE, NULL, 0x0,
2456
14
          NULL, HFILL }},
2457
14
      { &hf_mgcp_param_localconnoptions_t,
2458
14
        { "Type of Service (r)", "mgcp.param.localconnectionoptions.t", FT_STRING, BASE_NONE, NULL, 0x0,
2459
14
          NULL, HFILL }},
2460
14
      { &hf_mgcp_param_localconnoptions_rcnf,
2461
14
        { "Reservation Confirmation (r-cnf)", "mgcp.param.localconnectionoptions.rcnf", FT_STRING, BASE_NONE, NULL, 0x0,
2462
14
          NULL, HFILL }},
2463
14
      { &hf_mgcp_param_localconnoptions_rdir,
2464
14
        { "Reservation Direction (r-dir)", "mgcp.param.localconnectionoptions.rdir", FT_STRING, BASE_NONE, NULL, 0x0,
2465
14
          NULL, HFILL }},
2466
14
      { &hf_mgcp_param_localconnoptions_rsh,
2467
14
        { "Resource Sharing (r-sh)", "mgcp.param.localconnectionoptions.rsh", FT_STRING, BASE_NONE, NULL, 0x0,
2468
14
          NULL, HFILL }},
2469
14
      { &hf_mgcp_param_localconnoptions_mp,
2470
14
        { "Multiple Packetization period (mp)", "mgcp.param.localconnectionoptions.mp", FT_STRING, BASE_NONE, NULL, 0x0,
2471
14
          NULL, HFILL }},
2472
14
      { &hf_mgcp_param_localconnoptions_fxr,
2473
14
        { "FXR (fxr/fx)", "mgcp.param.localconnectionoptions.fxr", FT_STRING, BASE_NONE, NULL, 0x0,
2474
14
          NULL, HFILL }},
2475
14
      { &hf_mgcp_param_localvoicemetrics,
2476
14
        { "LocalVoiceMetrics (XRM/LVM)", "mgcp.param.localvoicemetrics", FT_STRING, BASE_NONE, NULL, 0x0,
2477
14
          NULL, HFILL }},
2478
14
      { &hf_mgcp_param_remotevoicemetrics,
2479
14
        { "RemoteVoiceMetrics (XRM/RVM)", "mgcp.param.remotevoicemetrics", FT_STRING, BASE_NONE, NULL, 0x0,
2480
14
          NULL, HFILL }},
2481
14
      { &hf_mgcp_param_voicemetrics_nlr,
2482
14
        { "Network packet loss rate(NLR)", "mgcp.param.voicemetrics.nlr", FT_STRING, BASE_NONE, NULL, 0x0,
2483
14
          "Voice Metrics NLR", HFILL }},
2484
14
      { &hf_mgcp_param_voicemetrics_jdr,
2485
14
        { "Jitter buffer discard rate(JDR)", "mgcp.param.voicemetrics.jdr", FT_STRING, BASE_NONE, NULL, 0x0,
2486
14
          "Voice Metrics JDR", HFILL }},
2487
14
      { &hf_mgcp_param_voicemetrics_bld,
2488
14
        { "Burst loss density(BLD)", "mgcp.param.voicemetrics.bld", FT_STRING, BASE_NONE, NULL, 0x0,
2489
14
          "Voice Metrics BLD", HFILL }},
2490
14
      { &hf_mgcp_param_voicemetrics_gld,
2491
14
        { "Gap loss density(GLD)", "mgcp.param.voicemetrics.gld", FT_STRING, BASE_NONE, NULL, 0x0,
2492
14
          "Voice Metrics GLD", HFILL }},
2493
14
      { &hf_mgcp_param_voicemetrics_bd,
2494
14
        { "Burst duration(BD)", "mgcp.param.voicemetrics.bd", FT_STRING, BASE_NONE, NULL, 0x0,
2495
14
          "Voice Metrics BD", HFILL }},
2496
14
      { &hf_mgcp_param_voicemetrics_gd,
2497
14
        { "Gap duration(GD)", "mgcp.param.voicemetrics.gd", FT_STRING, BASE_NONE, NULL, 0x0,
2498
14
          "Voice Metrics GD", HFILL }},
2499
14
      { &hf_mgcp_param_voicemetrics_rtd,
2500
14
        { "Round trip network delay(RTD)", "mgcp.param.voicemetrics.rtd", FT_STRING, BASE_NONE, NULL, 0x0,
2501
14
          "Voice Metrics RTD", HFILL }},
2502
14
      { &hf_mgcp_param_voicemetrics_esd,
2503
14
        { "End system delay(ESD)", "mgcp.param.voicemetrics.esd", FT_STRING, BASE_NONE, NULL, 0x0,
2504
14
          "Voice Metrics ESD", HFILL }},
2505
14
      { &hf_mgcp_param_voicemetrics_sl,
2506
14
        { "Signal level(SL)", "mgcp.param.voicemetrics.sl", FT_STRING, BASE_NONE, NULL, 0x0,
2507
14
          "Voice Metrics SL", HFILL }},
2508
14
      { &hf_mgcp_param_voicemetrics_nl,
2509
14
        { "Noise level(NL)", "mgcp.param.voicemetrics.nl", FT_STRING, BASE_NONE, NULL, 0x0,
2510
14
          "Voice Metricsx NL", HFILL }},
2511
14
      { &hf_mgcp_param_voicemetrics_rerl,
2512
14
        { "Residual echo return loss(RERL)", "mgcp.param.voicemetrics.rerl", FT_STRING, BASE_NONE, NULL, 0x0,
2513
14
          "Voice Metrics ERL", HFILL }},
2514
14
      { &hf_mgcp_param_voicemetrics_gmn,
2515
14
        { "Minimum gap threshold(GMN)", "mgcp.param.voicemetrics.gmn", FT_STRING, BASE_NONE, NULL, 0x0,
2516
14
          "Voice Metrics GMN", HFILL }},
2517
14
      { &hf_mgcp_param_voicemetrics_nsr,
2518
14
        { "R factor(NSR)", "mgcp.param.voicemetrics.nsr", FT_STRING, BASE_NONE, NULL, 0x0,
2519
14
          "Voice Metrics NSR", HFILL }},
2520
14
      { &hf_mgcp_param_voicemetrics_xsr,
2521
14
        { "External R factor(XSR)", "mgcp.param.voicemetrics.xsr", FT_STRING, BASE_NONE, NULL, 0x0,
2522
14
          "Voice Metrics XSR", HFILL }},
2523
14
      { &hf_mgcp_param_voicemetrics_mlq,
2524
14
        { "Estimated MOS-LQ(MLQ)", "mgcp.param.voicemetrics.mlq", FT_STRING, BASE_NONE, NULL, 0x0,
2525
14
          "Voice Metrics MLQ", HFILL }},
2526
14
      { &hf_mgcp_param_voicemetrics_mcq,
2527
14
        { "Estimated MOS-CQ(MCQ)", "mgcp.param.voicemetrics.mcq", FT_STRING, BASE_NONE, NULL, 0x0,
2528
14
          "Voice Metrics MCQ", HFILL }},
2529
14
      { &hf_mgcp_param_voicemetrics_plc,
2530
14
        { "Packet loss concealment type(PLC)", "mgcp.param.voicemetrics.plc", FT_STRING, BASE_NONE, NULL, 0x0,
2531
14
          "Voice Metrics PLC", HFILL }},
2532
14
      { &hf_mgcp_param_voicemetrics_jba,
2533
14
        { "Jitter Buffer Adaptive(JBA)", "mgcp.param.voicemetrics.jba", FT_STRING, BASE_NONE, NULL, 0x0,
2534
14
          "Voice Metrics JBA", HFILL }},
2535
14
      { &hf_mgcp_param_voicemetrics_jbr,
2536
14
        { "Jitter Buffer Rate(JBR)", "mgcp.param.voicemetrics.jbr", FT_STRING, BASE_NONE, NULL, 0x0,
2537
14
          "Voice Metrics JBR", HFILL }},
2538
14
      { &hf_mgcp_param_voicemetrics_jbn,
2539
14
        { "Nominal jitter buffer delay(JBN)", "mgcp.param.voicemetrics.jbn", FT_STRING, BASE_NONE, NULL, 0x0,
2540
14
          "Voice Metrics JBN", HFILL }},
2541
14
      { &hf_mgcp_param_voicemetrics_jbm,
2542
14
        { "Maximum jitter buffer delay(JBM)", "mgcp.param.voicemetrics.jbm", FT_STRING, BASE_NONE, NULL, 0x0,
2543
14
          "Voice Metrics JBM", HFILL }},
2544
14
      { &hf_mgcp_param_voicemetrics_jbs,
2545
14
        { "Absolute maximum jitter buffer delay(JBS)", "mgcp.param.voicemetrics.jbs", FT_STRING, BASE_NONE, NULL, 0x0,
2546
14
          "Voice Metrics JBS", HFILL }},
2547
14
      { &hf_mgcp_param_voicemetrics_iaj,
2548
14
        { "Inter-arrival Jitter(IAJ)", "mgcp.param.voicemetrics.iaj", FT_STRING, BASE_NONE, NULL, 0x0,
2549
14
          "Voice Metrics IAJ", HFILL }},
2550
14
      { &hf_mgcp_param_connectionmode,
2551
14
        { "ConnectionMode (M)", "mgcp.param.connectionmode", FT_STRING, BASE_NONE, NULL, 0x0,
2552
14
          "Connection Mode", HFILL }},
2553
14
      { &hf_mgcp_param_reqevents,
2554
14
        { "RequestedEvents (R)", "mgcp.param.reqevents", FT_STRING, BASE_NONE, NULL, 0x0,
2555
14
          "Requested Events", HFILL }},
2556
14
      { &hf_mgcp_param_signalreq,
2557
14
        { "SignalRequests (S)", "mgcp.param.signalreq", FT_STRING, BASE_NONE, NULL, 0x0,
2558
14
          "Signal Request", HFILL }},
2559
14
      { &hf_mgcp_param_restartmethod,
2560
14
        { "RestartMethod (RM)", "mgcp.param.restartmethod", FT_STRING, BASE_NONE, NULL, 0x0,
2561
14
          "Restart Method", HFILL }},
2562
14
      { &hf_mgcp_param_restartdelay,
2563
14
        { "RestartDelay (RD)", "mgcp.param.restartdelay", FT_STRING, BASE_NONE, NULL, 0x0,
2564
14
          "Restart Delay", HFILL }},
2565
14
      { &hf_mgcp_param_digitmap,
2566
14
        { "DigitMap (D)", "mgcp.param.digitmap", FT_STRING, BASE_NONE, NULL, 0x0,
2567
14
          "Digit Map", HFILL }},
2568
14
      { &hf_mgcp_param_observedevent,
2569
14
        { "ObservedEvents (O)", "mgcp.param.observedevents", FT_STRING, BASE_NONE, NULL, 0x0,
2570
14
          "Observed Events", HFILL }},
2571
14
      { &hf_mgcp_param_connectionparam,
2572
14
        { "ConnectionParameters (P)", "mgcp.param.connectionparam", FT_STRING, BASE_NONE, NULL, 0x0,
2573
14
          "Connection Parameters", HFILL }},
2574
14
      { &hf_mgcp_param_connectionparam_ps,
2575
14
        { "Packets sent (PS)", "mgcp.param.connectionparam.ps", FT_UINT32, BASE_DEC, NULL, 0x0,
2576
14
          "Packets sent (P:PS)", HFILL }},
2577
14
      { &hf_mgcp_param_connectionparam_os,
2578
14
        { "Octets sent (OS)", "mgcp.param.connectionparam.os", FT_UINT32, BASE_DEC, NULL, 0x0,
2579
14
          "Octets sent (P:OS)", HFILL }},
2580
14
      { &hf_mgcp_param_connectionparam_pr,
2581
14
        { "Packets received (PR)", "mgcp.param.connectionparam.pr", FT_UINT32, BASE_DEC, NULL, 0x0,
2582
14
          "Packets received (P:PR)", HFILL }},
2583
14
      { &hf_mgcp_param_connectionparam_or,
2584
14
        { "Octets received (OR)", "mgcp.param.connectionparam.or", FT_UINT32, BASE_DEC, NULL, 0x0,
2585
14
          "Octets received (P:OR)", HFILL }},
2586
14
      { &hf_mgcp_param_connectionparam_pl,
2587
14
        { "Packets lost (PL)", "mgcp.param.connectionparam.pl", FT_UINT32, BASE_DEC, NULL, 0x0,
2588
14
          "Packets lost (P:PL)", HFILL }},
2589
14
      { &hf_mgcp_param_connectionparam_ji,
2590
14
        { "Jitter (JI)", "mgcp.param.connectionparam.ji", FT_UINT32, BASE_DEC, NULL, 0x0,
2591
14
          "Average inter-packet arrival jitter in milliseconds (P:JI)", HFILL }},
2592
14
      { &hf_mgcp_param_connectionparam_la,
2593
14
        { "Latency (LA)", "mgcp.param.connectionparam.la", FT_UINT32, BASE_DEC, NULL, 0x0,
2594
14
          "Average latency in milliseconds (P:LA)", HFILL }},
2595
14
      { &hf_mgcp_param_connectionparam_pcrps,
2596
14
        { "Remote Packets sent (PC/RPS)", "mgcp.param.connectionparam.pcrps", FT_UINT32, BASE_DEC, NULL, 0x0,
2597
14
          "Remote Packets sent (P:PC/RPS)", HFILL }},
2598
14
      { &hf_mgcp_param_connectionparam_pcros,
2599
14
        { "Remote Octets sent (PC/ROS)", "mgcp.param.connectionparam.pcros", FT_UINT32, BASE_DEC, NULL, 0x0,
2600
14
          "Remote Octets sent (P:PC/ROS)", HFILL }},
2601
14
      { &hf_mgcp_param_connectionparam_pcrpl,
2602
14
        { "Remote Packets lost (PC/RPL)", "mgcp.param.connectionparam.pcrpl", FT_UINT32, BASE_DEC, NULL, 0x0,
2603
14
          "Remote Packets lost (P:PC/RPL)", HFILL }},
2604
14
      { &hf_mgcp_param_connectionparam_pcrji,
2605
14
        { "Remote Jitter (PC/RJI)", "mgcp.param.connectionparam.pcrji", FT_UINT32, BASE_DEC, NULL, 0x0,
2606
14
          "Remote Jitter (P:PC/RJI)", HFILL }},
2607
14
      { &hf_mgcp_param_connectionparam_x,
2608
14
        { "Vendor Extension", "mgcp.param.connectionparam.x", FT_STRING, BASE_NONE, NULL, 0x0,
2609
14
          "Vendor Extension (P:X-*)", HFILL }},
2610
14
      { &hf_mgcp_param_reasoncode,
2611
14
        { "ReasonCode (E)", "mgcp.param.reasoncode", FT_STRING, BASE_NONE, NULL, 0x0,
2612
14
          "Reason Code", HFILL }},
2613
14
      { &hf_mgcp_param_eventstates,
2614
14
        { "EventStates (ES)", "mgcp.param.eventstates", FT_STRING, BASE_NONE, NULL, 0x0,
2615
14
          "Event States", HFILL }},
2616
14
      { &hf_mgcp_param_specificendpoint,
2617
14
        { "SpecificEndpointID (Z)", "mgcp.param.specificendpointid", FT_STRING, BASE_NONE, NULL, 0x0,
2618
14
          "Specific Endpoint ID", HFILL }},
2619
14
      { &hf_mgcp_param_secondendpointid,
2620
14
        { "SecondEndpointID (Z2)", "mgcp.param.secondendpointid", FT_STRING, BASE_NONE, NULL, 0x0,
2621
14
          "Second Endpoint ID", HFILL }},
2622
14
      { &hf_mgcp_param_reqinfo,
2623
14
        { "RequestedInfo (F)", "mgcp.param.reqinfo", FT_STRING, BASE_NONE, NULL, 0x0,
2624
14
          "Requested Info", HFILL }},
2625
14
      { &hf_mgcp_param_quarantinehandling,
2626
14
        { "QuarantineHandling (Q)", "mgcp.param.quarantinehandling", FT_STRING, BASE_NONE, NULL, 0x0,
2627
14
          "Quarantine Handling", HFILL }},
2628
14
      { &hf_mgcp_param_detectedevents,
2629
14
        { "DetectedEvents (T)", "mgcp.param.detectedevents", FT_STRING, BASE_NONE, NULL, 0x0,
2630
14
          "Detected Events", HFILL }},
2631
14
      { &hf_mgcp_param_capabilities,
2632
14
        { "Capabilities (A)", "mgcp.param.capabilities", FT_STRING, BASE_NONE, NULL, 0x0,
2633
14
          NULL, HFILL }},
2634
14
      { &hf_mgcp_param_maxmgcpdatagram,
2635
14
        {"MaxMGCPDatagram (MD)", "mgcp.param.maxmgcpdatagram", FT_STRING, BASE_NONE, NULL, 0x0,
2636
14
         "Maximum MGCP Datagram size", HFILL }},
2637
14
      { &hf_mgcp_param_packagelist,
2638
14
        {"PackageList (PL)", "mgcp.param.packagelist", FT_STRING, BASE_NONE, NULL, 0x0,
2639
14
         "Package List", HFILL }},
2640
14
      { &hf_mgcp_param_extension,
2641
14
        { "Extension Parameter (non-critical)", "mgcp.param.extension", FT_STRING, BASE_NONE, NULL, 0x0,
2642
14
          NULL, HFILL }},
2643
14
      { &hf_mgcp_param_extension_critical,
2644
14
        { "Extension Parameter (critical)", "mgcp.param.extensioncritical", FT_STRING, BASE_NONE, NULL, 0x0,
2645
14
          "Critical Extension Parameter", HFILL }},
2646
14
      { &hf_mgcp_param_resourceid,
2647
14
        { "ResourceIdentifier (DQ-RI)", "mgcp.param.resourceid", FT_STRING, BASE_NONE, NULL, 0x0,
2648
14
          "Resource Identifier", HFILL }},
2649
14
      { &hf_mgcp_param_invalid,
2650
14
        { "Invalid Parameter", "mgcp.param.invalid", FT_STRING, BASE_NONE, NULL, 0x0,
2651
14
          NULL, HFILL }},
2652
14
      { &hf_mgcp_messagecount,
2653
14
        { "MGCP Message Count", "mgcp.messagecount", FT_UINT32, BASE_DEC, NULL, 0x0,
2654
14
          "Number of MGCP message in a packet", HFILL }},
2655
14
      { &hf_mgcp_dup,
2656
14
        { "Duplicate Message", "mgcp.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
2657
14
          NULL, HFILL }},
2658
14
      { &hf_mgcp_req_dup,
2659
14
        { "Duplicate Request", "mgcp.req.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
2660
14
          NULL, HFILL }},
2661
14
      { &hf_mgcp_req_dup_frame,
2662
14
        { "Original Request Frame", "mgcp.req.dup.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2663
14
          "Frame containing original request", HFILL }},
2664
14
      { &hf_mgcp_rsp_dup,
2665
14
        { "Duplicate Response", "mgcp.rsp.dup", FT_UINT32, BASE_DEC, NULL, 0x0,
2666
14
          NULL, HFILL }},
2667
14
      { &hf_mgcp_rsp_dup_frame,
2668
14
        { "Original Response Frame", "mgcp.rsp.dup.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2669
14
          "Frame containing original response", HFILL }},
2670
14
      { &hf_mgcp_param_x_osmux,
2671
14
        { "X-Osmux", "mgcp.param.x_osmux", FT_STRING, BASE_NONE, NULL, 0x0,
2672
14
          "Osmux CID", HFILL }},
2673
14
      { &hf_mgcp_unknown_parameter,
2674
14
        { "Unknown parameter", "mgcp.unknown_parameter", FT_STRING, BASE_NONE, NULL, 0x0,
2675
14
          NULL, HFILL }},
2676
14
      { &hf_mgcp_malformed_parameter,
2677
14
        { "Malformed parameter", "mgcp.rsp.malformed_parameter", FT_STRING, BASE_NONE, NULL, 0x0,
2678
14
          NULL, HFILL }},
2679
14
    };
2680
2681
14
  static int *ett[] =
2682
14
    {
2683
14
      &ett_mgcp,
2684
14
      &ett_mgcp_param,
2685
14
      &ett_mgcp_param_connectionparam,
2686
14
      &ett_mgcp_param_localconnectionoptions,
2687
14
      &ett_mgcp_param_localvoicemetrics,
2688
14
      &ett_mgcp_param_remotevoicemetrics
2689
14
    };
2690
2691
14
  static ei_register_info ei[] = {
2692
14
    { &ei_mgcp_rsp_rspcode_invalid, { "mgcp.rsp.rspcode.invalid", PI_MALFORMED, PI_ERROR,
2693
14
    "RSP code must be a string containing an integer", EXPFILL }}
2694
14
  };
2695
2696
14
  module_t *mgcp_module;
2697
2698
  /* Register protocol */
2699
14
  proto_mgcp = proto_register_protocol("Media Gateway Control Protocol", "MGCP", "mgcp");
2700
14
  proto_register_field_array(proto_mgcp, hf, array_length(hf));
2701
14
  proto_register_subtree_array(ett, array_length(ett));
2702
2703
14
  mgcp_calls = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), mgcp_call_hash, mgcp_call_equal);
2704
2705
14
  mgcp_handle = register_dissector("mgcp", dissect_mgcp, proto_mgcp);
2706
2707
  /* Register our configuration options */
2708
14
  mgcp_module = prefs_register_protocol(proto_mgcp, proto_reg_handoff_mgcp);
2709
2710
14
  prefs_register_uint_preference(mgcp_module, "tcp.gateway_port",
2711
14
               "MGCP Gateway TCP Port",
2712
14
               "Set the UDP port for gateway messages "
2713
14
               "(if other than the default of 2427)",
2714
14
               10, &global_mgcp_gateway_tcp_port);
2715
2716
14
  prefs_register_uint_preference(mgcp_module, "udp.gateway_port",
2717
14
               "MGCP Gateway UDP Port",
2718
14
               "Set the TCP port for gateway messages "
2719
14
               "(if other than the default of 2427)",
2720
14
               10, &global_mgcp_gateway_udp_port);
2721
2722
14
  prefs_register_uint_preference(mgcp_module, "tcp.callagent_port",
2723
14
               "MGCP Callagent TCP Port",
2724
14
               "Set the TCP port for callagent messages "
2725
14
               "(if other than the default of 2727)",
2726
14
               10, &global_mgcp_callagent_tcp_port);
2727
2728
14
  prefs_register_uint_preference(mgcp_module, "udp.callagent_port",
2729
14
               "MGCP Callagent UDP Port",
2730
14
               "Set the UDP port for callagent messages "
2731
14
               "(if other than the default of 2727)",
2732
14
               10, &global_mgcp_callagent_udp_port);
2733
2734
2735
14
  prefs_register_bool_preference(mgcp_module, "display_raw_text",
2736
14
               "Display raw text for MGCP message",
2737
14
               "Specifies that the raw text of the "
2738
14
               "MGCP message should be displayed "
2739
14
               "instead of (or in addition to) the "
2740
14
               "dissection tree",
2741
14
               &global_mgcp_raw_text);
2742
2743
14
  prefs_register_obsolete_preference(mgcp_module, "display_dissect_tree");
2744
2745
14
  prefs_register_bool_preference(mgcp_module, "display_mgcp_message_count",
2746
14
               "Display the number of MGCP messages",
2747
14
               "Display the number of MGCP messages "
2748
14
               "found in a packet in the protocol column.",
2749
14
               &global_mgcp_message_count);
2750
2751
14
  mgcp_tap = register_tap("mgcp");
2752
2753
14
  register_rtd_table(proto_mgcp, NULL, 1, NUM_TIMESTATS, mgcp_message_type, mgcpstat_packet, NULL);
2754
2755
14
  expert_mgcp = expert_register_protocol(proto_mgcp);
2756
14
  expert_register_field_array(expert_mgcp, ei, array_length(ei));
2757
2758
14
}
2759
2760
/* The registration hand-off routine */
2761
void proto_reg_handoff_mgcp(void)
2762
14
{
2763
14
  static bool mgcp_prefs_initialized = false;
2764
14
  static dissector_handle_t mgcp_tpkt_handle;
2765
  /*
2766
   * Variables to allow for proper deletion of dissector registration when
2767
   * the user changes port from the gui.
2768
   */
2769
14
  static unsigned gateway_tcp_port;
2770
14
  static unsigned gateway_udp_port;
2771
14
  static unsigned callagent_tcp_port;
2772
14
  static unsigned callagent_udp_port;
2773
2774
14
  if (!mgcp_prefs_initialized)
2775
14
  {
2776
    /* Get a handle for the SDP dissector. */
2777
14
    sdp_handle = find_dissector_add_dependency("sdp", proto_mgcp);
2778
14
    mgcp_tpkt_handle = create_dissector_handle(dissect_tpkt_mgcp, proto_mgcp);
2779
14
    mgcp_prefs_initialized = true;
2780
14
  }
2781
0
  else
2782
0
  {
2783
0
    dissector_delete_uint("tcp.port", gateway_tcp_port,   mgcp_tpkt_handle);
2784
0
    dissector_delete_uint("udp.port", gateway_udp_port,   mgcp_handle);
2785
0
    dissector_delete_uint("tcp.port", callagent_tcp_port, mgcp_tpkt_handle);
2786
0
    dissector_delete_uint("udp.port", callagent_udp_port, mgcp_handle);
2787
0
  }
2788
2789
  /* Set our port number for future use */
2790
14
  gateway_tcp_port = global_mgcp_gateway_tcp_port;
2791
14
  gateway_udp_port = global_mgcp_gateway_udp_port;
2792
2793
14
  callagent_tcp_port = global_mgcp_callagent_tcp_port;
2794
14
  callagent_udp_port = global_mgcp_callagent_udp_port;
2795
2796
  /* Names of port preferences too specific to add "auto" preference here */
2797
14
  dissector_add_uint("tcp.port", global_mgcp_gateway_tcp_port,   mgcp_tpkt_handle);
2798
14
  dissector_add_uint("udp.port", global_mgcp_gateway_udp_port,   mgcp_handle);
2799
14
  dissector_add_uint("tcp.port", global_mgcp_callagent_tcp_port, mgcp_tpkt_handle);
2800
14
  dissector_add_uint("udp.port", global_mgcp_callagent_udp_port, mgcp_handle);
2801
14
}
2802
2803
/*
2804
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2805
 *
2806
 * Local variables:
2807
 * c-basic-offset: 8
2808
 * tab-width: 8
2809
 * indent-tabs-mode: t
2810
 * End:
2811
 *
2812
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2813
 * :indentSize=8:tabSize=8:noTabs=false:
2814
 */