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
6 * Copyright 2001, Heinz Prantner <heinz.prantner[AT]radisys.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Copied from packet-m3ua.c
13 * Thanks to Michael Tuexen for his valuable improvements
15 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <epan/packet.h>
22 #include <wsutil/str_util.h>
24 #define M2TP_PAYLOAD_PROTOCOL_ID 99 /* s-link, not IANA-registered */
26 void proto_register_m2tp(void);
27 void proto_reg_handoff_m2tp(void);
29 static dissector_handle_t m2tp_handle
;
31 #define SCTP_PORT_M2TP 9908 /* unassigned port number (not assigned by IANA) */
33 #define VERSION_LENGTH 1
34 #define RESERVED_LENGTH 1
35 #define MESSAGE_CLASS_LENGTH 1
36 #define MESSAGE_TYPE_LENGTH 1
37 #define MESSAGE_LENGTH_LENGTH 4
38 #define COMMON_HEADER_LENGTH (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
39 MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
41 #define VERSION_OFFSET 0
42 #define RESERVED_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
43 #define MESSAGE_CLASS_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
44 #define MESSAGE_TYPE_OFFSET (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
45 #define MESSAGE_LENGTH_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
47 #define PARAMETER_TAG_LENGTH 2
48 #define PARAMETER_LENGTH_LENGTH 2
49 #define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
51 #define PARAMETER_TAG_OFFSET 0
52 #define PARAMETER_LENGTH_OFFSET (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
53 #define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
54 #define PARAMETER_HEADER_OFFSET PARAMETER_TAG_OFFSET
56 #define INTERFACE_IDENTIFIER_PARAMETER_TAG 1
57 #define MASTER_SLAVE_INDICATOR_PARAMETER_TAG 2
58 #define M2TP_USER_IDENTIFIER_PARAMETER_TAG 3
59 #define INFO_PARAMETER_TAG 4
60 #define DIAGNOSTIC_INFORMATION_PARAMETER_TAG 7
61 #define HEARTBEAT_DATA_PARAMETER_TAG 9
62 #define REASON_PARAMETER_TAG 10
63 #define ERROR_CODE_PARAMETER_TAG 12
64 #define PROTOCOL_DATA_PARAMETER_TAG 13
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" },
79 #define PROTOCOL_VERSION_RELEASE_1 1
81 static const value_string m2tp_protocol_version_values
[] = {
82 { PROTOCOL_VERSION_RELEASE_1
, "Release 1" },
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
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" },
97 /* management messages */
98 #define MESSAGE_TYPE_ERR 0
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
108 /* mtp2 user message */
109 #define MESSAGE_TYPE_DATA 1
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)" },
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" },
136 #define HEARTBEAT_PERIOD_OFFSET PARAMETER_VALUE_OFFSET
138 #define INTERFACE_IDENTIFIER_LENGTH 4
139 #define INTERFACE_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
141 #define M2TP_USER_LENGTH 4
142 #define M2TP_USER_OFFSET PARAMETER_VALUE_OFFSET
144 #define PROTOCOL_DATA_OFFSET PARAMETER_VALUE_OFFSET
146 #define MASTER_SLAVE_LENGTH 4
147 #define MASTER_SLAVE_OFFSET PARAMETER_VALUE_OFFSET
149 #define REASON_LENGTH 4
150 #define REASON_OFFSET PARAMETER_VALUE_OFFSET
152 #define HEART_BEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
154 #define ERROR_CODE_LENGTH 4
155 #define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
157 #define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
159 #define BSN_OFFSET PARAMETER_VALUE_OFFSET
160 #define FSN_OFFSET PARAMETER_VALUE_OFFSET+1
162 #define M2TP_USER_MTP2 1
163 #define M2TP_USER_Q921 2
164 #define M2TP_USER_FRAME_RELAY 3
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" },
172 #define M2TP_MODE_MASTER 1
173 #define M2TP_MODE_SLAVE 2
175 static const value_string m2tp_mode_values
[] = {
176 { M2TP_MODE_MASTER
, "Master" },
177 { M2TP_MODE_SLAVE
, "Slave" },
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
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" },
202 #define MANAGEMENT_ORDER_REASON_CODE 1
203 #define MTP_RELEASE_REASON_CODE 2
205 static const value_string m2tp_reason_code_values
[] = {
206 { MANAGEMENT_ORDER_REASON_CODE
, "Management Order" },
207 { MTP_RELEASE_REASON_CODE
, "MTP Release" },
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
;
231 /* Initialize the subtree pointers */
233 static int ett_m2tp_parameter
;
235 static dissector_handle_t mtp2_handle
;
238 nr_of_padding_bytes (unsigned length
)
242 remainder
= length
% 4;
247 return 4 - remainder
;
252 dissect_m2tp_common_header(tvbuff_t
*common_header_tvb
, packet_info
*pinfo
, proto_tree
*m2tp_tree
)
254 uint8_t version
, reserved
, message_class
, message_type
;
255 uint32_t message_length
;
257 /* Extract the common header */
258 version
= tvb_get_uint8(common_header_tvb
, VERSION_OFFSET
);
259 reserved
= tvb_get_uint8(common_header_tvb
, RESERVED_OFFSET
);
260 message_class
= tvb_get_uint8(common_header_tvb
, MESSAGE_CLASS_OFFSET
);
261 message_type
= tvb_get_uint8(common_header_tvb
, MESSAGE_TYPE_OFFSET
);
262 message_length
= tvb_get_ntohl (common_header_tvb
, MESSAGE_LENGTH_OFFSET
);
264 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", val_to_str_const(message_class
* 256 + message_type
, m2tp_message_class_type_acro_values
, "reserved"));
267 /* add the components of the common header to the protocol tree */
268 proto_tree_add_uint(m2tp_tree
, hf_m2tp_version
, common_header_tvb
, VERSION_OFFSET
, VERSION_LENGTH
, version
);
269 proto_tree_add_uint(m2tp_tree
, hf_m2tp_reserved
, common_header_tvb
, RESERVED_OFFSET
, RESERVED_LENGTH
, reserved
);
270 proto_tree_add_uint(m2tp_tree
, hf_m2tp_message_class
, common_header_tvb
, MESSAGE_CLASS_OFFSET
, MESSAGE_CLASS_LENGTH
, message_class
);
271 proto_tree_add_uint_format_value(m2tp_tree
, hf_m2tp_message_type
,
272 common_header_tvb
, MESSAGE_TYPE_OFFSET
, MESSAGE_TYPE_LENGTH
,
273 message_type
, "%u (%s)",
274 message_type
, val_to_str_const(message_class
* 256 + message_type
, m2tp_message_class_type_values
, "reserved"));
275 proto_tree_add_uint(m2tp_tree
, hf_m2tp_message_length
, common_header_tvb
, MESSAGE_LENGTH_OFFSET
, MESSAGE_LENGTH_LENGTH
, message_length
);
279 /* Interface Identifier */
281 dissect_m2tp_interface_identifier_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo _U_
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
283 uint32_t parameter_value
;
285 if (parameter_tree
) {
286 parameter_value
= tvb_get_ntohl(parameter_tvb
, PARAMETER_VALUE_OFFSET
);
287 proto_tree_add_uint(parameter_tree
, hf_m2tp_interface_identifier
, parameter_tvb
, INTERFACE_IDENTIFIER_OFFSET
, INTERFACE_IDENTIFIER_LENGTH
, parameter_value
);
288 proto_item_set_text(parameter_item
, "Interface Identifier (%u)", parameter_value
);
292 /* Master Slave Indicator */
294 dissect_m2tp_master_slave_parameter (tvbuff_t
*parameter_tvb
, packet_info
*pinfo _U_
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
296 uint32_t parameter_value
;
298 if (parameter_tree
) {
299 parameter_value
= tvb_get_ntohl(parameter_tvb
, PARAMETER_VALUE_OFFSET
);
300 proto_tree_add_uint(parameter_tree
, hf_m2tp_master_slave
, parameter_tvb
, MASTER_SLAVE_OFFSET
, MASTER_SLAVE_LENGTH
, parameter_value
);
301 proto_item_set_text(parameter_item
, "Master Slave Indicator (%s)", val_to_str_const(parameter_value
, m2tp_mode_values
, "unknown"));
305 /* M2tp User Identifier */
307 dissect_m2tp_user_identifier_parameter (tvbuff_t
*parameter_tvb
, packet_info
*pinfo _U_
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
309 uint32_t parameter_value
;
311 if (parameter_tree
) {
312 parameter_value
= tvb_get_ntohl(parameter_tvb
, PARAMETER_VALUE_OFFSET
);
313 proto_tree_add_uint(parameter_tree
, hf_m2tp_user
, parameter_tvb
, M2TP_USER_OFFSET
, M2TP_USER_LENGTH
, parameter_value
);
314 proto_item_set_text(parameter_item
, "M2TP User Identifier (%u)", parameter_value
);
320 dissect_m2tp_info_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
322 uint16_t length
, info_string_length
;
323 const uint8_t *info_string
;
325 if (parameter_tree
) {
326 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
327 info_string_length
= length
- PARAMETER_HEADER_LENGTH
;
328 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 proto_item_set_text(parameter_item
, "Info String (%s)", info_string
);
333 /* Diagnostic Information */
335 dissect_m2tp_diagnostic_information_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo _U_
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
337 uint16_t length
, diagnostic_info_length
;
339 if (parameter_tree
) {
340 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
341 diagnostic_info_length
= length
- PARAMETER_HEADER_LENGTH
;
342 proto_tree_add_item(parameter_tree
, hf_m2tp_diagnostic_info
, parameter_tvb
, PARAMETER_VALUE_OFFSET
, diagnostic_info_length
, ENC_NA
);
343 proto_item_set_text(parameter_item
, "Diagnostic information (%u byte%s)", diagnostic_info_length
, plurality(diagnostic_info_length
, "", "s"));
349 dissect_m2tp_heartbeat_data_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo _U_
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
351 uint16_t length
, heartbeat_data_length
;
353 if (parameter_tree
) {
354 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
355 heartbeat_data_length
= length
- PARAMETER_HEADER_LENGTH
;
356 proto_tree_add_item(parameter_tree
, hf_m2tp_heartbeat_data
, parameter_tvb
, PARAMETER_VALUE_OFFSET
, heartbeat_data_length
, ENC_NA
);
357 proto_item_set_text(parameter_item
, "Heartbeat data (%u byte%s)", heartbeat_data_length
, plurality(heartbeat_data_length
, "", "s"));
361 /* Reason Parameter */
363 dissect_m2tp_reason_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo _U_
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
367 if (parameter_tree
) {
368 reason
= tvb_get_ntohl(parameter_tvb
, REASON_OFFSET
);
369 proto_tree_add_uint(parameter_tree
, hf_m2tp_reason
, parameter_tvb
, REASON_OFFSET
, REASON_LENGTH
, reason
);
370 proto_item_set_text(parameter_item
, "Reason parameter (%s)", val_to_str_const(reason
, m2tp_reason_code_values
, "unknown"));
376 dissect_m2tp_error_code_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo _U_
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
380 if (parameter_tree
) {
381 error_code
= tvb_get_ntohl(parameter_tvb
, ERROR_CODE_OFFSET
);
382 proto_tree_add_uint(parameter_tree
, hf_m2tp_error_code
, parameter_tvb
, ERROR_CODE_OFFSET
, ERROR_CODE_LENGTH
, error_code
);
383 proto_item_set_text(parameter_item
, "Error code parameter (%s)", val_to_str_const(error_code
, m2tp_error_code_values
, "unknown"));
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
)
391 uint16_t length
, protocol_data_length
, padding_length
;
394 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
395 padding_length
= nr_of_padding_bytes(length
);
396 protocol_data_length
= length
- PARAMETER_HEADER_LENGTH
;
398 mtp2_tvb
= tvb_new_subset_length(parameter_tvb
, PARAMETER_VALUE_OFFSET
, protocol_data_length
);
399 call_dissector(mtp2_handle
, mtp2_tvb
, pinfo
, tree
);
401 if (parameter_tree
) {
402 proto_item_set_text(parameter_item
, "Protocol data (SS7 message)");
403 proto_item_set_len(parameter_item
, proto_item_get_len(parameter_item
) - protocol_data_length
- padding_length
);
404 proto_item_set_len(m2tp_item
, proto_item_get_len(m2tp_item
) - protocol_data_length
- padding_length
);
409 /* Unknown Parameter */
411 dissect_m2tp_unknown_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo _U_
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
413 uint16_t tag
, length
, parameter_value_length
;
415 if (parameter_tree
) {
416 tag
= tvb_get_ntohs(parameter_tvb
, PARAMETER_TAG_OFFSET
);
417 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
419 parameter_value_length
= length
- PARAMETER_HEADER_LENGTH
;
420 proto_tree_add_item(parameter_tree
, hf_m2tp_parameter_value
, parameter_tvb
, PARAMETER_VALUE_OFFSET
, parameter_value_length
, ENC_NA
);
422 proto_item_set_text(parameter_item
, "Parameter with tag %u and %u byte%s value", tag
, parameter_value_length
, plurality(parameter_value_length
, "", "s"));
428 dissect_m2tp_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo
, proto_tree
*m2tp_tree
, proto_item
*m2tp_item
, proto_tree
*tree
)
430 uint16_t tag
, length
, padding_length
, total_length
;
431 proto_item
*parameter_item
= NULL
;
432 proto_tree
*parameter_tree
= NULL
;
434 /* extract tag and length from the parameter */
435 tag
= tvb_get_ntohs(parameter_tvb
, PARAMETER_TAG_OFFSET
);
436 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
438 /* calculate padding and total length */
439 padding_length
= nr_of_padding_bytes(length
);
440 total_length
= length
+ padding_length
;
443 /* create proto_tree stuff */
444 parameter_tree
= proto_tree_add_subtree(m2tp_tree
, parameter_tvb
, PARAMETER_HEADER_OFFSET
, total_length
,
445 ett_m2tp_parameter
, ¶meter_item
, "Incomplete parameter");
447 /* add tag and length to the m2tp tree */
448 proto_tree_add_uint(parameter_tree
, hf_m2tp_parameter_tag
, parameter_tvb
, PARAMETER_TAG_OFFSET
, PARAMETER_TAG_LENGTH
, tag
);
449 proto_tree_add_uint(parameter_tree
, hf_m2tp_parameter_length
, parameter_tvb
, PARAMETER_LENGTH_OFFSET
, PARAMETER_LENGTH_LENGTH
, length
);
453 case INTERFACE_IDENTIFIER_PARAMETER_TAG
:
454 dissect_m2tp_interface_identifier_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
456 case MASTER_SLAVE_INDICATOR_PARAMETER_TAG
:
457 dissect_m2tp_master_slave_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
459 case M2TP_USER_IDENTIFIER_PARAMETER_TAG
:
460 dissect_m2tp_user_identifier_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
462 case INFO_PARAMETER_TAG
:
463 dissect_m2tp_info_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
465 case DIAGNOSTIC_INFORMATION_PARAMETER_TAG
:
466 dissect_m2tp_diagnostic_information_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
468 case HEARTBEAT_DATA_PARAMETER_TAG
:
469 dissect_m2tp_heartbeat_data_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
471 case REASON_PARAMETER_TAG
:
472 dissect_m2tp_reason_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
474 case ERROR_CODE_PARAMETER_TAG
:
475 dissect_m2tp_error_code_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
477 case PROTOCOL_DATA_PARAMETER_TAG
:
478 dissect_m2tp_protocol_data_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
, m2tp_item
, tree
);
481 dissect_m2tp_unknown_parameter(parameter_tvb
, pinfo
, parameter_tree
, parameter_item
);
485 if ((parameter_tree
) && (padding_length
> 0))
486 proto_tree_add_item(parameter_tree
, hf_m2tp_parameter_padding
, parameter_tvb
, PARAMETER_HEADER_OFFSET
+ length
, padding_length
, ENC_NA
);
491 dissect_m2tp_message(tvbuff_t
*message_tvb
, packet_info
*pinfo
, proto_item
*m2tp_item
, proto_tree
*m2tp_tree
, proto_tree
*tree
)
493 int offset
, length
, padding_length
, total_length
;
494 tvbuff_t
*common_header_tvb
, *parameter_tvb
;
498 /* extract and process the common header */
499 common_header_tvb
= tvb_new_subset_length(message_tvb
, offset
, COMMON_HEADER_LENGTH
);
500 dissect_m2tp_common_header(common_header_tvb
, pinfo
, m2tp_tree
);
501 offset
+= COMMON_HEADER_LENGTH
;
503 /* extract zero or more parameters and process them individually */
504 while(tvb_reported_length_remaining(message_tvb
, offset
) > 0) {
505 length
= tvb_get_ntohs(message_tvb
, offset
+ PARAMETER_LENGTH_OFFSET
);
506 padding_length
= nr_of_padding_bytes(length
);
507 total_length
= length
+ padding_length
;
508 /* create a tvb for the parameter including the padding bytes */
509 parameter_tvb
= tvb_new_subset_length(message_tvb
, offset
, total_length
);
510 dissect_m2tp_parameter(parameter_tvb
, pinfo
, m2tp_tree
, m2tp_item
, tree
);
511 /* get rid of the handled parameter */
512 offset
+= total_length
;
518 dissect_m2tp(tvbuff_t
*message_tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
520 proto_item
*m2tp_item
;
521 proto_tree
*m2tp_tree
;
523 /* make entry in the Protocol column on summary display */
524 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "M2TP");
526 /* create the m2tp protocol tree */
527 m2tp_item
= proto_tree_add_item(tree
, proto_m2tp
, message_tvb
, 0, -1, ENC_NA
);
528 m2tp_tree
= proto_item_add_subtree(m2tp_item
, ett_m2tp
);
530 /* dissect the message */
531 dissect_m2tp_message(message_tvb
, pinfo
, m2tp_item
, m2tp_tree
, tree
);
532 return tvb_captured_length(message_tvb
);
535 /* Register the protocol with Wireshark */
537 proto_register_m2tp(void)
540 /* Setup list of header fields */
541 static hf_register_info hf
[] = {
543 { "Version", "m2tp.version",
544 FT_UINT8
, BASE_DEC
, VALS(m2tp_protocol_version_values
), 0x0,
548 { "Reserved", "m2tp.reserved",
549 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
552 { &hf_m2tp_message_class
,
553 { "Message class", "m2tp.message_class",
554 FT_UINT8
, BASE_DEC
, VALS(m2tp_message_class_values
), 0x0,
557 { &hf_m2tp_message_type
,
558 { "Message Type", "m2tp.message_type",
559 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
562 { &hf_m2tp_message_length
,
563 { "Message length", "m2tp.message_length",
564 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
567 { &hf_m2tp_parameter_tag
,
568 { "Parameter Tag", "m2tp.parameter_tag",
569 FT_UINT16
, BASE_DEC
, VALS(m2tp_parameter_tag_values
), 0x0,
572 { &hf_m2tp_parameter_length
,
573 { "Parameter length", "m2tp.parameter_length",
574 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
577 { &hf_m2tp_parameter_value
,
578 { "Parameter Value", "m2tp.parameter_value",
579 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
582 { &hf_m2tp_parameter_padding
,
583 { "Padding", "m2tp.parameter_padding",
584 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
587 { &hf_m2tp_interface_identifier
,
588 { "Interface Identifier", "m2tp.interface_identifier",
589 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
593 { "M2tp User Identifier", "m2tp.user_identifier",
594 FT_UINT32
, BASE_DEC
, VALS(m2tp_user_identifier_values
), 0x0,
597 { &hf_m2tp_master_slave
,
598 { "Master Slave Indicator", "m2tp.master_slave",
599 FT_UINT32
, BASE_DEC
, VALS(m2tp_mode_values
), 0x0,
602 { &hf_m2tp_info_string
,
603 { "Info string", "m2tp.info_string",
604 FT_STRING
, BASE_NONE
, NULL
, 0x0,
607 { &hf_m2tp_diagnostic_info
,
608 { "Diagnostic information", "m2tp.diagnostic_info",
609 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
612 { &hf_m2tp_heartbeat_data
,
613 { "Heartbeat data", "m2tp.heartbeat_data",
614 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
617 { &hf_m2tp_error_code
,
618 { "Error code", "m2tp.error_code",
619 FT_UINT32
, BASE_DEC
, VALS(m2tp_error_code_values
), 0x0,
623 { "Reason", "m2tp.reason",
624 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
629 /* Setup protocol subtree array */
630 static int *ett
[] = {
635 /* Register the protocol name and description */
636 proto_m2tp
= proto_register_protocol("MTP 2 Transparent Proxy", "M2TP", "m2tp");
638 /* Required function calls to register the header fields and subtrees used */
639 proto_register_field_array(proto_m2tp
, hf
, array_length(hf
));
640 proto_register_subtree_array(ett
, array_length(ett
));
642 /* Register the dissector */
643 m2tp_handle
= register_dissector("m2tp", dissect_m2tp
, proto_m2tp
);
647 proto_reg_handoff_m2tp(void)
649 mtp2_handle
= find_dissector_add_dependency("mtp2", proto_m2tp
);
650 dissector_add_uint("sctp.ppi", M2TP_PAYLOAD_PROTOCOL_ID
, m2tp_handle
);
651 dissector_add_uint("sctp.port", SCTP_PORT_M2TP
, m2tp_handle
);
655 * Editor modelines - https://www.wireshark.org/tools/modelines.html
660 * indent-tabs-mode: nil
663 * ex: set shiftwidth=2 tabstop=8 expandtab:
664 * :indentSize=2:tabSize=8:noTabs=true: