Fix Gerald's e-mail address - and fix it in "README.developer", so
[obnox/wireshark/wip.git] / packet-m3ua.c
1 /* packet-m3ua.c
2  * Routines for MTP3 User Adaptation Layer dissection
3  * It is hopefully (needs testing) compilant to
4  * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-m3ua-05.txt
5  * To do: - clean up the code
6  *        - provide better handling of length parameters
7  *        - provide good information in summary window
8  *
9  * Copyright 2000, Michael Tüxen <Michael.Tuexen@icn.siemens.de>
10  *
11  * $Id: packet-m3ua.c,v 1.5 2001/04/20 20:34:28 guy Exp $
12  *
13  * Ethereal - Network traffic analyzer
14  * By Gerald Combs <gerald@ethereal.com>
15  * Copyright 1998 Gerald Combs
16  *
17  * Copied from README.developer
18  * 
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  * 
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  * 
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40
41
42 #ifdef HAVE_SYS_TYPES_H
43 # include <sys/types.h>
44 #endif
45
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49
50 #include <string.h>
51 #include <glib.h>
52
53 #ifdef NEED_SNPRINTF_H
54 # include "snprintf.h"
55 #endif
56
57 #include "packet.h"
58 #include "packet-ip.h"
59
60
61 #define SCTP_PORT_M3UA 2905
62 #define M3UA_PAYLOAD_PROTO_ID 3
63
64 #define VERSION_LENGTH         1
65 #define RESERVED_LENGTH        1
66 #define MESSAGE_CLASS_LENGTH   1
67 #define MESSAGE_TYPE_LENGTH    1
68 #define MESSAGE_LENGTH_LENGTH  4
69 #define COMMON_HEADER_LENGTH   (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
70                                 MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
71
72 #define VERSION_OFFSET         0
73 #define RESERVED_OFFSET        (VERSION_OFFSET + VERSION_LENGTH)
74 #define MESSAGE_CLASS_OFFSET   (RESERVED_OFFSET + RESERVED_LENGTH)
75 #define MESSAGE_TYPE_OFFSET    (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
76 #define MESSAGE_LENGTH_OFFSET  (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
77
78 #define PARAMETER_TAG_LENGTH    2
79 #define PARAMETER_LENGTH_LENGTH 2
80 #define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
81
82 #define PARAMETER_TAG_OFFSET      0
83 #define PARAMETER_LENGTH_OFFSET   (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
84 #define PARAMETER_VALUE_OFFSET    (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
85 #define PARAMETER_HEADER_OFFSET   PARAMETER_TAG_OFFSET
86
87 #define NETWORK_APPEARANCE_PARAMETER_TAG       1
88 #define PROTOCOL_DATA_PARAMETER_TAG            3
89 #define INFO_PARAMETER_TAG                     4
90 #define AFFECTED_DESTINATIONS_PARAMETER_TAG    5
91 #define ROUTING_CONTEXT_PARAMETER_TAG          6
92 #define DIAGNOSTIC_INFORMATION_PARAMETER_TAG   7
93 #define HEARTBEAT_DATA_PARAMETER_TAG           8
94 #define USER_CAUSE_PARAMETER_TAG               9
95 #define REASON_PARAMETER_TAG                  10
96 #define TRAFFIC_MODE_TYPE_PARAMETER_TAG       11
97 #define ERROR_CODE_PARAMETER_TAG              12
98 #define STATUS_TYPE_PARAMETER_TAG             13
99 #define CONGESTION_INDICATION_PARAMETER_TAG   14
100
101
102 static const value_string m3ua_parameter_tag_values[] = {
103   { NETWORK_APPEARANCE_PARAMETER_TAG,           "Network appearance" },
104   { PROTOCOL_DATA_PARAMETER_TAG,                "Protocol data" },
105   { INFO_PARAMETER_TAG,                         "Info" },
106   { AFFECTED_DESTINATIONS_PARAMETER_TAG,        "Affected destinations" },
107   { ROUTING_CONTEXT_PARAMETER_TAG,              "Routing context" },
108   { DIAGNOSTIC_INFORMATION_PARAMETER_TAG,       "Diagnostic information" },
109   { HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat data" },
110   { USER_CAUSE_PARAMETER_TAG,                   "User / Cause" },
111   { REASON_PARAMETER_TAG,                       "Reason" },
112   { TRAFFIC_MODE_TYPE_PARAMETER_TAG,            "Traffic mode type" },
113   { ERROR_CODE_PARAMETER_TAG,                   "Error code" },
114   { STATUS_TYPE_PARAMETER_TAG,                  "Status type" }, 
115   { CONGESTION_INDICATION_PARAMETER_TAG,        "Congestion Indication" },
116   { 0,                           NULL } };
117
118 #define PROTOCOL_VERSION_RELEASE_1             1
119
120 static const value_string m3ua_protocol_version_values[] = {
121   { PROTOCOL_VERSION_RELEASE_1,  "Release 1" },
122   { 0,                           NULL } };
123
124 #define MESSAGE_CLASS_MGMT_MESSAGE        0
125 #define MESSAGE_CLASS_TFER_MESSAGE        1
126 #define MESSAGE_CLASS_SSNM_MESSAGE        2
127 #define MESSAGE_CLASS_ASPSM_MESSAGE       3
128 #define MESSAGE_CLASS_ASPTM_MESSAGE       4
129
130 static const value_string m3ua_message_class_values[] = {
131   { MESSAGE_CLASS_MGMT_MESSAGE,   "Management messages" },
132   { MESSAGE_CLASS_TFER_MESSAGE,   "Transfer messages" },
133   { MESSAGE_CLASS_SSNM_MESSAGE,   "SS7 signalling network management messages" },
134   { MESSAGE_CLASS_ASPSM_MESSAGE,  "ASP state maintenance messages" },
135   { MESSAGE_CLASS_ASPTM_MESSAGE,  "ASP traffic maintenance messages" },
136   { 0,                           NULL } };
137
138 #define MESSAGE_TYPE_ERR                  0
139 #define MESSAGE_TYPE_NTFY                 1
140
141 #define MESSAGE_TYPE_DATA                 1
142
143 #define MESSAGE_TYPE_DUNA                 1
144 #define MESSAGE_TYPE_DAVA                 2
145 #define MESSAGE_TYPE_DAUD                 3
146 #define MESSAGE_TYPE_SCON                 4
147 #define MESSAGE_TYPE_DUPU                 5
148
149 #define MESSAGE_TYPE_UP                   1
150 #define MESSAGE_TYPE_DOWN                 2
151 #define MESSAGE_TYPE_BEAT                 3
152 #define MESSAGE_TYPE_UP_ACK               4
153 #define MESSAGE_TYPE_DOWN_ACK             5
154 #define MESSAGE_TYPE_BEAT_ACK             6
155
156 #define MESSAGE_TYPE_ACTIVE               1
157 #define MESSAGE_TYPE_INACTIVE             2
158 #define MESSAGE_TYPE_ACTIVE_ACK           3
159 #define MESSAGE_TYPE_INACTIVE_ACK         4
160
161 static const value_string m3ua_message_class_type_values[] = {
162   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "Error (ERR)" },
163   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "Notify (NTFY)" },
164   { MESSAGE_CLASS_TFER_MESSAGE  * 256 + MESSAGE_TYPE_DATA,          "Payload data (DATA)" },
165   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "Destination unavailable (DUNA)" },
166   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "Destination available (DAVA)" },
167   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "Destination state audit (DAUD)" },
168   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SS7 Network congestion state (SCON)" },
169   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "Destination userpart unavailable (DUPU)" },
170   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP up (UP)" },
171   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP down (DOWN)" },
172   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "Heartbeat (BEAT)" },
173   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP up ack (UP ACK)" },
174   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP down ack (DOWN ACK)" },
175   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "Heartbeat ack (BEAT ACK)" },
176   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP active (ACTIVE)" },
177   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP inactive (INACTIVE)" },
178   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP active ack (ACTIVE ACK)" },
179   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (INACTIVE ACK)" },
180   { 0,                           NULL } };
181
182 static const value_string m3ua_message_class_type_acro_values[] = {
183   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "ERR" },
184   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "NTFY" },
185   { MESSAGE_CLASS_TFER_MESSAGE  * 256 + MESSAGE_TYPE_DATA,          "DATA" },
186   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "DUNA" },
187   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "DAVA" },
188   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "DAUD" },
189   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SCON" },
190   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "DUPU" },
191   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP_UP" },
192   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP_DOWN" },
193   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "BEAT" },
194   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP_UP_ACK" },
195   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP_DOWN_ACK" },
196   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "BEAT_ACK" },
197   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP_ACTIVE" },
198   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP_INACTIVE" },
199   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP_ACTIVE_ACK" },
200   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
201   { 0,                           NULL } };
202
203
204
205
206 #define NETWORK_APPEARANCE_LENGTH 4
207 #define NETWORK_APPEARANCE_OFFSET PARAMETER_VALUE_OFFSET
208
209 #define PROTOCOL_DATA_OFFSET PARAMETER_VALUE_OFFSET
210
211 #define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
212
213
214 #define INVALID_VERSION_ERROR_CODE               1
215 #define INVALID_NETWORK_APPEARANCE_ERROR_CODE    2
216 #define UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE      3
217 #define INVALID_MESSAGE_TYPE_ERROR_CODE          4
218 #define INVALID_TRAFFIC_HANDLING_MODE_ERROR_CODE 5
219 #define UNEXPECTED_MESSAGE_ERROR_CODE            6
220 #define PROTOCOL_ERROR_ERROR_CODE                7
221 #define INVALID_ROUTING_CONTEXT_ERROR_CODE       8
222
223 static const value_string m3ua_error_code_values[] = {
224   { INVALID_VERSION_ERROR_CODE,               "Invalid version" },
225   { INVALID_NETWORK_APPEARANCE_ERROR_CODE,    "Invalid network appearance" },
226   { UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE,      "Unsupported message type" },
227   { INVALID_MESSAGE_TYPE_ERROR_CODE,          "Invalid message type" },
228   { INVALID_TRAFFIC_HANDLING_MODE_ERROR_CODE, "Invalid traffic handling mode" },
229   { UNEXPECTED_MESSAGE_ERROR_CODE,            "Unexpected message" },
230   { PROTOCOL_ERROR_ERROR_CODE,                "Protocol error" },
231   { INVALID_ROUTING_CONTEXT_ERROR_CODE,       "Invalid routing contexted" },
232   { 0,                           NULL } };
233
234 #define ERROR_CODE_LENGTH 4
235 #define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
236
237 #define AS_STATE_CHANGE_TYPE       1
238 #define OTHER_TYPE                 2
239
240 static const value_string m3ua_status_type_values[] = {
241   { AS_STATE_CHANGE_TYPE,            "Application server state change" },
242   { OTHER_TYPE,                      "Other" },
243   { 0,                           NULL } };
244
245 #define RESERVED_INFO              1
246 #define AS_INACTIVE_INFO           2
247 #define AS_ACTIVE_INFO             3
248 #define AS_PENDING_INFO            4
249
250 #define INSUFFICIENT_ASP_RES_INFO  1
251 #define ALTERNATE_ASP_ACTIVE_INFO  2
252
253 static const value_string m3ua_status_type_info_values[] = {
254   { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO,             "Reserved" },
255   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO,          "Application server inactive" },
256   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO,            "Application server active" },
257   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO,           "Application server pending" },
258   { OTHER_TYPE           * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
259   { OTHER_TYPE           * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
260   {0,                           NULL } };
261
262 #define STATUS_TYPE_LENGTH 2
263 #define STATUS_INFO_LENGTH 2
264
265 #define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
266 #define STATUS_INFO_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
267
268 #define UNKNOWN_UNAVAIL_CAUSE                  0
269 #define UNEQUIPPED_REMOTE_USER_UNAVAIL_CAUSE   1
270 #define INACCESSABLE_REMOTE_USER_UNAVAIL_CAUSE 2
271
272 static const value_string m3ua_unavailability_cause_values[] = {
273   { UNKNOWN_UNAVAIL_CAUSE,                             "Unknown" },
274   { UNEQUIPPED_REMOTE_USER_UNAVAIL_CAUSE,              "Unequipped remote user" },
275   { INACCESSABLE_REMOTE_USER_UNAVAIL_CAUSE,            "Inaccessable remote user" },
276   {0,                           NULL } };
277
278 #define RESERVED_0_USER_ID                0
279 #define RESERVED_1_USER_ID                1
280 #define RESERVED_2_USER_ID                2
281 #define SCCP_USER_ID                      3
282 #define TUP_USER_ID                       4
283 #define ISUP_USER_ID                      5
284 #define RESERVED_6_USER_ID                6
285 #define RESERVED_7_USER_ID                7
286 #define RESERVED_8_USER_ID                8
287 #define BROADBAND_ISUP_USER_ID            9
288 #define SATELLITE_ISUP_USER_ID           10
289
290 static const value_string m3ua_user_identity_values[] = {
291   { RESERVED_0_USER_ID,                             "Reserved" },
292   { RESERVED_1_USER_ID,                             "Reserved" },
293   { RESERVED_2_USER_ID,                             "Reserved" },
294   { SCCP_USER_ID,                                   "SCCP" },
295   { TUP_USER_ID,                                    "TUP" },
296   { ISUP_USER_ID,                                   "ISUP" },
297   { RESERVED_6_USER_ID,                             "Reserved" },
298   { RESERVED_7_USER_ID,                             "Reserved" },
299   { RESERVED_8_USER_ID,                             "Reserved" },
300   { BROADBAND_ISUP_USER_ID,                         "Broadband ISUP" },
301   { SATELLITE_ISUP_USER_ID,                         "Satellite ISUP" },
302   {0,                           NULL } };
303
304 #define CAUSE_LENGTH 2
305 #define USER_LENGTH  2
306
307 #define CAUSE_OFFSET  PARAMETER_VALUE_OFFSET
308 #define USER_OFFSET   (CAUSE_OFFSET + CAUSE_LENGTH)
309
310 #define UNSPECIFIED_REASON          0
311 #define USER_UNAVAILABLE_REASON     1
312 #define MANAGEMENT_BLOCKING_REASON  2
313
314 static const value_string m3ua_reason_values[] = {
315   { UNSPECIFIED_REASON,                             "Unspecified" },
316   { USER_UNAVAILABLE_REASON,                        "User unavailable" },
317   { MANAGEMENT_BLOCKING_REASON,                     "Management blocking" },
318   {0,                           NULL } };
319
320 #define REASON_LENGTH 4
321 #define REASON_OFFSET PARAMETER_VALUE_OFFSET
322
323
324 #define OVER_RIDE_TYPE           1
325 #define LOAD_SHARE_TYPE          2
326 #define OVER_RIDE_STANDBY_TYPE   3
327 #define LOAD_SHARE_STANDBY_TYPE  4
328
329 static const value_string m3ua_traffic_mode_type_values[] = {
330   { OVER_RIDE_TYPE ,                             "Over-ride" },
331   { LOAD_SHARE_TYPE,                             "Load-share" },
332   { OVER_RIDE_STANDBY_TYPE,                      "Over-ride (standby)" },
333   { LOAD_SHARE_STANDBY_TYPE,                     "Load-share (standby)" },
334   {0,                           NULL } };
335
336 #define TRAFFIC_MODE_TYPE_LENGTH 4
337 #define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
338
339 #define ROUTING_CONTEXT_LENGTH 4
340
341 #define AFFECTED_DESTINATION_LENGTH 4
342 #define AFFECTED_MASK_LENGTH        1
343 #define AFFECTED_DPC_LENGTH         3
344
345 #define AFFECTED_MASK_OFFSET        0
346 #define AFFECTED_DPC_OFFSET         (AFFECTED_MASK_OFFSET + AFFECTED_MASK_LENGTH)
347
348 #define NO_CONGESTION_LEVEL         0
349 #define CONGESTION_LEVEL_1_LEVEL    1
350 #define CONGESTION_LEVEL_2_LEVEL    2
351 #define CONGESTION_LEVEL_3_LEVEL    3
352
353 static const value_string m3ua_congestion_level_values[] = {
354   { NO_CONGESTION_LEVEL,                             "No congestion or undefined" },
355   { CONGESTION_LEVEL_1_LEVEL,                        "Congestion level 1" },
356   { CONGESTION_LEVEL_2_LEVEL,                        "Congestion level 2" },
357   { CONGESTION_LEVEL_3_LEVEL,                        "Congestion level 3" },
358   {0,                           NULL } };
359
360 #define CONG_IND_RESERVED_LENGTH    3
361 #define CONG_IND_LEVEL_LENGTH       1
362
363 #define CONG_IND_RESERVED_OFFSET     PARAMETER_VALUE_OFFSET
364 #define CONG_IND_LEVEL_OFFSET        (CONG_IND_RESERVED_OFFSET + CONG_IND_RESERVED_LENGTH)
365
366 /* Initialize the protocol and registered fields */
367 static int proto_m3ua = -1;
368 static int hf_m3ua_version = -1;
369 static int hf_m3ua_reserved = -1;
370 static int hf_m3ua_message_class = -1;
371 static int hf_m3ua_message_type = -1;
372 static int hf_m3ua_message_length = -1;
373 static int hf_m3ua_parameter_tag = -1;
374 static int hf_m3ua_parameter_length = -1;
375 static int hf_m3ua_network_appearance = -1;
376 static int hf_m3ua_info_string = -1;
377 static int hf_m3ua_error_code = -1;
378 static int hf_m3ua_status_type = -1;
379 static int hf_m3ua_status_info = -1;
380 static int hf_m3ua_unavailability_cause = -1;
381 static int hf_m3ua_user_identity = -1;
382 static int hf_m3ua_reason = -1;
383 static int hf_m3ua_traffic_mode_type = -1;
384 static int hf_m3ua_routing_context = -1;
385 static int hf_m3ua_mask = -1;
386 static int hf_m3ua_dpc = -1;
387 static int hf_m3ua_congestion_level = -1;
388
389 /* Initialize the subtree pointers */
390 static gint ett_m3ua = -1;
391 static gint ett_m3ua_parameter = -1;
392 static gint ett_m3ua_affected_destination = -1;
393
394 static guint 
395 nr_of_padding_bytes (guint length)
396 {
397   guint remainder;
398
399   remainder = length % 4;
400
401   if (remainder == 0)
402     return 0;
403   else
404     return 4 - remainder;
405 }
406
407 static void
408 dissect_m3ua_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *m3ua_tree)
409 {
410   guint8  version, reserved, message_class, message_type;
411   guint32 message_length;
412   /* Extract the common header */
413   version        = tvb_get_guint8(common_header_tvb, VERSION_OFFSET);
414   reserved       = tvb_get_guint8(common_header_tvb, RESERVED_OFFSET);
415   message_class  = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
416   message_type   = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
417   message_length = tvb_get_ntohl (common_header_tvb, MESSAGE_LENGTH_OFFSET);
418
419   if (check_col(pinfo->fd, COL_INFO)) {
420     col_append_str(pinfo->fd, COL_INFO, val_to_str(message_class * 256 + message_type, m3ua_message_class_type_acro_values, "reserved"));
421     col_append_str(pinfo->fd, COL_INFO, " ");
422   };
423
424   if (m3ua_tree) {
425     /* add the components of the common header to the protocol tree */
426     proto_tree_add_uint_format(m3ua_tree, hf_m3ua_version, 
427                                common_header_tvb, VERSION_OFFSET, VERSION_LENGTH,
428                                version, "Version: %u (%s)",
429                                version, val_to_str(version, m3ua_protocol_version_values, "unknown"));
430     proto_tree_add_uint(m3ua_tree, hf_m3ua_reserved,
431                         common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH,
432                         reserved);
433     proto_tree_add_uint_format(m3ua_tree, hf_m3ua_message_class, 
434                                common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH,
435                              message_class, "Message class: %u (%s)",
436                                message_class, val_to_str(message_class, m3ua_message_class_values, "reserved"));
437     proto_tree_add_uint_format(m3ua_tree, hf_m3ua_message_type, 
438                                common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH,
439                                message_type, "Message type: %u (%s)",
440                                message_type, val_to_str(message_class * 256 + message_type, m3ua_message_class_type_values, "reserved"));
441     proto_tree_add_uint(m3ua_tree, hf_m3ua_message_length,
442                         common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH,
443                         message_length);
444   };
445 }
446
447 static void
448 dissect_m3ua_network_appearance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
449 {
450   guint32 network_appearance;
451
452   network_appearance = tvb_get_ntohl(parameter_tvb, NETWORK_APPEARANCE_OFFSET);
453   
454   proto_tree_add_uint(parameter_tree, hf_m3ua_network_appearance, 
455                       parameter_tvb, NETWORK_APPEARANCE_OFFSET, NETWORK_APPEARANCE_LENGTH,
456                       network_appearance);
457  
458   proto_item_set_text(parameter_item, "Network appearance: %u", network_appearance);
459 }
460
461 static void
462 dissect_m3ua_protocol_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
463 {
464   guint16 length, protocol_data_length;
465   
466   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
467   
468   protocol_data_length = length - PARAMETER_HEADER_LENGTH;
469
470   proto_tree_add_text(parameter_tree, parameter_tvb, PROTOCOL_DATA_OFFSET, protocol_data_length,
471                       "Protocol data (%u byte%s)",
472                       protocol_data_length, plurality(protocol_data_length, "", "s"));
473
474   proto_item_set_text(parameter_item, "Protocol data (SS7 message of %u byte%s)",
475                       protocol_data_length, plurality(protocol_data_length, "", "s"));
476 }
477
478 static void
479 dissect_m3ua_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
480 {
481   guint16 length, info_string_length;
482   char *info_string;
483
484   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
485   
486   info_string_length = length - PARAMETER_HEADER_LENGTH;
487   info_string = (char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length);
488
489   proto_tree_add_string(parameter_tree, hf_m3ua_info_string,
490                         parameter_tvb, INFO_STRING_OFFSET, info_string_length ,
491                         info_string);
492
493   proto_item_set_text(parameter_item, "Info String (%s)", info_string);
494 }
495
496 static void
497 dissect_m3ua_affected_destinations_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
498 {
499   guint8  mask;
500   guint16 length, number_of_destinations, destination_number;
501   guint32 dpc;
502   gint destination_offset;
503   proto_item *destination_item;
504   proto_tree *destination_tree;
505
506   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
507   number_of_destinations= (length - PARAMETER_HEADER_LENGTH) / 4;
508
509   destination_offset = PARAMETER_VALUE_OFFSET;
510   for(destination_number=1; destination_number <= number_of_destinations; destination_number++) {
511     mask = tvb_get_guint8(parameter_tvb, destination_offset + AFFECTED_MASK_OFFSET);
512     dpc  = tvb_get_ntoh24(parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET);
513     destination_item = proto_tree_add_text(parameter_tree, parameter_tvb, destination_offset, AFFECTED_DESTINATION_LENGTH,
514                                           "Affected destination");
515     destination_tree = proto_item_add_subtree(destination_item, ett_m3ua_affected_destination);
516
517     proto_tree_add_uint(destination_tree, hf_m3ua_mask, 
518                         parameter_tvb, destination_offset + AFFECTED_MASK_OFFSET, AFFECTED_MASK_LENGTH,
519                         mask);
520     proto_tree_add_uint(destination_tree, hf_m3ua_dpc, 
521                         parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET, AFFECTED_DPC_LENGTH,
522                         dpc);
523     destination_offset += AFFECTED_DESTINATION_LENGTH;
524   };
525   proto_item_set_text(parameter_item, "Affected destinations parameter (%u destination%s)",
526                       number_of_destinations, plurality(number_of_destinations, "", "s"));
527
528 }
529
530 static void
531 dissect_m3ua_routing_context_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
532 {
533   guint16 length, number_of_contexts, context_number;
534   guint32 context;
535   gint context_offset;
536
537   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
538   number_of_contexts = (length - PARAMETER_HEADER_LENGTH) / 4;
539
540   context_offset = PARAMETER_VALUE_OFFSET;
541   for(context_number=1; context_number <= number_of_contexts; context_number++) {
542     context = tvb_get_ntohl(parameter_tvb, context_offset);
543     proto_tree_add_uint(parameter_tree, hf_m3ua_routing_context, 
544                         parameter_tvb, context_offset, ROUTING_CONTEXT_LENGTH,
545                         context);
546     context_offset += ROUTING_CONTEXT_LENGTH;
547   };
548   proto_item_set_text(parameter_item, "Routing context parameter (%u context%s)",
549                       number_of_contexts, plurality(number_of_contexts, "", "s"));
550 }
551
552 static void
553 dissect_m3ua_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
554 {
555   guint16 length, diagnostic_info_length;
556   
557   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
558   
559   diagnostic_info_length = length - PARAMETER_HEADER_LENGTH;
560
561   proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, diagnostic_info_length,
562                       "Diagnostic information (%u byte%s)",
563                       diagnostic_info_length, plurality(diagnostic_info_length, "", "s"));
564
565   proto_item_set_text(parameter_item, "Diagnostic information (%u byte%s)",
566                       diagnostic_info_length, plurality(diagnostic_info_length, "", "s"));
567 }
568
569 static void
570 dissect_m3ua_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
571 {
572   guint16 length, heartbeat_data_length;
573   
574   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
575   
576   heartbeat_data_length = length - PARAMETER_HEADER_LENGTH;
577
578   proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, heartbeat_data_length,
579                       "Heartbeat data (%u byte%s)",
580                       heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
581
582   proto_item_set_text(parameter_item, "Heartbeat data (%u byte%s)",
583                       heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
584 }
585
586 static void
587 dissect_m3ua_user_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
588 {
589   guint16 cause, user;
590
591   cause = tvb_get_ntohs(parameter_tvb, CAUSE_OFFSET);
592   user  = tvb_get_ntohs(parameter_tvb, USER_OFFSET);
593
594   proto_tree_add_uint_format(parameter_tree, hf_m3ua_unavailability_cause, 
595                              parameter_tvb, CAUSE_OFFSET, CAUSE_LENGTH,
596                              cause, "Unavailability cause: %u (%s)",
597                              cause, val_to_str(cause, m3ua_unavailability_cause_values, "unknown"));
598   proto_tree_add_uint_format(parameter_tree, hf_m3ua_user_identity, 
599                              parameter_tvb, USER_OFFSET, USER_LENGTH,
600                              user, "User identity: %u (%s)",
601                              user, val_to_str(user, m3ua_user_identity_values, "unknown"));
602   proto_item_set_text(parameter_item, "User / Cause parameter (%s: %s)",
603                       val_to_str(user, m3ua_user_identity_values, "Unknown user"),
604                       val_to_str(cause, m3ua_unavailability_cause_values, "unknown cause"));
605 }
606
607 static void
608 dissect_m3ua_reason_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
609 {
610   guint32 reason;
611
612   reason = tvb_get_ntohl(parameter_tvb, REASON_OFFSET);
613
614   proto_tree_add_uint_format(parameter_tree, hf_m3ua_reason, 
615                              parameter_tvb, REASON_OFFSET, REASON_LENGTH,
616                              reason, "Reason: %u (%s)",
617                              reason, val_to_str(reason, m3ua_reason_values, "unknown"));
618   proto_item_set_text(parameter_item, "Reason parameter (%s)",
619                       val_to_str(reason, m3ua_reason_values, "unknown"));
620 }
621
622 static void
623 dissect_m3ua_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
624 {
625   guint32 traffic_mode_type;
626
627   traffic_mode_type = tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET);
628
629   proto_tree_add_uint_format(parameter_tree, hf_m3ua_traffic_mode_type, 
630                              parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH,
631                              traffic_mode_type, "Traffic mode type: %u (%s)",
632                              traffic_mode_type, val_to_str(traffic_mode_type, m3ua_traffic_mode_type_values, "unknown"));
633   proto_item_set_text(parameter_item, "Traffic mode type parameter (%s)",
634                       val_to_str(traffic_mode_type, m3ua_traffic_mode_type_values, "unknown"));
635 }
636
637 static void
638 dissect_m3ua_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
639 {
640   guint32 error_code;
641
642   error_code = tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET);
643   proto_tree_add_uint_format(parameter_tree, hf_m3ua_error_code, 
644                              parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH,
645                              error_code, "Error code: %u (%s)",
646                              error_code, val_to_str(error_code, m3ua_error_code_values, "unknown"));
647   proto_item_set_text(parameter_item, "Error code parameter (%s)",
648                       val_to_str(error_code, m3ua_error_code_values, "unknown"));
649 }
650
651 static void
652 dissect_m3ua_status_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
653 {
654   guint16 status_type, status_info;
655
656   status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
657   status_info = tvb_get_ntohs(parameter_tvb, STATUS_INFO_OFFSET);
658
659   proto_tree_add_uint_format(parameter_tree, hf_m3ua_status_type, 
660                              parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH,
661                              status_type, "Status type: %u (%s)",
662                              status_type, val_to_str(status_type, m3ua_status_type_values, "unknown"));
663   proto_tree_add_uint_format(parameter_tree, hf_m3ua_status_info, 
664                              parameter_tvb, STATUS_INFO_OFFSET, STATUS_INFO_LENGTH,
665                              status_info, "Status info: %u (%s)",
666                              status_info, val_to_str(status_type * 256 * 256 + 
667                                                      status_info, m3ua_status_type_info_values, "unknown"));
668
669   proto_item_set_text(parameter_item, "Status type / ID (%s)",
670                       val_to_str(status_type * 256 * 256 + 
671                                  status_info, m3ua_status_type_info_values, "unknown status information"));
672 }
673
674 static void
675 dissect_m3ua_congestion_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
676 {
677   guint8 level;
678   
679   level = tvb_get_guint8(parameter_tvb, CONG_IND_LEVEL_OFFSET);
680
681   proto_tree_add_text(parameter_tree, parameter_tvb, CONG_IND_RESERVED_OFFSET, CONG_IND_RESERVED_LENGTH,
682                         "Reserved: %u byte%s",
683                         CONG_IND_RESERVED_LENGTH, plurality(CONG_IND_RESERVED_LENGTH, "", "s"));
684   proto_tree_add_uint_format(parameter_tree, hf_m3ua_congestion_level, 
685                              parameter_tvb, CONG_IND_LEVEL_OFFSET, CONG_IND_LEVEL_LENGTH,
686                              level, "Congestion level: %u (%s)",
687                              level, val_to_str(level, m3ua_congestion_level_values, "unknown"));
688   proto_item_set_text(parameter_item, "Congestion indication (%s)",
689                       val_to_str(level, m3ua_congestion_level_values, "unknown"));
690 }
691
692 static void
693 dissect_m3ua_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
694 {
695   guint16 tag, length, parameter_value_length;
696   
697   tag    = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
698   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
699   
700   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
701
702   proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length,
703                       "Parameter value (%u byte%s)",
704                       parameter_value_length, plurality(parameter_value_length, "", "s"));
705
706   proto_item_set_text(parameter_item, "Parameter with tag %u and %u byte%s value",
707                       tag, parameter_value_length, plurality(parameter_value_length, "", "s"));
708 }
709
710 static void
711 dissect_m3ua_parameter(tvbuff_t *parameter_tvb, proto_tree *m3ua_tree)
712 {
713   guint16 tag, length, padding_length, total_length;
714   proto_item *parameter_item;
715   proto_tree *parameter_tree;
716
717   /* extract tag and length from the parameter */
718   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
719   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
720
721   /* calculate padding and total length */
722   padding_length = nr_of_padding_bytes(length);
723   total_length   = length + padding_length;
724
725   /* create proto_tree stuff */
726   parameter_item   = proto_tree_add_text(m3ua_tree, parameter_tvb,
727                                      PARAMETER_HEADER_OFFSET, total_length, "Incomplete parameter");
728   parameter_tree   = proto_item_add_subtree(parameter_item, ett_m3ua_parameter);
729
730   /* add tag and length to the m3ua tree */
731   proto_tree_add_uint_format(parameter_tree, hf_m3ua_parameter_tag, 
732                              parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH,
733                              tag, "Identifier: %u (%s)",
734                              tag, val_to_str(tag, m3ua_parameter_tag_values, "unknown"));
735   proto_tree_add_uint(parameter_tree, hf_m3ua_parameter_length, 
736                       parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH,
737                       length);
738
739   switch(tag) {
740   case NETWORK_APPEARANCE_PARAMETER_TAG:
741     dissect_m3ua_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
742     break;
743   case PROTOCOL_DATA_PARAMETER_TAG:
744     dissect_m3ua_protocol_data_parameter(parameter_tvb, parameter_tree, parameter_item);
745     break;
746   case INFO_PARAMETER_TAG:
747     dissect_m3ua_info_parameter(parameter_tvb, parameter_tree, parameter_item);
748     break;
749   case AFFECTED_DESTINATIONS_PARAMETER_TAG:
750     dissect_m3ua_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
751     break;
752   case ROUTING_CONTEXT_PARAMETER_TAG:
753     dissect_m3ua_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
754     break;
755   case DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
756     dissect_m3ua_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
757     break;
758   case HEARTBEAT_DATA_PARAMETER_TAG:
759     dissect_m3ua_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
760     break;
761   case USER_CAUSE_PARAMETER_TAG:
762     dissect_m3ua_user_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
763     break;
764   case REASON_PARAMETER_TAG:
765     dissect_m3ua_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
766     break;
767   case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
768     dissect_m3ua_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
769     break;
770   case ERROR_CODE_PARAMETER_TAG:
771     dissect_m3ua_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
772     break;
773   case  STATUS_TYPE_PARAMETER_TAG:
774     dissect_m3ua_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
775     break;
776   case  CONGESTION_INDICATION_PARAMETER_TAG:
777     dissect_m3ua_congestion_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
778     break;
779   default:
780     dissect_m3ua_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
781     break;
782   };
783
784   if (padding_length > 0)
785     proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length,
786                         "Padding: %u byte%s",
787                         padding_length, plurality(padding_length, "", "s"));
788 }
789
790 static void
791 dissect_m3ua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *m3ua_tree)
792 {
793   gint offset, length, padding_length, total_length;
794   tvbuff_t *common_header_tvb, *parameter_tvb;
795
796   offset = 0;
797
798   /* extract and process the common header */
799   common_header_tvb = tvb_new_subset(message_tvb, offset, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
800   dissect_m3ua_common_header(common_header_tvb, pinfo, m3ua_tree);
801   offset += COMMON_HEADER_LENGTH;
802   
803   if (m3ua_tree) {
804     /* extract zero or more parameters and process them individually */
805     while(tvb_length_remaining(message_tvb, offset)) {
806       length         = tvb_get_ntohs(message_tvb, offset + PARAMETER_LENGTH_OFFSET);
807       padding_length = nr_of_padding_bytes(length);
808       total_length   = length + padding_length;
809       /* create a tvb for the parameter including the padding bytes */
810       parameter_tvb    = tvb_new_subset(message_tvb, offset, total_length, total_length);
811       dissect_m3ua_parameter(parameter_tvb, m3ua_tree); 
812       /* get rid of the handled parameter */
813       offset += total_length;
814     }
815   }
816 }
817
818 static void
819 dissect_m3ua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
820 {
821   proto_item *m3ua_item;
822   proto_tree *m3ua_tree;
823
824   /* make entry in the Protocol column on summary display */
825   if (check_col(pinfo->fd, COL_PROTOCOL)) 
826     col_set_str(pinfo->fd, COL_PROTOCOL, "M3UA");
827   
828   /* In the interest of speed, if "tree" is NULL, don't do any work not
829      necessary to generate protocol tree items. */
830   if (tree) {
831     /* create the m3ua protocol tree */
832     m3ua_item = proto_tree_add_item(tree, proto_m3ua, message_tvb, 0, tvb_length(message_tvb), FALSE);
833     m3ua_tree = proto_item_add_subtree(m3ua_item, ett_m3ua);
834   } else {
835     m3ua_tree = NULL;
836   };
837   /* dissect the message */
838   dissect_m3ua_message(message_tvb, pinfo, m3ua_tree);
839 }
840
841 /* Register the protocol with Ethereal */
842 void
843 proto_register_m3ua(void)
844 {                 
845
846   /* Setup list of header fields */
847   static hf_register_info hf[] = {
848     { &hf_m3ua_version,
849       { "Version", "m3ua.version",
850         FT_UINT8, BASE_DEC, NULL, 0x0,          
851         ""}
852     },
853     { &hf_m3ua_reserved,
854       { "Reserved", "m3ua.reserved",
855         FT_UINT8, BASE_HEX, NULL, 0x0,          
856         ""}
857     }, 
858     { &hf_m3ua_message_class,
859       { "Message class", "m3ua.message_class",
860         FT_UINT8, BASE_DEC, NULL, 0x0,          
861         ""}
862     },
863     { &hf_m3ua_message_type,
864       { "Message Type", "m3ua.message_type",
865         FT_UINT8, BASE_DEC, NULL, 0x0,          
866         ""}
867     },
868     { &hf_m3ua_message_length,
869       { "Message length", "m3ua.message_length",
870         FT_UINT32, BASE_DEC, NULL, 0x0,          
871         ""}
872     }, 
873     { &hf_m3ua_parameter_tag,
874       { "Parameter Tag", "m3ua.parameter_tag",
875         FT_UINT16, BASE_DEC, NULL, 0x0,          
876         ""}
877     },
878     { &hf_m3ua_parameter_length,
879       { "Parameter length", "m3ua.parameter_length",
880         FT_UINT16, BASE_DEC, NULL, 0x0,          
881         ""}
882     }, 
883     { &hf_m3ua_network_appearance,
884       { "Network appearance", "m3ua.network_appearance",
885         FT_UINT32, BASE_DEC, NULL, 0x0,          
886         ""}
887     }, 
888     { &hf_m3ua_info_string,
889       { "Info string", "m3ua.info_string",
890         FT_STRING, BASE_DEC, NULL, 0x0,          
891         ""}
892     }, 
893     { &hf_m3ua_error_code,
894       { "Error code", "m3ua.error_code",
895         FT_UINT32, BASE_DEC, NULL, 0x0,          
896         ""}
897     }, 
898     { &hf_m3ua_status_type,
899       { "Status type", "m3ua.status_type",
900         FT_UINT16, BASE_DEC, NULL, 0x0,          
901         ""}
902     }, 
903     { &hf_m3ua_status_info,
904       { "Status info", "m3ua.status_info",
905         FT_UINT16, BASE_DEC, NULL, 0x0,          
906         ""}
907     }, 
908     { &hf_m3ua_unavailability_cause,
909       { "Unavailability cause", "m3ua.unavailability_cause",
910         FT_UINT16, BASE_DEC, NULL, 0x0,          
911         ""}
912     }, 
913     { &hf_m3ua_user_identity,
914       { "User Identity", "m3ua.user_identity",
915         FT_UINT16, BASE_DEC, NULL, 0x0,          
916         ""}
917     }, 
918     { &hf_m3ua_reason,
919       { "Reason", "m3ua.reason",
920         FT_UINT32, BASE_DEC, NULL, 0x0,          
921         ""}
922     }, 
923     { &hf_m3ua_traffic_mode_type,
924       { "Traffic mode Type", "m3ua.traffic_mode_type",
925         FT_UINT32, BASE_DEC, NULL, 0x0,          
926         ""}
927     }, 
928     { &hf_m3ua_routing_context,
929       { "Routing context", "m3ua.routing_context",
930         FT_UINT32, BASE_DEC, NULL, 0x0,          
931         ""}
932     }, 
933     { &hf_m3ua_mask,
934       { "Mask", "m3ua.mask",
935         FT_UINT8, BASE_DEC, NULL, 0x0,          
936         ""}
937     }, 
938     { &hf_m3ua_dpc,
939       { "Affected DPC", "m3ua.affected_dpc",
940         FT_UINT24, BASE_DEC, NULL, 0x0,          
941         ""}
942     }, 
943     { &hf_m3ua_congestion_level,
944       { "Congestion level", "m3ua.congestion_level",
945         FT_UINT8, BASE_DEC, NULL, 0x0,          
946         ""}
947     }, 
948   };
949   
950   /* Setup protocol subtree array */
951   static gint *ett[] = {
952     &ett_m3ua,
953     &ett_m3ua_parameter,
954     &ett_m3ua_affected_destination,
955   };
956   
957   /* Register the protocol name and description */
958   proto_m3ua = proto_register_protocol("MTP 3 User Adaptation Layer",
959                                       "M3UA",  "m3ua");
960   
961   /* Required function calls to register the header fields and subtrees used */
962   proto_register_field_array(proto_m3ua, hf, array_length(hf));
963   proto_register_subtree_array(ett, array_length(ett));
964 };
965
966 void
967 proto_reg_handoff_m3ua(void)
968 {
969   dissector_add("sctp.ppi",  M3UA_PAYLOAD_PROTO_ID, dissect_m3ua, proto_m3ua);
970   dissector_add("sctp.port", SCTP_PORT_M3UA, dissect_m3ua, proto_m3ua);
971 }