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-m2tp.c
Line
Count
Source
1
/* packet-m2tp.c
2
 * Routines for M2TP User Adaptation Layer dissection
3
 * M2TP - MTP2 Transparent Proxy - is a Radisys proprietary
4
 * protocol based on the IETF SIGTRAN standard
5
 *
6
 * Copyright 2001, Heinz Prantner <heinz.prantner[AT]radisys.com>
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * Copied from packet-m3ua.c
13
 * Thanks to Michael Tuexen for his valuable improvements
14
 *
15
 * SPDX-License-Identifier: GPL-2.0-or-later
16
 */
17
18
#include "config.h"
19
20
#include <epan/packet.h>
21
22
#include <wsutil/str_util.h>
23
24
14
#define M2TP_PAYLOAD_PROTOCOL_ID                       99    /* s-link, not IANA-registered */
25
26
void proto_register_m2tp(void);
27
void proto_reg_handoff_m2tp(void);
28
29
static dissector_handle_t m2tp_handle;
30
31
14
#define SCTP_PORT_M2TP        9908  /* unassigned port number (not assigned by IANA) */
32
33
121
#define VERSION_LENGTH         1
34
99
#define RESERVED_LENGTH        1
35
77
#define MESSAGE_CLASS_LENGTH   1
36
55
#define MESSAGE_TYPE_LENGTH    1
37
33
#define MESSAGE_LENGTH_LENGTH  4
38
22
#define COMMON_HEADER_LENGTH   (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
39
22
                                MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
40
41
110
#define VERSION_OFFSET         0
42
88
#define RESERVED_OFFSET        (VERSION_OFFSET + VERSION_LENGTH)
43
66
#define MESSAGE_CLASS_OFFSET   (RESERVED_OFFSET + RESERVED_LENGTH)
44
44
#define MESSAGE_TYPE_OFFSET    (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
45
22
#define MESSAGE_LENGTH_OFFSET  (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
46
47
142
#define PARAMETER_TAG_LENGTH    2
48
60
#define PARAMETER_LENGTH_LENGTH 2
49
18
#define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
50
51
189
#define PARAMETER_TAG_OFFSET      0
52
104
#define PARAMETER_LENGTH_OFFSET   (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
53
22
#define PARAMETER_VALUE_OFFSET    (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
54
26
#define PARAMETER_HEADER_OFFSET   PARAMETER_TAG_OFFSET
55
56
1
#define INTERFACE_IDENTIFIER_PARAMETER_TAG     1
57
0
#define MASTER_SLAVE_INDICATOR_PARAMETER_TAG   2
58
1
#define M2TP_USER_IDENTIFIER_PARAMETER_TAG     3
59
1
#define INFO_PARAMETER_TAG                     4
60
0
#define DIAGNOSTIC_INFORMATION_PARAMETER_TAG   7
61
0
#define HEARTBEAT_DATA_PARAMETER_TAG           9
62
0
#define REASON_PARAMETER_TAG                  10
63
0
#define ERROR_CODE_PARAMETER_TAG              12
64
0
#define PROTOCOL_DATA_PARAMETER_TAG           13
65
66
67
static const value_string m2tp_parameter_tag_values[] = {
68
  { INTERFACE_IDENTIFIER_PARAMETER_TAG,         "Interface Identifier" },
69
  { MASTER_SLAVE_INDICATOR_PARAMETER_TAG,       "Master Slave Indicator" },
70
  { M2TP_USER_IDENTIFIER_PARAMETER_TAG,         "M2tp User Identifier" },
71
  { INFO_PARAMETER_TAG,                         "Info" },
72
  { DIAGNOSTIC_INFORMATION_PARAMETER_TAG,       "Diagnostic Information" },
73
  { HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat Data" },
74
  { REASON_PARAMETER_TAG,                       "Reason" },
75
  { ERROR_CODE_PARAMETER_TAG,                   "Error Code" },
76
  { PROTOCOL_DATA_PARAMETER_TAG,                "Protocol Data" },
77
  { 0,                           NULL } };
78
79
#define PROTOCOL_VERSION_RELEASE_1             1
80
81
static const value_string m2tp_protocol_version_values[] = {
82
  { PROTOCOL_VERSION_RELEASE_1,  "Release 1" },
83
  { 0,                           NULL } };
84
85
#define MESSAGE_CLASS_MGMT_MESSAGE        0
86
#define MESSAGE_CLASS_SGSM_MESSAGE        3
87
#define MESSAGE_CLASS_MAUP_MESSAGE        6
88
#define MESSAGE_CLASS_DATA_MESSAGE        255
89
90
static const value_string m2tp_message_class_values[] = {
91
  { MESSAGE_CLASS_MGMT_MESSAGE,   "Management Messages" },
92
  { MESSAGE_CLASS_SGSM_MESSAGE,   "SG State Maintenance Messages" },
93
  { MESSAGE_CLASS_MAUP_MESSAGE,   "MTP2 User Adaptation Messages" },
94
  { MESSAGE_CLASS_DATA_MESSAGE,   "User Data Messages" },
95
  { 0,                            NULL } };
96
97
/* management messages */
98
#define MESSAGE_TYPE_ERR                  0
99
100
/* sg state maintenance messages */
101
#define MESSAGE_TYPE_UP                   1
102
#define MESSAGE_TYPE_DOWN                 2
103
#define MESSAGE_TYPE_BEAT                 3
104
#define MESSAGE_TYPE_UP_ACK               4
105
#define MESSAGE_TYPE_DOWN_ACK             5
106
#define MESSAGE_TYPE_BEAT_ACK             6
107
108
/* mtp2 user message */
109
#define MESSAGE_TYPE_DATA                 1
110
111
112
static const value_string m2tp_message_class_type_values[] = {
113
  { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "Error (ERR)" },
114
  { MESSAGE_CLASS_DATA_MESSAGE  * 256 + MESSAGE_TYPE_DATA,          "Payload data (DATA)" },
115
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_UP,            "ASP up (UP)" },
116
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_DOWN,          "ASP down (DOWN)" },
117
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_BEAT,          "Heartbeat (BEAT)" },
118
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_UP_ACK,        "ASP up ack (UP ACK)" },
119
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP down ack (DOWN ACK)" },
120
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_BEAT_ACK,      "Heartbeat ack (BEAT ACK)" },
121
  { 0,                           NULL } };
122
123
static const value_string m2tp_message_class_type_acro_values[] = {
124
  { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "ERR" },
125
  { MESSAGE_CLASS_DATA_MESSAGE  * 256 + MESSAGE_TYPE_DATA,          "DATA" },
126
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_UP,            "ASP_UP" },
127
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_DOWN,          "ASP_DOWN" },
128
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_BEAT,          "BEAT" },
129
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_UP_ACK,        "ASP_UP_ACK" },
130
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP_DOWN_ACK" },
131
  { MESSAGE_CLASS_SGSM_MESSAGE  * 256 + MESSAGE_TYPE_BEAT_ACK,      "BEAT_ACK" },
132
  { 0,                           NULL } };
133
134
135
136
#define HEARTBEAT_PERIOD_OFFSET PARAMETER_VALUE_OFFSET
137
138
1
#define INTERFACE_IDENTIFIER_LENGTH 4
139
1
#define INTERFACE_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
140
141
1
#define M2TP_USER_LENGTH 4
142
1
#define M2TP_USER_OFFSET PARAMETER_VALUE_OFFSET
143
144
#define PROTOCOL_DATA_OFFSET PARAMETER_VALUE_OFFSET
145
146
0
#define MASTER_SLAVE_LENGTH 4
147
0
#define MASTER_SLAVE_OFFSET PARAMETER_VALUE_OFFSET
148
149
0
#define REASON_LENGTH 4
150
0
#define REASON_OFFSET PARAMETER_VALUE_OFFSET
151
152
#define HEART_BEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
153
154
0
#define ERROR_CODE_LENGTH 4
155
0
#define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
156
157
1
#define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
158
159
#define BSN_OFFSET PARAMETER_VALUE_OFFSET
160
#define FSN_OFFSET PARAMETER_VALUE_OFFSET+1
161
162
#define M2TP_USER_MTP2          1
163
#define M2TP_USER_Q921          2
164
#define M2TP_USER_FRAME_RELAY   3
165
166
static const value_string m2tp_user_identifier_values[] = {
167
  { M2TP_USER_MTP2,        "MTP2" },
168
  { M2TP_USER_Q921,        "Q.921" },
169
  { M2TP_USER_FRAME_RELAY, "Frame Relay" },
170
  { 0, NULL }};
171
172
#define M2TP_MODE_MASTER 1
173
#define M2TP_MODE_SLAVE  2
174
175
static const value_string m2tp_mode_values[] = {
176
  { M2TP_MODE_MASTER,      "Master" },
177
  { M2TP_MODE_SLAVE,       "Slave" },
178
  { 0, NULL}};
179
180
#define M2TP_ERROR_CODE_INVALID_VERSION                         1
181
#define M2TP_ERROR_CODE_INVALID_INTERFACE_IDENTIFIER            2
182
#define M2TP_ERROR_CODE_INVALID_ADAPTATION_LAYER_IDENTIFIER     3
183
#define M2TP_ERROR_CODE_INVALID_MESSAGE_TYPE                    4
184
#define M2TP_ERROR_CODE_INVALID_TRAFFIC_HANDLING_MODE           5
185
#define M2TP_ERROR_CODE_UNEXPECTED_MESSAGE                      6
186
#define M2TP_ERROR_CODE_PROTOCOL_ERROR                          7
187
#define M2TP_ERROR_CODE_INVALID_STREAM_IDENTIFIER               8
188
#define M2TP_ERROR_CODE_INCOMPATIBLE_MASTER_SLAVE_CONFIGURATION 9
189
190
static const value_string m2tp_error_code_values[] = {
191
  { M2TP_ERROR_CODE_INVALID_VERSION,                        "Invalid Version" },
192
  { M2TP_ERROR_CODE_INVALID_INTERFACE_IDENTIFIER,           "Invalid Interface Identifier" },
193
  { M2TP_ERROR_CODE_INVALID_ADAPTATION_LAYER_IDENTIFIER,    "Invalid Adaptation Layer Identifier" },
194
  { M2TP_ERROR_CODE_INVALID_MESSAGE_TYPE,                   "Invalid Message Type" },
195
  { M2TP_ERROR_CODE_INVALID_TRAFFIC_HANDLING_MODE,          "Invalid Traffic Handling Mode" },
196
  { M2TP_ERROR_CODE_UNEXPECTED_MESSAGE,                     "Unexpected Message" },
197
  { M2TP_ERROR_CODE_PROTOCOL_ERROR,                         "Protocol Error" },
198
  { M2TP_ERROR_CODE_INVALID_STREAM_IDENTIFIER,              "Invalid Stream Identified" },
199
  { M2TP_ERROR_CODE_INCOMPATIBLE_MASTER_SLAVE_CONFIGURATION,"Incompatible Master Slave Configuration" },
200
  { 0,                                                      NULL } };
201
202
#define MANAGEMENT_ORDER_REASON_CODE       1
203
#define MTP_RELEASE_REASON_CODE            2
204
205
static const value_string m2tp_reason_code_values[] = {
206
  { MANAGEMENT_ORDER_REASON_CODE,                      "Management Order" },
207
  { MTP_RELEASE_REASON_CODE,                           "MTP Release" },
208
  { 0,                                                 NULL } };
209
210
211
/* Initialize the protocol and registered fields */
212
static int proto_m2tp;
213
static int hf_m2tp_version;
214
static int hf_m2tp_reserved;
215
static int hf_m2tp_message_class;
216
static int hf_m2tp_message_type;
217
static int hf_m2tp_message_length;
218
static int hf_m2tp_parameter_tag;
219
static int hf_m2tp_parameter_length;
220
static int hf_m2tp_parameter_value;
221
static int hf_m2tp_parameter_padding;
222
static int hf_m2tp_interface_identifier;
223
static int hf_m2tp_user;
224
static int hf_m2tp_master_slave;
225
static int hf_m2tp_info_string;
226
static int hf_m2tp_heartbeat_data;
227
static int hf_m2tp_diagnostic_info;
228
static int hf_m2tp_error_code;
229
static int hf_m2tp_reason;
230
231
/* Initialize the subtree pointers */
232
static int ett_m2tp;
233
static int ett_m2tp_parameter;
234
235
static dissector_handle_t mtp2_handle;
236
237
static unsigned
238
nr_of_padding_bytes (unsigned length)
239
42
{
240
42
  unsigned remainder;
241
242
42
  remainder = length % 4;
243
244
42
  if (remainder == 0)
245
24
    return 0;
246
18
  else
247
18
    return 4 - remainder;
248
42
}
249
250
/* Common Header */
251
static void
252
dissect_m2tp_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *m2tp_tree)
253
11
{
254
11
  uint8_t version, reserved, message_class, message_type;
255
11
  uint32_t message_length;
256
257
  /* Extract the common header */
258
11
  version        = tvb_get_uint8(common_header_tvb, VERSION_OFFSET);
259
11
  reserved       = tvb_get_uint8(common_header_tvb, RESERVED_OFFSET);
260
11
  message_class  = tvb_get_uint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
261
11
  message_type   = tvb_get_uint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
262
11
  message_length = tvb_get_ntohl (common_header_tvb, MESSAGE_LENGTH_OFFSET);
263
264
11
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(message_class * 256 + message_type, m2tp_message_class_type_acro_values, "reserved"));
265
266
11
  if (m2tp_tree) {
267
    /* add the components of the common header to the protocol tree */
268
11
    proto_tree_add_uint(m2tp_tree, hf_m2tp_version, common_header_tvb, VERSION_OFFSET, VERSION_LENGTH, version);
269
11
    proto_tree_add_uint(m2tp_tree, hf_m2tp_reserved, common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH, reserved);
270
11
    proto_tree_add_uint(m2tp_tree, hf_m2tp_message_class, common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH, message_class);
271
11
    proto_tree_add_uint_format_value(m2tp_tree, hf_m2tp_message_type,
272
11
                               common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH,
273
11
                               message_type, "%u (%s)",
274
11
                               message_type, val_to_str_const(message_class * 256 + message_type, m2tp_message_class_type_values, "reserved"));
275
11
    proto_tree_add_uint(m2tp_tree, hf_m2tp_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, message_length);
276
11
  };
277
11
}
278
279
/* Interface Identifier */
280
static void
281
dissect_m2tp_interface_identifier_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
282
1
{
283
1
  uint32_t parameter_value;
284
285
1
  if (parameter_tree) {
286
1
    parameter_value = tvb_get_ntohl(parameter_tvb, PARAMETER_VALUE_OFFSET);
287
1
    proto_tree_add_uint(parameter_tree, hf_m2tp_interface_identifier, parameter_tvb, INTERFACE_IDENTIFIER_OFFSET, INTERFACE_IDENTIFIER_LENGTH, parameter_value);
288
1
    proto_item_set_text(parameter_item, "Interface Identifier (%u)", parameter_value);
289
1
  }
290
1
}
291
292
/* Master Slave Indicator */
293
static void
294
dissect_m2tp_master_slave_parameter (tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
295
0
{
296
0
  uint32_t parameter_value;
297
298
0
  if (parameter_tree) {
299
0
    parameter_value = tvb_get_ntohl(parameter_tvb, PARAMETER_VALUE_OFFSET);
300
0
    proto_tree_add_uint(parameter_tree, hf_m2tp_master_slave, parameter_tvb, MASTER_SLAVE_OFFSET, MASTER_SLAVE_LENGTH, parameter_value);
301
0
    proto_item_set_text(parameter_item, "Master Slave Indicator (%s)", val_to_str_const(parameter_value, m2tp_mode_values, "unknown"));
302
0
  }
303
0
}
304
305
/* M2tp User Identifier */
306
static void
307
dissect_m2tp_user_identifier_parameter (tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
308
1
{
309
1
  uint32_t parameter_value;
310
311
1
  if (parameter_tree) {
312
1
    parameter_value = tvb_get_ntohl(parameter_tvb, PARAMETER_VALUE_OFFSET);
313
1
    proto_tree_add_uint(parameter_tree, hf_m2tp_user, parameter_tvb, M2TP_USER_OFFSET, M2TP_USER_LENGTH, parameter_value);
314
1
    proto_item_set_text(parameter_item, "M2TP User Identifier (%u)", parameter_value);
315
1
  }
316
1
}
317
318
/* Info String */
319
static void
320
dissect_m2tp_info_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
321
1
{
322
1
  uint16_t length, info_string_length;
323
1
  const uint8_t *info_string;
324
325
1
  if (parameter_tree) {
326
1
    length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
327
1
    info_string_length = length - PARAMETER_HEADER_LENGTH;
328
1
    proto_tree_add_item_ret_string(parameter_tree, hf_m2tp_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, ENC_ASCII, pinfo->pool, &info_string);
329
1
    proto_item_set_text(parameter_item, "Info String (%s)", info_string);
330
1
  }
331
1
}
332
333
/* Diagnostic Information */
334
static void
335
dissect_m2tp_diagnostic_information_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
336
0
{
337
0
  uint16_t length, diagnostic_info_length;
338
339
0
  if (parameter_tree) {
340
0
    length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
341
0
    diagnostic_info_length = length - PARAMETER_HEADER_LENGTH;
342
0
    proto_tree_add_item(parameter_tree, hf_m2tp_diagnostic_info, parameter_tvb, PARAMETER_VALUE_OFFSET, diagnostic_info_length, ENC_NA);
343
0
    proto_item_set_text(parameter_item, "Diagnostic information (%u byte%s)", diagnostic_info_length, plurality(diagnostic_info_length, "", "s"));
344
0
  }
345
0
}
346
347
/* Heartbeat Data */
348
static void
349
dissect_m2tp_heartbeat_data_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
350
0
{
351
0
  uint16_t length, heartbeat_data_length;
352
353
0
  if (parameter_tree) {
354
0
    length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
355
0
    heartbeat_data_length = length - PARAMETER_HEADER_LENGTH;
356
0
    proto_tree_add_item(parameter_tree, hf_m2tp_heartbeat_data, parameter_tvb, PARAMETER_VALUE_OFFSET, heartbeat_data_length, ENC_NA);
357
0
    proto_item_set_text(parameter_item, "Heartbeat data (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
358
0
  }
359
0
}
360
361
/* Reason Parameter */
362
static void
363
dissect_m2tp_reason_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
364
0
{
365
0
  uint32_t reason;
366
367
0
  if (parameter_tree) {
368
0
    reason = tvb_get_ntohl(parameter_tvb, REASON_OFFSET);
369
0
    proto_tree_add_uint(parameter_tree, hf_m2tp_reason, parameter_tvb, REASON_OFFSET, REASON_LENGTH, reason);
370
0
    proto_item_set_text(parameter_item, "Reason parameter (%s)", val_to_str_const(reason, m2tp_reason_code_values, "unknown"));
371
0
  }
372
0
}
373
374
/* Error Code */
375
static void
376
dissect_m2tp_error_code_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
377
0
{
378
0
  uint32_t error_code;
379
380
0
  if (parameter_tree) {
381
0
    error_code = tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET);
382
0
    proto_tree_add_uint(parameter_tree, hf_m2tp_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, error_code);
383
0
    proto_item_set_text(parameter_item, "Error code parameter (%s)", val_to_str_const(error_code, m2tp_error_code_values, "unknown"));
384
0
  }
385
0
}
386
387
/* Protocol Data */
388
static void
389
dissect_m2tp_protocol_data_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *m2tp_item, proto_tree *tree)
390
0
{
391
0
  uint16_t length, protocol_data_length, padding_length;
392
0
  tvbuff_t *mtp2_tvb;
393
394
0
  length               = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
395
0
  padding_length       = nr_of_padding_bytes(length);
396
0
  protocol_data_length = length - PARAMETER_HEADER_LENGTH;
397
398
0
  mtp2_tvb = tvb_new_subset_length(parameter_tvb, PARAMETER_VALUE_OFFSET, protocol_data_length);
399
0
  call_dissector(mtp2_handle, mtp2_tvb, pinfo, tree);
400
401
0
  if (parameter_tree) {
402
0
    proto_item_set_text(parameter_item, "Protocol data (SS7 message)");
403
0
    proto_item_set_len(parameter_item, proto_item_get_len(parameter_item) - protocol_data_length - padding_length);
404
0
    proto_item_set_len(m2tp_item,      proto_item_get_len(m2tp_item)      - protocol_data_length - padding_length);
405
406
0
  }
407
0
}
408
409
/* Unknown Parameter */
410
static void
411
dissect_m2tp_unknown_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
412
17
{
413
17
  uint16_t tag, length, parameter_value_length;
414
415
17
  if (parameter_tree) {
416
17
    tag    = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
417
17
    length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
418
419
17
    parameter_value_length = length - PARAMETER_HEADER_LENGTH;
420
17
    proto_tree_add_item(parameter_tree, hf_m2tp_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, ENC_NA);
421
422
17
    proto_item_set_text(parameter_item, "Parameter with tag %u and %u byte%s value", tag, parameter_value_length, plurality(parameter_value_length, "", "s"));
423
17
  }
424
17
}
425
426
/* M2TP Parameter */
427
static void
428
dissect_m2tp_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *m2tp_tree, proto_item *m2tp_item, proto_tree *tree)
429
22
{
430
22
  uint16_t tag, length, padding_length, total_length;
431
22
  proto_item *parameter_item = NULL;
432
22
  proto_tree *parameter_tree = NULL;
433
434
  /* extract tag and length from the parameter */
435
22
  tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
436
22
  length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
437
438
  /* calculate padding and total length */
439
22
  padding_length = nr_of_padding_bytes(length);
440
22
  total_length   = length + padding_length;
441
442
22
  if (tree) {
443
    /* create proto_tree stuff */
444
20
    parameter_tree = proto_tree_add_subtree(m2tp_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, total_length,
445
20
                                        ett_m2tp_parameter, &parameter_item, "Incomplete parameter");
446
447
    /* add tag and length to the m2tp tree */
448
20
    proto_tree_add_uint(parameter_tree, hf_m2tp_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, tag);
449
20
    proto_tree_add_uint(parameter_tree, hf_m2tp_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, length);
450
20
  }
451
452
22
  switch(tag) {
453
1
    case INTERFACE_IDENTIFIER_PARAMETER_TAG:
454
1
      dissect_m2tp_interface_identifier_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
455
1
      break;
456
0
    case MASTER_SLAVE_INDICATOR_PARAMETER_TAG:
457
0
      dissect_m2tp_master_slave_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
458
0
      break;
459
1
    case M2TP_USER_IDENTIFIER_PARAMETER_TAG:
460
1
      dissect_m2tp_user_identifier_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
461
1
      break;
462
1
    case INFO_PARAMETER_TAG:
463
1
      dissect_m2tp_info_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
464
1
      break;
465
0
    case DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
466
0
      dissect_m2tp_diagnostic_information_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
467
0
      break;
468
0
    case HEARTBEAT_DATA_PARAMETER_TAG:
469
0
      dissect_m2tp_heartbeat_data_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
470
0
      break;
471
0
    case REASON_PARAMETER_TAG:
472
0
      dissect_m2tp_reason_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
473
0
      break;
474
0
    case ERROR_CODE_PARAMETER_TAG:
475
0
      dissect_m2tp_error_code_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
476
0
      break;
477
0
    case PROTOCOL_DATA_PARAMETER_TAG:
478
0
      dissect_m2tp_protocol_data_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item, m2tp_item, tree);
479
0
      break;
480
17
    default:
481
17
      dissect_m2tp_unknown_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
482
17
      break;
483
22
  };
484
485
14
  if ((parameter_tree) && (padding_length > 0))
486
6
    proto_tree_add_item(parameter_tree, hf_m2tp_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_NA);
487
14
}
488
489
/* M2TP Message */
490
static void
491
dissect_m2tp_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2tp_item, proto_tree *m2tp_tree, proto_tree *tree)
492
11
{
493
11
  int offset, length, padding_length, total_length;
494
11
  tvbuff_t *common_header_tvb, *parameter_tvb;
495
496
11
  offset = 0;
497
498
  /* extract and process the common header */
499
11
  common_header_tvb = tvb_new_subset_length(message_tvb, offset, COMMON_HEADER_LENGTH);
500
11
  dissect_m2tp_common_header(common_header_tvb, pinfo, m2tp_tree);
501
11
  offset += COMMON_HEADER_LENGTH;
502
503
  /* extract zero or more parameters and process them individually */
504
33
  while(tvb_reported_length_remaining(message_tvb, offset) > 0) {
505
22
    length         = tvb_get_ntohs(message_tvb, offset + PARAMETER_LENGTH_OFFSET);
506
22
    padding_length = nr_of_padding_bytes(length);
507
22
    total_length   = length + padding_length;
508
    /* create a tvb for the parameter including the padding bytes */
509
22
    parameter_tvb    = tvb_new_subset_length(message_tvb, offset, total_length);
510
22
    dissect_m2tp_parameter(parameter_tvb, pinfo, m2tp_tree, m2tp_item, tree);
511
    /* get rid of the handled parameter */
512
22
    offset += total_length;
513
22
  }
514
11
}
515
516
/* M2tp */
517
static int
518
dissect_m2tp(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
519
11
{
520
11
  proto_item *m2tp_item;
521
11
  proto_tree *m2tp_tree;
522
523
  /* make entry in the Protocol column on summary display */
524
11
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "M2TP");
525
526
  /* create the m2tp protocol tree */
527
11
  m2tp_item = proto_tree_add_item(tree, proto_m2tp, message_tvb, 0, -1, ENC_NA);
528
11
  m2tp_tree = proto_item_add_subtree(m2tp_item, ett_m2tp);
529
530
  /* dissect the message */
531
11
  dissect_m2tp_message(message_tvb, pinfo, m2tp_item, m2tp_tree, tree);
532
11
  return tvb_captured_length(message_tvb);
533
11
}
534
535
/* Register the protocol with Wireshark */
536
void
537
proto_register_m2tp(void)
538
14
{
539
540
  /* Setup list of header fields */
541
14
  static hf_register_info hf[] = {
542
14
    { &hf_m2tp_version,
543
14
      { "Version", "m2tp.version",
544
14
        FT_UINT8, BASE_DEC, VALS(m2tp_protocol_version_values), 0x0,
545
14
        NULL, HFILL}
546
14
    },
547
14
    { &hf_m2tp_reserved,
548
14
      { "Reserved", "m2tp.reserved",
549
14
        FT_UINT8, BASE_HEX, NULL, 0x0,
550
14
        NULL, HFILL}
551
14
    },
552
14
    { &hf_m2tp_message_class,
553
14
      { "Message class", "m2tp.message_class",
554
14
        FT_UINT8, BASE_DEC, VALS(m2tp_message_class_values), 0x0,
555
14
        NULL, HFILL}
556
14
    },
557
14
    { &hf_m2tp_message_type,
558
14
      { "Message Type", "m2tp.message_type",
559
14
        FT_UINT8, BASE_DEC, NULL, 0x0,
560
14
        NULL, HFILL}
561
14
    },
562
14
    { &hf_m2tp_message_length,
563
14
      { "Message length", "m2tp.message_length",
564
14
        FT_UINT32, BASE_DEC, NULL, 0x0,
565
14
        NULL, HFILL}
566
14
    },
567
14
    { &hf_m2tp_parameter_tag,
568
14
      { "Parameter Tag", "m2tp.parameter_tag",
569
14
        FT_UINT16, BASE_DEC, VALS(m2tp_parameter_tag_values), 0x0,
570
14
        NULL, HFILL}
571
14
    },
572
14
    { &hf_m2tp_parameter_length,
573
14
      { "Parameter length", "m2tp.parameter_length",
574
14
        FT_UINT16, BASE_DEC, NULL, 0x0,
575
14
        NULL, HFILL}
576
14
    },
577
14
    { &hf_m2tp_parameter_value,
578
14
      { "Parameter Value", "m2tp.parameter_value",
579
14
        FT_BYTES, BASE_NONE, NULL, 0x0,
580
14
        NULL, HFILL }
581
14
    },
582
14
    { &hf_m2tp_parameter_padding,
583
14
      { "Padding", "m2tp.parameter_padding",
584
14
        FT_BYTES, BASE_NONE, NULL, 0x0,
585
14
        NULL, HFILL }
586
14
    },
587
14
    { &hf_m2tp_interface_identifier,
588
14
      { "Interface Identifier", "m2tp.interface_identifier",
589
14
        FT_UINT32, BASE_DEC, NULL, 0x0,
590
14
        NULL, HFILL}
591
14
    },
592
14
    { &hf_m2tp_user,
593
14
      { "M2tp User Identifier", "m2tp.user_identifier",
594
14
        FT_UINT32, BASE_DEC, VALS(m2tp_user_identifier_values), 0x0,
595
14
        NULL, HFILL}
596
14
    },
597
14
    { &hf_m2tp_master_slave,
598
14
      { "Master Slave Indicator", "m2tp.master_slave",
599
14
        FT_UINT32, BASE_DEC, VALS(m2tp_mode_values), 0x0,
600
14
        NULL, HFILL}
601
14
    },
602
14
    { &hf_m2tp_info_string,
603
14
      { "Info string", "m2tp.info_string",
604
14
        FT_STRING, BASE_NONE, NULL, 0x0,
605
14
        NULL, HFILL}
606
14
    },
607
14
    { &hf_m2tp_diagnostic_info,
608
14
      { "Diagnostic information", "m2tp.diagnostic_info",
609
14
        FT_BYTES, BASE_NONE, NULL, 0x0,
610
14
        NULL, HFILL }
611
14
    },
612
14
    { &hf_m2tp_heartbeat_data,
613
14
      { "Heartbeat data", "m2tp.heartbeat_data",
614
14
        FT_BYTES, BASE_NONE, NULL, 0x0,
615
14
        NULL, HFILL }
616
14
    },
617
14
    { &hf_m2tp_error_code,
618
14
      { "Error code", "m2tp.error_code",
619
14
        FT_UINT32, BASE_DEC, VALS(m2tp_error_code_values), 0x0,
620
14
        NULL, HFILL}
621
14
    },
622
14
    { &hf_m2tp_reason,
623
14
      { "Reason", "m2tp.reason",
624
14
        FT_UINT32, BASE_DEC, NULL, 0x0,
625
14
        NULL, HFILL}
626
14
    },
627
14
  };
628
629
  /* Setup protocol subtree array */
630
14
  static int *ett[] = {
631
14
    &ett_m2tp,
632
14
    &ett_m2tp_parameter,
633
14
  };
634
635
  /* Register the protocol name and description */
636
14
  proto_m2tp = proto_register_protocol("MTP 2 Transparent Proxy", "M2TP",  "m2tp");
637
638
  /* Required function calls to register the header fields and subtrees used */
639
14
  proto_register_field_array(proto_m2tp, hf, array_length(hf));
640
14
  proto_register_subtree_array(ett, array_length(ett));
641
642
  /* Register the dissector */
643
14
  m2tp_handle = register_dissector("m2tp", dissect_m2tp, proto_m2tp);
644
14
}
645
646
void
647
proto_reg_handoff_m2tp(void)
648
14
{
649
14
  mtp2_handle = find_dissector_add_dependency("mtp2", proto_m2tp);
650
14
  dissector_add_uint("sctp.ppi",  M2TP_PAYLOAD_PROTOCOL_ID, m2tp_handle);
651
14
  dissector_add_uint("sctp.port", SCTP_PORT_M2TP, m2tp_handle);
652
14
}
653
654
/*
655
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
656
 *
657
 * Local Variables:
658
 * c-basic-offset: 2
659
 * tab-width: 8
660
 * indent-tabs-mode: nil
661
 * End:
662
 *
663
 * ex: set shiftwidth=2 tabstop=8 expandtab:
664
 * :indentSize=2:tabSize=8:noTabs=true:
665
 */