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>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * Copied from packet-m3ua.c
15 * Thanks to Michael Tuexen for his valuable improvements
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include <epan/packet.h>
37 #include <epan/sctpppids.h>
39 #define SCTP_PORT_M2TP 9908 /* unassigned port number (not assigned by IANA) */
41 #define VERSION_LENGTH 1
42 #define RESERVED_LENGTH 1
43 #define MESSAGE_CLASS_LENGTH 1
44 #define MESSAGE_TYPE_LENGTH 1
45 #define MESSAGE_LENGTH_LENGTH 4
46 #define COMMON_HEADER_LENGTH (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
47 MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
49 #define VERSION_OFFSET 0
50 #define RESERVED_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
51 #define MESSAGE_CLASS_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
52 #define MESSAGE_TYPE_OFFSET (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
53 #define MESSAGE_LENGTH_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
55 #define PARAMETER_TAG_LENGTH 2
56 #define PARAMETER_LENGTH_LENGTH 2
57 #define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
59 #define PARAMETER_TAG_OFFSET 0
60 #define PARAMETER_LENGTH_OFFSET (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
61 #define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
62 #define PARAMETER_HEADER_OFFSET PARAMETER_TAG_OFFSET
64 #define INTERFACE_IDENTIFIER_PARAMETER_TAG 1
65 #define MASTER_SLAVE_INDICATOR_PARAMETER_TAG 2
66 #define M2TP_USER_IDENTIFIER_PARAMETER_TAG 3
67 #define INFO_PARAMETER_TAG 4
68 #define DIAGNOSTIC_INFORMATION_PARAMETER_TAG 7
69 #define HEARTBEAT_DATA_PARAMETER_TAG 9
70 #define REASON_PARAMETER_TAG 10
71 #define ERROR_CODE_PARAMETER_TAG 12
72 #define PROTOCOL_DATA_PARAMETER_TAG 13
75 static const value_string m2tp_parameter_tag_values
[] = {
76 { INTERFACE_IDENTIFIER_PARAMETER_TAG
, "Interface Identifier" },
77 { MASTER_SLAVE_INDICATOR_PARAMETER_TAG
, "Master Slave Indicator" },
78 { M2TP_USER_IDENTIFIER_PARAMETER_TAG
, "M2tp User Identifier" },
79 { INFO_PARAMETER_TAG
, "Info" },
80 { DIAGNOSTIC_INFORMATION_PARAMETER_TAG
, "Diagnostic Information" },
81 { HEARTBEAT_DATA_PARAMETER_TAG
, "Heartbeat Data" },
82 { REASON_PARAMETER_TAG
, "Reason" },
83 { ERROR_CODE_PARAMETER_TAG
, "Error Code" },
84 { PROTOCOL_DATA_PARAMETER_TAG
, "Protocol Data" },
87 #define PROTOCOL_VERSION_RELEASE_1 1
89 static const value_string m2tp_protocol_version_values
[] = {
90 { PROTOCOL_VERSION_RELEASE_1
, "Release 1" },
93 #define MESSAGE_CLASS_MGMT_MESSAGE 0
94 #define MESSAGE_CLASS_SGSM_MESSAGE 3
95 #define MESSAGE_CLASS_MAUP_MESSAGE 6
96 #define MESSAGE_CLASS_DATA_MESSAGE 255
98 static const value_string m2tp_message_class_values
[] = {
99 { MESSAGE_CLASS_MGMT_MESSAGE
, "Management Messages" },
100 { MESSAGE_CLASS_SGSM_MESSAGE
, "SG State Maintenance Messages" },
101 { MESSAGE_CLASS_MAUP_MESSAGE
, "MTP2 User Adaptation Messages" },
102 { MESSAGE_CLASS_DATA_MESSAGE
, "User Data Messages" },
105 /* management messages */
106 #define MESSAGE_TYPE_ERR 0
108 /* sg state maintenance messages */
109 #define MESSAGE_TYPE_UP 1
110 #define MESSAGE_TYPE_DOWN 2
111 #define MESSAGE_TYPE_BEAT 3
112 #define MESSAGE_TYPE_UP_ACK 4
113 #define MESSAGE_TYPE_DOWN_ACK 5
114 #define MESSAGE_TYPE_BEAT_ACK 6
116 /* mtp2 user message */
117 #define MESSAGE_TYPE_DATA 1
120 static const value_string m2tp_message_class_type_values
[] = {
121 { MESSAGE_CLASS_MGMT_MESSAGE
* 256 + MESSAGE_TYPE_ERR
, "Error (ERR)" },
122 { MESSAGE_CLASS_DATA_MESSAGE
* 256 + MESSAGE_TYPE_DATA
, "Payload data (DATA)" },
123 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_UP
, "ASP up (UP)" },
124 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_DOWN
, "ASP down (DOWN)" },
125 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_BEAT
, "Heartbeat (BEAT)" },
126 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_UP_ACK
, "ASP up ack (UP ACK)" },
127 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_DOWN_ACK
, "ASP down ack (DOWN ACK)" },
128 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_BEAT_ACK
, "Heartbeat ack (BEAT ACK)" },
131 static const value_string m2tp_message_class_type_acro_values
[] = {
132 { MESSAGE_CLASS_MGMT_MESSAGE
* 256 + MESSAGE_TYPE_ERR
, "ERR" },
133 { MESSAGE_CLASS_DATA_MESSAGE
* 256 + MESSAGE_TYPE_DATA
, "DATA" },
134 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_UP
, "ASP_UP" },
135 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_DOWN
, "ASP_DOWN" },
136 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_BEAT
, "BEAT" },
137 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_UP_ACK
, "ASP_UP_ACK" },
138 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_DOWN_ACK
, "ASP_DOWN_ACK" },
139 { MESSAGE_CLASS_SGSM_MESSAGE
* 256 + MESSAGE_TYPE_BEAT_ACK
, "BEAT_ACK" },
144 #define HEARTBEAT_PERIOD_OFFSET PARAMETER_VALUE_OFFSET
146 #define INTERFACE_IDENTIFIER_LENGTH 4
147 #define INTERFACE_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
149 #define M2TP_USER_LENGTH 4
150 #define M2TP_USER_OFFSET PARAMETER_VALUE_OFFSET
152 #define PROTOCOL_DATA_OFFSET PARAMETER_VALUE_OFFSET
154 #define MASTER_SLAVE_LENGTH 4
155 #define MASTER_SLAVE_OFFSET PARAMETER_VALUE_OFFSET
157 #define REASON_LENGTH 4
158 #define REASON_OFFSET PARAMETER_VALUE_OFFSET
160 #define HEART_BEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
162 #define ERROR_CODE_LENGTH 4
163 #define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
165 #define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
167 #define BSN_OFFSET PARAMETER_VALUE_OFFSET
168 #define FSN_OFFSET PARAMETER_VALUE_OFFSET+1
170 #define M2TP_USER_MTP2 1
171 #define M2TP_USER_Q921 2
172 #define M2TP_USER_FRAME_RELAY 3
174 static const value_string m2tp_user_identifier_values
[] = {
175 { M2TP_USER_MTP2
, "MTP2" },
176 { M2TP_USER_Q921
, "Q.921" },
177 { M2TP_USER_FRAME_RELAY
, "Frame Relay" },
180 #define M2TP_MODE_MASTER 1
181 #define M2TP_MODE_SLAVE 2
183 static const value_string m2tp_mode_values
[] = {
184 { M2TP_MODE_MASTER
, "Master" },
185 { M2TP_MODE_SLAVE
, "Slave" },
188 #define M2TP_ERROR_CODE_INVALID_VERSION 1
189 #define M2TP_ERROR_CODE_INVALID_INTERFACE_IDENTIFIER 2
190 #define M2TP_ERROR_CODE_INVALID_ADAPTATION_LAYER_IDENTIFIER 3
191 #define M2TP_ERROR_CODE_INVALID_MESSAGE_TYPE 4
192 #define M2TP_ERROR_CODE_INVALID_TRAFFIC_HANDLING_MODE 5
193 #define M2TP_ERROR_CODE_UNEXPECTED_MESSAGE 6
194 #define M2TP_ERROR_CODE_PROTOCOL_ERROR 7
195 #define M2TP_ERROR_CODE_INVALID_STREAM_IDENTIFIER 8
196 #define M2TP_ERROR_CODE_INCOMPATIBLE_MASTER_SLAVE_CONFIGURATION 9
198 static const value_string m2tp_error_code_values
[] = {
199 { M2TP_ERROR_CODE_INVALID_VERSION
, "Invalid Version" },
200 { M2TP_ERROR_CODE_INVALID_INTERFACE_IDENTIFIER
, "Invalid Interface Identifier" },
201 { M2TP_ERROR_CODE_INVALID_ADAPTATION_LAYER_IDENTIFIER
, "Invalid Adaptation Layer Identifier" },
202 { M2TP_ERROR_CODE_INVALID_MESSAGE_TYPE
, "Invalid Message Type" },
203 { M2TP_ERROR_CODE_INVALID_TRAFFIC_HANDLING_MODE
, "Invalid Traffic Handling Mode" },
204 { M2TP_ERROR_CODE_UNEXPECTED_MESSAGE
, "Unexpected Message" },
205 { M2TP_ERROR_CODE_PROTOCOL_ERROR
, "Protocol Error" },
206 { M2TP_ERROR_CODE_INVALID_STREAM_IDENTIFIER
, "Invalid Stream Identified" },
207 { M2TP_ERROR_CODE_INCOMPATIBLE_MASTER_SLAVE_CONFIGURATION
,"Incompatible Master Slave Configuration" },
210 #define MANAGEMENT_ORDER_REASON_CODE 1
211 #define MTP_RELEASE_REASON_CODE 2
213 static const value_string m2tp_reason_code_values
[] = {
214 { MANAGEMENT_ORDER_REASON_CODE
, "Management Order" },
215 { MTP_RELEASE_REASON_CODE
, "MTP Release" },
219 /* Initialize the protocol and registered fields */
220 static int proto_m2tp
= -1;
221 static int hf_m2tp_version
= -1;
222 static int hf_m2tp_reserved
= -1;
223 static int hf_m2tp_message_class
= -1;
224 static int hf_m2tp_message_type
= -1;
225 static int hf_m2tp_message_length
= -1;
226 static int hf_m2tp_parameter_tag
= -1;
227 static int hf_m2tp_parameter_length
= -1;
228 static int hf_m2tp_parameter_value
= -1;
229 static int hf_m2tp_parameter_padding
= -1;
230 static int hf_m2tp_interface_identifier
= -1;
231 static int hf_m2tp_user
= -1;
232 static int hf_m2tp_master_slave
= -1;
233 static int hf_m2tp_info_string
= -1;
234 static int hf_m2tp_heartbeat_data
= -1;
235 static int hf_m2tp_diagnostic_info
= -1;
236 static int hf_m2tp_error_code
= -1;
237 static int hf_m2tp_reason
= -1;
239 /* Initialize the subtree pointers */
240 static gint ett_m2tp
= -1;
241 static gint ett_m2tp_parameter
= -1;
243 static dissector_handle_t mtp2_handle
;
246 nr_of_padding_bytes (guint length
)
250 remainder
= length
% 4;
255 return 4 - remainder
;
260 dissect_m2tp_common_header(tvbuff_t
*common_header_tvb
, packet_info
*pinfo
, proto_tree
*m2tp_tree
)
262 guint8 version
, reserved
, message_class
, message_type
;
263 guint32 message_length
;
265 /* Extract the common header */
266 version
= tvb_get_guint8(common_header_tvb
, VERSION_OFFSET
);
267 reserved
= tvb_get_guint8(common_header_tvb
, RESERVED_OFFSET
);
268 message_class
= tvb_get_guint8(common_header_tvb
, MESSAGE_CLASS_OFFSET
);
269 message_type
= tvb_get_guint8(common_header_tvb
, MESSAGE_TYPE_OFFSET
);
270 message_length
= tvb_get_ntohl (common_header_tvb
, MESSAGE_LENGTH_OFFSET
);
272 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", val_to_str_const(message_class
* 256 + message_type
, m2tp_message_class_type_acro_values
, "reserved"));
275 /* add the components of the common header to the protocol tree */
276 proto_tree_add_uint(m2tp_tree
, hf_m2tp_version
, common_header_tvb
, VERSION_OFFSET
, VERSION_LENGTH
, version
);
277 proto_tree_add_uint(m2tp_tree
, hf_m2tp_reserved
, common_header_tvb
, RESERVED_OFFSET
, RESERVED_LENGTH
, reserved
);
278 proto_tree_add_uint(m2tp_tree
, hf_m2tp_message_class
, common_header_tvb
, MESSAGE_CLASS_OFFSET
, MESSAGE_CLASS_LENGTH
, message_class
);
279 proto_tree_add_uint_format_value(m2tp_tree
, hf_m2tp_message_type
,
280 common_header_tvb
, MESSAGE_TYPE_OFFSET
, MESSAGE_TYPE_LENGTH
,
281 message_type
, "%u (%s)",
282 message_type
, val_to_str_const(message_class
* 256 + message_type
, m2tp_message_class_type_values
, "reserved"));
283 proto_tree_add_uint(m2tp_tree
, hf_m2tp_message_length
, common_header_tvb
, MESSAGE_LENGTH_OFFSET
, MESSAGE_LENGTH_LENGTH
, message_length
);
287 /* Interface Identifier */
289 dissect_m2tp_interface_identifier_parameter(tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
291 guint32 parameter_value
;
293 if (parameter_tree
) {
294 parameter_value
= tvb_get_ntohl(parameter_tvb
, PARAMETER_VALUE_OFFSET
);
295 proto_tree_add_uint(parameter_tree
, hf_m2tp_interface_identifier
, parameter_tvb
, INTERFACE_IDENTIFIER_OFFSET
, INTERFACE_IDENTIFIER_LENGTH
, parameter_value
);
296 proto_item_set_text(parameter_item
, "Interface Identifier (%u)", parameter_value
);
300 /* Master Slave Indicator */
302 dissect_m2tp_master_slave_parameter (tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
304 guint32 parameter_value
;
306 if (parameter_tree
) {
307 parameter_value
= tvb_get_ntohl(parameter_tvb
, PARAMETER_VALUE_OFFSET
);
308 proto_tree_add_uint(parameter_tree
, hf_m2tp_master_slave
, parameter_tvb
, MASTER_SLAVE_OFFSET
, MASTER_SLAVE_LENGTH
, parameter_value
);
309 proto_item_set_text(parameter_item
, "Master Slave Indicator (%s)", val_to_str_const(parameter_value
, m2tp_mode_values
, "unknown"));
313 /* M2tp User Identifier */
315 dissect_m2tp_user_identifier_parameter (tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
317 guint32 parameter_value
;
319 if (parameter_tree
) {
320 parameter_value
= tvb_get_ntohl(parameter_tvb
, PARAMETER_VALUE_OFFSET
);
321 proto_tree_add_uint(parameter_tree
, hf_m2tp_user
, parameter_tvb
, M2TP_USER_OFFSET
, M2TP_USER_LENGTH
, parameter_value
);
322 proto_item_set_text(parameter_item
, "M2TP User Identifier (%u)", parameter_value
);
328 dissect_m2tp_info_parameter(tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
330 guint16 length
, info_string_length
;
331 const char *info_string
;
333 if (parameter_tree
) {
334 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
335 info_string_length
= length
- PARAMETER_HEADER_LENGTH
;
336 info_string
= tvb_get_string(wmem_packet_scope(), parameter_tvb
, INFO_STRING_OFFSET
, info_string_length
);
337 proto_tree_add_string(parameter_tree
, hf_m2tp_info_string
, parameter_tvb
, INFO_STRING_OFFSET
, info_string_length
, info_string
);
338 proto_item_set_text(parameter_item
, "Info String (%.*s)", info_string_length
, info_string
);
342 /* Diagnostic Information */
344 dissect_m2tp_diagnostic_information_parameter(tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
346 guint16 length
, diagnostic_info_length
;
348 if (parameter_tree
) {
349 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
350 diagnostic_info_length
= length
- PARAMETER_HEADER_LENGTH
;
351 proto_tree_add_item(parameter_tree
, hf_m2tp_diagnostic_info
, parameter_tvb
, PARAMETER_VALUE_OFFSET
, diagnostic_info_length
, ENC_NA
);
352 proto_item_set_text(parameter_item
, "Diagnostic information (%u byte%s)", diagnostic_info_length
, plurality(diagnostic_info_length
, "", "s"));
358 dissect_m2tp_heartbeat_data_parameter(tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
360 guint16 length
, heartbeat_data_length
;
362 if (parameter_tree
) {
363 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
364 heartbeat_data_length
= length
- PARAMETER_HEADER_LENGTH
;
365 proto_tree_add_item(parameter_tree
, hf_m2tp_heartbeat_data
, parameter_tvb
, PARAMETER_VALUE_OFFSET
, heartbeat_data_length
, ENC_NA
);
366 proto_item_set_text(parameter_item
, "Heartbeat data (%u byte%s)", heartbeat_data_length
, plurality(heartbeat_data_length
, "", "s"));
370 /* Reason Parameter */
372 dissect_m2tp_reason_parameter(tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
376 if (parameter_tree
) {
377 reason
= tvb_get_ntohl(parameter_tvb
, REASON_OFFSET
);
378 proto_tree_add_uint(parameter_tree
, hf_m2tp_reason
, parameter_tvb
, REASON_OFFSET
, REASON_LENGTH
, reason
);
379 proto_item_set_text(parameter_item
, "Reason parameter (%s)", val_to_str_const(reason
, m2tp_reason_code_values
, "unknown"));
385 dissect_m2tp_error_code_parameter(tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
389 if (parameter_tree
) {
390 error_code
= tvb_get_ntohl(parameter_tvb
, ERROR_CODE_OFFSET
);
391 proto_tree_add_uint(parameter_tree
, hf_m2tp_error_code
, parameter_tvb
, ERROR_CODE_OFFSET
, ERROR_CODE_LENGTH
, error_code
);
392 proto_item_set_text(parameter_item
, "Error code parameter (%s)", val_to_str_const(error_code
, m2tp_error_code_values
, "unknown"));
398 dissect_m2tp_protocol_data_parameter(tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
, packet_info
*pinfo
, proto_item
*m2tp_item
, proto_tree
*tree
)
400 guint16 length
, protocol_data_length
, padding_length
;
403 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
404 padding_length
= nr_of_padding_bytes(length
);
405 protocol_data_length
= length
- PARAMETER_HEADER_LENGTH
;
407 mtp2_tvb
= tvb_new_subset(parameter_tvb
, PARAMETER_VALUE_OFFSET
, protocol_data_length
, protocol_data_length
);
408 call_dissector(mtp2_handle
, mtp2_tvb
, pinfo
, tree
);
410 if (parameter_tree
) {
411 proto_item_set_text(parameter_item
, "Protocol data (SS7 message)");
412 proto_item_set_len(parameter_item
, proto_item_get_len(parameter_item
) - protocol_data_length
- padding_length
);
413 proto_item_set_len(m2tp_item
, proto_item_get_len(m2tp_item
) - protocol_data_length
- padding_length
);
418 /* Unknown Parameter */
420 dissect_m2tp_unknown_parameter(tvbuff_t
*parameter_tvb
, proto_tree
*parameter_tree
, proto_item
*parameter_item
)
422 guint16 tag
, length
, parameter_value_length
;
424 if (parameter_tree
) {
425 tag
= tvb_get_ntohs(parameter_tvb
, PARAMETER_TAG_OFFSET
);
426 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
428 parameter_value_length
= length
- PARAMETER_HEADER_LENGTH
;
429 proto_tree_add_item(parameter_tree
, hf_m2tp_parameter_value
, parameter_tvb
, PARAMETER_VALUE_OFFSET
, parameter_value_length
, ENC_NA
);
431 proto_item_set_text(parameter_item
, "Parameter with tag %u and %u byte%s value", tag
, parameter_value_length
, plurality(parameter_value_length
, "", "s"));
437 dissect_m2tp_parameter(tvbuff_t
*parameter_tvb
, packet_info
*pinfo
, proto_tree
*m2tp_tree
, proto_item
*m2tp_item
, proto_tree
*tree
)
439 guint16 tag
, length
, padding_length
, total_length
;
440 proto_item
*parameter_item
= NULL
;
441 proto_tree
*parameter_tree
= NULL
;
443 /* extract tag and length from the parameter */
444 tag
= tvb_get_ntohs(parameter_tvb
, PARAMETER_TAG_OFFSET
);
445 length
= tvb_get_ntohs(parameter_tvb
, PARAMETER_LENGTH_OFFSET
);
447 /* calculate padding and total length */
448 padding_length
= nr_of_padding_bytes(length
);
449 total_length
= length
+ padding_length
;
452 /* create proto_tree stuff */
453 parameter_item
= proto_tree_add_text(m2tp_tree
, parameter_tvb
, PARAMETER_HEADER_OFFSET
, total_length
, "Incomplete parameter");
454 parameter_tree
= proto_item_add_subtree(parameter_item
, ett_m2tp_parameter
);
456 /* add tag and length to the m2tp tree */
457 proto_tree_add_uint(parameter_tree
, hf_m2tp_parameter_tag
, parameter_tvb
, PARAMETER_TAG_OFFSET
, PARAMETER_TAG_LENGTH
, tag
);
458 proto_tree_add_uint(parameter_tree
, hf_m2tp_parameter_length
, parameter_tvb
, PARAMETER_LENGTH_OFFSET
, PARAMETER_LENGTH_LENGTH
, length
);
462 case INTERFACE_IDENTIFIER_PARAMETER_TAG
:
463 dissect_m2tp_interface_identifier_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
465 case MASTER_SLAVE_INDICATOR_PARAMETER_TAG
:
466 dissect_m2tp_master_slave_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
468 case M2TP_USER_IDENTIFIER_PARAMETER_TAG
:
469 dissect_m2tp_user_identifier_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
471 case INFO_PARAMETER_TAG
:
472 dissect_m2tp_info_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
474 case DIAGNOSTIC_INFORMATION_PARAMETER_TAG
:
475 dissect_m2tp_diagnostic_information_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
477 case HEARTBEAT_DATA_PARAMETER_TAG
:
478 dissect_m2tp_heartbeat_data_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
480 case REASON_PARAMETER_TAG
:
481 dissect_m2tp_reason_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
483 case ERROR_CODE_PARAMETER_TAG
:
484 dissect_m2tp_error_code_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
486 case PROTOCOL_DATA_PARAMETER_TAG
:
487 dissect_m2tp_protocol_data_parameter(parameter_tvb
, parameter_tree
, parameter_item
, pinfo
, m2tp_item
, tree
);
490 dissect_m2tp_unknown_parameter(parameter_tvb
, parameter_tree
, parameter_item
);
494 if ((parameter_tree
) && (padding_length
> 0))
495 proto_tree_add_item(parameter_tree
, hf_m2tp_parameter_padding
, parameter_tvb
, PARAMETER_HEADER_OFFSET
+ length
, padding_length
, ENC_NA
);
500 dissect_m2tp_message(tvbuff_t
*message_tvb
, packet_info
*pinfo
, proto_item
*m2tp_item
, proto_tree
*m2tp_tree
, proto_tree
*tree
)
502 gint offset
, length
, padding_length
, total_length
;
503 tvbuff_t
*common_header_tvb
, *parameter_tvb
;
507 /* extract and process the common header */
508 common_header_tvb
= tvb_new_subset(message_tvb
, offset
, COMMON_HEADER_LENGTH
, COMMON_HEADER_LENGTH
);
509 dissect_m2tp_common_header(common_header_tvb
, pinfo
, m2tp_tree
);
510 offset
+= COMMON_HEADER_LENGTH
;
512 /* extract zero or more parameters and process them individually */
513 while(tvb_reported_length_remaining(message_tvb
, offset
) > 0) {
514 length
= tvb_get_ntohs(message_tvb
, offset
+ PARAMETER_LENGTH_OFFSET
);
515 padding_length
= nr_of_padding_bytes(length
);
516 total_length
= length
+ padding_length
;
517 /* create a tvb for the parameter including the padding bytes */
518 parameter_tvb
= tvb_new_subset(message_tvb
, offset
, total_length
, total_length
);
519 dissect_m2tp_parameter(parameter_tvb
, pinfo
, m2tp_tree
, m2tp_item
, tree
);
520 /* get rid of the handled parameter */
521 offset
+= total_length
;
527 dissect_m2tp(tvbuff_t
*message_tvb
, packet_info
*pinfo
, proto_tree
*tree
)
529 proto_item
*m2tp_item
;
530 proto_tree
*m2tp_tree
;
532 /* make entry in the Protocol column on summary display */
533 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "M2TP");
535 /* In the interest of speed, if "tree" is NULL, don't do any work not
536 necessary to generate protocol tree items. */
538 /* create the m2tp protocol tree */
539 m2tp_item
= proto_tree_add_item(tree
, proto_m2tp
, message_tvb
, 0, -1, ENC_NA
);
540 m2tp_tree
= proto_item_add_subtree(m2tp_item
, ett_m2tp
);
545 /* dissect the message */
546 dissect_m2tp_message(message_tvb
, pinfo
, m2tp_item
, m2tp_tree
, tree
);
549 /* Register the protocol with Wireshark */
551 proto_register_m2tp(void)
554 /* Setup list of header fields */
555 static hf_register_info hf
[] = {
557 { "Version", "m2tp.version",
558 FT_UINT8
, BASE_DEC
, VALS(m2tp_protocol_version_values
), 0x0,
562 { "Reserved", "m2tp.reserved",
563 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
566 { &hf_m2tp_message_class
,
567 { "Message class", "m2tp.message_class",
568 FT_UINT8
, BASE_DEC
, VALS(m2tp_message_class_values
), 0x0,
571 { &hf_m2tp_message_type
,
572 { "Message Type", "m2tp.message_type",
573 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
576 { &hf_m2tp_message_length
,
577 { "Message length", "m2tp.message_length",
578 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
581 { &hf_m2tp_parameter_tag
,
582 { "Parameter Tag", "m2tp.parameter_tag",
583 FT_UINT16
, BASE_DEC
, VALS(m2tp_parameter_tag_values
), 0x0,
586 { &hf_m2tp_parameter_length
,
587 { "Parameter length", "m2tp.parameter_length",
588 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
591 { &hf_m2tp_parameter_value
,
592 { "Parameter Value", "m2tp.parameter_value",
593 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
596 { &hf_m2tp_parameter_padding
,
597 { "Padding", "m2tp.parameter_padding",
598 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
601 { &hf_m2tp_interface_identifier
,
602 { "Interface Identifier", "m2tp.interface_identifier",
603 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
607 { "M2tp User Identifier", "m2tp.user_identifier",
608 FT_UINT32
, BASE_DEC
, VALS(m2tp_user_identifier_values
), 0x0,
611 { &hf_m2tp_master_slave
,
612 { "Master Slave Indicator", "m2tp.master_slave",
613 FT_UINT32
, BASE_DEC
, VALS(m2tp_mode_values
), 0x0,
616 { &hf_m2tp_info_string
,
617 { "Info string", "m2tp.info_string",
618 FT_STRING
, BASE_NONE
, NULL
, 0x0,
621 { &hf_m2tp_diagnostic_info
,
622 { "Diagnostic information", "m2tp.diagnostic_info",
623 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
626 { &hf_m2tp_heartbeat_data
,
627 { "Heartbeat data", "m2tp.heartbeat_data",
628 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
631 { &hf_m2tp_error_code
,
632 { "Error code", "m2tp.error_code",
633 FT_UINT32
, BASE_DEC
, VALS(m2tp_error_code_values
), 0x0,
637 { "Reason", "m2tp.reason",
638 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
643 /* Setup protocol subtree array */
644 static gint
*ett
[] = {
649 /* Register the protocol name and description */
650 proto_m2tp
= proto_register_protocol("MTP 2 Transparent Proxy", "M2TP", "m2tp");
652 /* Required function calls to register the header fields and subtrees used */
653 proto_register_field_array(proto_m2tp
, hf
, array_length(hf
));
654 proto_register_subtree_array(ett
, array_length(ett
));
658 proto_reg_handoff_m2tp(void)
660 dissector_handle_t m2tp_handle
;
661 mtp2_handle
= find_dissector("mtp2");
662 m2tp_handle
= create_dissector_handle(dissect_m2tp
, proto_m2tp
);
663 dissector_add_uint("sctp.ppi", M2TP_PAYLOAD_PROTOCOL_ID
, m2tp_handle
);
664 dissector_add_uint("sctp.port", SCTP_PORT_M2TP
, m2tp_handle
);