Refer to the endianness arguments as "encoding" rather than
[obnox/wireshark/wip.git] / epan / dissectors / packet-sua.c
1 /* packet-sua.c
2  * Routines for SS7 SCCP-User Adaptation Layer (SUA) dissection
3  * It is hopefully (needs testing) compliant to
4  * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-sua-08.txt
5  * http://www.ietf.org/rfc/rfc3868.txt
6  *
7  * Copyright 2002, 2003, 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
8  *
9  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * Copied from README.developer
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <epan/packet.h>
37 #include <epan/prefs.h>
38 #include <epan/sctpppids.h>
39 #include <epan/tap.h>
40 #include "packet-mtp3.h"
41 #include "packet-sccp.h"
42
43 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
44 #define SCTP_PORT_SUA          14001
45
46 #define RESERVED_1_LENGTH      1
47 #define RESERVED_2_LENGTH      2
48 #define RESERVED_3_LENGTH      3
49
50 #define VERSION_LENGTH         1
51 #define RESERVED_LENGTH        1
52 #define MESSAGE_CLASS_LENGTH   1
53 #define MESSAGE_TYPE_LENGTH    1
54 #define MESSAGE_LENGTH_LENGTH  4
55 #define COMMON_HEADER_LENGTH   (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
56                                 MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
57
58 #define COMMON_HEADER_OFFSET   0
59 #define VERSION_OFFSET         COMMON_HEADER_OFFSET
60 #define RESERVED_OFFSET        (VERSION_OFFSET + VERSION_LENGTH)
61 #define MESSAGE_CLASS_OFFSET   (RESERVED_OFFSET + RESERVED_LENGTH)
62 #define MESSAGE_TYPE_OFFSET    (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
63 #define MESSAGE_LENGTH_OFFSET  (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
64
65 #define PARAMETER_TAG_LENGTH    2
66 #define PARAMETER_LENGTH_LENGTH 2
67 #define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
68
69 #define PARAMETER_TAG_OFFSET      0
70 #define PARAMETER_LENGTH_OFFSET   (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
71 #define PARAMETER_VALUE_OFFSET    (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
72 #define PARAMETER_HEADER_OFFSET   PARAMETER_TAG_OFFSET
73
74 #define PROTOCOL_VERSION_RELEASE_1             1
75
76 static const value_string protocol_version_values[] = {
77   { PROTOCOL_VERSION_RELEASE_1,  "Release 1" },
78   { 0,                           NULL } };
79
80 #define MESSAGE_CLASS_MGMT_MESSAGE        0
81 #define MESSAGE_CLASS_TFER_MESSAGE        1
82 #define MESSAGE_CLASS_SSNM_MESSAGE        2
83 #define MESSAGE_CLASS_ASPSM_MESSAGE       3
84 #define MESSAGE_CLASS_ASPTM_MESSAGE       4
85 #define MESSAGE_CLASS_CL_MESSAGE          7
86 #define MESSAGE_CLASS_CO_MESSAGE          8
87 #define MESSAGE_CLASS_RKM_MESSAGE         9
88
89 static const value_string message_class_values[] = {
90   { MESSAGE_CLASS_MGMT_MESSAGE,   "Management messages" },
91   { MESSAGE_CLASS_SSNM_MESSAGE,   "SS7 signalling network management messages" },
92   { MESSAGE_CLASS_ASPSM_MESSAGE,  "ASP state maintenance messages" },
93   { MESSAGE_CLASS_ASPTM_MESSAGE,  "ASP traffic maintenance messages" },
94   { MESSAGE_CLASS_CL_MESSAGE,     "Connectionless messages" },
95   { MESSAGE_CLASS_CO_MESSAGE,     "Connection-Oriented messages" },
96   { MESSAGE_CLASS_RKM_MESSAGE,    "Routing key management Messages" },
97   { 0,                           NULL } };
98
99 #define MESSAGE_TYPE_ERR                  0
100 #define MESSAGE_TYPE_NTFY                 1
101
102 #define MESSAGE_TYPE_DUNA                 1
103 #define MESSAGE_TYPE_DAVA                 2
104 #define MESSAGE_TYPE_DAUD                 3
105 #define MESSAGE_TYPE_SCON                 4
106 #define MESSAGE_TYPE_DUPU                 5
107 #define MESSAGE_TYPE_DRST                 6
108
109 #define MESSAGE_TYPE_UP                   1
110 #define MESSAGE_TYPE_DOWN                 2
111 #define MESSAGE_TYPE_BEAT                 3
112 #define MESSAGE_TYPE_UP_ACK               4
113 #define MESSAGE_TYPE_DOWN_ACK             5
114 #define MESSAGE_TYPE_BEAT_ACK             6
115
116 #define MESSAGE_TYPE_ACTIVE               1
117 #define MESSAGE_TYPE_INACTIVE             2
118 #define MESSAGE_TYPE_ACTIVE_ACK           3
119 #define MESSAGE_TYPE_INACTIVE_ACK         4
120
121 #define MESSAGE_TYPE_CLDT                 1
122 #define MESSAGE_TYPE_CLDR                 2
123
124 #define MESSAGE_TYPE_CORE                 1
125 #define MESSAGE_TYPE_COAK                 2
126 #define MESSAGE_TYPE_COREF                3
127 #define MESSAGE_TYPE_RELRE                4
128 #define MESSAGE_TYPE_RELCO                5
129 #define MESSAGE_TYPE_RESCO                6
130 #define MESSAGE_TYPE_RESRE                7
131 #define MESSAGE_TYPE_CODT                 8
132 #define MESSAGE_TYPE_CODA                 9
133 #define MESSAGE_TYPE_COERR               10
134 #define MESSAGE_TYPE_COIT                11
135
136 #define MESSAGE_TYPE_REG_REQ              1
137 #define MESSAGE_TYPE_REG_RSP              2
138 #define MESSAGE_TYPE_DEREG_REQ            3
139 #define MESSAGE_TYPE_DEREG_RSP            4
140
141
142 static const value_string message_class_type_values[] = {
143   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "Error (ERR)" },
144   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "Notify (NTFY)" },
145   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "Destination unavailable (DUNA)" },
146   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "Destination available (DAVA)" },
147   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "Destination state audit (DAUD)" },
148   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SS7 Network congestion state (SCON)" },
149   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "Destination userpart unavailable (DUPU)" },
150   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DRST,          "Destination Restricted (DRST)" },
151   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP up (UP)" },
152   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP down (DOWN)" },
153   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "Heartbeat (BEAT)" },
154   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP up ack (UP ACK)" },
155   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP down ack (DOWN ACK)" },
156   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "Heartbeat ack (BEAT ACK)" },
157   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP active (ACTIVE)" },
158   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP inactive (INACTIVE)" },
159   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP active ack (ACTIVE ACK)" },
160   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (INACTIVE ACK)" },
161   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDR ,         "Connectionless Data Response (CLDR)" },
162   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDT ,         "Connectionless Data Transfer (CLDT)" },
163   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CORE ,         "Connection Request (CORE)" },
164   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COAK ,         "Connection Acknowledge (COAK)" },
165   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COREF ,        "Connection Refused (COREF)" },
166   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELRE ,        "Release Request (RELRE)" },
167   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELCO ,        "Release Complete (RELCO)" },
168   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESCO ,        "Reset Confirm (RESCO)" },
169   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESRE ,        "Reset Request (RESRE)" },
170   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODT ,         "Connection Oriented Data Transfer (CODT)" },
171   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODA ,         "Connection Oriented Data Acknowledge (CODA)" },
172   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COERR ,        "Connection Oriented Error (COERR)" },
173   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COIT ,         "Inactivity Test (COIT)" },
174   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_REQ ,      "Registration Request (REG_REQ)" },
175   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_RSP ,      "Registration Response (REG_RSP)" },
176   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_REQ ,    "Deregistration Request (DEREG_REQ)" },
177   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_RSP ,    "Deregistration Response (DEREG_RSP)" },
178   { 0,                           NULL } };
179
180 static const value_string message_class_type_acro_values[] = {
181   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "ERR" },
182   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "NTFY" },
183   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "DUNA" },
184   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "DAVA" },
185   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "DAUD" },
186   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SCON" },
187   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "DUPU" },
188   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DRST,          "DRST" },
189   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP_UP" },
190   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP_DOWN" },
191   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "BEAT" },
192   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP_UP_ACK" },
193   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP_DOWN_ACK" },
194   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "BEAT_ACK" },
195   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP_ACTIVE" },
196   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP_INACTIVE" },
197   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP_ACTIVE_ACK" },
198   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
199   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDR ,         "CLDR" },
200   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDT ,         "CLDT" },
201   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CORE ,         "CORE" },
202   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COAK ,         "COAK" },
203   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COREF ,        "COREF" },
204   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELRE ,        "RELRE" },
205   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELCO ,        "RELCO" },
206   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESCO ,        "RESCO" },
207   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESRE ,        "RESRE" },
208   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODT ,         "CODT" },
209   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODA ,         "CODA" },
210   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COERR ,        "COERR" },
211   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COIT ,         "COIT" },
212   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_REQ ,      "REG_REQ" },
213   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_RSP ,      "REG_RSP" },
214   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_REQ ,    "DEREG_REQ" },
215   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_RSP ,    "DEREG_RSP" },
216   { 0,                           NULL } };
217
218 const value_string sua_co_class_type_acro_values[] = {
219         { MESSAGE_TYPE_CORE ,         "CORE" },
220         { MESSAGE_TYPE_COAK ,         "COAK" },
221         { MESSAGE_TYPE_COREF ,        "COREF" },
222         { MESSAGE_TYPE_RELRE ,        "RELRE" },
223         { MESSAGE_TYPE_RELCO ,        "RELCO" },
224         { MESSAGE_TYPE_RESCO ,        "RESCO" },
225         { MESSAGE_TYPE_RESRE ,        "RESRE" },
226         { MESSAGE_TYPE_CODT ,         "CODT" },
227         { MESSAGE_TYPE_CODA ,         "CODA" },
228         { MESSAGE_TYPE_COERR ,        "COERR" },
229         { MESSAGE_TYPE_COIT ,         "COIT" },
230         { 0, NULL }
231 };
232
233 /* Initialize the protocol and registered fields */
234 static int proto_sua = -1;
235 static int hf_version = -1;
236 static int hf_reserved = -1;
237 static int hf_message_class = -1;
238 static int hf_message_type = -1;
239 static int hf_message_length = -1;
240 static int hf_parameter_tag = -1;
241 static int hf_v8_parameter_tag = -1;
242 static int hf_parameter_length = -1;
243 static int hf_parameter_value = -1;
244 static int hf_parameter_padding = -1;
245 static int hf_info_string = -1;
246 static int hf_routing_context = -1;
247 static int hf_diagnostic_information_info = -1;
248 static int hf_heartbeat_data = -1;
249 static int hf_traffic_mode_type = -1;
250 static int hf_error_code = -1;
251 static int hf_v8_error_code = -1;
252 static int hf_status_type = -1;
253 static int hf_status_info = -1;
254 static int hf_congestion_level = -1;
255 static int hf_asp_identifier = -1;
256 static int hf_mask = -1;
257 static int hf_dpc = -1;
258 static int hf_registration_status = -1;
259 static int hf_deregistration_status = -1;
260 static int hf_local_routing_key_identifier = -1;
261 static int hf_source_address_routing_indicator = -1;
262 static int hf_source_address_reserved_bits = -1;
263 static int hf_source_address_gt_bit = -1;
264 static int hf_source_address_pc_bit = -1;
265 static int hf_source_address_ssn_bit = -1;
266 static int hf_destination_address_routing_indicator = -1;
267 static int hf_destination_address_reserved_bits = -1;
268 static int hf_destination_address_gt_bit = -1;
269 static int hf_destination_address_pc_bit = -1;
270 static int hf_destination_address_ssn_bit = -1;
271 static int hf_ss7_hop_counter_counter = -1;
272 static int hf_ss7_hop_counter_reserved = -1;
273 static int hf_destination_reference_number = -1;
274 static int hf_source_reference_number = -1;
275 static int hf_cause_reserved = -1;
276 static int hf_cause_type = -1;
277 static int hf_cause_value = -1;
278 static int hf_sequence_number_reserved = -1;
279 static int hf_sequence_number_rec_number = -1;
280 static int hf_sequence_number_spare_bit = -1;
281 static int hf_sequence_number_sent_number = -1;
282 static int hf_sequence_number_more_data_bit = -1;
283 static int hf_receive_sequence_number_reserved = -1;
284 static int hf_receive_sequence_number_number = -1;
285 static int hf_receive_sequence_number_spare_bit = -1;
286 static int hf_asp_capabilities_reserved = -1;
287 static int hf_asp_capabilities_reserved_bits = -1;
288 static int hf_asp_capabilities_a_bit =-1;
289 static int hf_asp_capabilities_b_bit =-1;
290 static int hf_asp_capabilities_c_bit =-1;
291 static int hf_asp_capabilities_d_bit =-1;
292 static int hf_asp_capabilities_interworking = -1;
293 static int hf_credit = -1;
294 static int hf_data = -1;
295 static int hf_cause = -1;
296 static int hf_user = -1;
297 static int hf_network_appearance = -1;
298 static int hf_routing_key_identifier = -1;
299 static int hf_correlation_id = -1;
300 static int hf_importance_reserved = -1;
301 static int hf_importance = -1;
302 static int hf_message_priority_reserved = -1;
303 static int hf_message_priority = -1;
304 static int hf_protocol_class_reserved = -1;
305 static int hf_return_on_error_bit = -1;
306 static int hf_protocol_class = -1;
307 static int hf_sequence_control = -1;
308 static int hf_first_bit = -1;
309 static int hf_number_of_remaining_segments = -1;
310 static int hf_segmentation_reference = -1;
311 static int hf_smi = -1;
312 static int hf_smi_reserved = -1;
313 static int hf_tid_label_start = -1;
314 static int hf_tid_label_end = -1;
315 static int hf_tid_label_value = -1;
316 static int hf_drn_label_start = -1;
317 static int hf_drn_label_end = -1;
318 static int hf_drn_label_value = -1;
319 static int hf_gt_reserved = -1;
320 static int hf_gti = -1;
321 static int hf_number_of_digits = -1;
322 static int hf_translation_type = -1;
323 static int hf_numbering_plan = -1;
324 static int hf_nature_of_address = -1;
325 static int hf_global_title_digits = -1;
326 static int hf_point_code_dpc = -1;
327 static int hf_ssn_reserved = -1;
328 static int hf_ssn_number = -1;
329 static int hf_ipv4 = -1;
330 static int hf_hostname = -1;
331 static int hf_ipv6 = -1;
332 static int hf_assoc_id = -1;
333 static int hf_assoc_msg = -1;
334
335 /* Initialize the subtree pointers */
336 static gint ett_sua = -1;
337 static gint ett_sua_parameter = -1;
338 static gint ett_sua_source_address_indicator = -1;
339 static gint ett_sua_destination_address_indicator = -1;
340 static gint ett_sua_affected_destination = -1;
341 static gint ett_sua_first_remaining = -1;
342 static gint ett_sua_sequence_number_rec_number = -1;
343 static gint ett_sua_sequence_number_sent_number = -1;
344 static gint ett_sua_receive_sequence_number_number = -1;
345 static gint ett_sua_return_on_error_bit_and_protocol_class = -1;
346 static gint ett_sua_protcol_classes = -1;
347 static gint ett_sua_assoc = -1;
348
349 static int sua_tap = -1;
350
351 static dissector_handle_t data_handle;
352 static dissector_table_t sccp_ssn_dissector_table;
353 static heur_dissector_list_t heur_subdissector_list;
354
355 static guint32  message_class, message_type, drn, srn;
356
357 /* stuff for supporting multiple versions */
358 typedef enum {
359   SUA_V08,
360   SUA_RFC
361 } Version_Type;
362
363 static gint version = SUA_RFC;
364
365 static void
366 dissect_parameters(tvbuff_t *tlv_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn);
367
368 static void
369 dissect_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *sua_tree)
370 {
371
372   message_class  = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
373   message_type   = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
374
375   if (check_col(pinfo->cinfo, COL_INFO))
376     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_class * 256 + message_type, message_class_type_acro_values, "reserved"));
377
378   if (sua_tree) {
379     /* add the components of the common header to the protocol tree */
380     proto_tree_add_item(sua_tree, hf_version,        common_header_tvb, VERSION_OFFSET,        VERSION_LENGTH,        ENC_BIG_ENDIAN);
381     proto_tree_add_item(sua_tree, hf_reserved,       common_header_tvb, RESERVED_OFFSET,       RESERVED_LENGTH,       ENC_BIG_ENDIAN);
382     proto_tree_add_item(sua_tree, hf_message_class,  common_header_tvb, MESSAGE_CLASS_OFFSET,  MESSAGE_CLASS_LENGTH,  ENC_BIG_ENDIAN);
383     proto_tree_add_uint_format(sua_tree, hf_message_type, common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type, "Message Type: %s (%u)",
384                                            val_to_str(message_class * 256 + message_type, message_class_type_values, "reserved"), message_type);
385     proto_tree_add_item(sua_tree, hf_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, ENC_BIG_ENDIAN);
386   };
387 }
388
389 #define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
390
391 static void
392 dissect_info_string_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
393 {
394   guint16 info_string_length;
395
396   info_string_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
397   proto_tree_add_item(parameter_tree, hf_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, ENC_BIG_ENDIAN);
398   proto_item_append_text(parameter_item, " (%.*s)", info_string_length,
399                          (const char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length));
400 }
401
402 #define ROUTING_CONTEXT_LENGTH 4
403
404 static void
405 dissect_routing_context_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
406 {
407   guint16 number_of_contexts, context_number;
408   gint context_offset;
409
410   number_of_contexts = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / 4;
411   context_offset = PARAMETER_VALUE_OFFSET;
412   for(context_number=1; context_number <= number_of_contexts; context_number++) {
413     proto_tree_add_item(parameter_tree, hf_routing_context, parameter_tvb, context_offset, ROUTING_CONTEXT_LENGTH, ENC_BIG_ENDIAN);
414     context_offset += ROUTING_CONTEXT_LENGTH;
415   };
416   proto_item_append_text(parameter_item, " (%u context%s)", number_of_contexts, plurality(number_of_contexts, "", "s"));
417 }
418
419 #define DIAGNOSTIC_INFO_OFFSET PARAMETER_VALUE_OFFSET
420
421 static void
422 dissect_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
423 {
424   guint16 diag_info_length;
425
426   diag_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
427   proto_tree_add_item(parameter_tree, hf_diagnostic_information_info, parameter_tvb, DIAGNOSTIC_INFO_OFFSET, diag_info_length, ENC_BIG_ENDIAN);
428   proto_item_append_text(parameter_item, " (%u byte%s)", diag_info_length, plurality(diag_info_length, "", "s"));
429 }
430
431 #define HEARTBEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
432
433 static void
434 dissect_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
435 {
436   guint16 heartbeat_data_length;
437
438   heartbeat_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
439   proto_tree_add_item(parameter_tree, hf_heartbeat_data, parameter_tvb, HEARTBEAT_DATA_OFFSET, heartbeat_data_length, ENC_BIG_ENDIAN);
440   proto_item_append_text(parameter_item, " (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
441 }
442
443 #define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
444 #define TRAFFIC_MODE_TYPE_LENGTH 4
445
446 static const value_string traffic_mode_type_values[] = {
447   { 1, "Over-ride" },
448   { 2, "Load-share" },
449   { 3, "Broadcast" },
450   { 0, NULL } };
451
452 static void
453 dissect_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
454 {
455   proto_tree_add_item(parameter_tree, hf_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, ENC_BIG_ENDIAN);
456   proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), traffic_mode_type_values, "unknown"));
457 }
458
459 #define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
460 #define ERROR_CODE_LENGTH 4
461
462 static const value_string v8_error_code_values[] = {
463   { 0x01, "Invalid version" },
464   { 0x02, "Invalid interface identifier" },
465   { 0x03, "Unsupported message class" },
466   { 0x04, "Unsupported message type" },
467   { 0x05, "Unsupported traffic handling mode" },
468   { 0x06, "Unexpected message" },
469   { 0x07, "Protocol error" },
470   { 0x09, "Invalid stream identifier" },
471   { 0x0d, "Refused - management blocking" },
472   { 0x0e, "ASP identifier required" },
473   { 0x0f, "Invalid ASP identifier" },
474   { 0x11, "Invalid parameter value" },
475   { 0x12, "Parameter field error" },
476   { 0x13, "Unexpected parameter" },
477   { 0x14, "Destination status unknown" },
478   { 0x15, "Invalid network appearance" },
479   { 0x16, "Missing parameter" },
480   { 0x17, "Routing key change refused" },
481   { 0x18, "Invalid loadsharing label" },
482   { 0,    NULL } };
483
484 static void
485 dissect_v8_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
486 {
487   proto_tree_add_item(parameter_tree, hf_v8_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, ENC_BIG_ENDIAN);
488   proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), v8_error_code_values, "unknown"));
489 }
490
491 static const value_string error_code_values[] = {
492   { 0x01, "Invalid version" },
493   { 0x03, "Unsupported message class" },
494   { 0x04, "Unsupported message type" },
495   { 0x05, "Unsupported traffic handling mode" },
496   { 0x06, "Unexpected message" },
497   { 0x07, "Protocol error" },
498   { 0x09, "Invalid stream identifier" },
499   { 0x0d, "Refused - management blocking" },
500   { 0x0e, "ASP identifier required" },
501   { 0x0f, "Invalid ASP identifier" },
502   { 0x11, "Invalid parameter value" },
503   { 0x12, "Parameter field error" },
504   { 0x13, "Unexpected parameter" },
505   { 0x14, "Destination status unknown" },
506   { 0x15, "Invalid network appearance" },
507   { 0x16, "Missing parameter" },
508   { 0x19, "Invalid routing context" },
509   { 0x1a, "No configured AS for ASP" },
510   { 0x1b, "Subsystem status unknown" },
511   { 0x1c, "Invalid loadsharing label" },
512   { 0,    NULL } };
513
514 static void
515 dissect_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
516 {
517   proto_tree_add_item(parameter_tree, hf_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, ENC_BIG_ENDIAN);
518   proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), error_code_values, "unknown"));
519 }
520
521 #define STATUS_TYPE_LENGTH 2
522 #define STATUS_INFO_LENGTH 2
523 #define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
524 #define STATUS_INFO_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
525
526 #define AS_STATE_CHANGE_TYPE       1
527 #define OTHER_TYPE                 2
528
529 static const value_string status_type_values[] = {
530   { AS_STATE_CHANGE_TYPE,            "Application server state change" },
531   { OTHER_TYPE,                      "Other" },
532   { 0,                               NULL } };
533
534 #define RESERVED_INFO              1
535 #define AS_INACTIVE_INFO           2
536 #define AS_ACTIVE_INFO             3
537 #define AS_PENDING_INFO            4
538
539 #define INSUFFICIENT_ASP_RES_INFO  1
540 #define ALTERNATE_ASP_ACTIVE_INFO  2
541 #define ASP_FAILURE                3
542
543 static const value_string status_type_info_values[] = {
544   { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO,             "Reserved" },
545   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO,          "Application server inactive" },
546   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO,            "Application server active" },
547   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO,           "Application server pending" },
548   { OTHER_TYPE           * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
549   { OTHER_TYPE           * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
550   { OTHER_TYPE           * 256 * 256 + ASP_FAILURE,               "ASP Failure" },
551   {0,                           NULL } };
552
553 static void
554 dissect_status_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
555 {
556   guint16 status_type, status_info;
557
558   status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
559   status_info = tvb_get_ntohs(parameter_tvb, STATUS_INFO_OFFSET);
560
561   proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, ENC_BIG_ENDIAN);
562   proto_tree_add_uint_format(parameter_tree, hf_status_info, parameter_tvb, STATUS_INFO_OFFSET, STATUS_INFO_LENGTH,
563                                          status_info, "Status info: %s (%u)", val_to_str(status_type * 256 * 256 + status_info, status_type_info_values, "unknown"), status_info);
564
565   proto_item_append_text(parameter_item, " (%s)", val_to_str(status_type * 256 * 256 + status_info, status_type_info_values, "unknown"));
566 }
567
568 #define ASP_IDENTIFIER_LENGTH 4
569 #define ASP_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
570
571 static void
572 dissect_asp_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
573 {
574   proto_tree_add_item(parameter_tree, hf_asp_identifier, parameter_tvb, ASP_IDENTIFIER_OFFSET, ASP_IDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
575   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, ASP_IDENTIFIER_OFFSET));
576 }
577
578 #define AFFECTED_MASK_LENGTH 1
579 #define AFFECTED_DPC_LENGTH  3
580 #define AFFECTED_DESTINATION_LENGTH (AFFECTED_MASK_LENGTH + AFFECTED_DPC_LENGTH)
581
582 #define AFFECTED_MASK_OFFSET 0
583 #define AFFECTED_DPC_OFFSET  1
584
585 static void
586 dissect_affected_destinations_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
587 {
588   guint16 number_of_destinations, destination_number;
589   gint destination_offset;
590   proto_item *dpc_item;
591
592   number_of_destinations= (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / 4;
593   destination_offset = PARAMETER_VALUE_OFFSET;
594   for(destination_number=1; destination_number <= number_of_destinations; destination_number++) {
595     proto_tree_add_item(parameter_tree, hf_mask, parameter_tvb, destination_offset + AFFECTED_MASK_OFFSET, AFFECTED_MASK_LENGTH, ENC_BIG_ENDIAN);
596     dpc_item = proto_tree_add_item(parameter_tree, hf_dpc,  parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET,  AFFECTED_DPC_LENGTH,  ENC_BIG_ENDIAN);
597     if (mtp3_pc_structured())
598       proto_item_append_text(dpc_item, " (%s)", mtp3_pc_to_str(tvb_get_ntoh24(parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET)));
599     destination_offset += AFFECTED_DESTINATION_LENGTH;
600   }
601   proto_item_append_text(parameter_item, " (%u destination%s)", number_of_destinations, plurality(number_of_destinations, "", "s"));
602 }
603
604 #define CORRELATION_ID_LENGTH 4
605 #define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
606
607 static void
608 dissect_correlation_id_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
609 {
610   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
611   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
612 }
613
614 static void
615 dissect_registration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
616 {
617   tvbuff_t *parameters_tvb;
618
619   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET);
620   dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
621 }
622
623 static void
624 dissect_deregistration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
625 {
626   tvbuff_t *parameters_tvb;
627
628   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET);
629   dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
630 }
631
632 #define REGISTRATION_STATUS_LENGTH 4
633 #define REGISTRATION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
634
635 static const value_string registration_status_values[] = {
636   {  0,            "Successfully registered" },
637   {  1,            "Error - unknown" },
638   {  2,            "Error - invalid destination address" },
639   {  3,            "Error - invalid network appearance" },
640   {  4,            "Error - invalid routing key" },
641   {  5,            "Error - permission denied" },
642   {  6,            "Error - cannot support unique routing" },
643   {  7,            "Error - routing key not currently provisioned" },
644   {  8,            "Error - insufficient resources" },
645   {  9,            "Error - unsupported RK parameter field" },
646   { 10,            "Error - unsupported/invalid traffic mode type" },
647   { 11,            "Error - routing key change refused" },
648   {  0,            NULL } };
649
650 static void
651 dissect_registration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
652 {
653   proto_tree_add_item(parameter_tree, hf_registration_status, parameter_tvb, REGISTRATION_STATUS_OFFSET, REGISTRATION_STATUS_LENGTH, ENC_BIG_ENDIAN);
654   proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, REGISTRATION_STATUS_OFFSET), registration_status_values, "unknown"));
655 }
656
657 #define DEREGISTRATION_STATUS_LENGTH 4
658 #define DEREGISTRATION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
659
660 static const value_string deregistration_status_values[] = {
661   {  0,            "Successfully deregistered" },
662   {  1,            "Error - unknown" },
663   {  2,            "Error - invalid routing context" },
664   {  3,            "Error - permission denied" },
665   {  4,            "Error - not registered" },
666   {  5,            "Error - ASP currently active for routing context" },
667   {  0,            NULL } };
668
669 static void
670 dissect_deregistration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
671 {
672   proto_tree_add_item(parameter_tree, hf_deregistration_status, parameter_tvb, DEREGISTRATION_STATUS_OFFSET, DEREGISTRATION_STATUS_LENGTH, ENC_BIG_ENDIAN);
673   proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, DEREGISTRATION_STATUS_OFFSET), deregistration_status_values, "unknown"));
674 }
675
676 #define LOCAL_ROUTING_KEY_IDENTIFIER_LENGTH 4
677 #define LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
678
679 static void
680 dissect_local_routing_key_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
681 {
682   proto_tree_add_item(parameter_tree, hf_local_routing_key_identifier, parameter_tvb, LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET, LOCAL_ROUTING_KEY_IDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
683   proto_item_append_text(parameter_item, " (%d)", tvb_get_ntohl(parameter_tvb, LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET));
684 }
685
686 #define SS7_HOP_COUNTER_LENGTH 1
687 #define SS7_HOP_COUNTER_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
688
689 static void
690 dissect_ss7_hop_counter_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
691 {
692   proto_tree_add_item(parameter_tree, hf_ss7_hop_counter_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,      ENC_BIG_ENDIAN);
693   proto_tree_add_item(parameter_tree, hf_ss7_hop_counter_counter,  parameter_tvb, SS7_HOP_COUNTER_OFFSET, SS7_HOP_COUNTER_LENGTH, ENC_BIG_ENDIAN);
694   proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb,  SS7_HOP_COUNTER_OFFSET));
695 }
696
697 #define ROUTING_INDICATOR_LENGTH  2
698 #define ADDRESS_INDICATOR_LENGTH  2
699
700 #define ROUTING_INDICATOR_OFFSET  PARAMETER_VALUE_OFFSET
701 #define ADDRESS_INDICATOR_OFFSET  (ROUTING_INDICATOR_OFFSET + ROUTING_INDICATOR_LENGTH)
702 #define ADDRESS_PARAMETERS_OFFSET (ADDRESS_INDICATOR_OFFSET + ADDRESS_INDICATOR_LENGTH)
703
704 #define RESERVED_ROUTING_INDICATOR              0
705 #define ROUTE_ON_GT_ROUTING_INDICATOR           1
706 #define ROUTE_ON_SSN_PC_ROUTING_INDICATOR       2
707 #define ROUTE_ON_HOSTNAMEROUTING_INDICATOR      3
708 #define ROUTE_ON_SSN_IP_ROUTING_INDICATOR       4
709
710 static const value_string routing_indicator_values[] = {
711   { RESERVED_ROUTING_INDICATOR,            "Reserved" },
712   { ROUTE_ON_GT_ROUTING_INDICATOR,         "Route on Global Title" },
713   { ROUTE_ON_SSN_PC_ROUTING_INDICATOR,     "Route on SSN + PC" },
714   { ROUTE_ON_HOSTNAMEROUTING_INDICATOR,    "Route on Hostname" },
715   { ROUTE_ON_SSN_IP_ROUTING_INDICATOR,     "Route on SSN + IP Address" },
716   { 0,                                     NULL } };
717
718 #define ADDRESS_RESERVED_BITMASK 0xfff8
719 #define ADDRESS_GT_BITMASK       0x0004
720 #define ADDRESS_PC_BITMASK       0x0002
721 #define ADDRESS_SSN_BITMASK      0x0001
722
723 static void
724 dissect_source_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, guint8 *ssn)
725 {
726   proto_item *address_indicator_item;
727   proto_tree *address_indicator_tree;
728   tvbuff_t *parameters_tvb;
729
730   if(parameter_tree) {
731     proto_tree_add_item(parameter_tree, hf_source_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
732     address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
733     address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_source_address_indicator);
734     proto_tree_add_item(address_indicator_tree, hf_source_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
735     proto_tree_add_item(address_indicator_tree, hf_source_address_gt_bit,        parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
736     proto_tree_add_item(address_indicator_tree, hf_source_address_pc_bit,        parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
737     proto_tree_add_item(address_indicator_tree, hf_source_address_ssn_bit,       parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
738   }
739
740   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, ADDRESS_PARAMETERS_OFFSET);
741   dissect_parameters(parameters_tvb, parameter_tree, NULL, ssn, NULL);
742 }
743
744 static void
745 dissect_destination_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, guint8 *ssn)
746 {
747   proto_item *address_indicator_item;
748   proto_tree *address_indicator_tree;
749   tvbuff_t *parameters_tvb;
750
751   if(parameter_tree) {
752     proto_tree_add_item(parameter_tree, hf_destination_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
753     address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
754     address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_destination_address_indicator);
755     proto_tree_add_item(address_indicator_tree, hf_destination_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
756     proto_tree_add_item(address_indicator_tree, hf_destination_address_gt_bit,        parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
757     proto_tree_add_item(address_indicator_tree, hf_destination_address_pc_bit,        parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
758     proto_tree_add_item(address_indicator_tree, hf_destination_address_ssn_bit,       parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
759   }
760
761   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, ADDRESS_PARAMETERS_OFFSET);
762   dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, ssn);
763 }
764
765 #define SOURCE_REFERENCE_NUMBER_LENGTH 4
766 #define SOURCE_REFERENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
767
768 static void
769 dissect_source_reference_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
770 {
771   srn = tvb_get_ntohl(parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET);
772   proto_tree_add_item(parameter_tree, hf_source_reference_number, parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET, SOURCE_REFERENCE_NUMBER_LENGTH, ENC_BIG_ENDIAN);
773   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET));
774 }
775
776 #define DESTINATION_REFERENCE_NUMBER_LENGTH 4
777 #define DESTINATION_REFERENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
778
779 static void
780 dissect_destination_reference_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
781 {
782   drn = tvb_get_ntohl(parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET);
783   proto_tree_add_item(parameter_tree, hf_destination_reference_number, parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET, DESTINATION_REFERENCE_NUMBER_LENGTH, ENC_BIG_ENDIAN);
784   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET));
785 }
786
787 #define CAUSE_TYPE_LENGTH 1
788 #define CAUSE_VALUE_LENGTH 1
789
790 #define CAUSE_TYPE_OFFSET  (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
791 #define CAUSE_VALUE_OFFSET (CAUSE_TYPE_OFFSET + CAUSE_TYPE_LENGTH)
792
793 #define CAUSE_TYPE_RETURN  0x1
794 #define CAUSE_TYPE_REFUSAL 0x2
795 #define CAUSE_TYPE_RELEASE 0x3
796 #define CAUSE_TYPE_RESET   0x4
797 #define CAUSE_TYPE_ERROR   0x5
798 static const value_string cause_type_values[] = {
799   { CAUSE_TYPE_RETURN,  "Return Cause" },
800   { CAUSE_TYPE_REFUSAL, "Refusal Cause" },
801   { CAUSE_TYPE_RELEASE, "Release Cause" },
802   { CAUSE_TYPE_RESET,   "Reset Cause" },
803   { CAUSE_TYPE_ERROR,   "Error cause" },
804   { 0,                  NULL } };
805
806 static void
807 dissect_sccp_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
808 {
809   guint8 cause_type, cause;
810   proto_item *pi;
811   const gchar *cause_string;
812
813   proto_tree_add_item(parameter_tree, hf_cause_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH,  ENC_BIG_ENDIAN);
814   proto_tree_add_item(parameter_tree, hf_cause_type,     parameter_tvb, CAUSE_TYPE_OFFSET,      CAUSE_TYPE_LENGTH,  ENC_BIG_ENDIAN);
815   cause_type = tvb_get_guint8(parameter_tvb, CAUSE_TYPE_OFFSET);
816   pi = proto_tree_add_item(parameter_tree, hf_cause_value, parameter_tvb, CAUSE_VALUE_OFFSET,   CAUSE_VALUE_LENGTH, ENC_BIG_ENDIAN);
817   cause = tvb_get_guint8(parameter_tvb, CAUSE_VALUE_OFFSET);
818
819   switch (cause_type) {
820   case CAUSE_TYPE_RETURN:
821     cause_string = val_to_str(cause, sccp_return_cause_values, "unknown");
822     break;
823   case CAUSE_TYPE_REFUSAL:
824     cause_string = val_to_str(cause, sccp_refusal_cause_values, "unknown");
825     break;
826   case CAUSE_TYPE_RELEASE:
827     cause_string = val_to_str(cause, sccp_release_cause_values, "unknown");
828     break;
829   case CAUSE_TYPE_RESET:
830     cause_string = val_to_str(cause, sccp_reset_cause_values, "unknown");
831     break;
832   case CAUSE_TYPE_ERROR:
833     cause_string = val_to_str(cause, sccp_error_cause_values, "unknown");
834     break;
835   default:
836     cause_string = "unknown";
837   }
838
839   proto_item_append_text(pi, " (%s)", cause_string);
840   proto_item_append_text(parameter_item, " (%s: %s)", val_to_str(cause_type, cause_type_values, "unknown"), cause_string);
841 }
842
843 #define SEQUENCE_NUMBER_REC_SEQ_LENGTH  1
844 #define SEQUENCE_NUMBER_SENT_SEQ_LENGTH 1
845 #define SEQUENCE_NUMBER_REC_SEQ_OFFSET  (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
846 #define SEQUENCE_NUMBER_SENT_SEQ_OFFSET (SEQUENCE_NUMBER_REC_SEQ_OFFSET + SEQUENCE_NUMBER_REC_SEQ_LENGTH)
847
848 #define SEQ_NUM_MASK       0xFE
849 #define SPARE_BIT_MASK     0x01
850 #define MORE_DATA_BIT_MASK 0x01
851
852 static const true_false_string more_data_bit_value = {
853   "More Data",
854   "Not More Data"
855 };
856
857 static void
858 dissect_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
859 {
860   proto_item *sent_sequence_number_item;
861   proto_tree *sent_sequence_number_tree;
862   proto_item *receive_sequence_number_item;
863   proto_tree *receive_sequence_number_tree;
864
865   proto_tree_add_item(parameter_tree, hf_sequence_number_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH, ENC_BIG_ENDIAN);
866
867   receive_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, "Receive Sequence Number");
868   receive_sequence_number_tree = proto_item_add_subtree(receive_sequence_number_item, ett_sua_sequence_number_rec_number);
869   proto_tree_add_item(receive_sequence_number_tree, hf_sequence_number_rec_number,    parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, ENC_BIG_ENDIAN);
870   proto_tree_add_item(receive_sequence_number_tree, hf_sequence_number_more_data_bit, parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, ENC_BIG_ENDIAN);
871
872   sent_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, "Sent Sequence Number");
873   sent_sequence_number_tree = proto_item_add_subtree(sent_sequence_number_item, ett_sua_sequence_number_sent_number);
874   proto_tree_add_item(sent_sequence_number_tree, hf_sequence_number_sent_number, parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, ENC_BIG_ENDIAN);
875   proto_tree_add_item(sent_sequence_number_tree, hf_sequence_number_spare_bit,   parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, ENC_BIG_ENDIAN);
876 }
877
878 #define RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH 1
879 #define RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
880
881 static void
882 dissect_receive_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
883 {
884   proto_item *receive_sequence_number_item;
885   proto_tree *receive_sequence_number_tree;
886
887   proto_tree_add_item(parameter_tree, hf_receive_sequence_number_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_BIG_ENDIAN);
888   receive_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, "Receive Sequence Number");
889   receive_sequence_number_tree = proto_item_add_subtree(receive_sequence_number_item, ett_sua_receive_sequence_number_number);
890   proto_tree_add_item(receive_sequence_number_tree, hf_receive_sequence_number_number,    parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, ENC_BIG_ENDIAN);
891   proto_tree_add_item(receive_sequence_number_tree, hf_receive_sequence_number_spare_bit, parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, ENC_BIG_ENDIAN);
892 }
893
894 #define PROTOCOL_CLASSES_LENGTH        1
895 #define INTERWORKING_LENGTH            1
896 #define PROTOCOL_CLASSES_OFFSET        (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
897 #define INTERWORKING_OFFSET            (PROTOCOL_CLASSES_OFFSET + PROTOCOL_CLASSES_LENGTH)
898
899 #define A_BIT_MASK 0x08
900 #define B_BIT_MASK 0x04
901 #define C_BIT_MASK 0x02
902 #define D_BIT_MASK 0x01
903 #define RESERVED_BITS_MASK 0xF0
904
905 static const value_string interworking_values[] = {
906   { 0x0,   "No Interworking with SS7 Networks" },
907   { 0x1,   "IP-Signalling Endpoint interworking with with SS7 networks" },
908   { 0x2,   "Signalling Gateway" },
909   { 0x3,   "Relay Node Support" },
910   { 0,     NULL } };
911
912 static void
913 dissect_asp_capabilities_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
914 {
915   proto_item *protocol_classes_item;
916   proto_tree *protocol_classes_tree;
917
918   proto_tree_add_item(parameter_tree, hf_asp_capabilities_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH, ENC_BIG_ENDIAN);
919   protocol_classes_item = proto_tree_add_text(parameter_tree, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, "Protocol classes");
920   protocol_classes_tree = proto_item_add_subtree(protocol_classes_item, ett_sua_protcol_classes);
921   proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_reserved_bits, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, ENC_BIG_ENDIAN);
922   proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_a_bit, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, ENC_BIG_ENDIAN);
923   proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_b_bit, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, ENC_BIG_ENDIAN);
924   proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_c_bit, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, ENC_BIG_ENDIAN);
925   proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_d_bit, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, ENC_BIG_ENDIAN);
926   proto_tree_add_item(parameter_tree, hf_asp_capabilities_interworking, parameter_tvb, INTERWORKING_OFFSET, INTERWORKING_LENGTH, ENC_BIG_ENDIAN);
927 }
928
929 #define CREDIT_LENGTH 4
930 #define CREDIT_OFFSET PARAMETER_VALUE_OFFSET
931
932 static void
933 dissect_credit_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
934 {
935   proto_tree_add_item(parameter_tree, hf_credit, parameter_tvb, CREDIT_OFFSET, CREDIT_LENGTH, ENC_BIG_ENDIAN);
936   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CREDIT_OFFSET));
937 }
938
939 #define DATA_PARAMETER_DATA_OFFSET PARAMETER_VALUE_OFFSET
940
941 static void
942 dissect_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, tvbuff_t **data_tvb)
943 {
944   guint16 data_length;
945
946   data_length    = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
947
948   if(parameter_tree) {
949     proto_tree_add_item(parameter_tree, hf_data, parameter_tvb, DATA_PARAMETER_DATA_OFFSET, data_length, ENC_BIG_ENDIAN);
950     proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", data_length, plurality(data_length, "", "s"));
951   }
952
953   if(data_tvb)
954   {
955     *data_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, data_length, data_length);
956   }
957 }
958
959
960 #define CAUSE_LENGTH 2
961 #define USER_LENGTH  2
962 #define CAUSE_OFFSET PARAMETER_VALUE_OFFSET
963 #define USER_OFFSET (CAUSE_OFFSET + CAUSE_LENGTH)
964
965 static const value_string cause_values[] = {
966   { 0x0,  "Remote SCCP unavailable, Reason unknown" },
967   { 0x2,  "Remote SCCP unequipped" },
968   { 0x3,  "Remote SCCP inaccessible" },
969   { 0,    NULL } };
970
971 static void
972 dissect_user_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
973 {
974   proto_tree_add_item(parameter_tree, hf_cause, parameter_tvb, CAUSE_OFFSET, CAUSE_LENGTH, ENC_BIG_ENDIAN);
975   proto_tree_add_item(parameter_tree, hf_user,  parameter_tvb, USER_OFFSET,  USER_LENGTH,  ENC_BIG_ENDIAN);
976 }
977
978 #define NETWORK_APPEARANCE_LENGTH 4
979 #define NETWORK_APPEARANCE_OFFSET PARAMETER_VALUE_OFFSET
980
981 static void
982 dissect_network_appearance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
983 {
984   proto_tree_add_item(parameter_tree, hf_network_appearance, parameter_tvb, NETWORK_APPEARANCE_OFFSET, NETWORK_APPEARANCE_LENGTH, ENC_BIG_ENDIAN);
985   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, NETWORK_APPEARANCE_OFFSET));
986 }
987
988 static void
989 dissect_routing_key_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
990 {
991   tvbuff_t *parameters_tvb;
992
993   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET);
994   dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
995 }
996 #define DRN_START_LENGTH 1
997 #define DRN_END_LENGTH 1
998 #define DRN_VALUE_LENGTH 2
999
1000 #define DRN_START_OFFSET PARAMETER_VALUE_OFFSET
1001 #define DRN_END_OFFSET   (DRN_START_OFFSET + DRN_START_LENGTH)
1002 #define DRN_VALUE_OFFSET (DRN_END_OFFSET + DRN_END_LENGTH)
1003
1004 static void
1005 dissect_drn_label_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1006 {
1007   proto_tree_add_item(parameter_tree, hf_drn_label_start, parameter_tvb, DRN_START_OFFSET, DRN_START_LENGTH, ENC_BIG_ENDIAN);
1008   proto_tree_add_item(parameter_tree, hf_drn_label_end,   parameter_tvb, DRN_END_OFFSET,   DRN_END_LENGTH,   ENC_BIG_ENDIAN);
1009   proto_tree_add_item(parameter_tree, hf_drn_label_value, parameter_tvb, DRN_VALUE_OFFSET, DRN_VALUE_LENGTH, ENC_BIG_ENDIAN);
1010 }
1011
1012 #define TID_START_LENGTH 1
1013 #define TID_END_LENGTH 1
1014 #define TID_VALUE_LENGTH 2
1015
1016 #define TID_START_OFFSET PARAMETER_VALUE_OFFSET
1017 #define TID_END_OFFSET   (TID_START_OFFSET + TID_START_LENGTH)
1018 #define TID_VALUE_OFFSET (TID_END_OFFSET + TID_END_LENGTH)
1019
1020 static void
1021 dissect_tid_label_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1022 {
1023   proto_tree_add_item(parameter_tree, hf_tid_label_start, parameter_tvb, TID_START_OFFSET, TID_START_LENGTH, ENC_BIG_ENDIAN);
1024   proto_tree_add_item(parameter_tree, hf_tid_label_end,   parameter_tvb, TID_END_OFFSET,   TID_END_LENGTH,   ENC_BIG_ENDIAN);
1025   proto_tree_add_item(parameter_tree, hf_tid_label_value, parameter_tvb, TID_VALUE_OFFSET, TID_VALUE_LENGTH, ENC_BIG_ENDIAN);
1026 }
1027
1028 #define ADDRESS_RANGE_ADDRESS_PARAMETERS_OFFSET  PARAMETER_VALUE_OFFSET
1029
1030 static void
1031 dissect_address_range_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1032 {
1033   tvbuff_t *parameters_tvb;
1034
1035   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET);
1036   dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
1037 }
1038
1039 #define SMI_LENGTH 1
1040 #define SMI_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1041
1042 static void
1043 dissect_smi_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1044 {
1045   proto_tree_add_item(parameter_tree, hf_smi_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_BIG_ENDIAN);
1046   proto_tree_add_item(parameter_tree, hf_smi,          parameter_tvb, SMI_OFFSET,             SMI_LENGTH,        ENC_BIG_ENDIAN);
1047   proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb,  SMI_OFFSET));
1048 }
1049
1050 #define IMPORTANCE_LENGTH 1
1051 #define IMPORTANCE_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1052
1053 static void
1054 dissect_importance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1055 {
1056   proto_tree_add_item(parameter_tree, hf_importance_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_BIG_ENDIAN);
1057   proto_tree_add_item(parameter_tree, hf_importance,          parameter_tvb, IMPORTANCE_OFFSET,      IMPORTANCE_LENGTH, ENC_BIG_ENDIAN);
1058   proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb,  IMPORTANCE_OFFSET));
1059 }
1060
1061 #define MESSAGE_PRIORITY_LENGTH 1
1062 #define MESSAGE_PRIORITY_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1063
1064 static void
1065 dissect_message_priority_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1066 {
1067   proto_tree_add_item(parameter_tree, hf_message_priority_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET,  RESERVED_3_LENGTH,       ENC_BIG_ENDIAN);
1068   proto_tree_add_item(parameter_tree, hf_message_priority,          parameter_tvb, MESSAGE_PRIORITY_OFFSET, MESSAGE_PRIORITY_LENGTH, ENC_BIG_ENDIAN);
1069   proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb,  MESSAGE_PRIORITY_OFFSET));
1070 }
1071
1072 #define PROTOCOL_CLASS_LENGTH         1
1073 #define PROTOCOL_CLASS_OFFSET         (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1074
1075 #define RETURN_ON_ERROR_BIT_MASK 0x80
1076 #define PROTOCOL_CLASS_MASK      0x7f
1077
1078
1079 static const true_false_string return_on_error_bit_value = {
1080   "Return Message On Error",
1081   "No Special Options"
1082 };
1083
1084 static void
1085 dissect_protocol_class_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1086 {
1087   proto_item *protocol_class_item;
1088   proto_tree *protocol_class_tree;
1089
1090   proto_tree_add_item(parameter_tree, hf_protocol_class_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_BIG_ENDIAN);
1091
1092   protocol_class_item = proto_tree_add_text(parameter_tree, parameter_tvb, PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH, "Protocol Class");
1093   protocol_class_tree = proto_item_add_subtree(protocol_class_item, ett_sua_return_on_error_bit_and_protocol_class);
1094
1095   proto_tree_add_item(protocol_class_tree, hf_return_on_error_bit, parameter_tvb, PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH, ENC_BIG_ENDIAN);
1096   proto_tree_add_item(protocol_class_tree, hf_protocol_class,      parameter_tvb, PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH, ENC_BIG_ENDIAN);
1097   proto_item_append_text(parameter_item, " (%d)", tvb_get_guint8(parameter_tvb, PROTOCOL_CLASS_OFFSET) & PROTOCOL_CLASS_MASK);
1098 }
1099
1100 #define SEQUENCE_CONTROL_LENGTH 4
1101 #define SEQUENCE_CONTROL_OFFSET PARAMETER_VALUE_OFFSET
1102
1103 static void
1104 dissect_sequence_control_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1105 {
1106   proto_tree_add_item(parameter_tree, hf_sequence_control, parameter_tvb, SEQUENCE_CONTROL_OFFSET, SEQUENCE_CONTROL_LENGTH, ENC_BIG_ENDIAN);
1107   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, SEQUENCE_CONTROL_OFFSET));
1108 }
1109
1110 #define FIRST_REMAINING_LENGTH        1
1111 #define SEGMENTATION_REFERENCE_LENGTH 3
1112 #define FIRST_REMAINING_OFFSET        PARAMETER_VALUE_OFFSET
1113 #define SEGMENTATION_REFERENCE_OFFSET (FIRST_REMAINING_OFFSET + FIRST_REMAINING_LENGTH)
1114
1115 #define FIRST_BIT_MASK 0x80
1116 #define NUMBER_OF_SEGMENTS_MASK 0x7f
1117
1118 static const true_false_string first_bit_value = {
1119   "First segment",
1120   "Subsequent segment"
1121 };
1122
1123 static void
1124 dissect_segmentation_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1125 {
1126   proto_item *first_remaining_item;
1127   proto_tree *first_remaining_tree;
1128
1129   first_remaining_item = proto_tree_add_text(parameter_tree, parameter_tvb, FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH, "First / Remaining");
1130   first_remaining_tree = proto_item_add_subtree(first_remaining_item, ett_sua_first_remaining);
1131   proto_tree_add_item(first_remaining_tree, hf_first_bit,                    parameter_tvb, FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH, ENC_BIG_ENDIAN);
1132   proto_tree_add_item(first_remaining_tree, hf_number_of_remaining_segments, parameter_tvb, FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH, ENC_BIG_ENDIAN);
1133   proto_tree_add_item(parameter_tree, hf_segmentation_reference, parameter_tvb, SEGMENTATION_REFERENCE_OFFSET, SEGMENTATION_REFERENCE_LENGTH, ENC_BIG_ENDIAN);
1134 }
1135
1136 #define CONGESTION_LEVEL_LENGTH 4
1137 #define CONGESTION_LEVEL_OFFSET PARAMETER_VALUE_OFFSET
1138
1139 static void
1140 dissect_congestion_level_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1141 {
1142   proto_tree_add_item(parameter_tree, hf_congestion_level, parameter_tvb, CONGESTION_LEVEL_OFFSET, CONGESTION_LEVEL_LENGTH, ENC_BIG_ENDIAN);
1143   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CONGESTION_LEVEL_OFFSET));
1144 }
1145
1146 #define GTI_LENGTH               1
1147 #define NO_OF_DIGITS_LENGTH      1
1148 #define TRANSLATION_TYPE_LENGTH  1
1149 #define NUMBERING_PLAN_LENGTH    1
1150 #define NATURE_OF_ADDRESS_LENGTH 1
1151
1152 #define GTI_OFFSET               (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1153 #define NO_OF_DIGITS_OFFSET      (GTI_OFFSET + GTI_LENGTH)
1154 #define TRANSLATION_TYPE_OFFSET  (NO_OF_DIGITS_OFFSET + NO_OF_DIGITS_LENGTH)
1155 #define NUMBERING_PLAN_OFFSET    (TRANSLATION_TYPE_OFFSET + TRANSLATION_TYPE_LENGTH)
1156 #define NATURE_OF_ADDRESS_OFFSET (NUMBERING_PLAN_OFFSET + NUMBERING_PLAN_LENGTH)
1157 #define GLOBAL_TITLE_OFFSET      (NATURE_OF_ADDRESS_OFFSET + NATURE_OF_ADDRESS_LENGTH)
1158
1159 #define ISDN_TELEPHONY_NUMBERING_PLAN   1
1160 #define GENERIC_NUMBERING_PLAN          2
1161 #define DATA_NUMBERING_PLAN             3
1162 #define TELEX_NUMBERING_PLAN            4
1163 #define MARITIME_MOBILE_NUMBERING_PLAN  5
1164 #define LAND_MOBILE_NUMBERING_PLAN      6
1165 #define ISDN_MOBILE_NUMBERING_PLAN      7
1166 #define PRIVATE_NETWORK_NUMBERING_PLAN 14
1167
1168 static const value_string numbering_plan_values[] = {
1169   { ISDN_TELEPHONY_NUMBERING_PLAN,  "ISDN/Telephony Numbering Plan (Rec. E.161 and E.164)" },
1170   { GENERIC_NUMBERING_PLAN,         "Generic Numbering Plan" },
1171   { DATA_NUMBERING_PLAN,            "Data Numbering Plan (Rec. X.121)" },
1172   { TELEX_NUMBERING_PLAN,           "Telex Numbering Plan (Rec. F.69)" },
1173   { MARITIME_MOBILE_NUMBERING_PLAN, "Maritime Mobile Numbering Plan (Rec. E.210 and E.211)" },
1174   { LAND_MOBILE_NUMBERING_PLAN,     "Land Mobile Numbering Plan (Rec. E.212)" },
1175   { ISDN_MOBILE_NUMBERING_PLAN,     "ISDN/Mobile Numbering Plan (Rec. E.214)" },
1176   { PRIVATE_NETWORK_NUMBERING_PLAN, "Private Network Or Network-Specific Numbering Plan" },
1177   { 0,                                             NULL } };
1178
1179 #define UNKNOWN_NATURE_OF_ADDRESS                       0
1180 #define SUBSCRIBER_NUMBER_NATURE_OF_ADDRESS             1
1181 #define RESERVED_FOR_NATIONAL_USE_NATURE_OF_ADDRESS     2
1182 #define NATIONAL_SIGNIFICANT_NUMBER_NATURE_OF_ADDRESS   3
1183 #define INTERNATION_NUMBER_NATURE_OF_ADDRESS            4
1184
1185 static const value_string nature_of_address_values[] = {
1186   { UNKNOWN_NATURE_OF_ADDRESS,                     "Unknown" },
1187   { SUBSCRIBER_NUMBER_NATURE_OF_ADDRESS,           "Subscriber Number" },
1188   { RESERVED_FOR_NATIONAL_USE_NATURE_OF_ADDRESS,   "Reserved For National Use" },
1189   { NATIONAL_SIGNIFICANT_NUMBER_NATURE_OF_ADDRESS, "National Significant Number" },
1190   { INTERNATION_NUMBER_NATURE_OF_ADDRESS,          "International Number" },
1191   { 0,                                             NULL } };
1192
1193 static void
1194 dissect_global_title_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1195 {
1196   guint16 global_title_length;
1197   guint16 offset;
1198   gboolean even_length;
1199   guint8 odd_signal, even_signal;
1200   guint8 number_of_digits;
1201   char gt_digits[GT_MAX_SIGNALS+1] = { 0 };
1202
1203   global_title_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) -
1204                         (PARAMETER_HEADER_LENGTH + RESERVED_3_LENGTH + GTI_LENGTH + NO_OF_DIGITS_LENGTH + TRANSLATION_TYPE_LENGTH + NUMBERING_PLAN_LENGTH + NATURE_OF_ADDRESS_LENGTH);
1205   proto_tree_add_item(parameter_tree, hf_gt_reserved,       parameter_tvb, PARAMETER_VALUE_OFFSET,   RESERVED_3_LENGTH,        ENC_BIG_ENDIAN);
1206   proto_tree_add_item(parameter_tree, hf_gti,               parameter_tvb, GTI_OFFSET,               GTI_LENGTH,               ENC_BIG_ENDIAN);
1207   proto_tree_add_item(parameter_tree, hf_number_of_digits,  parameter_tvb, NO_OF_DIGITS_OFFSET,      NO_OF_DIGITS_LENGTH,      ENC_BIG_ENDIAN);
1208   proto_tree_add_item(parameter_tree, hf_translation_type,  parameter_tvb, TRANSLATION_TYPE_OFFSET,  TRANSLATION_TYPE_LENGTH,  ENC_BIG_ENDIAN);
1209   proto_tree_add_item(parameter_tree, hf_numbering_plan,    parameter_tvb, NUMBERING_PLAN_OFFSET,    NUMBERING_PLAN_LENGTH,    ENC_BIG_ENDIAN);
1210   proto_tree_add_item(parameter_tree, hf_nature_of_address, parameter_tvb, NATURE_OF_ADDRESS_OFFSET, NATURE_OF_ADDRESS_LENGTH, ENC_BIG_ENDIAN);
1211
1212   number_of_digits = tvb_get_guint8(parameter_tvb, NO_OF_DIGITS_OFFSET);
1213   even_length = !(number_of_digits % 2);
1214   offset = GLOBAL_TITLE_OFFSET;
1215
1216   while(offset < GLOBAL_TITLE_OFFSET + global_title_length) {
1217     odd_signal = tvb_get_guint8(parameter_tvb, offset) & GT_ODD_SIGNAL_MASK;
1218     even_signal = tvb_get_guint8(parameter_tvb, offset) & GT_EVEN_SIGNAL_MASK;
1219     even_signal >>= GT_EVEN_SIGNAL_SHIFT;
1220
1221     g_strlcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
1222                                     "Unknown"), GT_MAX_SIGNALS+1);
1223
1224     /* If the last signal is NOT filler */
1225     if (offset != (GLOBAL_TITLE_OFFSET + global_title_length - 1) || even_length == TRUE)
1226       g_strlcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
1227                                    "Unknown"), GT_MAX_SIGNALS+1);
1228
1229     offset += GT_SIGNAL_LENGTH;
1230   }
1231
1232   proto_tree_add_string_format(parameter_tree, hf_global_title_digits,
1233                                parameter_tvb, GLOBAL_TITLE_OFFSET,
1234                                global_title_length, gt_digits,
1235                                "Address information (digits): %s", gt_digits);
1236 }
1237
1238 #define POINT_CODE_LENGTH 4
1239 #define POINT_CODE_OFFSET PARAMETER_VALUE_OFFSET
1240
1241 static void
1242 dissect_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1243 {
1244   proto_tree_add_item(parameter_tree, hf_point_code_dpc, parameter_tvb, POINT_CODE_OFFSET, POINT_CODE_LENGTH, ENC_BIG_ENDIAN);
1245   proto_item_append_text(parameter_item, " (%s)", mtp3_pc_to_str(tvb_get_ntohl(parameter_tvb, POINT_CODE_OFFSET)));
1246 }
1247
1248 #define SSN_LENGTH 1
1249 #define SSN_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1250 #define INVALID_SSN 0xff
1251
1252 static void
1253 dissect_ssn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, guint8 *ssn)
1254 {
1255   *ssn = tvb_get_guint8(parameter_tvb,  SSN_OFFSET);
1256
1257   if(parameter_tree) {
1258     proto_tree_add_item(parameter_tree, hf_ssn_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_BIG_ENDIAN);
1259     proto_tree_add_item(parameter_tree, hf_ssn_number,   parameter_tvb, SSN_OFFSET,             SSN_LENGTH,        ENC_BIG_ENDIAN);
1260     proto_item_append_text(parameter_item, " (%u)", *ssn);
1261   }
1262 }
1263
1264 #define IPV4_ADDRESS_LENGTH 4
1265 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1266
1267 static void
1268 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1269 {
1270   proto_tree_add_item(parameter_tree, hf_ipv4, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, ENC_BIG_ENDIAN);
1271   proto_item_append_text(parameter_item, " (%s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
1272 }
1273
1274 #define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
1275
1276 static void
1277 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1278 {
1279   guint16 hostname_length;
1280
1281   hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1282   proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, ENC_BIG_ENDIAN);
1283   proto_item_append_text(parameter_item, " (%.*s)", hostname_length,
1284                          (const char *)tvb_get_ptr(parameter_tvb, HOSTNAME_OFFSET, hostname_length));
1285 }
1286
1287 #define IPV6_ADDRESS_LENGTH 16
1288 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1289
1290 static void
1291 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1292 {
1293   proto_tree_add_item(parameter_tree, hf_ipv6, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, ENC_BIG_ENDIAN);
1294   proto_item_append_text(parameter_item, " (%s)", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
1295 }
1296
1297 static void
1298 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1299 {
1300   guint16 parameter_value_length;
1301
1302   parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1303   proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, ENC_BIG_ENDIAN);
1304   proto_item_append_text(parameter_item, "(tag %u and %u byte%s value)", tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET), parameter_value_length, plurality(parameter_value_length, "", "s"));
1305 }
1306
1307 #define V8_DATA_PARAMETER_TAG                         0x0003
1308 #define V8_INFO_STRING_PARAMETER_TAG                  0x0004
1309 #define V8_ROUTING_CONTEXT_PARAMETER_TAG              0x0006
1310 #define V8_DIAGNOSTIC_INFO_PARAMETER_TAG              0x0007
1311 #define V8_HEARTBEAT_DATA_PARAMETER_TAG               0x0009
1312 #define V8_TRAFFIC_MODE_TYPE_PARAMETER_TAG            0x000b
1313 #define V8_ERROR_CODE_PARAMETER_TAG                   0x000c
1314 #define V8_STATUS_PARAMETER_TAG                       0x000d
1315 #define V8_CONGESTION_LEVEL_PARAMETER_TAG             0x000f
1316 #define V8_ASP_IDENTIFIER_PARAMETER_TAG               0x0011
1317 #define V8_AFFECTED_POINT_CODE_PARAMETER_TAG          0x0012
1318
1319 #define V8_SS7_HOP_COUNTER_PARAMETER_TAG              0x0101
1320 #define V8_SOURCE_ADDRESS_PARAMETER_TAG               0x0102
1321 #define V8_DESTINATION_ADDRESS_PARAMETER_TAG          0x0103
1322 #define V8_SOURCE_REFERENCE_NUMBER_PARAMETER_TAG      0x0104
1323 #define V8_DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG 0x0105
1324 #define V8_SCCP_CAUSE_PARAMETER_TAG                   0x0106
1325 #define V8_SEQUENCE_NUMBER_PARAMETER_TAG              0x0107
1326 #define V8_RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG      0x0108
1327 #define V8_ASP_CAPABILITIES_PARAMETER_TAG             0x0109
1328 #define V8_CREDIT_PARAMETER_TAG                       0x010a
1329 #define V8_USER_CAUSE_PARAMETER_TAG                   0x010c
1330 #define V8_NETWORK_APPEARANCE_PARAMETER_TAG           0x010d
1331 #define V8_ROUTING_KEY_PARAMETER_TAG                  0x010e
1332 #define V8_REGISTRATION_RESULT_PARAMETER_TAG          0x010f
1333 #define V8_DEREGISTRATION_RESULT_PARAMETER_TAG        0x0110
1334 #define V8_ADDRESS_RANGE_PARAMETER_TAG                0x0111
1335 #define V8_CORRELATION_ID_PARAMETER_TAG               0x0112
1336 #define V8_IMPORTANCE_PARAMETER_TAG                   0x0113
1337 #define V8_MESSAGE_PRIORITY_PARAMETER_TAG             0x0114
1338 #define V8_PROTOCOL_CLASS_PARAMETER_TAG               0x0115
1339 #define V8_SEQUENCE_CONTROL_PARAMETER_TAG             0x0116
1340 #define V8_SEGMENTATION_PARAMETER_TAG                 0x0117
1341 #define V8_SMI_PARAMETER_TAG                          0x0118
1342 #define V8_TID_LABEL_PARAMETER_TAG                    0x0119
1343 #define V8_DRN_LABEL_PARAMETER_TAG                    0x011a
1344
1345 #define V8_GLOBAL_TITLE_PARAMETER_TAG                 0x8001
1346 #define V8_POINT_CODE_PARAMETER_TAG                   0x8002
1347 #define V8_SUBSYSTEM_NUMBER_PARAMETER_TAG             0x8003
1348 #define V8_IPV4_ADDRESS_PARAMETER_TAG                 0x8004
1349 #define V8_HOSTNAME_PARAMETER_TAG                     0x8005
1350 #define V8_IPV6_ADDRESS_PARAMETER_TAG                 0x8006
1351
1352 static const value_string v8_parameter_tag_values[] = {
1353   { V8_DATA_PARAMETER_TAG,                         "Data" },
1354   { V8_INFO_STRING_PARAMETER_TAG,                  "Info String" },
1355   { V8_ROUTING_CONTEXT_PARAMETER_TAG,              "Routing context" },
1356   { V8_DIAGNOSTIC_INFO_PARAMETER_TAG,              "Diagnostic info" },
1357   { V8_HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat data" },
1358   { V8_TRAFFIC_MODE_TYPE_PARAMETER_TAG,            "Traffic mode type" },
1359   { V8_ERROR_CODE_PARAMETER_TAG,                   "Error code" },
1360   { V8_STATUS_PARAMETER_TAG,                       "Status" },
1361   { V8_CONGESTION_LEVEL_PARAMETER_TAG,             "Congestion level" },
1362   { V8_ASP_IDENTIFIER_PARAMETER_TAG,               "ASP identifier" },
1363   { V8_AFFECTED_POINT_CODE_PARAMETER_TAG,          "Affected point code" },
1364   { V8_SS7_HOP_COUNTER_PARAMETER_TAG,              "SS7 hop counter" },
1365   { V8_SOURCE_ADDRESS_PARAMETER_TAG,               "Source address" },
1366   { V8_DESTINATION_ADDRESS_PARAMETER_TAG,          "Destination address" },
1367   { V8_SOURCE_REFERENCE_NUMBER_PARAMETER_TAG,      "Source reference number" },
1368   { V8_DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG, "Destination reference number" },
1369   { V8_SCCP_CAUSE_PARAMETER_TAG,                   "SCCP cause" },
1370   { V8_SEQUENCE_NUMBER_PARAMETER_TAG,              "Sequence number" },
1371   { V8_RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG,      "Receive sequence number" },
1372   { V8_ASP_CAPABILITIES_PARAMETER_TAG,             "ASP capabilities" },
1373   { V8_CREDIT_PARAMETER_TAG,                       "Credit" },
1374   { V8_USER_CAUSE_PARAMETER_TAG,                   "User/Cause" },
1375   { V8_NETWORK_APPEARANCE_PARAMETER_TAG,           "Network appearance" },
1376   { V8_ROUTING_KEY_PARAMETER_TAG,                  "Routing key" },
1377   { V8_REGISTRATION_RESULT_PARAMETER_TAG,          "Registration result" },
1378   { V8_DEREGISTRATION_RESULT_PARAMETER_TAG,        "Deregistration result" },
1379   { V8_ADDRESS_RANGE_PARAMETER_TAG,                "Address range" },
1380   { V8_CORRELATION_ID_PARAMETER_TAG,               "Correlation ID" },
1381   { V8_IMPORTANCE_PARAMETER_TAG,                   "Importance" },
1382   { V8_MESSAGE_PRIORITY_PARAMETER_TAG,             "Message priority" },
1383   { V8_PROTOCOL_CLASS_PARAMETER_TAG,               "Protocol class" },
1384   { V8_SEQUENCE_CONTROL_PARAMETER_TAG,             "Sequence control" },
1385   { V8_SEGMENTATION_PARAMETER_TAG,                 "Segmentation" },
1386   { V8_SMI_PARAMETER_TAG,                          "SMI" },
1387   { V8_TID_LABEL_PARAMETER_TAG,                    "TID label" },
1388   { V8_DRN_LABEL_PARAMETER_TAG,                    "DRN label" },
1389   { V8_GLOBAL_TITLE_PARAMETER_TAG,                 "Global title" },
1390   { V8_POINT_CODE_PARAMETER_TAG,                   "Point code" },
1391   { V8_SUBSYSTEM_NUMBER_PARAMETER_TAG,             "Subsystem number" },
1392   { V8_IPV4_ADDRESS_PARAMETER_TAG,                 "IPv4 address" },
1393   { V8_HOSTNAME_PARAMETER_TAG,                     "Hostname" },
1394   { V8_IPV6_ADDRESS_PARAMETER_TAG,                 "IPv6 address" },
1395   { 0,                                          NULL } };
1396
1397 static void
1398 dissect_v8_parameter(tvbuff_t *parameter_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
1399 {
1400   guint16 tag, length, padding_length;
1401   proto_item *parameter_item;
1402   proto_tree *parameter_tree;
1403   guint8 ssn = INVALID_SSN;
1404
1405   /* extract tag and length from the parameter */
1406   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1407   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1408   padding_length = tvb_length(parameter_tvb) - length;
1409
1410   if (tree) {
1411     /* create proto_tree stuff */
1412     parameter_item   = proto_tree_add_text(tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), "%s", val_to_str(tag, v8_parameter_tag_values, "Unknown parameter"));
1413     parameter_tree   = proto_item_add_subtree(parameter_item, ett_sua_parameter);
1414
1415     /* add tag and length to the sua tree */
1416     proto_tree_add_item(parameter_tree, hf_v8_parameter_tag,    parameter_tvb, PARAMETER_TAG_OFFSET,    PARAMETER_TAG_LENGTH,    ENC_BIG_ENDIAN);
1417     proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, ENC_BIG_ENDIAN);
1418   } else {
1419     parameter_tree = NULL;
1420     parameter_item = NULL;
1421   }
1422
1423   /*
1424   ** If no tree, only the data and ssn parameters in the source and destination
1425   ** address need to be dissected. This in order to make dissection of the data
1426   ** possible when there is no tree.
1427   */
1428   if (!tree && tag != V8_DATA_PARAMETER_TAG
1429             && tag != V8_SOURCE_ADDRESS_PARAMETER_TAG
1430             && tag != V8_DESTINATION_ADDRESS_PARAMETER_TAG
1431             && tag != V8_SUBSYSTEM_NUMBER_PARAMETER_TAG)
1432     return;
1433
1434   switch(tag) {
1435   case V8_DATA_PARAMETER_TAG:
1436     dissect_data_parameter(parameter_tvb, parameter_tree, parameter_item, data_tvb);
1437     break;
1438   case V8_INFO_STRING_PARAMETER_TAG:
1439     dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
1440     break;
1441   case V8_ROUTING_CONTEXT_PARAMETER_TAG:
1442     dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
1443     break;
1444   case V8_DIAGNOSTIC_INFO_PARAMETER_TAG:
1445     dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
1446     break;
1447   case V8_HEARTBEAT_DATA_PARAMETER_TAG:
1448     dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1449     break;
1450   case V8_TRAFFIC_MODE_TYPE_PARAMETER_TAG:
1451     dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1452     break;
1453   case V8_ERROR_CODE_PARAMETER_TAG:
1454     dissect_v8_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1455     break;
1456   case V8_STATUS_PARAMETER_TAG:
1457     dissect_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1458     break;
1459   case V8_CONGESTION_LEVEL_PARAMETER_TAG:
1460     dissect_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
1461     break;
1462   case V8_ASP_IDENTIFIER_PARAMETER_TAG:
1463     dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1464     break;
1465   case V8_AFFECTED_POINT_CODE_PARAMETER_TAG:
1466     dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
1467     break;
1468   case V8_SS7_HOP_COUNTER_PARAMETER_TAG:
1469     dissect_ss7_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
1470     break;
1471   case V8_SOURCE_ADDRESS_PARAMETER_TAG:
1472     dissect_source_address_parameter(parameter_tvb, parameter_tree, source_ssn);
1473     break;
1474   case V8_DESTINATION_ADDRESS_PARAMETER_TAG:
1475     dissect_destination_address_parameter(parameter_tvb, parameter_tree, dest_ssn);
1476     break;
1477   case V8_SOURCE_REFERENCE_NUMBER_PARAMETER_TAG:
1478     dissect_source_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1479     break;
1480   case V8_DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG:
1481     dissect_destination_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1482     break;
1483   case V8_SCCP_CAUSE_PARAMETER_TAG:
1484     dissect_sccp_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
1485     break;
1486   case V8_SEQUENCE_NUMBER_PARAMETER_TAG:
1487     dissect_sequence_number_parameter(parameter_tvb, parameter_tree);
1488     break;
1489   case V8_RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG:
1490     dissect_receive_sequence_number_parameter(parameter_tvb, parameter_tree);
1491     break;
1492   case V8_ASP_CAPABILITIES_PARAMETER_TAG:
1493     dissect_asp_capabilities_parameter(parameter_tvb, parameter_tree);
1494     break;
1495   case V8_CREDIT_PARAMETER_TAG:
1496     dissect_credit_parameter(parameter_tvb, parameter_tree, parameter_item);
1497     break;
1498   case V8_USER_CAUSE_PARAMETER_TAG:
1499     dissect_user_cause_parameter(parameter_tvb, parameter_tree);
1500     break;
1501   case V8_NETWORK_APPEARANCE_PARAMETER_TAG:
1502     dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
1503     break;
1504   case V8_ROUTING_KEY_PARAMETER_TAG:
1505     dissect_routing_key_parameter(parameter_tvb, parameter_tree);
1506     break;
1507   case V8_REGISTRATION_RESULT_PARAMETER_TAG:
1508     dissect_registration_result_parameter(parameter_tvb, parameter_tree);
1509     break;
1510   case V8_DEREGISTRATION_RESULT_PARAMETER_TAG:
1511     dissect_deregistration_result_parameter(parameter_tvb, parameter_tree);
1512     break;
1513   case V8_ADDRESS_RANGE_PARAMETER_TAG:
1514     dissect_address_range_parameter(parameter_tvb, parameter_tree);
1515     break;
1516   case V8_CORRELATION_ID_PARAMETER_TAG:
1517     dissect_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
1518     break;
1519   case V8_IMPORTANCE_PARAMETER_TAG:
1520     dissect_importance_parameter(parameter_tvb, parameter_tree, parameter_item);
1521     break;
1522   case V8_MESSAGE_PRIORITY_PARAMETER_TAG:
1523     dissect_message_priority_parameter(parameter_tvb, parameter_tree, parameter_item);
1524     break;
1525   case V8_PROTOCOL_CLASS_PARAMETER_TAG:
1526     dissect_protocol_class_parameter(parameter_tvb, parameter_tree, parameter_item);
1527     break;
1528   case V8_SEQUENCE_CONTROL_PARAMETER_TAG:
1529     dissect_sequence_control_parameter(parameter_tvb, parameter_tree, parameter_item);
1530     break;
1531   case V8_SEGMENTATION_PARAMETER_TAG:
1532     dissect_segmentation_parameter(parameter_tvb, parameter_tree);
1533     break;
1534   case V8_SMI_PARAMETER_TAG:
1535     dissect_smi_parameter(parameter_tvb, parameter_tree, parameter_item);
1536     break;
1537   case V8_TID_LABEL_PARAMETER_TAG:
1538     dissect_tid_label_parameter(parameter_tvb, parameter_tree);
1539     break;
1540   case V8_DRN_LABEL_PARAMETER_TAG:
1541     dissect_drn_label_parameter(parameter_tvb, parameter_tree);
1542     break;
1543   case V8_GLOBAL_TITLE_PARAMETER_TAG:
1544     dissect_global_title_parameter(parameter_tvb, parameter_tree);
1545     break;
1546   case V8_POINT_CODE_PARAMETER_TAG:
1547     dissect_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1548     break;
1549   case V8_SUBSYSTEM_NUMBER_PARAMETER_TAG:
1550     dissect_ssn_parameter(parameter_tvb, parameter_tree, parameter_item, &ssn);
1551     if(source_ssn)
1552     {
1553         *source_ssn = ssn;
1554     }
1555     if(dest_ssn)
1556     {
1557         *dest_ssn = ssn;
1558     }
1559     break;
1560   case V8_IPV4_ADDRESS_PARAMETER_TAG:
1561     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
1562     break;
1563   case V8_HOSTNAME_PARAMETER_TAG:
1564     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
1565     break;
1566   case V8_IPV6_ADDRESS_PARAMETER_TAG:
1567     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
1568     break;
1569   default:
1570     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1571     break;
1572   };
1573   if (parameter_tree && (padding_length > 0))
1574     proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_BIG_ENDIAN);
1575 }
1576
1577 #define INFO_STRING_PARAMETER_TAG                  0x0004
1578 #define ROUTING_CONTEXT_PARAMETER_TAG              0x0006
1579 #define DIAGNOSTIC_INFO_PARAMETER_TAG              0x0007
1580 #define HEARTBEAT_DATA_PARAMETER_TAG               0x0009
1581 #define TRAFFIC_MODE_TYPE_PARAMETER_TAG            0x000b
1582 #define ERROR_CODE_PARAMETER_TAG                   0x000c
1583 #define STATUS_PARAMETER_TAG                       0x000d
1584 #define ASP_IDENTIFIER_PARAMETER_TAG               0x0011
1585 #define AFFECTED_POINT_CODE_PARAMETER_TAG          0x0012
1586 #define CORRELATION_ID_PARAMETER_TAG               0x0013
1587 #define REGISTRATION_RESULT_PARAMETER_TAG          0x0014
1588 #define DEREGISTRATION_RESULT_PARAMETER_TAG        0x0015
1589 #define REGISTRATION_STATUS_PARAMETER_TAG          0x0016
1590 #define DEREGISTRATION_STATUS_PARAMETER_TAG        0x0017
1591 #define LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG 0x0018
1592
1593 #define SS7_HOP_COUNTER_PARAMETER_TAG              0x0101
1594 #define SOURCE_ADDRESS_PARAMETER_TAG               0x0102
1595 #define DESTINATION_ADDRESS_PARAMETER_TAG          0x0103
1596 #define SOURCE_REFERENCE_NUMBER_PARAMETER_TAG      0x0104
1597 #define DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG 0x0105
1598 #define SCCP_CAUSE_PARAMETER_TAG                   0x0106
1599 #define SEQUENCE_NUMBER_PARAMETER_TAG              0x0107
1600 #define RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG      0x0108
1601 #define ASP_CAPABILITIES_PARAMETER_TAG             0x0109
1602 #define CREDIT_PARAMETER_TAG                       0x010a
1603 #define DATA_PARAMETER_TAG                         0x010b
1604 #define USER_CAUSE_PARAMETER_TAG                   0x010c
1605 #define NETWORK_APPEARANCE_PARAMETER_TAG           0x010d
1606 #define ROUTING_KEY_PARAMETER_TAG                  0x010e
1607 #define DRN_LABEL_PARAMETER_TAG                    0x010f
1608 #define TID_LABEL_PARAMETER_TAG                    0x0110
1609 #define ADDRESS_RANGE_PARAMETER_TAG                0x0111
1610 #define SMI_PARAMETER_TAG                          0x0112
1611 #define IMPORTANCE_PARAMETER_TAG                   0x0113
1612 #define MESSAGE_PRIORITY_PARAMETER_TAG             0x0114
1613 #define PROTOCOL_CLASS_PARAMETER_TAG               0x0115
1614 #define SEQUENCE_CONTROL_PARAMETER_TAG             0x0116
1615 #define SEGMENTATION_PARAMETER_TAG                 0x0117
1616 #define CONGESTION_LEVEL_PARAMETER_TAG             0x0118
1617
1618 #define GLOBAL_TITLE_PARAMETER_TAG                 0x8001
1619 #define POINT_CODE_PARAMETER_TAG                   0x8002
1620 #define SUBSYSTEM_NUMBER_PARAMETER_TAG             0x8003
1621 #define IPV4_ADDRESS_PARAMETER_TAG                 0x8004
1622 #define HOSTNAME_PARAMETER_TAG                     0x8005
1623 #define IPV6_ADDRESS_PARAMETER_TAG                 0x8006
1624
1625 static const value_string parameter_tag_values[] = {
1626   { INFO_STRING_PARAMETER_TAG,                  "Info String" },
1627   { ROUTING_CONTEXT_PARAMETER_TAG,              "Routing context" },
1628   { DIAGNOSTIC_INFO_PARAMETER_TAG,              "Diagnostic info" },
1629   { HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat data" },
1630   { TRAFFIC_MODE_TYPE_PARAMETER_TAG,            "Traffic mode type" },
1631   { ERROR_CODE_PARAMETER_TAG,                   "Error code" },
1632   { STATUS_PARAMETER_TAG,                       "Status" },
1633   { ASP_IDENTIFIER_PARAMETER_TAG,               "ASP identifier" },
1634   { AFFECTED_POINT_CODE_PARAMETER_TAG,          "Affected point code" },
1635   { CORRELATION_ID_PARAMETER_TAG,               "Correlation ID" },
1636   { REGISTRATION_RESULT_PARAMETER_TAG,          "Registration result" },
1637   { DEREGISTRATION_RESULT_PARAMETER_TAG,        "Deregistration result" },
1638   { REGISTRATION_STATUS_PARAMETER_TAG,          "Registration status" },
1639   { DEREGISTRATION_STATUS_PARAMETER_TAG,        "Deregistration status" },
1640   { LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG, "Local routing key identifier" },
1641   { SS7_HOP_COUNTER_PARAMETER_TAG,              "SS7 hop counter" },
1642   { SOURCE_ADDRESS_PARAMETER_TAG,               "Source address" },
1643   { DESTINATION_ADDRESS_PARAMETER_TAG,          "Destination address" },
1644   { SOURCE_REFERENCE_NUMBER_PARAMETER_TAG,      "Source reference number" },
1645   { DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG, "Destination reference number" },
1646   { SCCP_CAUSE_PARAMETER_TAG,                   "SCCP cause" },
1647   { SEQUENCE_NUMBER_PARAMETER_TAG,              "Sequence number" },
1648   { RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG,      "Receive sequence number" },
1649   { ASP_CAPABILITIES_PARAMETER_TAG,             "ASP capabilities" },
1650   { CREDIT_PARAMETER_TAG,                       "Credit" },
1651   { DATA_PARAMETER_TAG,                         "Data" },
1652   { USER_CAUSE_PARAMETER_TAG,                   "User/Cause" },
1653   { NETWORK_APPEARANCE_PARAMETER_TAG,           "Network appearance" },
1654   { ROUTING_KEY_PARAMETER_TAG,                  "Routing key" },
1655   { DRN_LABEL_PARAMETER_TAG,                    "DRN label" },
1656   { TID_LABEL_PARAMETER_TAG,                    "TID label" },
1657   { ADDRESS_RANGE_PARAMETER_TAG,                "Address range" },
1658   { SMI_PARAMETER_TAG,                          "SMI" },
1659   { IMPORTANCE_PARAMETER_TAG,                   "Importance" },
1660   { MESSAGE_PRIORITY_PARAMETER_TAG,             "Message priority" },
1661   { PROTOCOL_CLASS_PARAMETER_TAG,               "Protocol class" },
1662   { SEQUENCE_CONTROL_PARAMETER_TAG,             "Sequence control" },
1663   { SEGMENTATION_PARAMETER_TAG,                 "Segmentation" },
1664   { CONGESTION_LEVEL_PARAMETER_TAG,             "Congestion level" },
1665   { GLOBAL_TITLE_PARAMETER_TAG,                 "Global title" },
1666   { POINT_CODE_PARAMETER_TAG,                   "Point code" },
1667   { SUBSYSTEM_NUMBER_PARAMETER_TAG,             "Subsystem number" },
1668   { IPV4_ADDRESS_PARAMETER_TAG,                 "IPv4 address" },
1669   { HOSTNAME_PARAMETER_TAG,                     "Hostname" },
1670   { IPV6_ADDRESS_PARAMETER_TAG,                 "IPv6 address" },
1671   { 0,                                          NULL } };
1672
1673 static void
1674 dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
1675 {
1676   guint16 tag, length, padding_length;
1677   proto_item *parameter_item;
1678   proto_tree *parameter_tree;
1679   guint8 ssn = INVALID_SSN;
1680
1681   /* extract tag and length from the parameter */
1682   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1683   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1684   padding_length = tvb_length(parameter_tvb) - length;
1685
1686   if (tree) {
1687     /* create proto_tree stuff */
1688     parameter_item   = proto_tree_add_text(tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), "%s", val_to_str(tag, parameter_tag_values, "Unknown parameter"));
1689     parameter_tree   = proto_item_add_subtree(parameter_item, ett_sua_parameter);
1690
1691     /* add tag and length to the sua tree */
1692     proto_tree_add_item(parameter_tree, hf_parameter_tag,    parameter_tvb, PARAMETER_TAG_OFFSET,    PARAMETER_TAG_LENGTH,    ENC_BIG_ENDIAN);
1693     proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, ENC_BIG_ENDIAN);
1694   } else {
1695     parameter_tree = NULL;
1696     parameter_item = NULL;
1697   }
1698
1699   /*
1700   ** If no tree, only the data and ssn parameters in the source and destination
1701   ** address need to be dissected. This in order to make dissection of the data
1702   ** possible when there is no tree.
1703   */
1704   if (!tree && tag != DATA_PARAMETER_TAG
1705             && tag != SOURCE_ADDRESS_PARAMETER_TAG
1706             && tag != DESTINATION_ADDRESS_PARAMETER_TAG
1707             && tag != SUBSYSTEM_NUMBER_PARAMETER_TAG)
1708     return;     /* Nothing to do here */
1709
1710   switch(tag) {
1711   case DATA_PARAMETER_TAG:
1712     dissect_data_parameter(parameter_tvb, parameter_tree, parameter_item, data_tvb);
1713     break;
1714   case INFO_STRING_PARAMETER_TAG:
1715     dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
1716     break;
1717   case ROUTING_CONTEXT_PARAMETER_TAG:
1718     dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
1719     break;
1720   case DIAGNOSTIC_INFO_PARAMETER_TAG:
1721     dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
1722     break;
1723   case HEARTBEAT_DATA_PARAMETER_TAG:
1724     dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1725     break;
1726   case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
1727     dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1728     break;
1729   case ERROR_CODE_PARAMETER_TAG:
1730     dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1731     break;
1732   case STATUS_PARAMETER_TAG:
1733     dissect_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1734     break;
1735   case CONGESTION_LEVEL_PARAMETER_TAG:
1736     dissect_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
1737     break;
1738   case ASP_IDENTIFIER_PARAMETER_TAG:
1739     dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1740     break;
1741   case AFFECTED_POINT_CODE_PARAMETER_TAG:
1742     dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
1743     break;
1744   case REGISTRATION_STATUS_PARAMETER_TAG:
1745     dissect_registration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1746     break;
1747   case DEREGISTRATION_STATUS_PARAMETER_TAG:
1748     dissect_deregistration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1749     break;
1750   case LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
1751     dissect_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1752     break;
1753   case SS7_HOP_COUNTER_PARAMETER_TAG:
1754     dissect_ss7_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
1755     break;
1756   case SOURCE_ADDRESS_PARAMETER_TAG:
1757     dissect_source_address_parameter(parameter_tvb, parameter_tree, source_ssn);
1758     break;
1759   case DESTINATION_ADDRESS_PARAMETER_TAG:
1760     dissect_destination_address_parameter(parameter_tvb, parameter_tree, dest_ssn);
1761     break;
1762   case SOURCE_REFERENCE_NUMBER_PARAMETER_TAG:
1763     dissect_source_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1764     break;
1765   case DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG:
1766     dissect_destination_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1767     break;
1768   case SCCP_CAUSE_PARAMETER_TAG:
1769     dissect_sccp_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
1770     break;
1771   case SEQUENCE_NUMBER_PARAMETER_TAG:
1772     dissect_sequence_number_parameter(parameter_tvb, parameter_tree);
1773     break;
1774   case RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG:
1775     dissect_receive_sequence_number_parameter(parameter_tvb, parameter_tree);
1776     break;
1777   case ASP_CAPABILITIES_PARAMETER_TAG:
1778     dissect_asp_capabilities_parameter(parameter_tvb, parameter_tree);
1779     break;
1780   case CREDIT_PARAMETER_TAG:
1781     dissect_credit_parameter(parameter_tvb, parameter_tree, parameter_item);
1782     break;
1783   case USER_CAUSE_PARAMETER_TAG:
1784     dissect_user_cause_parameter(parameter_tvb, parameter_tree);
1785     break;
1786   case NETWORK_APPEARANCE_PARAMETER_TAG:
1787     dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
1788     break;
1789   case ROUTING_KEY_PARAMETER_TAG:
1790     dissect_routing_key_parameter(parameter_tvb, parameter_tree);
1791     break;
1792   case REGISTRATION_RESULT_PARAMETER_TAG:
1793     dissect_registration_result_parameter(parameter_tvb, parameter_tree);
1794     break;
1795   case DEREGISTRATION_RESULT_PARAMETER_TAG:
1796     dissect_deregistration_result_parameter(parameter_tvb, parameter_tree);
1797     break;
1798   case ADDRESS_RANGE_PARAMETER_TAG:
1799     dissect_address_range_parameter(parameter_tvb, parameter_tree);
1800     break;
1801   case CORRELATION_ID_PARAMETER_TAG:
1802     dissect_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
1803     break;
1804   case IMPORTANCE_PARAMETER_TAG:
1805     dissect_importance_parameter(parameter_tvb, parameter_tree, parameter_item);
1806     break;
1807   case MESSAGE_PRIORITY_PARAMETER_TAG:
1808     dissect_message_priority_parameter(parameter_tvb, parameter_tree, parameter_item);
1809     break;
1810   case PROTOCOL_CLASS_PARAMETER_TAG:
1811     dissect_protocol_class_parameter(parameter_tvb, parameter_tree, parameter_item);
1812     break;
1813   case SEQUENCE_CONTROL_PARAMETER_TAG:
1814     dissect_sequence_control_parameter(parameter_tvb, parameter_tree, parameter_item);
1815     break;
1816   case SEGMENTATION_PARAMETER_TAG:
1817     dissect_segmentation_parameter(parameter_tvb, parameter_tree);
1818     break;
1819   case SMI_PARAMETER_TAG:
1820     dissect_smi_parameter(parameter_tvb, parameter_tree, parameter_item);
1821     break;
1822   case TID_LABEL_PARAMETER_TAG:
1823     dissect_tid_label_parameter(parameter_tvb, parameter_tree);
1824     break;
1825   case DRN_LABEL_PARAMETER_TAG:
1826     dissect_drn_label_parameter(parameter_tvb, parameter_tree);
1827     break;
1828   case GLOBAL_TITLE_PARAMETER_TAG:
1829     dissect_global_title_parameter(parameter_tvb, parameter_tree);
1830     break;
1831   case POINT_CODE_PARAMETER_TAG:
1832     dissect_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1833     break;
1834   case SUBSYSTEM_NUMBER_PARAMETER_TAG:
1835     dissect_ssn_parameter(parameter_tvb, parameter_tree, parameter_item, &ssn);
1836     if(source_ssn)
1837     {
1838         *source_ssn = ssn;
1839     }
1840     if(dest_ssn)
1841     {
1842         *dest_ssn = ssn;
1843     }
1844     break;
1845   case IPV4_ADDRESS_PARAMETER_TAG:
1846     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
1847     break;
1848   case HOSTNAME_PARAMETER_TAG:
1849     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
1850     break;
1851   case IPV6_ADDRESS_PARAMETER_TAG:
1852     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
1853     break;
1854   default:
1855     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1856     break;
1857   };
1858   if (parameter_tree && (padding_length > 0))
1859     proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_BIG_ENDIAN);
1860 }
1861
1862 static void
1863 dissect_parameters(tvbuff_t *parameters_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
1864 {
1865   gint offset, length, total_length, remaining_length;
1866   tvbuff_t *parameter_tvb;
1867
1868   offset = 0;
1869   while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
1870     length       = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
1871     total_length = ADD_PADDING(length);
1872     if (remaining_length >= length)
1873       total_length = MIN(total_length, remaining_length);
1874     /* create a tvb for the parameter including the padding bytes */
1875     parameter_tvb  = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
1876     switch(version) {
1877       case SUA_V08:
1878         dissect_v8_parameter(parameter_tvb, tree, data_tvb, source_ssn, dest_ssn);
1879         break;
1880       case SUA_RFC:
1881         dissect_parameter(parameter_tvb, tree, data_tvb, source_ssn, dest_ssn);
1882         break;
1883     }
1884     /* get rid of the handled parameter */
1885     offset += total_length;
1886   }
1887 }
1888
1889 static void
1890 dissect_sua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *sua_tree, proto_tree *tree)
1891 {
1892   tvbuff_t *common_header_tvb;
1893   tvbuff_t *parameters_tvb;
1894   tvbuff_t *data_tvb = NULL;
1895   guint8 source_ssn = INVALID_SSN;
1896   guint8 dest_ssn = INVALID_SSN;
1897
1898   message_class = 0;
1899   message_type = 0;
1900   drn = 0;
1901   srn = 0;
1902
1903   common_header_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_OFFSET, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
1904   dissect_common_header(common_header_tvb, pinfo, sua_tree);
1905
1906   parameters_tvb = tvb_new_subset_remaining(message_tvb, COMMON_HEADER_LENGTH);
1907   dissect_parameters(parameters_tvb, sua_tree, &data_tvb, &source_ssn, &dest_ssn);
1908
1909   if ( message_class == MESSAGE_CLASS_CO_MESSAGE) {
1910           /* XXX: this might fail with multihomed SCTP (on a path failure during a call) */
1911           sccp_assoc_info_t* assoc;
1912           reset_sccp_assoc();
1913           assoc = get_sccp_assoc(pinfo, tvb_offset_from_real_beginning(message_tvb), srn, drn, message_type);
1914
1915           if (assoc && assoc->curr_msg) {
1916                   pinfo->sccp_info = assoc->curr_msg;
1917                   tap_queue_packet(sua_tap,pinfo,assoc->curr_msg);
1918           } else {
1919                    pinfo->sccp_info = NULL;
1920           }
1921   } else {
1922           pinfo->sccp_info = NULL;
1923   }
1924
1925   /* If there was SUA data it could be dissected */
1926   if(data_tvb)
1927   {
1928     /* Try subdissectors (if we found a valid SSN on the current message) */
1929     if ((dest_ssn == INVALID_SSN ||
1930        !dissector_try_port(sccp_ssn_dissector_table, dest_ssn, data_tvb, pinfo, tree))
1931        && (source_ssn == INVALID_SSN ||
1932        !dissector_try_port(sccp_ssn_dissector_table, source_ssn, data_tvb, pinfo, tree)))
1933     {
1934                 /* try heuristic subdissector list to see if there are any takers */
1935                 if (dissector_try_heuristic(heur_subdissector_list, data_tvb, pinfo, tree)) {
1936                         return;
1937                 }
1938       /* No sub-dissection occured, treat it as raw data */
1939       call_dissector(data_handle, data_tvb, pinfo, tree);
1940     }
1941   }
1942 }
1943
1944 static void
1945 dissect_sua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
1946 {
1947   proto_item *sua_item;
1948   proto_tree *sua_tree;
1949
1950   /* make entry in the Protocol column on summary display */
1951   if (check_col(pinfo->cinfo, COL_PROTOCOL))
1952     switch (version) {
1953       case SUA_V08:
1954         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SUA (ID 08)");
1955         break;
1956       case SUA_RFC:
1957         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SUA (RFC 3868)");
1958         break;
1959     }
1960
1961   /* Clear entries in Info column on summary display */
1962   col_clear(pinfo->cinfo, COL_INFO);
1963
1964   /* In the interest of speed, if "tree" is NULL, don't do any work not
1965      necessary to generate protocol tree items. */
1966   if (tree) {
1967     /* create the sua protocol tree */
1968     sua_item = proto_tree_add_item(tree, proto_sua, message_tvb, 0, -1, ENC_NA);
1969     sua_tree = proto_item_add_subtree(sua_item, ett_sua);
1970   } else {
1971     sua_tree = NULL;
1972   };
1973
1974   /* dissect the message */
1975   dissect_sua_message(message_tvb, pinfo, sua_tree, tree);
1976
1977 }
1978
1979 /* Register the protocol with Wireshark */
1980 void
1981 proto_register_sua(void)
1982 {
1983
1984   /* Setup list of header fields */
1985   static hf_register_info hf[] = {
1986     { &hf_version,                               { "Version",                      "sua.version",                                   FT_UINT8,   BASE_DEC,  VALS(protocol_version_values),      0x0,                      NULL, HFILL } },
1987     { &hf_reserved,                              { "Reserved",                     "sua.reserved",                                  FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
1988     { &hf_message_class,                         { "Message Class",                "sua.message_class",                             FT_UINT8,   BASE_DEC,  VALS(message_class_values),         0x0,                      NULL, HFILL } },
1989     { &hf_message_type,                          { "Message Type",                 "sua.message_type",                              FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
1990     { &hf_message_length,                        { "Message Length",               "sua.message_length",                            FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
1991     { &hf_parameter_tag,                         { "Parameter Tag",                "sua.parameter_tag",                             FT_UINT16,  BASE_HEX,  VALS(parameter_tag_values),         0x0,                      NULL, HFILL } },
1992     { &hf_v8_parameter_tag,                      { "Parameter Tag",                "sua.parameter_tag",                             FT_UINT16,  BASE_HEX,  VALS(v8_parameter_tag_values),      0x0,                      NULL, HFILL } },
1993     { &hf_parameter_length,                      { "Parameter Length",             "sua.parameter_length",                          FT_UINT16,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
1994     { &hf_parameter_value,                       { "Parameter Value",              "sua.parameter_value",                           FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
1995     { &hf_parameter_padding,                     { "Padding",                      "sua.parameter_padding",                         FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
1996     { &hf_info_string,                           { "Info string",                  "sua.info_string",                               FT_STRING,  BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
1997     { &hf_routing_context,                       { "Routing context",              "sua.routing_context",                           FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
1998     { &hf_diagnostic_information_info,           { "Diagnostic Information",       "sua.diagnostic_information",                    FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
1999     { &hf_heartbeat_data,                        { "Heartbeat Data",               "sua.heartbeat_data",                            FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2000     { &hf_traffic_mode_type,                     { "Traffic mode Type",            "sua.traffic_mode_type",                         FT_UINT32,  BASE_DEC,  VALS(traffic_mode_type_values),     0x0,                      NULL, HFILL } },
2001     { &hf_error_code,                            { "Error code",                   "sua.error_code",                                FT_UINT32,  BASE_DEC,  VALS(error_code_values),            0x0,                      NULL, HFILL } },
2002     { &hf_v8_error_code,                         { "Error code",                   "sua.error_code",                                FT_UINT32,  BASE_DEC,  VALS(v8_error_code_values),         0x0,                      NULL, HFILL } },
2003     { &hf_status_type,                           { "Status type",                  "sua.status_type",                               FT_UINT16,  BASE_DEC,  VALS(status_type_values),           0x0,                      NULL, HFILL } },
2004     { &hf_status_info,                           { "Status info",                  "sua.status_info",                               FT_UINT16,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2005     { &hf_congestion_level,                      { "Congestion Level",             "sua.congestion_level",                          FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2006     { &hf_asp_identifier,                        { "ASP Identifier",               "sua.asp_identifier",                            FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2007     { &hf_mask,                                  { "Mask",                         "sua.affected_point_code_mask",                  FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2008     { &hf_dpc,                                   { "Affected DPC",                 "sua.affected_pointcode_dpc",                    FT_UINT24,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2009     { &hf_registration_status,                   { "Registration status",          "sua.registration_status",                       FT_UINT32,  BASE_DEC,  VALS(registration_status_values),   0x0,                      NULL, HFILL } },
2010     { &hf_deregistration_status,                 { "Deregistration status",        "sua.deregistration_status",                     FT_UINT32,  BASE_DEC,  VALS(deregistration_status_values), 0x0,                      NULL, HFILL } },
2011     { &hf_local_routing_key_identifier,          { "Local routing key identifier", "sua.local_routing_key_identifier",              FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2012     { &hf_source_address_routing_indicator,      { "Routing Indicator",            "sua.source_address_routing_indicator",          FT_UINT16,  BASE_DEC,  VALS(routing_indicator_values),     0x0,                      NULL, HFILL } },
2013     { &hf_source_address_reserved_bits,          { "Reserved Bits",                "sua.source_address_reserved_bits",              FT_UINT16,  BASE_DEC,  NULL,                               ADDRESS_RESERVED_BITMASK, NULL, HFILL } },
2014     { &hf_source_address_gt_bit,                 { "Include GT",                   "sua.source_address_gt_bit",                     FT_BOOLEAN, 16,        NULL,                               ADDRESS_GT_BITMASK,       NULL, HFILL } },
2015     { &hf_source_address_pc_bit,                 { "Include PC",                   "sua.source_address_pc_bit",                     FT_BOOLEAN, 16,        NULL,                               ADDRESS_PC_BITMASK,       NULL, HFILL } },
2016     { &hf_source_address_ssn_bit,                { "Include SSN",                  "sua.source_address_ssn_bit",                    FT_BOOLEAN, 16,        NULL,                               ADDRESS_SSN_BITMASK,      NULL, HFILL } },
2017     { &hf_destination_address_routing_indicator, { "Routing Indicator",            "sua.destination_address_routing_indicator",     FT_UINT16,  BASE_DEC,  VALS(routing_indicator_values),     0x0,                      NULL, HFILL } },
2018     { &hf_destination_address_reserved_bits,     { "Reserved Bits",                "sua.destination_address_reserved_bits",         FT_UINT16,  BASE_DEC,  NULL,                               ADDRESS_RESERVED_BITMASK, NULL, HFILL } },
2019     { &hf_destination_address_gt_bit,            { "Include GT",                   "sua.destination_address_gt_bit",                FT_BOOLEAN, 16,        NULL,                               ADDRESS_GT_BITMASK,       NULL, HFILL } },
2020     { &hf_destination_address_pc_bit,            { "Include PC",                   "sua.destination_address_pc_bit",                FT_BOOLEAN, 16,        NULL,                               ADDRESS_PC_BITMASK,       NULL, HFILL } },
2021     { &hf_destination_address_ssn_bit,           { "Include SSN",                  "sua.destination_address_ssn_bit",               FT_BOOLEAN, 16,        NULL,                               ADDRESS_SSN_BITMASK,      NULL, HFILL } },
2022     { &hf_ss7_hop_counter_counter,               { "SS7 Hop Counter",              "sua.ss7_hop_counter_counter",                   FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2023     { &hf_ss7_hop_counter_reserved,              { "Reserved",                     "sua.ss7_hop_counter_reserved",                  FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2024     { &hf_destination_reference_number,          { "Destination Reference Number", "sua.destination_reference_number",              FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2025     { &hf_source_reference_number,               { "Source Reference Number",      "sua.source_reference_number",                   FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2026     { &hf_cause_reserved,                        { "Reserved",                     "sua.sccp_cause_reserved",                       FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2027     { &hf_cause_type,                            { "Cause Type",                   "sua.sccp_cause_type",                           FT_UINT8,   BASE_HEX,  VALS(cause_type_values),            0x0,                      NULL, HFILL } },
2028     { &hf_cause_value,                           { "Cause Value",                  "sua.sccp_cause_value",                          FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2029     { &hf_sequence_number_reserved,              { "Reserved",                     "sua.sequence_number_reserved",                  FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2030     { &hf_sequence_number_rec_number,            { "Receive Sequence Number P(R)", "sua.sequence_number_receive_sequence_number",   FT_UINT8,   BASE_DEC,  NULL,                               SEQ_NUM_MASK,             NULL, HFILL } },
2031     { &hf_sequence_number_more_data_bit,         { "More Data Bit",                "sua.sequence_number_more_data_bit",             FT_BOOLEAN, 8,         TFS(&more_data_bit_value),          MORE_DATA_BIT_MASK,       NULL, HFILL } },
2032     { &hf_sequence_number_sent_number,           { "Sent Sequence Number P(S)",    "sua.sequence_number_sent_sequence_number",      FT_UINT8,   BASE_DEC,  NULL,                               SEQ_NUM_MASK,             NULL, HFILL } },
2033     { &hf_sequence_number_spare_bit,             { "Spare Bit",                    "sua.sequence_number_spare_bit",                 FT_UINT8,   BASE_DEC,  NULL,                               SPARE_BIT_MASK,           NULL, HFILL } },
2034     { &hf_receive_sequence_number_reserved,      { "Reserved",                     "sua.receive_sequence_number_reserved",          FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2035     { &hf_receive_sequence_number_number,        { "Receive Sequence Number P(R)", "sua.receive_sequence_number_number",            FT_UINT8,   BASE_DEC,  NULL,                               SEQ_NUM_MASK,             NULL, HFILL } },
2036     { &hf_receive_sequence_number_spare_bit,     { "Spare Bit",                    "sua.receive_sequence_number_spare_bit",         FT_UINT8,   BASE_DEC,  NULL,                               SPARE_BIT_MASK,           NULL, HFILL } },
2037     { &hf_asp_capabilities_reserved,             { "Reserved",                     "sua.asp_capabilities_reserved",                 FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2038     { &hf_asp_capabilities_reserved_bits,        { "Reserved Bits",                "sua.asp_capabilities_reserved_bits",            FT_UINT8,   BASE_HEX,  NULL,                               RESERVED_BITS_MASK,       NULL, HFILL } },
2039     { &hf_asp_capabilities_a_bit,                { "Protocol Class 3",             "sua.asp_capabilities_a_bit",                    FT_BOOLEAN, 8,         TFS(&tfs_supported_not_supported),      A_BIT_MASK,               NULL, HFILL } },
2040     { &hf_asp_capabilities_b_bit,                { "Protocol Class 2",             "sua.asp_capabilities_b_bit",                    FT_BOOLEAN, 8,         TFS(&tfs_supported_not_supported),      B_BIT_MASK,               NULL, HFILL } },
2041     { &hf_asp_capabilities_c_bit,                { "Protocol Class 1",             "sua.asp_capabilities_c_bit",                    FT_BOOLEAN, 8,         TFS(&tfs_supported_not_supported),      C_BIT_MASK,               NULL, HFILL } },
2042     { &hf_asp_capabilities_d_bit,                { "Protocol Class 0",             "sua.asp_capabilities_d_bit",                    FT_BOOLEAN, 8,         TFS(&tfs_supported_not_supported),      D_BIT_MASK,               NULL, HFILL } },
2043     { &hf_asp_capabilities_interworking,         { "Interworking",                 "sua.asp_capabilities_interworking",             FT_UINT8,   BASE_HEX,  VALS(interworking_values),          0x0,                      NULL, HFILL } },
2044     { &hf_credit,                                { "Credit",                       "sua.credit",                                    FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2045     { &hf_cause,                                 { "Cause",                        "sua.cause_user_cause",                          FT_UINT16,  BASE_DEC,  VALS(cause_values),                 0x0,                      NULL, HFILL } },
2046     { &hf_user,                                  { "User",                         "sua.cause_user_user",                           FT_UINT16,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2047     { &hf_data,                                  { "Data",                         "sua.data",                                      FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2048     { &hf_network_appearance,                    { "Network Appearance",           "sua.network_appearance",                        FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2049     { &hf_routing_key_identifier,                { "Local Routing Key Identifier", "sua.routing_key_identifier",                    FT_UINT32,  BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2050     { &hf_correlation_id,                        { "Correlation ID",               "sua.correlation_id",                            FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2051     { &hf_importance_reserved,                   { "Reserved",                     "sua.importance_reserved",                       FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2052     { &hf_importance,                            { "Importance",                   "sua.importance_inportance",                     FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2053     { &hf_message_priority_reserved,             { "Reserved",                     "sua.message_priority_reserved",                 FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2054     { &hf_message_priority,                      { "Message Priority",             "sua.message_priority_priority",                 FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2055     { &hf_protocol_class_reserved,               { "Reserved",                     "sua.protcol_class_reserved",                    FT_BYTES,   BASE_NONE,  NULL,                               0x0,                      NULL, HFILL } },
2056     { &hf_return_on_error_bit,                   { "Return On Error Bit",          "sua.protocol_class_return_on_error_bit",        FT_BOOLEAN, 8,         TFS(&return_on_error_bit_value),    RETURN_ON_ERROR_BIT_MASK, NULL, HFILL } },
2057     { &hf_protocol_class,                        { "Protocol Class",               "sua.protocol_class_class",                      FT_UINT8,   BASE_DEC,  NULL,                               PROTOCOL_CLASS_MASK,      NULL, HFILL } },
2058     { &hf_sequence_control,                      { "Sequence Control",             "sua.sequence_control_sequence_control",         FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2059     { &hf_first_bit,                             { "First Segment Bit",            "sua.segmentation_first_bit",                    FT_BOOLEAN, 8,         TFS(&first_bit_value),              FIRST_BIT_MASK,           NULL, HFILL } },
2060     { &hf_number_of_remaining_segments,          { "Number of Remaining Segments", "sua.segmentation_number_of_remaining_segments", FT_UINT8,   BASE_DEC,  NULL,                               NUMBER_OF_SEGMENTS_MASK,  NULL, HFILL } },
2061     { &hf_segmentation_reference,                { "Segmentation Reference",       "sua.segmentation_reference",                    FT_UINT24,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2062     { &hf_smi_reserved,                          { "Reserved",                     "sua.smi_reserved",                              FT_BYTES,   BASE_NONE,  NULL,                               0x0,                      NULL, HFILL } },
2063     { &hf_smi,                                   { "SMI",                          "sua.smi_smi",                                   FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2064     { &hf_tid_label_start,                       { "Start",                        "sua.tid_label_start",                           FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2065     { &hf_tid_label_end,                         { "End",                          "sua.tid_label_end",                             FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2066     { &hf_tid_label_value,                       { "Label Value",                  "sua.tid_label_value",                           FT_UINT16,  BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2067     { &hf_drn_label_start,                       { "Start",                        "sua.drn_label_start",                           FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2068     { &hf_drn_label_end,                         { "End",                          "sua.drn_label_end",                             FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2069     { &hf_drn_label_value,                       { "Label Value",                  "sua.drn_label_value",                           FT_UINT16,  BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2070     { &hf_gt_reserved,                           { "Reserved",                     "sua.gt_reserved",                               FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2071     { &hf_gti,                                   { "GTI",                          "sua.gti",                                       FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2072     { &hf_number_of_digits,                      { "Number of Digits",             "sua.global_title_number_of_digits",             FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2073     { &hf_translation_type,                      { "Translation Type",             "sua.global_title_translation_type",             FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2074     { &hf_numbering_plan,                        { "Numbering Plan",               "sua.global_title_numbering_plan",               FT_UINT8,   BASE_HEX,  VALS(numbering_plan_values),        0x0,                      NULL, HFILL } },
2075     { &hf_nature_of_address,                     { "Nature of Address",            "sua.global_title_nature_of_address",            FT_UINT8,   BASE_HEX,  VALS(nature_of_address_values),     0x0,                      NULL, HFILL } },
2076     { &hf_global_title_digits,                   { "Global Title Digits",          "sua.global_title_digits",                       FT_STRING,  BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2077     { &hf_point_code_dpc,                        { "Point Code",                   "sua.point_code",                                FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2078     { &hf_ssn_reserved,                          { "Reserved",                     "sua.ssn_reserved",                              FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2079     { &hf_ssn_number,                            { "Subsystem Number",             "sua.ssn",                                       FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2080     { &hf_ipv4,                                  { "IP Version 4 address",         "sua.ipv4_address",                              FT_IPv4,    BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2081     { &hf_hostname,                              { "Hostname",                     "sua.hostname.name",                             FT_STRING,  BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2082     { &hf_ipv6,                                  { "IP Version 6 address",         "sua.ipv6_address",                              FT_IPv6,    BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2083      { &hf_assoc_id,
2084       { "Association ID", "sccp.assoc.id",
2085         FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2086     {&hf_assoc_msg,
2087         {"Message in frame", "sccp.assoc.msg",
2088         FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
2089     },
2090  };
2091
2092   /* Setup protocol subtree array */
2093   static gint *ett[] = {
2094     &ett_sua,
2095     &ett_sua_parameter,
2096     &ett_sua_source_address_indicator,
2097     &ett_sua_destination_address_indicator,
2098     &ett_sua_affected_destination,
2099     &ett_sua_sequence_number_rec_number,
2100     &ett_sua_sequence_number_sent_number,
2101     &ett_sua_receive_sequence_number_number,
2102     &ett_sua_protcol_classes,
2103     &ett_sua_first_remaining,
2104     &ett_sua_return_on_error_bit_and_protocol_class,
2105     &ett_sua_assoc
2106
2107   };
2108
2109   module_t *sua_module;
2110
2111   static enum_val_t options[] = {
2112     { "draft-08", "Internet Draft version 08", SUA_V08  },
2113     { "rfc3868",  "RFC 3868",                  SUA_RFC  },
2114     { NULL, NULL, 0 }
2115   };
2116
2117   /* Register the protocol name and description */
2118   proto_sua = proto_register_protocol("SS7 SCCP-User Adaptation Layer", "SUA", "sua");
2119   register_dissector("sua", dissect_sua, proto_sua);
2120
2121   /* Required function calls to register the header fields and subtrees used */
2122   proto_register_field_array(proto_sua, hf, array_length(hf));
2123   proto_register_subtree_array(ett, array_length(ett));
2124
2125   sua_module = prefs_register_protocol(proto_sua, NULL);
2126   prefs_register_obsolete_preference(sua_module, "sua_version");
2127   prefs_register_enum_preference(sua_module, "version", "SUA Version", "Version used by Wireshark", &version, options, FALSE);
2128
2129   register_heur_dissector_list("sua", &heur_subdissector_list);
2130   sua_tap = register_tap("sua");
2131
2132 }
2133
2134 void
2135 proto_reg_handoff_sua(void)
2136 {
2137   dissector_handle_t sua_handle;
2138
2139   sua_handle = find_dissector("sua");
2140   dissector_add("sctp.ppi",  SUA_PAYLOAD_PROTOCOL_ID, sua_handle);
2141   dissector_add("sctp.port", SCTP_PORT_SUA,           sua_handle);
2142
2143   data_handle = find_dissector("data");
2144   sccp_ssn_dissector_table = find_dissector_table("sccp.ssn");
2145
2146 }