2 * Routines for MTP2 Peer Adaptation Layer dissection
3 * It is hopefully (needs testing) compliant to
4 * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-m2pa-02.txt
6 * Copyright 2001, Jeff Morriss <jeff.morriss[AT]ulticom.com>
8 * $Id: packet-m2pa.c,v 1.1 2001/06/21 22:25:51 guy Exp $
10 * Ethereal - Network traffic analyzer
11 * By Gerald Combs <gerald@ethereal.com>
12 * Copyright 1998 Gerald Combs
14 * Copied from packet-m3ua.c
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
43 #ifdef HAVE_NETINET_IN_H
44 # include <netinet/in.h>
50 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
57 /* Warning: Neither of these are standardized yet! */
58 #define SCTP_PORT_M2PA 2904
59 #define M2PA_PAYLOAD_PROTOCOL_ID 5
61 #define VERSION_LENGTH 1
62 #define SPARE_LENGTH 1
63 #define MESSAGE_TYPE_LENGTH 2
64 #define MESSAGE_LENGTH_LENGTH 4
65 #define COMMON_HEADER_LENGTH (VERSION_LENGTH + SPARE_LENGTH + \
66 MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
68 #define VERSION_OFFSET 0
69 #define SPARE_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
70 #define MESSAGE_TYPE_OFFSET (SPARE_OFFSET + SPARE_LENGTH)
71 #define MESSAGE_LENGTH_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
74 #define PROTOCOL_VERSION_RELEASE_1 1
75 static const value_string m2pa_protocol_version_values[] = {
76 { PROTOCOL_VERSION_RELEASE_1, "Release 1" },
80 #define MESSAGE_TYPE_USER_DATA 0x0601
81 #define MESSAGE_TYPE_LINK_STATUS 0x0602
82 static const value_string m2pa_message_type_values[] = {
83 { MESSAGE_TYPE_USER_DATA, "User Data" },
84 { MESSAGE_TYPE_LINK_STATUS, "Link Status" },
88 /* parts of User Data message */
91 #define USER_OFFSET (LI_OFFSET + LI_LENGTH)
93 /* LI is only used for (ITU national) priority in M2PA */
94 #define LI_SPARE_MASK 0xfc
95 #define LI_PRIORITY_MASK 0x3
98 /* parts of Link Status message */
99 #define STATUS_LENGTH 4
100 #define STATUS_OFFSET 0
105 #define STATUS_BUSY 4
106 #define STATUS_BUSY_E 5
107 static const value_string m2pa_link_status_values[] = {
108 { STATUS_IS, "In Service" },
109 { STATUS_PO, "Processor Outage" },
110 { STATUS_POE, "Processor Outage Ended" },
111 { STATUS_BUSY, "Busy" },
112 { STATUS_BUSY_E, "Busy Ended" },
116 /* Initialize the protocol and registered fields */
117 static int proto_m2pa = -1;
118 static int hf_m2pa_version = -1;
119 static int hf_m2pa_spare = -1;
120 static int hf_m2pa_message_type = -1;
121 static int hf_m2pa_message_length = -1;
122 static int hf_m2pa_ls_status = -1;
123 static int hf_m2pa_data_li = -1;
124 static int hf_m2pa_data_li_spare = -1;
125 static int hf_m2pa_data_li_prio = -1;
127 /* Initialize the subtree pointers */
128 static gint ett_m2pa = -1;
129 static gint ett_m2pa_message_ud = -1;
130 static gint ett_m2pa_message_ud_li = -1;
131 static gint ett_m2pa_message_ls = -1;
133 static dissector_handle_t mtp3_handle;
136 dissect_m2pa_unknown_message(tvbuff_t *message_tvb, packet_info *pinfo,
137 proto_tree *m2pa_tree, guint32 message_length,
138 guint16 message_type)
141 if (check_col(pinfo->fd, COL_INFO)) {
142 col_set_str(pinfo->fd, COL_INFO,
143 val_to_str(message_type, m2pa_message_type_values, "Unknown"));
147 proto_tree_add_text(m2pa_tree, message_tvb, 0, message_length,
148 "Unknown message (%u byte%s)",
149 message_length, plurality(message_length, "", "s"));
156 dissect_m2pa_link_status_message(tvbuff_t *message_tvb, packet_info *pinfo,
157 proto_tree *m2pa_tree, guint16 message_type)
160 proto_item *m2pa_ls_item;
161 proto_tree *m2pa_ls_tree;
163 status = tvb_get_ntohl (message_tvb, STATUS_OFFSET);
165 if (check_col(pinfo->fd, COL_INFO)) {
166 col_set_str(pinfo->fd, COL_INFO,
167 val_to_str(message_type, m2pa_message_type_values, "unknown"));
169 col_append_str(pinfo->fd, COL_INFO, " (");
170 col_append_str(pinfo->fd, COL_INFO,
171 val_to_str(status, m2pa_link_status_values, "unknown"));
172 col_append_str(pinfo->fd, COL_INFO, ")");
176 /* create the link status message tree */
177 m2pa_ls_item = proto_tree_add_text(m2pa_tree, message_tvb, 0,
179 val_to_str(message_type,
180 m2pa_message_type_values,
182 m2pa_ls_tree = proto_item_add_subtree(m2pa_ls_item, ett_m2pa_message_ls);
184 /* add the components of the link status message to the protocol tree */
185 proto_tree_add_uint(m2pa_ls_tree, hf_m2pa_ls_status,
186 message_tvb, STATUS_OFFSET,
187 STATUS_LENGTH, status);
194 dissect_m2pa_user_data_message(tvbuff_t *message_tvb, packet_info *pinfo,
195 proto_item *m2pa_item, proto_tree *m2pa_tree,
196 guint32 message_length, proto_tree *tree,
197 guint16 message_type)
199 proto_item *m2pa_ud_item;
200 proto_tree *m2pa_ud_tree;
201 proto_item *m2pa_ud_li_item;
202 proto_tree *m2pa_ud_li_tree;
203 tvbuff_t *payload_tvb;
205 guint32 payload_length;
207 li = tvb_get_guint8(message_tvb, LI_OFFSET);
208 payload_length = message_length - LI_LENGTH;
211 /* create the user data message tree */
212 m2pa_ud_item = proto_tree_add_item(m2pa_tree, proto_m2pa, message_tvb, 0,
213 tvb_length(message_tvb), FALSE);
214 m2pa_ud_tree = proto_item_add_subtree(m2pa_ud_item, ett_m2pa_message_ud);
216 /* add the components of the user data message to the protocol tree */
218 m2pa_ud_li_item = proto_tree_add_uint(m2pa_ud_tree, hf_m2pa_data_li,
219 message_tvb, LI_OFFSET, LI_LENGTH,
221 m2pa_ud_li_tree = proto_item_add_subtree(m2pa_ud_li_item,
222 ett_m2pa_message_ud_li);
223 proto_tree_add_uint(m2pa_ud_li_tree, hf_m2pa_data_li_spare, message_tvb,
224 LI_OFFSET, LI_LENGTH, li);
225 proto_tree_add_uint(m2pa_ud_li_tree, hf_m2pa_data_li_prio, message_tvb,
226 LI_OFFSET, LI_LENGTH, li);
228 proto_item_set_text(m2pa_ud_item, "Protocol data (SS7 message of %u byte%s)",
229 payload_length, plurality(payload_length, "", "s"));
231 /* Re-adjust length of M2PA item since it will be dissected as MTP3 */
232 proto_item_set_len(m2pa_item, COMMON_HEADER_LENGTH + LI_LENGTH);
236 payload_tvb = tvb_new_subset(message_tvb, USER_OFFSET, payload_length,
238 call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
243 dissect_m2pa_message(tvbuff_t *tvb, packet_info *pinfo, proto_item *m2pa_item,
244 proto_tree *m2pa_tree, proto_tree *tree)
246 guint8 version, spare;
247 guint16 message_type;
248 guint32 message_length;
249 tvbuff_t *message_tvb;
251 /* Extract the common header */
252 version = tvb_get_guint8(tvb, VERSION_OFFSET);
253 spare = tvb_get_guint8(tvb, SPARE_OFFSET);
254 message_type = tvb_get_ntohs(tvb, MESSAGE_TYPE_OFFSET);
255 message_length = tvb_get_ntohl(tvb, MESSAGE_LENGTH_OFFSET);
258 /* add the components of the common header to the protocol tree */
259 proto_tree_add_uint(m2pa_tree, hf_m2pa_version, tvb, VERSION_OFFSET,
260 VERSION_LENGTH, version);
261 proto_tree_add_uint(m2pa_tree, hf_m2pa_spare,
262 tvb, SPARE_OFFSET, SPARE_LENGTH,
264 proto_tree_add_uint(m2pa_tree, hf_m2pa_message_type, tvb,
265 MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH,
267 proto_tree_add_uint(m2pa_tree, hf_m2pa_message_length,
268 tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH,
272 /* create a tvb for the message */
273 message_tvb = tvb_new_subset(tvb, COMMON_HEADER_LENGTH, message_length,
276 switch(message_type) {
277 case MESSAGE_TYPE_USER_DATA:
278 dissect_m2pa_user_data_message(message_tvb, pinfo, m2pa_item, m2pa_tree,
279 message_length, tree, message_type);
282 case MESSAGE_TYPE_LINK_STATUS:
283 dissect_m2pa_link_status_message(message_tvb, pinfo, m2pa_tree,
288 dissect_m2pa_unknown_message(message_tvb, pinfo, m2pa_tree,
289 message_length, message_type);
295 dissect_m2pa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
297 proto_item *m2pa_item;
298 proto_tree *m2pa_tree;
300 /* make entry in the Protocol column on summary display */
301 if (check_col(pinfo->fd, COL_PROTOCOL))
302 col_set_str(pinfo->fd, COL_PROTOCOL, "M2PA");
304 /* Clear entries in Info column on summary display */
305 if (check_col(pinfo->fd, COL_INFO))
306 col_clear(pinfo->fd, COL_INFO);
308 /* In the interest of speed, if "tree" is NULL, don't do any work not
309 necessary to generate protocol tree items. */
311 /* create the m2pa protocol tree */
312 m2pa_item = proto_tree_add_item(tree, proto_m2pa, tvb, 0,
313 COMMON_HEADER_LENGTH, FALSE);
314 m2pa_tree = proto_item_add_subtree(m2pa_item, ett_m2pa);
320 /* dissect the message */
321 dissect_m2pa_message(tvb, pinfo, m2pa_item, m2pa_tree, tree);
324 /* Register the protocol with Ethereal */
326 proto_register_m2pa(void)
329 /* Setup list of header fields */
330 static hf_register_info hf[] = {
332 { "Version", "m2pa.version",
333 FT_UINT8, BASE_DEC, VALS(m2pa_protocol_version_values), 0x0,
337 { "Spare", "m2pa.spare",
338 FT_UINT8, BASE_HEX, NULL, 0x0,
341 { &hf_m2pa_message_type,
342 { "Message Type", "m2pa.message_type",
343 FT_UINT16, BASE_HEX, VALS(m2pa_message_type_values), 0x0,
346 { &hf_m2pa_message_length,
347 { "Message length", "m2pa.message_length",
348 FT_UINT32, BASE_DEC, NULL, 0x0,
351 { &hf_m2pa_ls_status,
352 { "Link Status Status", "m2pa.status",
353 FT_UINT32, BASE_DEC, VALS(m2pa_link_status_values), 0x0,
357 { "Length Indicator", "m2pa.li",
358 FT_UINT8, BASE_HEX, NULL, 0x0,
361 { &hf_m2pa_data_li_spare,
362 { "Spare", "m2pa.li.spare",
363 FT_UINT8, BASE_HEX, NULL, LI_SPARE_MASK,
366 { &hf_m2pa_data_li_prio,
367 { "Priority", "m2pa.li.prio",
368 FT_UINT8, BASE_HEX, NULL, LI_PRIORITY_MASK,
373 /* Setup protocol subtree array */
374 static gint *ett[] = {
376 &ett_m2pa_message_ud,
377 &ett_m2pa_message_ud_li,
381 /* Register the protocol name and description */
382 proto_m2pa = proto_register_protocol("MTP2 Peer Adaptation Layer",
385 /* Required function calls to register the header fields and subtrees used */
386 proto_register_field_array(proto_m2pa, hf, array_length(hf));
387 proto_register_subtree_array(ett, array_length(ett));
392 proto_reg_handoff_m2pa(void)
395 * Get a handle for the MTP3 dissector.
397 mtp3_handle = find_dissector("mtp3");
399 dissector_add("sctp.ppi", M2PA_PAYLOAD_PROTOCOL_ID,
400 dissect_m2pa, proto_m2pa);
401 dissector_add("sctp.port", SCTP_PORT_M2PA, dissect_m2pa, proto_m2pa);