From Michael Tuexen: add missing support for the T-Bit in ABORT chunks.
[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-06.txt
5  * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-m3ua-12.txt
6  * To do: - clean up the code
7  *        - provide better handling of length parameters
8  *        - provide good information in summary window
9  *
10  * Copyright 2000, 2001, 2002, Michael Tuexen <Michael.Tuexen@icn.siemens.de>
11  *
12  * $Id: packet-m3ua.c,v 1.17 2002/03/28 21:48:46 guy Exp $
13  *
14  * Ethereal - Network traffic analyzer
15  * By Gerald Combs <gerald@ethereal.com>
16  * Copyright 1998 Gerald Combs
17  *
18  * Copied from README.developer
19  * 
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  * 
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  * 
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <stdio.h>
40 #include <stdlib.h>
41
42
43 #ifdef HAVE_SYS_TYPES_H
44 # include <sys/types.h>
45 #endif
46
47 #ifdef HAVE_NETINET_IN_H
48 # include <netinet/in.h>
49 #endif
50
51 #include <string.h>
52 #include <glib.h>
53
54 #ifdef NEED_SNPRINTF_H
55 # include "snprintf.h"
56 #endif
57
58 #include <epan/packet.h>
59 #include "prefs.h"
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 V6_NETWORK_APPEARANCE_PARAMETER_TAG            1
88 #define V6_PROTOCOL_DATA_1_PARAMETER_TAG               2
89 #define V6_PROTOCOL_DATA_2_PARAMETER_TAG               3
90 #define V6_INFO_PARAMETER_TAG                          4
91 #define V6_AFFECTED_DESTINATIONS_PARAMETER_TAG         5
92 #define V6_ROUTING_CONTEXT_PARAMETER_TAG               6
93 #define V6_DIAGNOSTIC_INFORMATION_PARAMETER_TAG        7
94 #define V6_HEARTBEAT_DATA_PARAMETER_TAG                8
95 #define V6_USER_CAUSE_PARAMETER_TAG                    9
96 #define V6_REASON_PARAMETER_TAG                       10
97 #define V6_TRAFFIC_MODE_TYPE_PARAMETER_TAG            11
98 #define V6_ERROR_CODE_PARAMETER_TAG                   12
99 #define V6_STATUS_PARAMETER_TAG                       13
100 #define V6_CONGESTION_INDICATION_PARAMETER_TAG        14
101 #define V6_CONCERNED_DESTINATION_PARAMETER_TAG        15
102 #define V6_ROUTING_KEY_PARAMETER_TAG                  16
103 #define V6_REGISTRATION_RESULT_PARAMETER_TAG          17
104 #define V6_DEREGISTRATION_RESULT_PARAMETER_TAG        18
105 #define V6_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG 19
106 #define V6_DESTINATION_POINT_CODE_PARAMETER_TAG       20
107 #define V6_SERVICE_INDICATORS_PARAMETER_TAG           21
108 #define V6_SUBSYSTEM_NUMBERS_PARAMETER_TAG            22
109 #define V6_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG  23
110 #define V6_CIRCUIT_RANGE_PARAMETER_TAG                24
111 #define V6_REGISTRATION_RESULTS_PARAMETER_TAG         25
112 #define V6_DEREGISTRATION_RESULTS_PARAMETER_TAG       26
113
114 static const value_string m3ua_v6_parameter_tag_values[] = {
115   { V6_NETWORK_APPEARANCE_PARAMETER_TAG,           "Network appearance" },
116   { V6_PROTOCOL_DATA_1_PARAMETER_TAG,              "Protocol data 1" },
117   { V6_PROTOCOL_DATA_2_PARAMETER_TAG,              "Protocol data 2" },
118   { V6_INFO_PARAMETER_TAG,                         "Info" },
119   { V6_AFFECTED_DESTINATIONS_PARAMETER_TAG,        "Affected destinations" },
120   { V6_ROUTING_CONTEXT_PARAMETER_TAG,              "Routing context" },
121   { V6_DIAGNOSTIC_INFORMATION_PARAMETER_TAG,       "Diagnostic information" },
122   { V6_HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat data" },
123   { V6_USER_CAUSE_PARAMETER_TAG,                   "User / Cause" },
124   { V6_REASON_PARAMETER_TAG,                       "Reason" },
125   { V6_TRAFFIC_MODE_TYPE_PARAMETER_TAG,            "Traffic mode type" },
126   { V6_ERROR_CODE_PARAMETER_TAG,                   "Error code" },
127   { V6_STATUS_PARAMETER_TAG,                       "Status" }, 
128   { V6_CONGESTION_INDICATION_PARAMETER_TAG,        "Congestion indication" },
129   { V6_CONCERNED_DESTINATION_PARAMETER_TAG,        "Concerned destination" },
130   { V6_ROUTING_KEY_PARAMETER_TAG,                  "Routing Key" },
131   { V6_REGISTRATION_RESULT_PARAMETER_TAG,          "Registration result" },
132   { V6_DEREGISTRATION_RESULT_PARAMETER_TAG,        "De-registration result" },
133   { V6_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG, "Local routing key identifier" },
134   { V6_DESTINATION_POINT_CODE_PARAMETER_TAG,       "Destination point code" },
135   { V6_SERVICE_INDICATORS_PARAMETER_TAG,           "Service indicators" },
136   { V6_SUBSYSTEM_NUMBERS_PARAMETER_TAG,            "Subsystem numbers" },
137   { V6_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG,  "Originating point code list" },
138   { V6_CIRCUIT_RANGE_PARAMETER_TAG,                "Circuit range" },
139   { V6_REGISTRATION_RESULTS_PARAMETER_TAG,         "Registration results" },
140   { V6_DEREGISTRATION_RESULTS_PARAMETER_TAG,       "De-registration results" },
141   { 0,                           NULL } };
142   
143 #define V12_INFO_STRING_PARAMETER_TAG                  0x0004
144 #define V12_ROUTING_CONTEXT_PARAMETER_TAG              0x0006
145 #define V12_DIAGNOSTIC_INFORMATION_PARAMETER_TAG       0x0007
146 #define V12_HEARTBEAT_DATA_PARAMETER_TAG               0x0009
147 #define V12_TRAFFIC_MODE_TYPE_PARAMETER_TAG            0x000b
148 #define V12_ERROR_CODE_PARAMETER_TAG                   0x000c
149 #define V12_STATUS_PARAMETER_TAG                       0x000d
150 #define V12_ASP_IDENTIFIER_PARAMETER_TAG               0x0011
151 #define V12_AFFECTED_POINT_CODE_PARAMETER_TAG          0x0012
152 #define V12_CORRELATION_IDENTIFIER_PARAMETER_TAG       0x0013
153
154 #define V12_NETWORK_APPEARANCE_PARAMETER_TAG           0x0200
155 #define V12_USER_CAUSE_PARAMETER_TAG                   0x0204
156 #define V12_CONGESTION_INDICATIONS_PARAMETER_TAG       0x0205
157 #define V12_CONCERNED_DESTINATION_PARAMETER_TAG        0x0206
158 #define V12_ROUTING_KEY_PARAMETER_TAG                  0x0207
159 #define V12_REGISTRATION_RESULT_PARAMETER_TAG          0x0208
160 #define V12_DEREGISTRATION_RESULT_PARAMETER_TAG        0x0209
161 #define V12_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG 0x020a
162 #define V12_DESTINATION_POINT_CODE_PARAMETER_TAG       0x020b
163 #define V12_SERVICE_INDICATORS_PARAMETER_TAG           0x020c
164 #define V12_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG  0x020e
165 #define V12_CIRCUIT_RANGE_PARAMETER_TAG                0x020f
166 #define V12_PROTOCOL_DATA_PARAMETER_TAG                0x0210
167 #define V12_REGISTRATION_STATUS_PARAMETER_TAG          0x0212
168 #define V12_DEREGISTRATION_STATUS_PARAMETER_TAG        0x0213
169
170 static const value_string m3ua_v12_parameter_tag_values[] = {
171   { V12_INFO_STRING_PARAMETER_TAG,                  "Info string" } ,
172   { V12_ROUTING_CONTEXT_PARAMETER_TAG,              "Routing context" } ,
173   { V12_DIAGNOSTIC_INFORMATION_PARAMETER_TAG,       "Diagnostic Information" } ,
174   { V12_HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat data" } ,
175   { V12_TRAFFIC_MODE_TYPE_PARAMETER_TAG,            "Traffic mode type" } ,
176   { V12_ERROR_CODE_PARAMETER_TAG,                   "Error code" } ,
177   { V12_STATUS_PARAMETER_TAG,                       "Status" } ,
178   { V12_ASP_IDENTIFIER_PARAMETER_TAG,               "ASP identifier" } ,
179   { V12_AFFECTED_POINT_CODE_PARAMETER_TAG,          "Affected point code" } ,
180   { V12_CORRELATION_IDENTIFIER_PARAMETER_TAG,       "Correlation identifier" } ,
181   { V12_NETWORK_APPEARANCE_PARAMETER_TAG,           "Network appearance" } ,
182   { V12_USER_CAUSE_PARAMETER_TAG,                   "User / cause" } ,
183   { V12_CONGESTION_INDICATIONS_PARAMETER_TAG,       "Congestion indications" } ,
184   { V12_CONCERNED_DESTINATION_PARAMETER_TAG,        "Concerned destination" } ,
185   { V12_ROUTING_KEY_PARAMETER_TAG,                  "Routing key" } ,
186   { V12_REGISTRATION_RESULT_PARAMETER_TAG,          "Registration result" } ,
187   { V12_DEREGISTRATION_RESULT_PARAMETER_TAG,        "Deregistration result" } ,
188   { V12_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG, "Local routing key identifier" } ,
189   { V12_DESTINATION_POINT_CODE_PARAMETER_TAG,       "Destination point code" } ,
190   { V12_SERVICE_INDICATORS_PARAMETER_TAG,           "Service indicators" } ,
191   { V12_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG,  "Originating point code list" } ,
192   { V12_CIRCUIT_RANGE_PARAMETER_TAG,                "Circuit range" } ,
193   { V12_PROTOCOL_DATA_PARAMETER_TAG,                "Protocol data" } ,
194   { V12_REGISTRATION_STATUS_PARAMETER_TAG,          "Registration status" } ,
195   { V12_DEREGISTRATION_STATUS_PARAMETER_TAG,        "Deregistration status" } ,
196   { 0,                           NULL } };
197
198 #define PROTOCOL_VERSION_RELEASE_1             1
199
200 static const value_string m3ua_protocol_version_values[] = {
201   { PROTOCOL_VERSION_RELEASE_1,  "Release 1" },
202   { 0,                           NULL } };
203
204 #define MESSAGE_CLASS_MGMT_MESSAGE        0
205 #define MESSAGE_CLASS_TFER_MESSAGE        1
206 #define MESSAGE_CLASS_SSNM_MESSAGE        2
207 #define MESSAGE_CLASS_ASPSM_MESSAGE       3
208 #define MESSAGE_CLASS_ASPTM_MESSAGE       4
209 #define MESSAGE_CLASS_RKM_MESSAGE         9
210
211 static const value_string m3ua_message_class_values[] = {
212   { MESSAGE_CLASS_MGMT_MESSAGE,   "Management messages" },
213   { MESSAGE_CLASS_TFER_MESSAGE,   "Transfer messages" },
214   { MESSAGE_CLASS_SSNM_MESSAGE,   "SS7 signalling network management messages" },
215   { MESSAGE_CLASS_ASPSM_MESSAGE,  "ASP state maintenance messages" },
216   { MESSAGE_CLASS_ASPTM_MESSAGE,  "ASP traffic maintenance messages" },
217   { MESSAGE_CLASS_RKM_MESSAGE,    "Routing key management messages" },
218   { 0,                           NULL } };
219
220 #define MESSAGE_TYPE_ERR                  0
221 #define MESSAGE_TYPE_NTFY                 1
222
223 #define MESSAGE_TYPE_DATA                 1
224
225 #define MESSAGE_TYPE_DUNA                 1
226 #define MESSAGE_TYPE_DAVA                 2
227 #define MESSAGE_TYPE_DAUD                 3
228 #define MESSAGE_TYPE_SCON                 4
229 #define MESSAGE_TYPE_DUPU                 5
230 #define MESSAGE_TYPE_DRST                 6
231
232 #define MESSAGE_TYPE_UP                   1
233 #define MESSAGE_TYPE_DOWN                 2
234 #define MESSAGE_TYPE_BEAT                 3
235 #define MESSAGE_TYPE_UP_ACK               4
236 #define MESSAGE_TYPE_DOWN_ACK             5
237 #define MESSAGE_TYPE_BEAT_ACK             6
238
239 #define MESSAGE_TYPE_ACTIVE               1
240 #define MESSAGE_TYPE_INACTIVE             2
241 #define MESSAGE_TYPE_ACTIVE_ACK           3
242 #define MESSAGE_TYPE_INACTIVE_ACK         4
243
244 #define MESSAGE_TYPE_REG_REQ              1
245 #define MESSAGE_TYPE_REG_RSP              2
246 #define MESSAGE_TYPE_DEREG_REQ            3
247 #define MESSAGE_TYPE_DEREG_RSP            4
248
249
250 static const value_string m3ua_message_class_type_values[] = {
251   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "Error (ERR)" },
252   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "Notify (NTFY)" },
253   { MESSAGE_CLASS_TFER_MESSAGE  * 256 + MESSAGE_TYPE_DATA,          "Payload data (DATA)" },
254   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "Destination unavailable (DUNA)" },
255   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "Destination available (DAVA)" },
256   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "Destination state audit (DAUD)" },
257   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SS7 Network congestion state (SCON)" },
258   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "Destination userpart unavailable (DUPU)" },
259   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DRST,          "Destination Restricted (DRST)" },
260   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP up (UP)" },
261   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP down (DOWN)" },
262   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "Heartbeat (BEAT)" },
263   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP up ack (UP ACK)" },
264   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP down ack (DOWN ACK)" },
265   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "Heartbeat ack (BEAT ACK)" },
266   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP active (ACTIVE)" },
267   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP inactive (INACTIVE)" },
268   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP active ack (ACTIVE ACK)" },
269   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (INACTIVE ACK)" },
270   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_REQ ,      "Registration request (REG_REQ)" },
271   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_RSP ,      "Registration response (REG_RSP)" },
272   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_REQ ,    "Deregistration request (DEREG_REQ)" },
273   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_RSP ,    "Deregistration response (DEREG_RSP)" },
274   { 0,                           NULL } };
275
276 static const value_string m3ua_message_class_type_acro_values[] = {
277   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "ERR" },
278   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "NTFY" },
279   { MESSAGE_CLASS_TFER_MESSAGE  * 256 + MESSAGE_TYPE_DATA,          "DATA" },
280   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "DUNA" },
281   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "DAVA" },
282   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "DAUD" },
283   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SCON" },
284   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "DUPU" },
285   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DRST,          "DRST" },
286   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP_UP" },
287   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP_DOWN" },
288   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "BEAT" },
289   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP_UP_ACK" },
290   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP_DOWN_ACK" },
291   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "BEAT_ACK" },
292   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP_ACTIVE" },
293   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP_INACTIVE" },
294   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP_ACTIVE_ACK" },
295   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
296   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_REQ ,      "REG_REQ" },
297   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_RSP ,      "REG_RSP" },
298   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_REQ ,    "DEREG_REQ" },
299   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_RSP ,    "DEREG_RSP" },
300   { 0,                           NULL } };
301
302
303
304
305
306 #define PROTOCOL_DATA_OFFSET PARAMETER_VALUE_OFFSET
307
308
309 #define UNSPECIFIED_REASON          0
310 #define USER_UNAVAILABLE_REASON     1
311 #define MANAGEMENT_BLOCKING_REASON  2
312
313 static const value_string m3ua_reason_values[] = {
314   { UNSPECIFIED_REASON,                             "Unspecified" },
315   { USER_UNAVAILABLE_REASON,                        "User unavailable" },
316   { MANAGEMENT_BLOCKING_REASON,                     "Management blocking" },
317   {0,                           NULL } };
318
319 #define REASON_LENGTH 4
320 #define REASON_OFFSET PARAMETER_VALUE_OFFSET
321
322 #define TRAFFIC_MODE_TYPE_LENGTH 4
323 #define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
324
325 /* Initialize the protocol and registered fields */
326 static int proto_m3ua = -1;
327 static int hf_m3ua_version = -1;
328 static int hf_m3ua_reserved = -1;
329 static int hf_m3ua_message_class = -1;
330 static int hf_m3ua_message_type = -1;
331 static int hf_m3ua_message_length = -1;
332 static int hf_m3ua_parameter_tag = -1;
333 static int hf_m3ua_parameter_length = -1;
334 static int hf_m3ua_parameter_value = -1;
335 static int hf_m3ua_parameter_padding = -1;
336 static int hf_m3ua_network_appearance = -1;
337 static int hf_m3ua_info_string = -1;
338 static int hf_m3ua_routing_context = -1;
339 static int hf_m3ua_diagnostic_information = -1;
340 static int hf_m3ua_heartbeat_data = -1;
341 static int hf_m3ua_error_code = -1;
342 static int hf_m3ua_status_type = -1;
343 static int hf_m3ua_status_info = -1;
344 static int hf_m3ua_asp_identifier = -1;
345 static int hf_m3ua_affected_point_code_mask = -1;
346 static int hf_m3ua_affected_point_code_pc = -1;
347 static int hf_m3ua_unavailability_cause = -1;
348 static int hf_m3ua_user_identity = -1;
349 static int hf_m3ua_reason = -1;
350 static int hf_m3ua_traffic_mode_type = -1;
351 static int hf_m3ua_congestion_reserved = -1;
352 static int hf_m3ua_congestion_level = -1;
353 static int hf_m3ua_concerned_dest_reserved = -1;
354 static int hf_m3ua_concerned_dest_pc = -1;
355 static int hf_m3ua_local_rk_identifier = -1;
356 static int hf_m3ua_dpc_mask = -1;
357 static int hf_m3ua_dpc_pc = -1;
358 static int hf_m3ua_si = -1;
359 static int hf_m3ua_ssn = -1;
360 static int hf_m3ua_opc_list_mask = -1;
361 static int hf_m3ua_opc_list_pc = -1;
362 static int hf_m3ua_cic_range_mask = -1;
363 static int hf_m3ua_cic_range_pc = -1;
364 static int hf_m3ua_cic_range_upper = -1;
365 static int hf_m3ua_cic_range_lower = -1;
366 static int hf_m3ua_protocol_data_opc = -1;
367 static int hf_m3ua_protocol_data_dpc = -1;
368 static int hf_m3ua_protocol_data_si = -1;
369 static int hf_m3ua_protocol_data_ni = -1;
370 static int hf_m3ua_protocol_data_mp = -1;
371 static int hf_m3ua_protocol_data_sls = -1;
372 static int hf_m3ua_correlation_identifier = -1;
373 static int hf_m3ua_registration_status = -1;
374 static int hf_m3ua_deregistration_status = -1;
375 static int hf_m3ua_registration_result_identifier = -1;
376 static int hf_m3ua_registration_result_status = -1;
377 static int hf_m3ua_registration_result_context = -1;
378 static int hf_m3ua_deregistration_result_status = -1;
379 static int hf_m3ua_deregistration_result_context = -1;
380 static int hf_m3ua_li = -1;
381
382 /* Initialize the subtree pointers */
383 static gint ett_m3ua = -1;
384 static gint ett_m3ua_parameter = -1;
385
386 static module_t *m3ua_module;
387 static dissector_handle_t mtp3_handle, data_handle;
388 static dissector_table_t m3ua_si_dissector_table;
389
390 /* stuff for supporting multiple versions */
391 #define M3UA_V6            1
392 #define M3UA_V12           2
393 static gint m3ua_version = M3UA_V12;
394
395 static void
396 dissect_m3ua_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_tree *);
397
398 static guint 
399 nr_of_padding_bytes (guint length)
400 {
401   guint remainder;
402
403   remainder = length % 4;
404
405   if (remainder == 0)
406     return 0;
407   else
408     return 4 - remainder;
409 }
410
411 static void
412 dissect_m3ua_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *m3ua_tree)
413 {
414   guint8  version, reserved, message_class, message_type;
415   guint32 message_length;
416   
417   /* Extract the common header */
418   version        = tvb_get_guint8(common_header_tvb, VERSION_OFFSET);
419   reserved       = tvb_get_guint8(common_header_tvb, RESERVED_OFFSET);
420   message_class  = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
421   message_type   = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
422   message_length = tvb_get_ntohl (common_header_tvb, MESSAGE_LENGTH_OFFSET);
423
424   if (check_col(pinfo->cinfo, COL_INFO)) {
425     col_append_str(pinfo->cinfo, COL_INFO, val_to_str(message_class * 256 + message_type, m3ua_message_class_type_acro_values, "reserved"));
426     col_append_str(pinfo->cinfo, COL_INFO, " ");
427   }
428
429   if (m3ua_tree) {
430     /* add the components of the common header to the protocol tree */
431     proto_tree_add_uint(m3ua_tree, hf_m3ua_version, common_header_tvb, VERSION_OFFSET, VERSION_LENGTH, version);
432     proto_tree_add_uint(m3ua_tree, hf_m3ua_reserved, common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH, reserved);
433     proto_tree_add_uint(m3ua_tree, hf_m3ua_message_class, common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH, message_class);
434     proto_tree_add_uint_format(m3ua_tree, hf_m3ua_message_type, common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type,
435                                "Message type: %s (%u)", 
436                                val_to_str(message_class * 256 + message_type, m3ua_message_class_type_values, "reserved"), message_type);
437     proto_tree_add_uint(m3ua_tree, hf_m3ua_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, message_length);
438   }
439 }
440
441 #define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
442
443 static void
444 dissect_m3ua_info_string_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
445 {
446   guint16 length, info_string_length;
447   char *info_string;
448
449   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
450   
451   info_string_length = length - PARAMETER_HEADER_LENGTH;
452   info_string = (char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length);
453   proto_tree_add_string(parameter_tree, hf_m3ua_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, info_string);
454   proto_item_set_text(parameter_item, "Info String (%.*s)", info_string_length, info_string);
455 }
456
457 #define ROUTING_CONTEXT_LENGTH 4
458
459 static void
460 dissect_m3ua_routing_context_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
461 {
462   guint16 length, number_of_contexts, context_number;
463   guint32 context;
464   gint context_offset;
465
466   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
467   number_of_contexts = (length - PARAMETER_HEADER_LENGTH) / 4;
468   context_offset = PARAMETER_VALUE_OFFSET;
469   for(context_number=1; context_number <= number_of_contexts; context_number++) {
470     context = tvb_get_ntohl(parameter_tvb, context_offset);
471     proto_tree_add_uint(parameter_tree, hf_m3ua_routing_context, parameter_tvb, context_offset, ROUTING_CONTEXT_LENGTH, context);
472     context_offset += ROUTING_CONTEXT_LENGTH;
473   }
474   proto_item_set_text(parameter_item, "Routing context parameter (%u context%s)", number_of_contexts, plurality(number_of_contexts, "", "s"));
475 }
476
477 static void
478 dissect_m3ua_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
479 {
480   guint16 length, diagnostic_info_length;
481   
482   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
483   diagnostic_info_length = length - PARAMETER_HEADER_LENGTH;
484
485   proto_tree_add_bytes(parameter_tree, hf_m3ua_diagnostic_information, parameter_tvb, PARAMETER_VALUE_OFFSET, diagnostic_info_length,
486                                    tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, diagnostic_info_length));
487
488   proto_item_set_text(parameter_item, "Diagnostic information (%u byte%s)", diagnostic_info_length, plurality(diagnostic_info_length, "", "s"));
489 }
490
491 static void
492 dissect_m3ua_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
493 {
494   guint16 length, heartbeat_data_length;
495   
496   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
497   
498   heartbeat_data_length = length - PARAMETER_HEADER_LENGTH;
499
500   proto_tree_add_bytes(parameter_tree, hf_m3ua_heartbeat_data, parameter_tvb, PARAMETER_VALUE_OFFSET, heartbeat_data_length,
501                                    tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, heartbeat_data_length));
502
503   proto_item_set_text(parameter_item, "Heartbeat data (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
504 }
505
506 #define OVER_RIDE_TYPE           1
507 #define LOAD_SHARE_TYPE          2
508 #define OVER_RIDE_STANDBY_TYPE   3
509 #define LOAD_SHARE_STANDBY_TYPE  4
510
511 static const value_string m3ua_v6_traffic_mode_type_values[] = {
512   { OVER_RIDE_TYPE ,                             "Over-ride" },
513   { LOAD_SHARE_TYPE,                             "Load-share" },
514   { OVER_RIDE_STANDBY_TYPE,                      "Over-ride (standby)" },
515   { LOAD_SHARE_STANDBY_TYPE,                     "Load-share (standby)" },
516   {0,                           NULL } };
517
518 static void
519 dissect_m3ua_v6_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
520 {
521   guint32 traffic_mode_type;
522
523   traffic_mode_type = tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET);
524
525   proto_tree_add_uint_format(parameter_tree, hf_m3ua_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, traffic_mode_type,
526                              "Traffic mode type: %u (%s)", traffic_mode_type, val_to_str(traffic_mode_type, m3ua_v6_traffic_mode_type_values, "unknown"));
527   proto_item_set_text(parameter_item, "Traffic mode type parameter (%s)", val_to_str(traffic_mode_type, m3ua_v6_traffic_mode_type_values, "unknown"));
528 }
529
530 #define BROADCAST_TYPE   3
531
532 static const value_string m3ua_v12_traffic_mode_type_values[] = {
533   { OVER_RIDE_TYPE ,                             "Over-ride" },
534   { LOAD_SHARE_TYPE,                             "Load-share" },
535   { BROADCAST_TYPE,                              "Broadcast" },
536   {0,                           NULL } };
537
538 static void
539 dissect_m3ua_v12_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
540 {
541   guint32 traffic_mode_type;
542
543   traffic_mode_type = tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET);
544
545   proto_tree_add_uint_format(parameter_tree, hf_m3ua_traffic_mode_type, 
546                                                parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH,
547                                                traffic_mode_type, "Traffic mode type: %u (%s)",
548                                                traffic_mode_type, val_to_str(traffic_mode_type, m3ua_v12_traffic_mode_type_values, "unknown"));
549   proto_item_set_text(parameter_item, "Traffic mode type parameter (%s)", val_to_str(traffic_mode_type, m3ua_v12_traffic_mode_type_values, "unknown"));
550 }
551
552 #define V6_INVALID_VERSION_ERROR_CODE               1
553 #define V6_INVALID_NETWORK_APPEARANCE_ERROR_CODE    2
554 #define V6_UNSUPPORTED_MESSAGE_CLASS_ERROR_CODE     3
555 #define V6_UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE      4
556 #define V6_INVALID_TRAFFIC_HANDLING_MODE_ERROR_CODE 5
557 #define V6_UNEXPECTED_MESSAGE_ERROR_CODE            6
558 #define V6_PROTOCOL_ERROR_ERROR_CODE                7
559 #define V6_INVALID_ROUTING_CONTEXT_ERROR_CODE       8
560 #define V6_INVALID_STREAM_IDENTIFIER_ERROR_CODE     9
561 #define V6_INVALID_PARAMETER_VALUE_ERROR_CODE      10
562
563 static const value_string m3ua_v6_error_code_values[] = {
564   { V6_INVALID_VERSION_ERROR_CODE,               "Invalid version" },
565   { V6_INVALID_NETWORK_APPEARANCE_ERROR_CODE,    "Invalid network appearance" },
566   { V6_UNSUPPORTED_MESSAGE_CLASS_ERROR_CODE,     "Unsupported message class" },
567   { V6_UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE,      "Unsupported message type" },
568   { V6_INVALID_TRAFFIC_HANDLING_MODE_ERROR_CODE, "Invalid traffic handling mode" },
569   { V6_UNEXPECTED_MESSAGE_ERROR_CODE,            "Unexpected message" },
570   { V6_PROTOCOL_ERROR_ERROR_CODE,                "Protocol error" },
571   { V6_INVALID_ROUTING_CONTEXT_ERROR_CODE,       "Invalid routing context" },
572   { V6_INVALID_STREAM_IDENTIFIER_ERROR_CODE,     "Invalid stream identifier" },
573   { V6_INVALID_PARAMETER_VALUE_ERROR_CODE,       "Invalid parameter value" },
574   { 0,                           NULL } };
575
576 #define ERROR_CODE_LENGTH 4
577 #define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
578
579 static void
580 dissect_m3ua_v6_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
581 {
582   guint32 error_code;
583
584   error_code = tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET);
585   proto_tree_add_uint_format(parameter_tree, hf_m3ua_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, error_code,
586                              "Error code: %u (%s)", error_code, val_to_str(error_code, m3ua_v6_error_code_values, "unknown"));
587   proto_item_set_text(parameter_item, "Error code parameter (%s)", val_to_str(error_code, m3ua_v6_error_code_values, "unknown"));
588 }
589
590
591 #define V12_INVALID_VERSION_ERROR_CODE                   0x01
592 #define V12_UNSUPPORTED_MESSAGE_CLASS_ERROR_CODE         0x03
593 #define V12_UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE          0x04
594 #define V12_UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR_CODE 0x05
595 #define V12_UNEXPECTED_MESSAGE_ERROR_CODE                0x06
596 #define V12_PROTOCOL_ERROR_ERROR_CODE                    0x07
597 #define V12_INVALID_STREAM_IDENTIFIER_ERROR_CODE         0x09
598 #define V12_REFUSED_ERROR_CODE                           0x0d
599 #define V12_ASP_IDENTIFIER_REQUIRED_ERROR_CODE           0x0e
600 #define V12_INVALID_ASP_IDENTIFIER_ERROR_CODE            0x0f
601 #define V12_INVALID_PARAMETER_VALUE_ERROR_CODE           0x11
602 #define V12_PARAMETER_FIELD_ERROR_CODE                   0x12
603 #define V12_UNEXPECTED_PARAMETER_ERROR_CODE              0x13
604 #define V12_DESTINATION_STATUS_UNKNOWN_ERROR_CODE        0x14
605 #define V12_INVALID_NETWORK_APPEARANCE_ERROR_CODE        0x15
606 #define V12_MISSING_PARAMETER_ERROR_CODE                 0x16
607 #define V12_INVALID_ROUTING_CONTEXT_ERROR_CODE           0x19
608 #define V12_NO_CONFIGURED_AS_FOR_ASP_ERROR_CODE          0x1a
609
610 static const value_string m3ua_v12_error_code_values[] = {
611   { V12_INVALID_VERSION_ERROR_CODE,                   "Invalid version" },
612   { V12_UNSUPPORTED_MESSAGE_CLASS_ERROR_CODE,         "Unsupported message class" },
613   { V12_UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE,          "Unsupported message type" },
614   { V12_UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR_CODE, "Unsupported traffic handling mode" },
615   { V12_UNEXPECTED_MESSAGE_ERROR_CODE,                "Unexpected message" },
616   { V12_PROTOCOL_ERROR_ERROR_CODE,                    "Protocol error" },
617   { V12_INVALID_STREAM_IDENTIFIER_ERROR_CODE,         "Invalid stream identifier" },
618   { V12_REFUSED_ERROR_CODE,                           "Refused - management blocking" },
619   { V12_ASP_IDENTIFIER_REQUIRED_ERROR_CODE,           "ASP identifier required" },
620   { V12_INVALID_ASP_IDENTIFIER_ERROR_CODE,            "Invalid ASP identifier" },
621   { V12_INVALID_PARAMETER_VALUE_ERROR_CODE,           "Invalid parameter value" },
622   { V12_PARAMETER_FIELD_ERROR_CODE,                   "Parameter field error" },
623   { V12_UNEXPECTED_PARAMETER_ERROR_CODE,              "Unexpected parameter" },
624   { V12_DESTINATION_STATUS_UNKNOWN_ERROR_CODE,        "Destination status unknown" },
625   { V12_INVALID_NETWORK_APPEARANCE_ERROR_CODE,        "Invalid network appearance" },
626   { V12_MISSING_PARAMETER_ERROR_CODE,                 "Missing parameter" },
627   { V12_INVALID_ROUTING_CONTEXT_ERROR_CODE,           "Invalid routing context" },
628   { V12_NO_CONFIGURED_AS_FOR_ASP_ERROR_CODE,          "No configured AS for ASP" },
629   { 0,                                            NULL } };
630
631 static void
632 dissect_m3ua_v12_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
633 {
634   guint32 error_code;
635
636   error_code = tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET);
637   proto_tree_add_uint_format(parameter_tree, hf_m3ua_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, error_code,
638                              "Error code: %u (%s)",error_code, val_to_str(error_code, m3ua_v12_error_code_values, "unknown"));
639   proto_item_set_text(parameter_item, "Error code parameter (%s)", val_to_str(error_code, m3ua_v12_error_code_values, "unknown"));
640 }
641
642 #define AS_STATE_CHANGE_TYPE       1
643 #define OTHER_TYPE                 2
644
645 static const value_string m3ua_status_type_values[] = {
646   { AS_STATE_CHANGE_TYPE,            "Application server state change" },
647   { OTHER_TYPE,                      "Other" },
648   { 0,                           NULL } };
649
650 #define RESERVED_INFO              1
651 #define AS_INACTIVE_INFO           2
652 #define AS_ACTIVE_INFO             3
653 #define AS_PENDING_INFO            4
654
655 #define INSUFFICIENT_ASP_RES_INFO  1
656 #define ALTERNATE_ASP_ACTIVE_INFO  2
657 #define ASP_FAILURE_INFO           3
658
659 static const value_string m3ua_status_type_info_values[] = {
660   { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO,             "Reserved" },
661   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO,          "Application server inactive" },
662   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO,            "Application server active" },
663   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO,           "Application server pending" },
664   { OTHER_TYPE           * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
665   { OTHER_TYPE           * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
666   { OTHER_TYPE           * 256 * 256 + ASP_FAILURE_INFO,          "ASP Failure" },
667   {0,                           NULL } };
668
669 #define STATUS_TYPE_LENGTH 2
670 #define STATUS_INFO_LENGTH 2
671
672 #define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
673 #define STATUS_INFO_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
674
675 static void
676 dissect_m3ua_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
677 {
678   guint16 status_type, status_info;
679
680   status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
681   status_info = tvb_get_ntohs(parameter_tvb, STATUS_INFO_OFFSET);
682
683   proto_tree_add_uint(parameter_tree, hf_m3ua_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, status_type);
684   proto_tree_add_uint_format(parameter_tree, hf_m3ua_status_info, parameter_tvb, STATUS_INFO_OFFSET, STATUS_INFO_LENGTH, status_info,
685                              "Status info: %s (%u)", val_to_str(status_type * 256 * 256 + status_info, m3ua_status_type_info_values, "unknown"), status_info);
686
687   proto_item_set_text(parameter_item, 
688                       "Status type / ID (%s)", val_to_str(status_type * 256 * 256 + status_info, m3ua_status_type_info_values, "unknown status information"));
689 }
690
691 #define ASP_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
692 #define ASP_IDENTIFIER_LENGTH  4
693
694 static void
695 dissect_m3ua_asp_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
696 {
697   guint32 identifier;
698   
699   identifier = tvb_get_ntohl(parameter_tvb, ASP_IDENTIFIER_OFFSET);
700   proto_tree_add_uint(parameter_tree, hf_m3ua_asp_identifier, parameter_tvb, ASP_IDENTIFIER_OFFSET, ASP_IDENTIFIER_LENGTH, identifier);
701   proto_item_set_text(parameter_item, "ASP identifier (%u)", identifier);
702 }
703
704 #define AFFECTED_MASK_LENGTH       1
705 #define AFFECTED_PC_LENGTH         3
706 #define AFFECTED_POINT_CODE_LENGTH (AFFECTED_MASK_LENGTH + AFFECTED_PC_LENGTH)
707
708 #define AFFECTED_MASK_OFFSET        0
709 #define AFFECTED_PC_OFFSET         (AFFECTED_MASK_OFFSET + AFFECTED_MASK_LENGTH)
710
711 static void
712 dissect_m3ua_affected_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
713 {
714   guint8  mask;
715   guint16 length, number_of_point_codes, point_code_number;
716   guint32 pc;
717   gint point_code_offset;
718
719   length                = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
720   number_of_point_codes = (length - PARAMETER_HEADER_LENGTH) / AFFECTED_POINT_CODE_LENGTH;
721
722   point_code_offset = PARAMETER_VALUE_OFFSET;
723   for(point_code_number=1; point_code_number <= number_of_point_codes; point_code_number++) {
724     mask = tvb_get_guint8(parameter_tvb, point_code_offset + AFFECTED_MASK_OFFSET);
725     pc   = tvb_get_ntoh24(parameter_tvb, point_code_offset + AFFECTED_PC_OFFSET);
726     proto_tree_add_uint(parameter_tree, hf_m3ua_affected_point_code_mask, parameter_tvb, point_code_offset + AFFECTED_MASK_OFFSET, AFFECTED_MASK_LENGTH, mask);
727     proto_tree_add_uint(parameter_tree, hf_m3ua_affected_point_code_pc, parameter_tvb, point_code_offset + AFFECTED_PC_OFFSET, AFFECTED_PC_LENGTH, pc);
728     point_code_offset += AFFECTED_POINT_CODE_LENGTH;
729   };
730   proto_item_set_text(parameter_item, "Affected point code parameter (%u point code%s)", number_of_point_codes, plurality(number_of_point_codes, "", "s"));
731
732 }
733
734 #define NETWORK_APPEARANCE_LENGTH 4
735 #define NETWORK_APPEARANCE_OFFSET PARAMETER_VALUE_OFFSET
736
737 static void
738 dissect_m3ua_network_appearance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
739 {
740   guint32 network_appearance;
741
742   network_appearance = tvb_get_ntohl(parameter_tvb, NETWORK_APPEARANCE_OFFSET);
743   proto_tree_add_uint(parameter_tree, hf_m3ua_network_appearance, parameter_tvb, NETWORK_APPEARANCE_OFFSET, NETWORK_APPEARANCE_LENGTH, network_appearance);
744   proto_item_set_text(parameter_item, "Network appearance: %u", network_appearance);
745 }
746
747 #define UNKNOWN_UNAVAIL_CAUSE                  0
748 #define UNEQUIPPED_REMOTE_USER_UNAVAIL_CAUSE   1
749 #define INACCESSABLE_REMOTE_USER_UNAVAIL_CAUSE 2
750
751 static const value_string m3ua_unavailability_cause_values[] = {
752   { UNKNOWN_UNAVAIL_CAUSE,                             "Unknown" },
753   { UNEQUIPPED_REMOTE_USER_UNAVAIL_CAUSE,              "Unequipped remote user" },
754   { INACCESSABLE_REMOTE_USER_UNAVAIL_CAUSE,            "Inaccessable remote user" },
755   {0,                           NULL } };
756
757 #define RESERVED_0_USER_ID                0
758 #define RESERVED_1_USER_ID                1
759 #define RESERVED_2_USER_ID                2
760 #define SCCP_USER_ID                      3
761 #define TUP_USER_ID                       4
762 #define ISUP_USER_ID                      5
763 #define RESERVED_6_USER_ID                6
764 #define RESERVED_7_USER_ID                7
765 #define RESERVED_8_USER_ID                8
766 #define BROADBAND_ISUP_USER_ID            9
767 #define SATELLITE_ISUP_USER_ID           10
768
769 static const value_string m3ua_user_identity_values[] = {
770   { RESERVED_0_USER_ID,                             "Reserved" },
771   { RESERVED_1_USER_ID,                             "Reserved" },
772   { RESERVED_2_USER_ID,                             "Reserved" },
773   { SCCP_USER_ID,                                   "SCCP" },
774   { TUP_USER_ID,                                    "TUP" },
775   { ISUP_USER_ID,                                   "ISUP" },
776   { RESERVED_6_USER_ID,                             "Reserved" },
777   { RESERVED_7_USER_ID,                             "Reserved" },
778   { RESERVED_8_USER_ID,                             "Reserved" },
779   { BROADBAND_ISUP_USER_ID,                         "Broadband ISUP" },
780   { SATELLITE_ISUP_USER_ID,                         "Satellite ISUP" },
781   {0,                           NULL } };
782
783 #define CAUSE_LENGTH 2
784 #define USER_LENGTH  2
785
786 #define CAUSE_OFFSET  PARAMETER_VALUE_OFFSET
787 #define USER_OFFSET   (CAUSE_OFFSET + CAUSE_LENGTH)
788
789 static void
790 dissect_m3ua_user_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
791 {
792   guint16 cause, user;
793
794   cause = tvb_get_ntohs(parameter_tvb, CAUSE_OFFSET);
795   user  = tvb_get_ntohs(parameter_tvb, USER_OFFSET);
796
797   proto_tree_add_uint(parameter_tree, hf_m3ua_unavailability_cause, parameter_tvb, CAUSE_OFFSET, CAUSE_LENGTH, cause);
798   proto_tree_add_uint(parameter_tree, hf_m3ua_user_identity, parameter_tvb, USER_OFFSET, USER_LENGTH, user);
799   proto_item_set_text(parameter_item, "User / Cause parameter (%s: %s)",
800                                   val_to_str(user, m3ua_user_identity_values, "Unknown user"),
801                       val_to_str(cause, m3ua_unavailability_cause_values, "unknown cause"));
802 }
803
804 static void
805 dissect_m3ua_protocol_data_1_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
806 {
807   guint16 length, protocol_data_length;
808   tvbuff_t *payload_tvb;
809
810   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
811   protocol_data_length = length - PARAMETER_HEADER_LENGTH;
812   payload_tvb          = tvb_new_subset(parameter_tvb, PROTOCOL_DATA_OFFSET, protocol_data_length, protocol_data_length);
813   proto_item_set_text(parameter_item, "Protocol data (SS7 message of %u byte%s)", protocol_data_length, plurality(protocol_data_length, "", "s"));
814   proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH);
815   call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
816
817 }
818
819 #define LI_OCTETT_LENGTH 1
820 #define LI_OCTETT_OFFSET PARAMETER_VALUE_OFFSET
821
822 static void
823 dissect_m3ua_protocol_data_2_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
824 {
825   guint8 li;
826   guint16 length, protocol_data_length;
827   tvbuff_t *payload_tvb;
828
829   length               = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
830   li                   = tvb_get_guint8(parameter_tvb, LI_OCTETT_OFFSET);
831   protocol_data_length = length - PARAMETER_HEADER_LENGTH - LI_OCTETT_LENGTH;
832   payload_tvb          = tvb_new_subset(parameter_tvb, PROTOCOL_DATA_OFFSET + LI_OCTETT_LENGTH, protocol_data_length, protocol_data_length);
833   proto_tree_add_uint(parameter_tree, hf_m3ua_li, parameter_tvb, LI_OCTETT_OFFSET, LI_OCTETT_LENGTH, li);
834   proto_item_set_text(parameter_item, "Protocol data (SS7 message of %u byte%s)", protocol_data_length, plurality(protocol_data_length, "", "s"));
835   proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH + LI_OCTETT_LENGTH);
836   call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
837 }
838
839 static void
840 dissect_m3ua_reason_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
841 {
842   guint32 reason;
843
844   reason = tvb_get_ntohl(parameter_tvb, REASON_OFFSET);
845
846   proto_tree_add_uint(parameter_tree, hf_m3ua_reason, parameter_tvb, REASON_OFFSET, REASON_LENGTH, reason);
847   proto_item_set_text(parameter_item, "Reason parameter (%s)", val_to_str(reason, m3ua_reason_values, "unknown"));
848 }
849
850 #define NO_CONGESTION_LEVEL         0
851 #define CONGESTION_LEVEL_1_LEVEL    1
852 #define CONGESTION_LEVEL_2_LEVEL    2
853 #define CONGESTION_LEVEL_3_LEVEL    3
854
855 static const value_string m3ua_congestion_level_values[] = {
856   { NO_CONGESTION_LEVEL,                             "No congestion or undefined" },
857   { CONGESTION_LEVEL_1_LEVEL,                        "Congestion level 1" },
858   { CONGESTION_LEVEL_2_LEVEL,                        "Congestion level 2" },
859   { CONGESTION_LEVEL_3_LEVEL,                        "Congestion level 3" },
860   {0,                           NULL } };
861
862 #define CONG_IND_RESERVED_LENGTH    3
863 #define CONG_IND_LEVEL_LENGTH       1
864
865 #define CONG_IND_RESERVED_OFFSET     PARAMETER_VALUE_OFFSET
866 #define CONG_IND_LEVEL_OFFSET        (CONG_IND_RESERVED_OFFSET + CONG_IND_RESERVED_LENGTH)
867
868 static void
869 dissect_m3ua_congestion_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
870 {
871   guint8 level;
872   
873   level = tvb_get_guint8(parameter_tvb, CONG_IND_LEVEL_OFFSET);
874
875   proto_tree_add_bytes(parameter_tree, hf_m3ua_congestion_reserved, parameter_tvb, CONG_IND_RESERVED_OFFSET, CONG_IND_RESERVED_LENGTH,
876                        tvb_get_ptr(parameter_tvb, CONG_IND_RESERVED_OFFSET, CONG_IND_RESERVED_LENGTH));
877   proto_tree_add_uint(parameter_tree, hf_m3ua_congestion_level, parameter_tvb, CONG_IND_LEVEL_OFFSET, CONG_IND_LEVEL_LENGTH, level);
878   proto_item_set_text(parameter_item, "Congestion indication(%s)", val_to_str(level, m3ua_congestion_level_values, "unknown"));
879 }
880
881 #define CON_DEST_RESERVED_LENGTH    1
882 #define CON_DEST_PC_LENGTH          3
883
884 #define CON_DEST_RESERVED_OFFSET    PARAMETER_VALUE_OFFSET
885 #define CON_DEST_PC_OFFSET          (CON_DEST_RESERVED_OFFSET + CON_DEST_RESERVED_LENGTH)
886
887 static void
888 dissect_m3ua_concerned_destination_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
889 {
890   guint32 pc;
891   
892   pc = tvb_get_ntoh24(parameter_tvb, CON_DEST_PC_OFFSET);
893
894   proto_tree_add_bytes(parameter_tree, hf_m3ua_concerned_dest_reserved, parameter_tvb, CON_DEST_RESERVED_OFFSET, CON_DEST_RESERVED_LENGTH,
895                        tvb_get_ptr(parameter_tvb, CON_DEST_RESERVED_OFFSET, CON_DEST_RESERVED_LENGTH));
896   proto_tree_add_uint(parameter_tree, hf_m3ua_concerned_dest_pc, parameter_tvb, CON_DEST_PC_OFFSET, CON_DEST_PC_LENGTH, pc);
897   proto_item_set_text(parameter_item, "Concerned destination (%u)", pc);
898 }
899
900 static void
901 dissect_m3ua_routing_key_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
902 {
903   tvbuff_t *parameters_tvb;
904   guint16 length, parameters_length;
905   
906   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
907   parameters_length = length - PARAMETER_HEADER_LENGTH;
908   parameters_tvb          = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
909   dissect_m3ua_parameters(parameters_tvb, pinfo, tree, parameter_tree);
910   proto_item_set_text(parameter_item, "Routing key");
911 }
912
913 static const value_string m3ua_registration_result_status_values[] = {
914   { 0,           "Successfully Registered" } ,
915   { 1,           "Error - Unknown" } ,
916   { 2,           "Error - Invalid DPC" } ,
917   { 3,           "Error - Invalid Network Appearance" } ,
918   { 4,           "Error - Invalid Routing Key" } ,
919   { 5,           "Error - Permission Denied" } ,
920   { 6,           "Error - Overlapping (Non-unique) Routing Key" } ,
921   { 7,           "Error - Routing Key not Provisioned" } ,
922   { 8,           "Error - Insufficient Resources" } ,
923   { 0,           NULL } };
924
925 #define REG_RES_IDENTIFIER_LENGTH 4
926 #define REG_RES_STATUS_LENGTH     4
927 #define REG_RES_CONTEXT_LENGTH    4
928
929 #define REG_RES_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
930 #define REG_RES_STATUS_OFFSET     (REG_RES_IDENTIFIER_OFFSET + REG_RES_IDENTIFIER_LENGTH)
931 #define REG_RES_CONTEXT_OFFSET    (REG_RES_STATUS_OFFSET + REG_RES_STATUS_LENGTH)
932
933 static void
934 dissect_m3ua_v6_registration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
935 {
936   guint32 id, status, context;
937
938   id      = tvb_get_ntohl(parameter_tvb, REG_RES_IDENTIFIER_OFFSET);
939   status  = tvb_get_ntohl(parameter_tvb, REG_RES_STATUS_OFFSET);
940   context = tvb_get_ntohl(parameter_tvb, REG_RES_CONTEXT_OFFSET);
941
942   proto_tree_add_uint(parameter_tree, hf_m3ua_registration_result_identifier, parameter_tvb, REG_RES_IDENTIFIER_OFFSET, REG_RES_IDENTIFIER_LENGTH, id);
943   proto_tree_add_uint(parameter_tree, hf_m3ua_registration_result_status, parameter_tvb, REG_RES_STATUS_OFFSET, REG_RES_STATUS_LENGTH, status);
944   proto_tree_add_uint(parameter_tree, hf_m3ua_registration_result_context, parameter_tvb, REG_RES_CONTEXT_OFFSET, REG_RES_CONTEXT_LENGTH, context); 
945   proto_item_set_text(parameter_item, "Registration result");
946 }
947
948 static void
949 dissect_m3ua_v12_registration_result_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
950 {
951   tvbuff_t *parameters_tvb;
952   guint16 length, parameters_length;
953   
954   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
955   parameters_length = length - PARAMETER_HEADER_LENGTH;
956   parameters_tvb          = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
957   dissect_m3ua_parameters(parameters_tvb, pinfo, tree, parameter_tree);
958   proto_item_set_text(parameter_item, "Registration result");
959 }
960
961 static const value_string m3ua_deregistration_result_status_values[] = {
962   { 0,           "Successfully De-registered" } ,
963   { 1,           "Error - Unknown" } ,
964   { 2,           "Error - Invalid Routing context" } ,
965   { 3,           "Error - Permission Denied" } ,
966   { 4,           "Error - Not registered" } ,
967   { 0,           NULL } };
968
969 #define DEREG_RES_CONTEXT_LENGTH 4
970 #define DEREG_RES_STATUS_LENGTH  4
971
972 #define DEREG_RES_CONTEXT_OFFSET PARAMETER_VALUE_OFFSET
973 #define DEREG_RES_STATUS_OFFSET  (DEREG_RES_CONTEXT_OFFSET + DEREG_RES_CONTEXT_LENGTH)
974
975 static void
976 dissect_m3ua_v6_deregistration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
977 {
978   guint32 status, context;
979
980   context = tvb_get_ntohl(parameter_tvb, DEREG_RES_CONTEXT_OFFSET);
981   status  = tvb_get_ntohl(parameter_tvb, DEREG_RES_STATUS_OFFSET);
982
983   proto_tree_add_uint(parameter_tree, hf_m3ua_deregistration_result_context, parameter_tvb, DEREG_RES_CONTEXT_OFFSET, DEREG_RES_CONTEXT_LENGTH, context); 
984   proto_tree_add_uint(parameter_tree, hf_m3ua_deregistration_result_status, parameter_tvb, DEREG_RES_STATUS_OFFSET, DEREG_RES_STATUS_LENGTH, status);
985   proto_item_set_text(parameter_item, "De-registration result");
986
987 }
988
989 static void
990 dissect_m3ua_v12_deregistration_result_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
991 {
992   tvbuff_t *parameters_tvb;
993   guint16 length, parameters_length;
994   
995   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
996   parameters_length = length - PARAMETER_HEADER_LENGTH;
997   parameters_tvb          = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
998   dissect_m3ua_parameters(parameters_tvb, pinfo, tree, parameter_tree);
999   proto_item_set_text(parameter_item, "Deregistration result");
1000 }
1001
1002
1003 #define LOCAL_RK_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
1004 #define LOCAL_RK_IDENTIFIER_LENGTH 4
1005
1006 static void
1007 dissect_m3ua_local_routing_key_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1008 {
1009   guint32 id;
1010   
1011   id = tvb_get_ntohl(parameter_tvb, LOCAL_RK_IDENTIFIER_OFFSET);
1012   proto_tree_add_uint(parameter_tree, hf_m3ua_local_rk_identifier, parameter_tvb, LOCAL_RK_IDENTIFIER_OFFSET, LOCAL_RK_IDENTIFIER_LENGTH, id);
1013   proto_item_set_text(parameter_item, "Local routing key identifier (%u)", id);
1014 }
1015
1016 #define DPC_MASK_LENGTH    1
1017 #define DPC_PC_LENGTH      3
1018
1019 #define DPC_MASK_OFFSET    PARAMETER_VALUE_OFFSET
1020 #define DPC_PC_OFFSET      (DPC_MASK_OFFSET + DPC_MASK_LENGTH)
1021
1022 static void
1023 dissect_m3ua_destination_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1024 {
1025   guint32 pc;
1026   guint8  mask;
1027  
1028   mask = tvb_get_guint8(parameter_tvb, DPC_MASK_OFFSET);
1029   pc   = tvb_get_ntoh24(parameter_tvb, DPC_PC_OFFSET);
1030
1031   proto_tree_add_uint(parameter_tree, hf_m3ua_dpc_mask, parameter_tvb, DPC_MASK_OFFSET, DPC_MASK_LENGTH, mask);
1032   proto_tree_add_uint(parameter_tree, hf_m3ua_dpc_pc, parameter_tvb, DPC_PC_OFFSET, DPC_PC_LENGTH, pc);
1033   proto_item_set_text(parameter_item, "Destination point code (%u)", pc);
1034 }
1035
1036 #define SI_LENGTH 1
1037
1038 static void
1039 dissect_m3ua_service_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1040 {
1041   guint8  si;
1042   guint16 length, number_of_sis, si_number;
1043   gint si_offset;
1044
1045   length        = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1046   number_of_sis = length - PARAMETER_HEADER_LENGTH;
1047
1048   si_offset = PARAMETER_VALUE_OFFSET;
1049   for(si_number=1; si_number <= number_of_sis; si_number++) {
1050     si = tvb_get_guint8(parameter_tvb, si_offset);
1051     proto_tree_add_uint(parameter_tree, hf_m3ua_si, parameter_tvb, si_offset, SI_LENGTH, si);
1052     si_offset += SI_LENGTH;
1053   };
1054   proto_item_set_text(parameter_item, "Service indicators (%u indicator%s)", number_of_sis, plurality(number_of_sis, "", "s"));
1055
1056 }
1057 #define SSN_LENGTH 1
1058
1059 static void
1060 dissect_m3ua_subsystem_numbers_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1061 {
1062   guint8  ssn;
1063   guint16 length, number_of_ssns, ssn_number;
1064   gint ssn_offset;
1065
1066   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1067   number_of_ssns = length - PARAMETER_HEADER_LENGTH;
1068
1069   ssn_offset = PARAMETER_VALUE_OFFSET;
1070   for(ssn_number=1; ssn_number <= number_of_ssns; ssn_number++) {
1071     ssn = tvb_get_guint8(parameter_tvb, ssn_offset);
1072     proto_tree_add_uint(parameter_tree, hf_m3ua_ssn, parameter_tvb, ssn_offset, SSN_LENGTH, ssn);
1073     ssn_offset += SSN_LENGTH;
1074   };
1075   proto_item_set_text(parameter_item, "Subsystem numbers (%u number%s)", number_of_ssns, plurality(number_of_ssns, "", "s"));
1076
1077 }
1078
1079 #define OPC_MASK_LENGTH             1
1080 #define OPC_PC_LENGTH               3
1081 #define OPC_LENGTH                  (OPC_MASK_LENGTH + OPC_PC_LENGTH)
1082 #define OPC_MASK_OFFSET             0
1083 #define OPC_PC_OFFSET               (OPC_MASK_OFFSET + OPC_MASK_LENGTH)
1084
1085 static void
1086 dissect_m3ua_originating_point_code_list_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1087 {
1088   guint8  mask;
1089   guint16 length, number_of_point_codes, point_code_number;
1090   guint32 pc;
1091   gint point_code_offset;
1092
1093   length                = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1094   number_of_point_codes = (length - PARAMETER_HEADER_LENGTH) / 4;
1095
1096   point_code_offset = PARAMETER_VALUE_OFFSET;
1097   for(point_code_number=1; point_code_number <= number_of_point_codes; point_code_number++) {
1098     mask = tvb_get_guint8(parameter_tvb, point_code_offset + AFFECTED_MASK_OFFSET);
1099     pc   = tvb_get_ntoh24(parameter_tvb, point_code_offset + AFFECTED_PC_OFFSET);
1100     proto_tree_add_uint(parameter_tree, hf_m3ua_opc_list_mask, parameter_tvb, point_code_offset + OPC_MASK_OFFSET, OPC_MASK_LENGTH, mask);
1101     proto_tree_add_uint(parameter_tree, hf_m3ua_opc_list_pc, parameter_tvb, point_code_offset + OPC_PC_OFFSET, OPC_PC_LENGTH, pc);
1102     point_code_offset += OPC_LENGTH;
1103   };
1104   proto_item_set_text(parameter_item, "Originating point code list (%u point code%s)", number_of_point_codes, plurality(number_of_point_codes, "", "s"));
1105 }
1106
1107 #define CIC_RANGE_MASK_LENGTH             1
1108 #define CIC_RANGE_PC_LENGTH               3
1109 #define CIC_RANGE_LOWER_LENGTH            2
1110 #define CIC_RANGE_UPPER_LENGTH            2
1111 #define CIC_RANGE_LENGTH                  (CIC_RANGE_MASK_LENGTH + CIC_RANGE_PC_LENGTH + CIC_RANGE_LOWER_LENGTH + CIC_RANGE_UPPER_LENGTH)
1112 #define CIC_RANGE_MASK_OFFSET             0
1113 #define CIC_RANGE_PC_OFFSET               (CIC_RANGE_MASK_OFFSET + CIC_RANGE_MASK_LENGTH)
1114 #define CIC_RANGE_LOWER_OFFSET            (CIC_RANGE_PC_OFFSET + CIC_RANGE_PC_LENGTH)
1115 #define CIC_RANGE_UPPER_OFFSET            (CIC_RANGE_LOWER_OFFSET + CIC_RANGE_LOWER_LENGTH)
1116
1117 static void
1118 dissect_m3ua_circuit_range_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1119 {
1120   guint8  mask;
1121   guint16 length, number_of_point_codes, point_code_number, lower, upper;
1122   guint32 pc;
1123   gint point_code_offset;
1124
1125   length                = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1126   number_of_point_codes = (length - PARAMETER_HEADER_LENGTH) / CIC_RANGE_LENGTH;
1127
1128   point_code_offset = PARAMETER_VALUE_OFFSET;
1129   for(point_code_number = 1; point_code_number <= number_of_point_codes; point_code_number++) {
1130     mask  = tvb_get_guint8(parameter_tvb, point_code_offset + CIC_RANGE_MASK_OFFSET);
1131     pc    = tvb_get_ntoh24(parameter_tvb, point_code_offset + CIC_RANGE_PC_OFFSET);
1132     lower = tvb_get_ntohs(parameter_tvb, point_code_offset + CIC_RANGE_LOWER_OFFSET);
1133     upper = tvb_get_ntohs(parameter_tvb, point_code_offset + CIC_RANGE_UPPER_OFFSET);
1134
1135     proto_tree_add_uint(parameter_tree, hf_m3ua_cic_range_mask, parameter_tvb, point_code_offset + CIC_RANGE_MASK_OFFSET, CIC_RANGE_MASK_LENGTH, mask);
1136     proto_tree_add_uint(parameter_tree, hf_m3ua_cic_range_pc, parameter_tvb, point_code_offset + CIC_RANGE_PC_OFFSET, CIC_RANGE_PC_LENGTH, pc);
1137     proto_tree_add_uint(parameter_tree, hf_m3ua_cic_range_lower, parameter_tvb, point_code_offset + CIC_RANGE_LOWER_OFFSET, CIC_RANGE_LOWER_LENGTH, lower);
1138     proto_tree_add_uint(parameter_tree, hf_m3ua_cic_range_upper, parameter_tvb, point_code_offset + CIC_RANGE_UPPER_OFFSET, CIC_RANGE_UPPER_LENGTH, upper);
1139     point_code_offset += CIC_RANGE_LENGTH;
1140   };
1141   proto_item_set_text(parameter_item, "Circuit range (%u range%s)", number_of_point_codes, plurality(number_of_point_codes, "", "s"));
1142 }
1143
1144 #define DATA_OPC_LENGTH   4
1145 #define DATA_DPC_LENGTH   4
1146 #define DATA_SI_LENGTH    1
1147 #define DATA_NI_LENGTH    1
1148 #define DATA_MP_LENGTH    1
1149 #define DATA_SLS_LENGTH   1
1150 #define DATA_HDR_LENGTH   (DATA_OPC_LENGTH + DATA_DPC_LENGTH + DATA_SI_LENGTH + DATA_NI_LENGTH + DATA_MP_LENGTH + DATA_SLS_LENGTH)
1151
1152 #define DATA_OPC_OFFSET   PARAMETER_VALUE_OFFSET
1153 #define DATA_DPC_OFFSET   (DATA_OPC_OFFSET + DATA_OPC_LENGTH)
1154 #define DATA_SI_OFFSET    (DATA_DPC_OFFSET + DATA_DPC_LENGTH)
1155 #define DATA_NI_OFFSET    (DATA_SI_OFFSET + DATA_SI_LENGTH)
1156 #define DATA_MP_OFFSET    (DATA_NI_OFFSET + DATA_NI_LENGTH)
1157 #define DATA_SLS_OFFSET   (DATA_MP_OFFSET + DATA_MP_LENGTH)
1158 #define DATA_ULP_OFFSET   (DATA_SLS_OFFSET + DATA_SLS_LENGTH)
1159
1160 static void
1161 dissect_m3ua_protocol_data_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
1162 {
1163   guint32 opc, dpc;
1164   guint16 length, ulp_length;
1165   guint8 si, ni, mp, sls;
1166   tvbuff_t *payload_tvb;
1167
1168   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1169   ulp_length = length - PARAMETER_HEADER_LENGTH - DATA_HDR_LENGTH;
1170   payload_tvb          = tvb_new_subset(parameter_tvb, DATA_ULP_OFFSET, ulp_length, ulp_length);
1171   opc = tvb_get_ntohl(parameter_tvb, DATA_OPC_OFFSET);
1172   dpc = tvb_get_ntohl(parameter_tvb, DATA_DPC_OFFSET);
1173   si  = tvb_get_guint8(parameter_tvb, DATA_SI_OFFSET);
1174   ni  = tvb_get_guint8(parameter_tvb, DATA_NI_OFFSET);
1175   mp  = tvb_get_guint8(parameter_tvb, DATA_MP_OFFSET);
1176   sls = tvb_get_guint8(parameter_tvb, DATA_SLS_OFFSET);
1177   proto_tree_add_uint(parameter_tree, hf_m3ua_protocol_data_opc, parameter_tvb, DATA_OPC_OFFSET, DATA_OPC_LENGTH, opc);
1178   proto_tree_add_uint(parameter_tree, hf_m3ua_protocol_data_dpc, parameter_tvb, DATA_DPC_OFFSET, DATA_DPC_LENGTH, dpc);
1179   proto_tree_add_uint(parameter_tree, hf_m3ua_protocol_data_si,  parameter_tvb, DATA_SI_OFFSET,  DATA_SI_LENGTH,  si);
1180   proto_tree_add_uint(parameter_tree, hf_m3ua_protocol_data_ni,  parameter_tvb, DATA_NI_OFFSET,  DATA_NI_LENGTH,  ni);
1181   proto_tree_add_uint(parameter_tree, hf_m3ua_protocol_data_mp,  parameter_tvb, DATA_MP_OFFSET,  DATA_MP_LENGTH,  mp);
1182   proto_tree_add_uint(parameter_tree, hf_m3ua_protocol_data_sls, parameter_tvb, DATA_SLS_OFFSET, DATA_SLS_LENGTH, sls);
1183
1184   proto_item_set_text(parameter_item, "Protocol data (SS7 message of %u byte%s)", ulp_length, plurality(ulp_length, "", "s"));
1185   proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH + DATA_HDR_LENGTH);
1186   
1187   if (!dissector_try_port(m3ua_si_dissector_table, si, payload_tvb, pinfo, tree)) {
1188     call_dissector(data_handle, payload_tvb, pinfo, tree);
1189   }
1190 }
1191
1192 #define CORR_ID_OFFSET PARAMETER_VALUE_OFFSET
1193 #define CORR_ID_LENGTH 4
1194
1195 static void
1196 dissect_m3ua_correlation_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1197 {
1198   guint32 id;
1199   
1200   id = tvb_get_ntohl(parameter_tvb, CORR_ID_OFFSET);
1201   proto_tree_add_uint(parameter_tree, hf_m3ua_correlation_identifier, parameter_tvb, CORR_ID_OFFSET, CORR_ID_LENGTH, id);
1202   proto_item_set_text(parameter_item, "Correlation Identifer (%u)", id);
1203 }
1204
1205 #define REG_STATUS_LENGTH  4
1206 #define REG_STATUS_OFFSET  PARAMETER_VALUE_OFFSET
1207
1208 static const value_string m3ua_registration_status_values[] = {
1209   {  0,           "Successfully Registered" },
1210   {  1,           "Error - Unknown" },
1211   {  2,           "Error - Invalid DPC" },
1212   {  3,           "Error - Invalid Network Appearance" },
1213   {  4,           "Error - Invalid Routing Key" },
1214   {  5,           "Error - Permission Denied" },
1215   {  6,           "Error - Cannot Support Unique Routing" },
1216   {  7,           "Error - Routing Key not Currently Provisioned" },
1217   {  8,           "Error - Insufficient Resources" },
1218   {  9,           "Error - Unsupported RK parameter Field" },
1219   { 10,           "Error - Unsupported/Invalid Traffic Handling Mode" },
1220   {  0,           NULL } };
1221
1222 static void
1223 dissect_m3ua_registration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1224 {
1225   guint32 status;
1226   
1227   status = tvb_get_ntohl(parameter_tvb, REG_STATUS_OFFSET);
1228   proto_tree_add_uint(parameter_tree, hf_m3ua_registration_status, parameter_tvb, REG_STATUS_OFFSET, REG_STATUS_LENGTH, status);
1229   proto_item_set_text(parameter_item, "Registration status (%s)", val_to_str(status, m3ua_registration_status_values, "unknown"));
1230 }
1231
1232 #define DEREG_STATUS_LENGTH  4
1233 #define DEREG_STATUS_OFFSET  PARAMETER_VALUE_OFFSET
1234
1235 static const value_string m3ua_deregistration_status_values[] = {
1236   { 0,          "Successfully Deregistered" },
1237   { 1,          "Error - Unknown" },
1238   { 2,          "Error - Invalid Routing Context" },
1239   { 3,          "Error - Permission Denied" },
1240   { 4,          "Error - Not Registered" },
1241   { 5,          "Error - ASP Currently Active for Routing Context" },
1242   { 0,          NULL } };
1243
1244 static void
1245 dissect_m3ua_deregistration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1246 {
1247   guint32 status;
1248   
1249   status = tvb_get_ntohl(parameter_tvb, DEREG_STATUS_OFFSET);
1250   proto_tree_add_uint(parameter_tree, hf_m3ua_deregistration_status, parameter_tvb, DEREG_STATUS_OFFSET, DEREG_STATUS_LENGTH, status);
1251   proto_item_set_text(parameter_item, "Deregistration status (%s)", val_to_str(status, m3ua_deregistration_status_values, "unknown"));
1252 }
1253
1254 static void
1255 dissect_m3ua_registration_results_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
1256 {
1257   tvbuff_t *parameters_tvb;
1258   guint16 length, parameters_length;
1259   
1260   length            = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1261   parameters_length = length - PARAMETER_HEADER_LENGTH;
1262   parameters_tvb    = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
1263   dissect_m3ua_parameters(parameters_tvb, pinfo, tree, parameter_tree);
1264   proto_item_set_text(parameter_item, "Registration results");
1265 }
1266
1267 static void
1268 dissect_m3ua_deregistration_results_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
1269 {
1270   tvbuff_t *parameters_tvb;
1271   guint16 length, parameters_length;
1272   
1273   length            = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1274   parameters_length = length - PARAMETER_HEADER_LENGTH;
1275   parameters_tvb    = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
1276   dissect_m3ua_parameters(parameters_tvb, pinfo, tree, parameter_tree);
1277   proto_item_set_text(parameter_item, "Deregistration results");
1278 }
1279
1280 static void
1281 dissect_m3ua_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1282 {
1283   guint16 tag, length, parameter_value_length;
1284   
1285   tag    = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1286   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1287   
1288   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
1289
1290   proto_tree_add_bytes(parameter_tree, hf_m3ua_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, 
1291                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length));
1292
1293   proto_item_set_text(parameter_item, "Parameter with tag %u and %u byte%s value", tag, parameter_value_length, plurality(parameter_value_length, "", "s"));
1294 }
1295
1296 static void
1297 dissect_m3ua_v6_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
1298 {
1299   guint16 tag, length, padding_length, total_length;
1300   proto_item *parameter_item;
1301   proto_tree *parameter_tree;
1302
1303   /* extract tag and length from the parameter */
1304   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1305   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1306
1307   /* calculate padding and total length */
1308   padding_length = tvb_length(parameter_tvb) - length;
1309   total_length   = length + padding_length;
1310
1311   /* create proto_tree stuff */
1312   parameter_item   = proto_tree_add_text(m3ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, total_length, "Incomplete parameter");
1313   parameter_tree   = proto_item_add_subtree(parameter_item, ett_m3ua_parameter);
1314
1315   /* add tag and length to the m3ua tree */
1316   proto_tree_add_uint_format(parameter_tree, hf_m3ua_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, tag, 
1317                              "Parameter tag: %s (0x%x)", val_to_str(tag, m3ua_v6_parameter_tag_values, "unknown"), tag);
1318   proto_tree_add_uint(parameter_tree, hf_m3ua_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, length);
1319
1320   switch(tag) {
1321   case V6_NETWORK_APPEARANCE_PARAMETER_TAG:
1322     dissect_m3ua_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
1323     break;
1324   case V6_PROTOCOL_DATA_1_PARAMETER_TAG:
1325     dissect_m3ua_protocol_data_1_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1326     break;
1327   case V6_PROTOCOL_DATA_2_PARAMETER_TAG:
1328     dissect_m3ua_protocol_data_2_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1329     break;
1330   case V6_INFO_PARAMETER_TAG:
1331     dissect_m3ua_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
1332     break;
1333   case V6_AFFECTED_DESTINATIONS_PARAMETER_TAG:
1334     dissect_m3ua_affected_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1335     break;
1336   case V6_ROUTING_CONTEXT_PARAMETER_TAG:
1337     dissect_m3ua_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
1338     break;
1339   case V6_DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
1340     dissect_m3ua_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
1341     break;
1342   case V6_HEARTBEAT_DATA_PARAMETER_TAG:
1343     dissect_m3ua_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1344     break;
1345   case V6_USER_CAUSE_PARAMETER_TAG:
1346     dissect_m3ua_user_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
1347     break;
1348   case V6_REASON_PARAMETER_TAG:
1349     dissect_m3ua_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
1350     break;
1351   case V6_TRAFFIC_MODE_TYPE_PARAMETER_TAG:
1352     dissect_m3ua_v6_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1353     break;
1354   case V6_ERROR_CODE_PARAMETER_TAG:
1355     dissect_m3ua_v6_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1356     break;
1357   case V6_STATUS_PARAMETER_TAG:
1358     dissect_m3ua_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1359     break;
1360   case V6_CONGESTION_INDICATION_PARAMETER_TAG:
1361     dissect_m3ua_congestion_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
1362     break;
1363   case V6_CONCERNED_DESTINATION_PARAMETER_TAG:
1364     dissect_m3ua_concerned_destination_parameter(parameter_tvb, parameter_tree, parameter_item);
1365     break;
1366   case V6_ROUTING_KEY_PARAMETER_TAG:
1367     dissect_m3ua_routing_key_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1368     break;
1369   case V6_REGISTRATION_RESULT_PARAMETER_TAG:
1370     dissect_m3ua_v6_registration_result_parameter(parameter_tvb, parameter_tree, parameter_item);
1371     break;
1372   case V6_DEREGISTRATION_RESULT_PARAMETER_TAG:
1373     dissect_m3ua_v6_deregistration_result_parameter(parameter_tvb, parameter_tree, parameter_item);
1374     break;
1375   case V6_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
1376     dissect_m3ua_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1377     break;
1378   case V6_DESTINATION_POINT_CODE_PARAMETER_TAG:
1379     dissect_m3ua_destination_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1380     break;
1381   case V6_SERVICE_INDICATORS_PARAMETER_TAG:
1382     dissect_m3ua_service_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
1383     break;
1384   case V6_SUBSYSTEM_NUMBERS_PARAMETER_TAG:
1385     dissect_m3ua_subsystem_numbers_parameter(parameter_tvb, parameter_tree, parameter_item);
1386     break;
1387   case V6_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG:
1388     dissect_m3ua_originating_point_code_list_parameter(parameter_tvb, parameter_tree, parameter_item);
1389     break;
1390   case V6_CIRCUIT_RANGE_PARAMETER_TAG:
1391     dissect_m3ua_circuit_range_parameter(parameter_tvb, parameter_tree, parameter_item);
1392     break;
1393   case V6_REGISTRATION_RESULTS_PARAMETER_TAG:
1394     dissect_m3ua_registration_results_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1395     break;
1396   case V6_DEREGISTRATION_RESULTS_PARAMETER_TAG:
1397     dissect_m3ua_deregistration_results_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1398     break;
1399   default:
1400     dissect_m3ua_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1401     break;
1402   };
1403
1404   if (padding_length > 0)
1405     proto_tree_add_bytes(parameter_tree, hf_m3ua_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, 
1406                          tvb_get_ptr(parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length));
1407 }
1408
1409 static void
1410 dissect_m3ua_v12_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
1411 {
1412   guint16 tag, length, padding_length, total_length;
1413   proto_item *parameter_item;
1414   proto_tree *parameter_tree;
1415
1416   /* extract tag and length from the parameter */
1417   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1418   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1419
1420   /* calculate padding and total length */
1421   padding_length = tvb_length(parameter_tvb) - length;
1422   total_length   = length + padding_length;
1423
1424   /* create proto_tree stuff */
1425   parameter_item   = proto_tree_add_text(m3ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, total_length, "Incomplete parameter");
1426   parameter_tree   = proto_item_add_subtree(parameter_item, ett_m3ua_parameter);
1427
1428   /* add tag and length to the m3ua tree */
1429   proto_tree_add_uint_format(parameter_tree, hf_m3ua_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, tag, 
1430                              "Parameter tag: %s (0x%x)", val_to_str(tag, m3ua_v12_parameter_tag_values, "unknown"), tag);
1431   proto_tree_add_uint(parameter_tree, hf_m3ua_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, length);
1432
1433   switch(tag) {
1434   case V12_INFO_STRING_PARAMETER_TAG:
1435     dissect_m3ua_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
1436     break;
1437   case V12_ROUTING_CONTEXT_PARAMETER_TAG:
1438     dissect_m3ua_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
1439     break;
1440   case V12_DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
1441     dissect_m3ua_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
1442     break;
1443   case V12_HEARTBEAT_DATA_PARAMETER_TAG:
1444     dissect_m3ua_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1445     break;
1446   case V12_TRAFFIC_MODE_TYPE_PARAMETER_TAG:
1447     dissect_m3ua_v12_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1448     break;
1449   case V12_ERROR_CODE_PARAMETER_TAG:
1450     dissect_m3ua_v12_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1451     break;
1452   case V12_STATUS_PARAMETER_TAG:
1453     dissect_m3ua_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1454     break;
1455   case V12_ASP_IDENTIFIER_PARAMETER_TAG:
1456     dissect_m3ua_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1457     break;
1458   case V12_AFFECTED_POINT_CODE_PARAMETER_TAG:
1459     dissect_m3ua_affected_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1460     break;
1461   case V12_NETWORK_APPEARANCE_PARAMETER_TAG:
1462     dissect_m3ua_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
1463     break;
1464   case V12_USER_CAUSE_PARAMETER_TAG:
1465     dissect_m3ua_user_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
1466     break;
1467   case V12_CONGESTION_INDICATIONS_PARAMETER_TAG:
1468     dissect_m3ua_congestion_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
1469     break;
1470   case V12_CONCERNED_DESTINATION_PARAMETER_TAG:
1471     dissect_m3ua_concerned_destination_parameter(parameter_tvb, parameter_tree, parameter_item);
1472     break;
1473   case V12_ROUTING_KEY_PARAMETER_TAG:
1474     dissect_m3ua_routing_key_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1475     break;
1476   case V12_REGISTRATION_RESULT_PARAMETER_TAG:
1477     dissect_m3ua_v12_registration_result_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1478     break;
1479   case V12_DEREGISTRATION_RESULT_PARAMETER_TAG:
1480     dissect_m3ua_v12_deregistration_result_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1481     break;
1482   case V12_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
1483     dissect_m3ua_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1484     break;
1485   case V12_DESTINATION_POINT_CODE_PARAMETER_TAG:
1486     dissect_m3ua_destination_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1487     break;
1488   case V12_SERVICE_INDICATORS_PARAMETER_TAG:
1489     dissect_m3ua_service_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
1490     break;
1491   case V12_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG:
1492     dissect_m3ua_originating_point_code_list_parameter(parameter_tvb, parameter_tree, parameter_item);
1493     break;
1494   case V12_CIRCUIT_RANGE_PARAMETER_TAG:
1495     dissect_m3ua_circuit_range_parameter(parameter_tvb, parameter_tree, parameter_item);
1496     break;
1497   case V12_PROTOCOL_DATA_PARAMETER_TAG:
1498     dissect_m3ua_protocol_data_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
1499     break;
1500   case V12_CORRELATION_IDENTIFIER_PARAMETER_TAG:
1501     dissect_m3ua_correlation_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1502     break;
1503   case V12_REGISTRATION_STATUS_PARAMETER_TAG:
1504     dissect_m3ua_registration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1505     break;
1506   case V12_DEREGISTRATION_STATUS_PARAMETER_TAG:
1507     dissect_m3ua_deregistration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1508     break;
1509   default:
1510     dissect_m3ua_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1511     break;
1512   };
1513
1514   if (padding_length > 0)
1515     proto_tree_add_bytes(parameter_tree, hf_m3ua_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, 
1516                          tvb_get_ptr(parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length));
1517 }
1518
1519 static void
1520 dissect_m3ua_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
1521 {
1522   gint offset, length, padding_length, total_length, remaining_length;
1523   tvbuff_t *parameter_tvb;
1524
1525   offset = 0;
1526   while((remaining_length = tvb_reported_length_remaining(parameters_tvb, offset))) {
1527     length         = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
1528     padding_length = nr_of_padding_bytes(length);
1529     if (remaining_length >= length)
1530       total_length = MIN(length + padding_length, remaining_length);
1531     else
1532       total_length = length + padding_length;
1533     /* create a tvb for the parameter including the padding bytes */
1534     parameter_tvb    = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
1535     switch(m3ua_version) {
1536       case M3UA_V6:
1537         dissect_m3ua_v6_parameter(parameter_tvb, pinfo, tree, m3ua_tree); 
1538         break;
1539       case M3UA_V12:
1540         dissect_m3ua_v12_parameter(parameter_tvb, pinfo, tree, m3ua_tree);
1541         break;
1542     }
1543     /* get rid of the handled parameter */
1544     offset += total_length;
1545   }
1546 }
1547
1548
1549 static void
1550 dissect_m3ua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
1551 {
1552   tvbuff_t *common_header_tvb, *parameters_tvb;
1553
1554   common_header_tvb = tvb_new_subset(message_tvb, 0, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
1555   parameters_tvb    = tvb_new_subset(message_tvb, COMMON_HEADER_LENGTH, -1, -1);
1556   dissect_m3ua_common_header(common_header_tvb, pinfo, m3ua_tree);  
1557   if (m3ua_tree)
1558     dissect_m3ua_parameters(parameters_tvb, pinfo, tree, m3ua_tree);
1559 }
1560
1561 static void
1562 dissect_m3ua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
1563 {
1564   proto_item *m3ua_item;
1565   proto_tree *m3ua_tree;
1566
1567   /* make entry in the Protocol column on summary display */
1568   if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
1569     col_set_str(pinfo->cinfo, COL_PROTOCOL, "M3UA");
1570   
1571   /* In the interest of speed, if "tree" is NULL, don't do any work not
1572      necessary to generate protocol tree items. */
1573   if (tree) {
1574     /* create the m3ua protocol tree */
1575     m3ua_item = proto_tree_add_item(tree, proto_m3ua, message_tvb, 0, -1, FALSE);
1576     m3ua_tree = proto_item_add_subtree(m3ua_item, ett_m3ua);
1577   } else {
1578     m3ua_tree = NULL;
1579   };
1580   /* dissect the message */
1581   dissect_m3ua_message(message_tvb, pinfo, tree, m3ua_tree);
1582 }
1583
1584 /* Register the protocol with Ethereal */
1585 void
1586 proto_register_m3ua(void)
1587 {                 
1588
1589   /* Setup list of header fields */
1590   static hf_register_info hf[] = {
1591     { &hf_m3ua_version,
1592       { "Version", "m3ua.version",
1593               FT_UINT8, BASE_DEC, VALS(m3ua_protocol_version_values), 0x0,          
1594         "", HFILL }
1595     },
1596     { &hf_m3ua_reserved,
1597       { "Reserved", "m3ua.reserved",
1598               FT_UINT8, BASE_HEX, NULL, 0x0,          
1599               "", HFILL }
1600     }, 
1601     { &hf_m3ua_message_class,
1602       { "Message class", "m3ua.message_class",
1603         FT_UINT8, BASE_DEC, VALS(m3ua_message_class_values), 0x0,          
1604               "", HFILL }
1605     },
1606     { &hf_m3ua_message_type,
1607       { "Message Type", "m3ua.message_type",
1608               FT_UINT8, BASE_DEC, NULL, 0x0,          
1609               "", HFILL }
1610     },
1611     { &hf_m3ua_message_length,
1612       { "Message length", "m3ua.message_length",
1613         FT_UINT32, BASE_DEC, NULL, 0x0,          
1614               "", HFILL }
1615     }, 
1616     { &hf_m3ua_parameter_tag,
1617       { "Parameter Tag", "m3ua.parameter_tag",
1618         FT_UINT16, BASE_DEC, NULL, 0x0,          
1619         "", HFILL }
1620     },
1621     { &hf_m3ua_parameter_length,
1622       { "Parameter length", "m3ua.parameter_length",
1623         FT_UINT16, BASE_DEC, NULL, 0x0,          
1624               "", HFILL }
1625     }, 
1626     { &hf_m3ua_parameter_value,
1627       { "Parameter value", "m3ua.parameter_value",
1628               FT_BYTES, BASE_NONE, NULL, 0x0,          
1629               "", HFILL }
1630     },    
1631     { &hf_m3ua_parameter_padding,
1632       { "Padding", "m3ua.parameter_padding",
1633               FT_BYTES, BASE_NONE, NULL, 0x0,          
1634               "", HFILL }
1635     },    
1636     { &hf_m3ua_info_string,
1637       { "Info string", "m3ua.info_string",
1638               FT_STRING, BASE_DEC, NULL, 0x0,          
1639               "", HFILL }
1640     }, 
1641     { &hf_m3ua_routing_context,
1642       { "Routing context", "m3ua.routing_context",
1643               FT_UINT32, BASE_DEC, NULL, 0x0,          
1644         "", HFILL }
1645     }, 
1646     { &hf_m3ua_diagnostic_information,
1647       { "Diagnostic information", "m3ua.diagnostic_information",
1648               FT_BYTES, BASE_NONE, NULL, 0x0,          
1649               "", HFILL }
1650     },    
1651     { &hf_m3ua_heartbeat_data,
1652       { "Heartbeat data", "m3ua.heartbeat_data",
1653               FT_BYTES, BASE_NONE, NULL, 0x0,          
1654               "", HFILL }
1655     },    
1656     { &hf_m3ua_error_code,
1657       { "Error code", "m3ua.error_code",
1658         FT_UINT32, BASE_DEC, NULL, 0x0,          
1659               "", HFILL }
1660     }, 
1661     { &hf_m3ua_status_type,
1662       { "Status type", "m3ua.status_type",
1663               FT_UINT16, BASE_DEC, VALS(m3ua_status_type_values), 0x0,          
1664               "", HFILL }
1665     }, 
1666     { &hf_m3ua_status_info,
1667       { "Status info", "m3ua.status_info",
1668               FT_UINT16, BASE_DEC, NULL, 0x0,          
1669               "", HFILL }
1670     }, 
1671     { &hf_m3ua_asp_identifier,
1672       { "ASP identifier", "m3ua.asp_identifier",
1673               FT_UINT32, BASE_DEC, NULL, 0x0,          
1674               "", HFILL }
1675     },    
1676     { &hf_m3ua_affected_point_code_mask,
1677       { "Mask", "m3ua.affected_point_code_mask",
1678         FT_UINT8, BASE_DEC, NULL, 0x0,          
1679               "", HFILL }
1680     }, 
1681     { &hf_m3ua_affected_point_code_pc,
1682       { "Affected point code", "m3ua.affected_point_code_pc",
1683               FT_UINT24, BASE_DEC, NULL, 0x0,          
1684               "", HFILL }
1685     }, 
1686     { &hf_m3ua_network_appearance,
1687       { "Network appearance", "m3ua.network_appearance",
1688               FT_UINT32, BASE_DEC, NULL, 0x0,          
1689               "", HFILL }
1690     }, 
1691     { &hf_m3ua_unavailability_cause,
1692       { "Unavailability cause", "m3ua.unavailability_cause",
1693               FT_UINT16, BASE_DEC, VALS(m3ua_unavailability_cause_values), 0x0,          
1694         "", HFILL }
1695     }, 
1696     { &hf_m3ua_user_identity,
1697       { "User Identity", "m3ua.user_identity",
1698                FT_UINT16, BASE_DEC, VALS(m3ua_user_identity_values), 0x0,          
1699                "", HFILL }
1700     }, 
1701     { &hf_m3ua_congestion_reserved,
1702       { "Reserved", "m3ua.congestion_reserved",
1703               FT_BYTES, BASE_NONE, NULL, 0x0,          
1704               "", HFILL }
1705     },    
1706     { &hf_m3ua_congestion_level,
1707       { "Congestion level", "m3ua.congestion_level",
1708                FT_UINT8, BASE_DEC, VALS(m3ua_congestion_level_values), 0x0,          
1709                "", HFILL }
1710     }, 
1711     { &hf_m3ua_concerned_dest_reserved,
1712       { "Reserved", "m3ua.concerned_reserved",
1713               FT_BYTES, BASE_NONE, NULL, 0x0,          
1714               "", HFILL }
1715     },    
1716     { &hf_m3ua_concerned_dest_pc,
1717       { "Concerned DPC", "m3ua.concerned_dpc",
1718                FT_UINT24, BASE_DEC, NULL, 0x0,          
1719                "", HFILL }
1720     }, 
1721     { &hf_m3ua_dpc_mask,
1722       { "Mask", "m3ua.dpc_mask",
1723               FT_UINT8, BASE_DEC, NULL, 0x0,          
1724               "", HFILL }
1725     },    
1726     { &hf_m3ua_dpc_pc,
1727       { "Destination point code", "m3ua.dpc_pc",
1728                FT_UINT24, BASE_DEC, NULL, 0x0,          
1729                "", HFILL }
1730     }, 
1731     { &hf_m3ua_si,
1732       { "Service indicator", "m3ua_si",
1733         FT_UINT8, BASE_DEC, VALS(m3ua_user_identity_values), 0x0,          
1734               "", HFILL }
1735     }, 
1736     { &hf_m3ua_ssn,
1737       { "Subsystem number", "m3ua_ssn",
1738         FT_UINT8, BASE_DEC, NULL, 0x0,          
1739               "", HFILL }
1740     }, 
1741     { &hf_m3ua_opc_list_mask,
1742       { "Mask", "m3ua.opc_list_mask",
1743               FT_UINT8, BASE_DEC, NULL, 0x0,          
1744               "", HFILL }
1745     },    
1746     { &hf_m3ua_opc_list_pc,
1747       { "Originating point code", "m3ua.opc_list_pc",
1748                FT_UINT24, BASE_DEC, NULL, 0x0,          
1749                "", HFILL }
1750     }, 
1751     { &hf_m3ua_cic_range_mask,
1752       { "Mask", "m3ua.cic_range_mask",
1753               FT_UINT8, BASE_DEC, NULL, 0x0,          
1754               "", HFILL }
1755     },    
1756     { &hf_m3ua_cic_range_pc,
1757       { "Originating point code", "m3ua.cic_range_pc",
1758                FT_UINT24, BASE_DEC, NULL, 0x0,          
1759                "", HFILL }
1760     }, 
1761     { &hf_m3ua_cic_range_lower,
1762       { "Lower CIC value", "m3ua.cic_range_lower",
1763               FT_UINT16, BASE_DEC, NULL, 0x0,          
1764               "", HFILL }
1765     },    
1766     { &hf_m3ua_cic_range_upper,
1767       { "Upper CIC value", "m3ua.cic_range_upper",
1768                FT_UINT16, BASE_DEC, NULL, 0x0,          
1769                "", HFILL }
1770     }, 
1771     { &hf_m3ua_local_rk_identifier,
1772       { "Local routing key identifier", "m3ua.local_rk_identifier",
1773               FT_UINT32, BASE_DEC, NULL, 0x0,          
1774               "", HFILL }
1775     }, 
1776     { &hf_m3ua_li,
1777       { "Length indicator", "m3ua.protocol_data_2_li",
1778               FT_UINT8, BASE_DEC, NULL, 0x0,          
1779               "", HFILL }
1780     }, 
1781     { &hf_m3ua_protocol_data_opc,
1782       { "OPC", "m3ua.protocol_data_opc",
1783               FT_UINT32, BASE_DEC, NULL, 0x0,          
1784               "", HFILL }
1785     }, 
1786     { &hf_m3ua_protocol_data_dpc,
1787       { "DPC", "m3ua.protocol_data_dpc",
1788               FT_UINT32, BASE_DEC, NULL, 0x0,          
1789               "", HFILL }
1790     }, 
1791     { &hf_m3ua_protocol_data_si,
1792       { "SI", "m3ua.protocol_data_si",
1793               FT_UINT8, BASE_DEC, NULL, 0x0,          
1794               "", HFILL }
1795     }, 
1796     { &hf_m3ua_protocol_data_ni,
1797       { "NI", "m3ua.protocol_data_ni",
1798               FT_UINT8, BASE_DEC, NULL, 0x0,          
1799               "", HFILL }
1800     }, 
1801     { &hf_m3ua_protocol_data_mp,
1802       { "MP", "m3ua.protocol_data_mp",
1803               FT_UINT8, BASE_DEC, NULL, 0x0,          
1804               "", HFILL }
1805     }, 
1806     { &hf_m3ua_protocol_data_sls,
1807       { "SLS", "m3ua.protocol_data_sls",
1808               FT_UINT8, BASE_DEC, NULL, 0x0,          
1809               "", HFILL }
1810     }, 
1811     { &hf_m3ua_correlation_identifier,
1812       { "Correlation Identifier", "m3ua.correlation_identifier",
1813               FT_UINT32, BASE_DEC, NULL, 0x0,          
1814               "", HFILL }
1815     },
1816     { &hf_m3ua_registration_status,
1817       { "Registration status", "m3ua.registration_status",
1818               FT_UINT32, BASE_DEC, VALS(m3ua_registration_status_values), 0x0,          
1819               "", HFILL }
1820     },
1821     { &hf_m3ua_deregistration_status,
1822       { "Deregistration status", "m3ua.deregistration_status",
1823               FT_UINT32, BASE_DEC, VALS(m3ua_deregistration_status_values), 0x0,          
1824               "", HFILL }
1825     },
1826     { &hf_m3ua_reason,
1827       { "Reason", "m3ua_reason",
1828         FT_UINT32, BASE_DEC, VALS(m3ua_reason_values), 0x0,          
1829         "", HFILL }
1830     }, 
1831     { &hf_m3ua_traffic_mode_type,
1832       { "Traffic mode Type", "m3ua.traffic_mode_type",
1833               FT_UINT32, BASE_DEC, NULL, 0x0,          
1834               "", HFILL }
1835     }, 
1836     { &hf_m3ua_registration_result_identifier,
1837       { "Local RK-identifier value", "m3ua.registration_result_identifier",
1838               FT_UINT32, BASE_DEC, NULL, 0x0,          
1839               "", HFILL }
1840     }, 
1841     { &hf_m3ua_registration_result_status,
1842       { "Registration status", "m3ua.registration_results_status",
1843               FT_UINT32, BASE_DEC, VALS(m3ua_registration_result_status_values), 0x0,          
1844               "", HFILL }
1845     }, 
1846     { &hf_m3ua_registration_result_context,
1847       { "Routing context", "m3ua.registration_result_routing_context",
1848               FT_UINT32, BASE_DEC, NULL, 0x0,          
1849               "", HFILL }
1850     }, 
1851     { &hf_m3ua_deregistration_result_status,
1852       { "De-Registration status", "m3ua.deregistration_results_status",
1853               FT_UINT32, BASE_DEC, VALS(m3ua_deregistration_result_status_values), 0x0,          
1854               "", HFILL }
1855     }, 
1856     { &hf_m3ua_deregistration_result_context,
1857       { "Routing context", "m3ua.deregistration_result_routing_context",
1858               FT_UINT32, BASE_DEC, NULL, 0x0,          
1859               "", HFILL }
1860     }, 
1861   };
1862   
1863   /* Setup protocol subtree array */
1864   static gint *ett[] = {
1865     &ett_m3ua,
1866     &ett_m3ua_parameter,
1867   };
1868   
1869   static enum_val_t m3ua_options[] = {
1870     { "Internet Draft version 6",        M3UA_V6 },
1871     { "Internet Draft version 12",       M3UA_V12 },
1872     { NULL, 0 }
1873   };
1874
1875   /* Register the protocol name and description */
1876   proto_m3ua = proto_register_protocol("MTP 3 User Adaptation Layer", "M3UA",  "m3ua");
1877   m3ua_module = prefs_register_protocol(proto_m3ua, NULL);
1878   prefs_register_enum_preference(m3ua_module,
1879                                                          "version", "M3UA Version", "Internet Draft version used by Ethereal",
1880                                                          &m3ua_version, m3ua_options, FALSE);
1881
1882   /* Required function calls to register the header fields and subtrees used */
1883   proto_register_field_array(proto_m3ua, hf, array_length(hf));
1884   proto_register_subtree_array(ett, array_length(ett));
1885   m3ua_si_dissector_table = register_dissector_table("m3ua.protocol_data_si", "MTP3 Service indicator", FT_UINT8, BASE_HEX);
1886
1887 };
1888
1889 void
1890 proto_reg_handoff_m3ua(void)
1891 {
1892   dissector_handle_t m3ua_handle;
1893
1894   /*
1895    * Get a handle for the MTP3 dissector.
1896    */
1897   mtp3_handle = find_dissector("mtp3");
1898   data_handle = find_dissector("data");
1899   m3ua_handle = create_dissector_handle(dissect_m3ua, proto_m3ua);
1900   dissector_add("sctp.ppi",  M3UA_PAYLOAD_PROTO_ID, m3ua_handle);
1901   dissector_add("sctp.port", SCTP_PORT_M3UA, m3ua_handle);
1902 }