Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-m2tp.c
blob59814f71a4857255bdfcd64bc4b99cb0fd8f7ce2
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
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
18 #include "config.h"
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" },
77 { 0, NULL } };
79 #define PROTOCOL_VERSION_RELEASE_1 1
81 static const value_string m2tp_protocol_version_values[] = {
82 { PROTOCOL_VERSION_RELEASE_1, "Release 1" },
83 { 0, NULL } };
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" },
95 { 0, NULL } };
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)" },
121 { 0, NULL } };
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 } };
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" },
170 { 0, NULL }};
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" },
178 { 0, NULL}};
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" },
200 { 0, NULL } };
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" },
208 { 0, NULL } };
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 */
232 static int ett_m2tp;
233 static int ett_m2tp_parameter;
235 static dissector_handle_t mtp2_handle;
237 static unsigned
238 nr_of_padding_bytes (unsigned length)
240 unsigned remainder;
242 remainder = length % 4;
244 if (remainder == 0)
245 return 0;
246 else
247 return 4 - remainder;
250 /* Common Header */
251 static void
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"));
266 if (m2tp_tree) {
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 */
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)
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 */
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)
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 */
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)
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);
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)
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 */
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)
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"));
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)
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 */
362 static void
363 dissect_m2tp_reason_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo _U_, proto_tree *parameter_tree, proto_item *parameter_item)
365 uint32_t reason;
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"));
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)
378 uint32_t error_code;
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"));
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)
391 uint16_t length, protocol_data_length, padding_length;
392 tvbuff_t *mtp2_tvb;
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 */
410 static void
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"));
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)
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;
442 if (tree) {
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, &parameter_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);
452 switch(tag) {
453 case INTERFACE_IDENTIFIER_PARAMETER_TAG:
454 dissect_m2tp_interface_identifier_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
455 break;
456 case MASTER_SLAVE_INDICATOR_PARAMETER_TAG:
457 dissect_m2tp_master_slave_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
458 break;
459 case M2TP_USER_IDENTIFIER_PARAMETER_TAG:
460 dissect_m2tp_user_identifier_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
461 break;
462 case INFO_PARAMETER_TAG:
463 dissect_m2tp_info_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
464 break;
465 case DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
466 dissect_m2tp_diagnostic_information_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
467 break;
468 case HEARTBEAT_DATA_PARAMETER_TAG:
469 dissect_m2tp_heartbeat_data_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
470 break;
471 case REASON_PARAMETER_TAG:
472 dissect_m2tp_reason_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
473 break;
474 case ERROR_CODE_PARAMETER_TAG:
475 dissect_m2tp_error_code_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
476 break;
477 case PROTOCOL_DATA_PARAMETER_TAG:
478 dissect_m2tp_protocol_data_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item, m2tp_item, tree);
479 break;
480 default:
481 dissect_m2tp_unknown_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
482 break;
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);
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)
493 int offset, length, padding_length, total_length;
494 tvbuff_t *common_header_tvb, *parameter_tvb;
496 offset = 0;
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;
516 /* M2tp */
517 static int
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 */
536 void
537 proto_register_m2tp(void)
540 /* Setup list of header fields */
541 static hf_register_info hf[] = {
542 { &hf_m2tp_version,
543 { "Version", "m2tp.version",
544 FT_UINT8, BASE_DEC, VALS(m2tp_protocol_version_values), 0x0,
545 NULL, HFILL}
547 { &hf_m2tp_reserved,
548 { "Reserved", "m2tp.reserved",
549 FT_UINT8, BASE_HEX, NULL, 0x0,
550 NULL, HFILL}
552 { &hf_m2tp_message_class,
553 { "Message class", "m2tp.message_class",
554 FT_UINT8, BASE_DEC, VALS(m2tp_message_class_values), 0x0,
555 NULL, HFILL}
557 { &hf_m2tp_message_type,
558 { "Message Type", "m2tp.message_type",
559 FT_UINT8, BASE_DEC, NULL, 0x0,
560 NULL, HFILL}
562 { &hf_m2tp_message_length,
563 { "Message length", "m2tp.message_length",
564 FT_UINT32, BASE_DEC, NULL, 0x0,
565 NULL, HFILL}
567 { &hf_m2tp_parameter_tag,
568 { "Parameter Tag", "m2tp.parameter_tag",
569 FT_UINT16, BASE_DEC, VALS(m2tp_parameter_tag_values), 0x0,
570 NULL, HFILL}
572 { &hf_m2tp_parameter_length,
573 { "Parameter length", "m2tp.parameter_length",
574 FT_UINT16, BASE_DEC, NULL, 0x0,
575 NULL, HFILL}
577 { &hf_m2tp_parameter_value,
578 { "Parameter Value", "m2tp.parameter_value",
579 FT_BYTES, BASE_NONE, NULL, 0x0,
580 NULL, HFILL }
582 { &hf_m2tp_parameter_padding,
583 { "Padding", "m2tp.parameter_padding",
584 FT_BYTES, BASE_NONE, NULL, 0x0,
585 NULL, HFILL }
587 { &hf_m2tp_interface_identifier,
588 { "Interface Identifier", "m2tp.interface_identifier",
589 FT_UINT32, BASE_DEC, NULL, 0x0,
590 NULL, HFILL}
592 { &hf_m2tp_user,
593 { "M2tp User Identifier", "m2tp.user_identifier",
594 FT_UINT32, BASE_DEC, VALS(m2tp_user_identifier_values), 0x0,
595 NULL, HFILL}
597 { &hf_m2tp_master_slave,
598 { "Master Slave Indicator", "m2tp.master_slave",
599 FT_UINT32, BASE_DEC, VALS(m2tp_mode_values), 0x0,
600 NULL, HFILL}
602 { &hf_m2tp_info_string,
603 { "Info string", "m2tp.info_string",
604 FT_STRING, BASE_NONE, NULL, 0x0,
605 NULL, HFILL}
607 { &hf_m2tp_diagnostic_info,
608 { "Diagnostic information", "m2tp.diagnostic_info",
609 FT_BYTES, BASE_NONE, NULL, 0x0,
610 NULL, HFILL }
612 { &hf_m2tp_heartbeat_data,
613 { "Heartbeat data", "m2tp.heartbeat_data",
614 FT_BYTES, BASE_NONE, NULL, 0x0,
615 NULL, HFILL }
617 { &hf_m2tp_error_code,
618 { "Error code", "m2tp.error_code",
619 FT_UINT32, BASE_DEC, VALS(m2tp_error_code_values), 0x0,
620 NULL, HFILL}
622 { &hf_m2tp_reason,
623 { "Reason", "m2tp.reason",
624 FT_UINT32, BASE_DEC, NULL, 0x0,
625 NULL, HFILL}
629 /* Setup protocol subtree array */
630 static int *ett[] = {
631 &ett_m2tp,
632 &ett_m2tp_parameter,
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);
646 void
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
657 * Local Variables:
658 * c-basic-offset: 2
659 * tab-width: 8
660 * indent-tabs-mode: nil
661 * End:
663 * ex: set shiftwidth=2 tabstop=8 expandtab:
664 * :indentSize=2:tabSize=8:noTabs=true: