From Michael Tuexen: add missing support for the T-Bit in ABORT chunks.
[obnox/wireshark/wip.git] / packet-sua.c
1 /* packet-sua.c
2  * Routines for  SS7 SCCP-User Adaptation Layer (SUA) dissection
3  * It is hopefully (needs testing) compilant to
4  * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-sua-08.txt
5  * and also supports SUA light, a trivial Siemens proprietary version.
6  *
7  * Copyright 2000, Michael Tüxen <Michael.Tuexen@icn.siemens.de>
8  *
9  * $Id: packet-sua.c,v 1.6 2002/01/24 09:20:52 guy Exp $
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
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 <stdio.h>
37 #include <stdlib.h>
38
39
40 #ifdef HAVE_SYS_TYPES_H
41 # include <sys/types.h>
42 #endif
43
44 #ifdef HAVE_NETINET_IN_H
45 # include <netinet/in.h>
46 #endif
47
48 #include <string.h>
49 #include <glib.h>
50
51 #ifdef NEED_SNPRINTF_H
52 # include "snprintf.h"
53 #endif
54
55 #include <epan/packet.h>
56 #include "prefs.h"
57
58 #define SCTP_PORT_SUA          14001
59 #define SUA_PAYLOAD_PROTO_ID   4
60
61 #define RESERVED_1_LENGTH      1
62 #define RESERVED_2_LENGTH      2
63 #define RESERVED_3_LENGTH      3
64
65 #define VERSION_LENGTH         1
66 #define RESERVED_LENGTH        1
67 #define MESSAGE_CLASS_LENGTH   1
68 #define MESSAGE_TYPE_LENGTH    1
69 #define MESSAGE_LENGTH_LENGTH  4
70 #define COMMON_HEADER_LENGTH   (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
71                                 MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
72
73 #define COMMON_HEADER_OFFSET   0
74 #define VERSION_OFFSET         COMMON_HEADER_OFFSET
75 #define RESERVED_OFFSET        (VERSION_OFFSET + VERSION_LENGTH)
76 #define MESSAGE_CLASS_OFFSET   (RESERVED_OFFSET + RESERVED_LENGTH)
77 #define MESSAGE_TYPE_OFFSET    (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
78 #define MESSAGE_LENGTH_OFFSET  (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
79
80 #define PARAMETER_TAG_LENGTH    2
81 #define PARAMETER_LENGTH_LENGTH 2
82 #define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
83
84 #define PARAMETER_TAG_OFFSET      0
85 #define PARAMETER_LENGTH_OFFSET   (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
86 #define PARAMETER_VALUE_OFFSET    (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
87 #define PARAMETER_HEADER_OFFSET   PARAMETER_TAG_OFFSET
88
89 #define DATA_PARAMETER_TAG                         0x0003
90 #define INFO_STRING_PARAMETER_TAG                  0x0004
91 #define ROUTING_CONTEXT_PARAMETER_TAG              0x0006
92 #define DIAGNOSTIC_INFO_PARAMETER_TAG              0x0007
93 #define HEARTBEAT_DATA_PARAMETER_TAG               0x0009
94 #define TRAFFIC_MODE_TYPE_PARAMETER_TAG            0x000b
95 #define ERROR_CODE_PARAMETER_TAG                   0x000c
96 #define STATUS_PARAMETER_TAG                       0x000d
97 #define CONGESTION_LEVEL_PARAMETER_TAG             0x000f
98 #define ASP_IDENTIFIER_PARAMETER_TAG               0x0011
99 #define AFFECTED_POINT_CODE_PARAMETER_TAG          0x0012
100 #define SS7_HOP_COUNTER_PARAMETER_TAG              0x0101
101 #define SOURCE_ADDRESS_PARAMETER_TAG               0x0102
102 #define DESTINATION_ADDRESS_PARAMETER_TAG          0x0103
103 #define SOURCE_REFERENCE_NUMBER_PARAMETER_TAG      0x0104
104 #define DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG 0x0105
105 #define SCCP_CAUSE_PARAMETER_TAG                   0x0106
106 #define SEQUENCE_NUMBER_PARAMETER_TAG              0x0107
107 #define RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG      0x0108
108 #define ASP_CAPABILITIES_PARAMETER_TAG             0x0109
109 #define CREDIT_PARAMETER_TAG                       0x010a
110 #define USER_CAUSE_PARAMETER_TAG                   0x010c
111 #define NETWORK_APPEARANCE_PARAMETER_TAG           0x010d
112 #define ROUTING_KEY_PARAMETER_TAG                  0x010e
113 #define REGISTRATION_RESULT_PARAMETER_TAG          0x010f
114 #define DEREGISTRATION_RESULT_PARAMETER_TAG        0x0110
115 #define ADDRESS_RANGE_PARAMETER_TAG                0x0111
116 #define CORRELATION_ID_PARAMETER_TAG               0x0112
117 #define IMPORTANCE_PARAMETER_TAG                   0x0113
118 #define MESSAGE_PRIORITY_PARAMETER_TAG             0x0114
119 #define PROTOCOL_CLASS_PARAMETER_TAG               0x0115
120 #define SEQUENCE_CONTROL_PARAMETER_TAG             0x0116
121 #define SEGMENTATION_PARAMETER_TAG                 0x0117
122 #define SMI_PARAMETER_TAG                          0x0118
123 #define TID_LABEL_PARAMETER_TAG                    0x0119
124 #define DRN_LABEL_PARAMETER_TAG                    0x011a
125 #define GLOBAL_TITLE_PARAMETER_TAG                 0x8001
126 #define POINT_CODE_PARAMETER_TAG                   0x8002
127 #define SUBSYSTEM_NUMBER_PARAMETER_TAG             0x8003
128 #define IPV4_ADDRESS_PARAMETER_TAG                 0x8004
129 #define HOSTNAME_PARAMETER_TAG                     0x8005
130 #define IPV6_ADDRESS_PARAMETER_TAG                 0x8006
131
132 static const value_string sua_parameter_tag_values[] = {
133   { DATA_PARAMETER_TAG,                         "Data" },
134   { INFO_STRING_PARAMETER_TAG,                  "Info String" },
135   { ROUTING_CONTEXT_PARAMETER_TAG,              "Routing context" },
136   { DIAGNOSTIC_INFO_PARAMETER_TAG,              "Diagnostic Info" },
137   { HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat data" },
138   { TRAFFIC_MODE_TYPE_PARAMETER_TAG,            "Traffic mode type" },
139   { ERROR_CODE_PARAMETER_TAG,                   "Error code" },  
140   { STATUS_PARAMETER_TAG,                       "Status" },
141   { CONGESTION_LEVEL_PARAMETER_TAG,             "Congestion Level" },
142   { ASP_IDENTIFIER_PARAMETER_TAG,               "ASP Identifier" },
143   { AFFECTED_POINT_CODE_PARAMETER_TAG,          "Affected Point Code" },
144   { SS7_HOP_COUNTER_PARAMETER_TAG,              "SS7 Hop Counter" },
145   { SOURCE_ADDRESS_PARAMETER_TAG,               "Source Address" },
146   { DESTINATION_ADDRESS_PARAMETER_TAG,          "Destination Address" },
147   { SOURCE_REFERENCE_NUMBER_PARAMETER_TAG,      "Source Reference Number" },
148   { DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG, "Destination Reference Number" },
149   { SCCP_CAUSE_PARAMETER_TAG,                   "SCCP Cause" },
150   { SEQUENCE_NUMBER_PARAMETER_TAG,              "Sequence Number" },
151   { RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG,      "Receive Sequence Number" },
152   { ASP_CAPABILITIES_PARAMETER_TAG,             "ASP Capabilities" },
153   { CREDIT_PARAMETER_TAG,                       "Credit" },
154   { USER_CAUSE_PARAMETER_TAG,                   "User/Cause" },
155   { NETWORK_APPEARANCE_PARAMETER_TAG,           "Network Appearance" },
156   { ROUTING_KEY_PARAMETER_TAG,                  "Routing Key" },
157   { REGISTRATION_RESULT_PARAMETER_TAG,          "Registration Result" },
158   { DEREGISTRATION_RESULT_PARAMETER_TAG,        "Deregistration Result" },
159   { ADDRESS_RANGE_PARAMETER_TAG,                "Address Range" },
160   { CORRELATION_ID_PARAMETER_TAG,               "Correlation ID" },
161   { IMPORTANCE_PARAMETER_TAG,                   "Importance" },
162   { MESSAGE_PRIORITY_PARAMETER_TAG,             "Message Priority" },
163   { PROTOCOL_CLASS_PARAMETER_TAG,               "Protocol Class" },
164   { SEQUENCE_CONTROL_PARAMETER_TAG,             "Sequence Control" },
165   { SEGMENTATION_PARAMETER_TAG,                 "Segmentation" },
166   { SMI_PARAMETER_TAG,                          "SMI" },
167   { TID_LABEL_PARAMETER_TAG,                    "TID Label" },
168   { DRN_LABEL_PARAMETER_TAG,                    "DRN Label" },
169   { GLOBAL_TITLE_PARAMETER_TAG,                 "Global Title" },
170   { POINT_CODE_PARAMETER_TAG,                   "Point Code" },
171   { SUBSYSTEM_NUMBER_PARAMETER_TAG,             "Subsystem Number" },
172   { IPV4_ADDRESS_PARAMETER_TAG,                 "IPv4 Address" },
173   { HOSTNAME_PARAMETER_TAG,                     "Hostname" },
174   { IPV6_ADDRESS_PARAMETER_TAG,                 "IPv6 Address" },
175   { 0,                                          NULL } };
176
177 #define PROTOCOL_VERSION_RELEASE_1             1
178
179 static const value_string sua_protocol_version_values[] = {
180   { PROTOCOL_VERSION_RELEASE_1,  "Release 1" },
181   { 0,                           NULL } };
182
183 #define MESSAGE_CLASS_MGMT_MESSAGE        0
184 #define MESSAGE_CLASS_TFER_MESSAGE        1
185 #define MESSAGE_CLASS_SSNM_MESSAGE        2
186 #define MESSAGE_CLASS_ASPSM_MESSAGE       3
187 #define MESSAGE_CLASS_ASPTM_MESSAGE       4
188 #define MESSAGE_CLASS_CL_MESSAGE          7
189 #define MESSAGE_CLASS_CO_MESSAGE          8
190 #define MESSAGE_CLASS_RKM_MESSAGE         9
191
192 static const value_string sua_message_class_values[] = {
193   { MESSAGE_CLASS_MGMT_MESSAGE,   "Management messages" },
194   { MESSAGE_CLASS_SSNM_MESSAGE,   "SS7 signalling network management messages" },
195   { MESSAGE_CLASS_ASPSM_MESSAGE,  "ASP state maintenance messages" },
196   { MESSAGE_CLASS_ASPTM_MESSAGE,  "ASP traffic maintenance messages" },
197   { MESSAGE_CLASS_CL_MESSAGE,     "Connectionless messages" },
198   { MESSAGE_CLASS_CO_MESSAGE,     "Connection-Oriented messages" },
199   { MESSAGE_CLASS_RKM_MESSAGE,    "Routing key management Messages" },
200   { 0,                           NULL } };
201
202 #define MESSAGE_TYPE_ERR                  0
203 #define MESSAGE_TYPE_NTFY                 1
204
205 #define MESSAGE_TYPE_DUNA                 1
206 #define MESSAGE_TYPE_DAVA                 2
207 #define MESSAGE_TYPE_DAUD                 3
208 #define MESSAGE_TYPE_SCON                 4
209 #define MESSAGE_TYPE_DUPU                 5
210 #define MESSAGE_TYPE_DRST                 6
211
212 #define MESSAGE_TYPE_UP                   1
213 #define MESSAGE_TYPE_DOWN                 2
214 #define MESSAGE_TYPE_BEAT                 3
215 #define MESSAGE_TYPE_UP_ACK               4
216 #define MESSAGE_TYPE_DOWN_ACK             5
217 #define MESSAGE_TYPE_BEAT_ACK             6
218
219 #define MESSAGE_TYPE_ACTIVE               1
220 #define MESSAGE_TYPE_INACTIVE             2
221 #define MESSAGE_TYPE_ACTIVE_ACK           3
222 #define MESSAGE_TYPE_INACTIVE_ACK         4
223
224 #define MESSAGE_TYPE_CLDT                 1
225 #define MESSAGE_TYPE_CLDR                 2
226
227 #define MESSAGE_TYPE_CORE                 1
228 #define MESSAGE_TYPE_COAK                 2
229 #define MESSAGE_TYPE_COREF                3
230 #define MESSAGE_TYPE_RELRE                4
231 #define MESSAGE_TYPE_RELCO                5
232 #define MESSAGE_TYPE_RESCO                6
233 #define MESSAGE_TYPE_RESRE                7
234 #define MESSAGE_TYPE_CODT                 8
235 #define MESSAGE_TYPE_CODA                 9
236 #define MESSAGE_TYPE_COERR               10
237 #define MESSAGE_TYPE_COIT                11
238
239 #define MESSAGE_TYPE_REG_REQ              1
240 #define MESSAGE_TYPE_REG_RSP              2
241 #define MESSAGE_TYPE_DEREG_REQ            3
242 #define MESSAGE_TYPE_DEREG_RSP            4
243
244
245 static const value_string sua_message_class_type_values[] = {
246   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "Error (ERR)" },
247   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "Notify (NTFY)" },
248   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "Destination unavailable (DUNA)" },
249   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "Destination available (DAVA)" },
250   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "Destination state audit (DAUD)" },
251   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SS7 Network congestion state (SCON)" },
252   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "Destination userpart unavailable (DUPU)" },
253   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP up (UP)" },
254   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP down (DOWN)" },
255   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "Heartbeat (BEAT)" },
256   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP up ack (UP ACK)" },
257   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP down ack (DOWN ACK)" },
258   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "Heartbeat ack (BEAT ACK)" },
259   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP active (ACTIVE)" },
260   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP inactive (INACTIVE)" },
261   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP active ack (ACTIVE ACK)" },
262   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (INACTIVE ACK)" },
263   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDR ,         "Connectionless Data Response (CLDR)" },
264   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDT ,         "Connectionless Data Transfer (CLDT)" },
265   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CORE ,         "Connection Request (CORE)" },
266   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COAK ,         "Connection Acknowledge (COAK)" },
267   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COREF ,        "Connection Refused (COREF)" },
268   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELRE ,        "Release Request (RELRE)" },
269   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELCO ,        "Release Complete (RELCO)" },
270   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESCO ,        "Reset Confirm (RESCO)" },
271   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESRE ,        "Reset Request (RESRE)" },
272   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODT ,         "Connection Oriented Data Transfer (CODT)" },
273   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODA ,         "Connection Oriented Data Acknowledge (CODA)" },
274   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COERR ,        "Connection Oriented Error (COERR)" },
275   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COIT ,         "Inactivity Test (COIT)" },
276   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_REQ ,      "Registration Request (REG_REQ)" },
277   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_RSP ,      "Registartion Response (REG_RSP)" },
278   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_REQ ,    "Deregistration Request (DEREG_REQ)" },
279   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_RSP ,    "Deregistartion Response (DEREG_RSP)" },
280   { 0,                           NULL } };
281
282 static const value_string sua_message_class_type_acro_values[] = {
283   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "ERR" },
284   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "NTFY" },
285   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "DUNA" },
286   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "DAVA" },
287   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "DAUD" },
288   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SCON" },
289   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "DUPU" },
290   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP_UP" },
291   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP_DOWN" },
292   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "BEAT" },
293   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP_UP_ACK" },
294   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP_DOWN_ACK" },
295   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "BEAT_ACK" },
296   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP_ACTIVE" },
297   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP_INACTIVE" },
298   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP_ACTIVE_ACK" },
299   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
300   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDR ,         "CLDR" },
301   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDT ,         "CLDT" },
302   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CORE ,         "CORE" },
303   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COAK ,         "COAK" },
304   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COREF ,        "COREF" },
305   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELRE ,        "RELRE" },
306   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELCO ,        "RELCO" },
307   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESCO ,        "RESCO" },
308   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESRE ,        "RESRE" },
309   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODT ,         "CODT" },
310   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODA ,         "CODA" },
311   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COERR ,        "COERR" },
312   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COIT ,         "COIT" },
313   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_REQ ,      "REG_REQ" },
314   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_RSP ,      "REG_RSP" },
315   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_REQ ,    "DEREG_REQ" },
316   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_RSP ,    "DEREG_RSP" },
317   { 0,                           NULL } };
318
319 /* Initialize the protocol and registered fields */
320 static module_t *sua_module;
321 static int proto_sua = -1;
322 static int hf_sua_version = -1;
323 static int hf_sua_reserved = -1;
324 static int hf_sua_message_class = -1;
325 static int hf_sua_message_type = -1;
326 static int hf_sua_message_length = -1;
327 static int hf_sua_parameter_tag = -1;
328 static int hf_sua_parameter_length = -1;
329 static int hf_sua_parameter_value = -1;
330 static int hf_sua_parameter_padding = -1;
331 static int hf_sua_data_padding = -1;
332 static int hf_sua_info_string = -1;
333 static int hf_sua_info_string_padding = -1;
334 static int hf_sua_routing_context = -1;
335 static int hf_sua_diagnostic_information_info = -1;
336 static int hf_sua_diagnostic_information_padding = -1;
337 static int hf_sua_heartbeat_data = -1;
338 static int hf_sua_heartbeat_padding = -1;
339 static int hf_sua_traffic_mode_type = -1;
340 static int hf_sua_error_code = -1;
341 static int hf_sua_status_type = -1;
342 static int hf_sua_status_info = -1;
343 static int hf_sua_congestion_level = -1;
344 static int hf_sua_asp_identifier = -1;
345 static int hf_sua_mask = -1;
346 static int hf_sua_dpc = -1;
347 static int hf_sua_source_address_routing_indicator = -1;
348 static int hf_sua_source_address_reserved_bits = -1;
349 static int hf_sua_source_address_gt_bit = -1;
350 static int hf_sua_source_address_pc_bit = -1;
351 static int hf_sua_source_address_ssn_bit = -1;
352 static int hf_sua_destination_address_routing_indicator = -1;
353 static int hf_sua_destination_address_reserved_bits = -1;
354 static int hf_sua_destination_address_gt_bit = -1;
355 static int hf_sua_destination_address_pc_bit = -1;
356 static int hf_sua_destination_address_ssn_bit = -1;
357 static int hf_sua_ss7_hop_counter_counter = -1;
358 static int hf_sua_ss7_hop_counter_reserved = -1;
359 static int hf_sua_destination_reference_number = -1;
360 static int hf_sua_source_reference_number = -1;
361 static int hf_sua_cause_reserved = -1;
362 static int hf_sua_cause_type = -1;
363 static int hf_sua_cause_value = -1;
364 static int hf_sua_sequence_number_reserved = -1;
365 static int hf_sua_sequence_number_rec_number = -1;
366 static int hf_sua_sequence_number_spare_bit = -1;
367 static int hf_sua_sequence_number_sent_number = -1;
368 static int hf_sua_sequence_number_more_data_bit = -1;
369 static int hf_sua_receive_sequence_number_reserved = -1;
370 static int hf_sua_receive_sequence_number_number = -1;
371 static int hf_sua_receive_sequence_number_spare_bit = -1;
372 static int hf_sua_asp_capabilities_reserved = -1;
373 static int hf_sua_asp_capabilities_reserved_bits = -1;
374 static int hf_sua_asp_capabilities_a_bit =-1;
375 static int hf_sua_asp_capabilities_b_bit =-1;
376 static int hf_sua_asp_capabilities_c_bit =-1;
377 static int hf_sua_asp_capabilities_d_bit =-1;
378 static int hf_sua_asp_capabilities_interworking = -1;
379 static int hf_sua_credit = -1;
380 static int hf_sua_cause = -1;
381 static int hf_sua_user = -1;
382 static int hf_sua_network_appearance = -1;
383 static int hf_sua_routing_key_identifier = -1;
384 static int hf_sua_registration_result_routing_key_identifier = -1;
385 static int hf_sua_registration_result_status = -1;
386 static int hf_sua_registration_result_routing_context = -1;
387 static int hf_sua_deregistration_result_status = -1;
388 static int hf_sua_deregistration_result_routing_context = -1;
389 static int hf_sua_correlation_id = -1;
390 static int hf_sua_importance_reserved = -1;
391 static int hf_sua_importance = -1;
392 static int hf_sua_message_priority_reserved = -1;
393 static int hf_sua_message_priority = -1;
394 static int hf_sua_protocol_class_reserved = -1;
395 static int hf_sua_return_on_error_bit = -1;
396 static int hf_sua_protocol_class = -1;
397 static int hf_sua_sequence_control = -1;
398 static int hf_sua_first_bit = -1;
399 static int hf_sua_number_of_remaining_segments = -1;
400 static int hf_sua_segmentation_reference = -1;
401 static int hf_sua_smi = -1;
402 static int hf_sua_smi_reserved = -1;
403 static int hf_sua_tid_label_start = -1;
404 static int hf_sua_tid_label_end = -1;
405 static int hf_sua_tid_label_value = -1;
406 static int hf_sua_drn_label_start = -1;
407 static int hf_sua_drn_label_end = -1;
408 static int hf_sua_drn_label_value = -1;
409 static int hf_sua_number_of_digits = -1;
410 static int hf_sua_translation_type = -1;
411 static int hf_sua_numbering_plan = -1;
412 static int hf_sua_nature_of_address = -1;
413 static int hf_sua_global_title = -1;
414 static int hf_sua_global_title_padding = -1;
415 static int hf_sua_point_code_mask = -1;
416 static int hf_sua_point_code_dpc = -1;
417 static int hf_sua_ssn_reserved = -1;
418 static int hf_sua_ssn_number = -1;
419 static int hf_sua_ipv4 = -1;
420 static int hf_sua_hostname = -1;
421 static int hf_sua_hostname_padding = -1;
422 static int hf_sua_ipv6 = -1;
423 /* Support of Light version starts here */
424 static int hf_sua_light_version = -1;
425 static int hf_sua_light_spare_1 = -1;
426 static int hf_sua_light_message_type = -1;
427 static int hf_sua_light_subsystem_number = -1;
428 static int hf_sua_light_spare_2 = -1;
429 static int hf_sua_light_message_length = -1;
430 static int hf_sua_light_error_code = -1;
431 /* Support of Light version end here */
432
433 /* Initialize the subtree pointers */
434 static gint ett_sua = -1;
435 static gint ett_sua_parameter = -1;
436 static gint ett_sua_source_address_indicator = -1;
437 static gint ett_sua_destination_address_indicator = -1;
438 static gint ett_sua_affected_destination = -1;
439 static gint ett_sua_first_remaining = -1;
440 static gint ett_sua_sequence_number_rec_number = -1;
441 static gint ett_sua_sequence_number_sent_number = -1;
442 static gint ett_sua_receive_sequence_number_number = -1;
443 static gint ett_sua_return_on_error_bit_and_protocol_class = -1;
444 static gint ett_sua_protcol_classes = -1;
445
446 /* stuff for supporting multiple versions */
447 #define SIEMENS_VERSION   1
448 #define IETF_VERSION08    2
449 static gint sua_version = IETF_VERSION08;
450
451 static dissector_table_t sua_light_dissector_table;
452 /* ends here */
453
454 static void
455 dissect_sua_tlv_list(tvbuff_t *tlv_tvb, proto_tree *sua_tree, gint initial_offset);
456
457 static guint 
458 nr_of_padding_bytes (guint length)
459 {
460   guint remainder;
461
462   remainder = length % 4;
463
464   if (remainder == 0)
465     return 0;
466   else
467     return 4 - remainder;
468 }
469
470 static void
471 dissect_sua_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *sua_tree)
472 {
473   guint8  version, message_class, message_type;
474   guint32 message_length;
475   /* Extract the common header */
476   version        = tvb_get_guint8(common_header_tvb, VERSION_OFFSET);
477   message_class  = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
478   message_type   = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
479   message_length = tvb_get_ntohl (common_header_tvb, MESSAGE_LENGTH_OFFSET);
480
481   if (check_col(pinfo->cinfo, COL_INFO)) {
482     col_append_str(pinfo->cinfo, COL_INFO, val_to_str(message_class * 256 + message_type, sua_message_class_type_acro_values, "reserved"));
483     col_append_str(pinfo->cinfo, COL_INFO, " ");
484   };
485
486   if (sua_tree) {
487     /* add the components of the common header to the protocol tree */
488     proto_tree_add_uint(sua_tree, hf_sua_version, 
489                         common_header_tvb, VERSION_OFFSET, VERSION_LENGTH,
490                         version);
491     proto_tree_add_bytes(sua_tree, hf_sua_reserved,
492                                            common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH,
493                          tvb_get_ptr(common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH));
494     proto_tree_add_uint(sua_tree, hf_sua_message_class, 
495                         common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH,
496                         message_class);
497     proto_tree_add_uint_format(sua_tree, hf_sua_message_type, 
498                                common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH,
499                                message_type, "Message Type: %s (%u)",
500                                                  val_to_str(message_class * 256 + message_type, sua_message_class_type_values, "reserved"), message_type);
501     proto_tree_add_uint(sua_tree, hf_sua_message_length,
502                         common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH,
503                                           message_length);
504   };
505 }
506
507 #define DATA_PARAMETER_DATA_OFFSET PARAMETER_VALUE_OFFSET
508
509 static void
510 dissect_sua_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
511 {
512   guint16 length, data_length, padding_length;
513  
514   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
515   data_length    = length - PARAMETER_HEADER_LENGTH;
516   padding_length = nr_of_padding_bytes(length);
517   
518   proto_tree_add_text(parameter_tree, parameter_tvb, DATA_PARAMETER_DATA_OFFSET, data_length,
519                                   "Data (%u byte%s)", data_length, plurality(data_length, "", "s"));
520
521   if (padding_length > 0)
522     proto_tree_add_bytes(parameter_tree, hf_sua_data_padding, 
523                          parameter_tvb, PARAMETER_VALUE_OFFSET + data_length, padding_length,
524                          tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET + data_length, padding_length));
525
526   proto_item_set_text(parameter_item, "Data (SS7 message of %u byte%s)",
527                                   data_length, plurality(data_length, "", "s"));
528 }
529
530 #define INFO_PARAMETER_INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
531
532 static void
533 dissect_sua_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
534 {
535   guint16 length, info_string_length, padding_length;
536   char *info_string;
537
538   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
539   padding_length = nr_of_padding_bytes(length);
540  
541   info_string_length = length - PARAMETER_HEADER_LENGTH;
542   proto_tree_add_item(parameter_tree, hf_sua_info_string,
543                                         parameter_tvb, INFO_PARAMETER_INFO_STRING_OFFSET, info_string_length, FALSE);
544
545   if (padding_length > 0)
546     proto_tree_add_bytes(parameter_tree, hf_sua_info_string_padding, 
547                          parameter_tvb, PARAMETER_VALUE_OFFSET + info_string_length, padding_length,
548                          tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET + info_string_length, padding_length));
549                          
550   info_string = (char *)tvb_get_ptr(parameter_tvb, INFO_PARAMETER_INFO_STRING_OFFSET, info_string_length);
551   proto_item_set_text(parameter_item, "Info String (%.*s)", (int) info_string_length, info_string);
552 }
553
554 #define ROUTING_CONTEXT_LENGTH 4
555
556 static void
557 dissect_sua_routing_context_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
558 {
559   guint16 length, number_of_contexts, context_number;
560   guint32 context;
561   gint context_offset;
562
563   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
564   number_of_contexts = (length - PARAMETER_HEADER_LENGTH) / 4;
565
566   context_offset = PARAMETER_VALUE_OFFSET;
567   for(context_number=1; context_number <= number_of_contexts; context_number++) {
568     context = tvb_get_ntohl(parameter_tvb, context_offset);
569     proto_tree_add_uint(parameter_tree, hf_sua_routing_context, parameter_tvb, context_offset, ROUTING_CONTEXT_LENGTH, context);
570     context_offset += ROUTING_CONTEXT_LENGTH;
571   };
572   
573   proto_item_set_text(parameter_item, "Routing context (%u context%s)",
574                                   number_of_contexts, plurality(number_of_contexts, "", "s"));
575 }
576
577 static void
578 dissect_sua_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
579 {
580   guint16 length, info_length, padding_length;
581   
582   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
583   padding_length = nr_of_padding_bytes(length);
584   info_length    = length - PARAMETER_HEADER_LENGTH;
585
586   proto_tree_add_bytes(parameter_tree, hf_sua_diagnostic_information_info, 
587                        parameter_tvb, PARAMETER_VALUE_OFFSET, info_length,
588                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, info_length));
589   
590   if (padding_length > 0)
591     proto_tree_add_bytes(parameter_tree, hf_sua_diagnostic_information_padding, 
592                          parameter_tvb, PARAMETER_VALUE_OFFSET + info_length, padding_length,
593                          tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET + info_length, padding_length));
594
595   proto_item_set_text(parameter_item, "Diagnostic information (%u byte%s)", info_length, plurality(info_length, "", "s"));
596 }
597
598 static void
599 dissect_sua_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
600 {
601   guint16 length, data_length, padding_length;
602   
603   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
604   padding_length = nr_of_padding_bytes(length);
605   data_length    = length - PARAMETER_HEADER_LENGTH;
606
607   proto_tree_add_bytes(parameter_tree, hf_sua_heartbeat_data, 
608                        parameter_tvb, PARAMETER_VALUE_OFFSET, data_length,
609                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, data_length));
610   
611   if (padding_length > 0)
612     proto_tree_add_bytes(parameter_tree, hf_sua_heartbeat_padding, 
613                          parameter_tvb, PARAMETER_VALUE_OFFSET + data_length, padding_length,
614                          tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET + data_length, padding_length));
615
616   proto_item_set_text(parameter_item, "Heartbeat data (%u byte%s)", data_length, plurality(data_length, "", "s"));
617 }
618
619 #define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
620 #define TRAFFIC_MODE_TYPE_LENGTH 4
621         
622 #define OVER_RIDE_TYPE           1
623 #define LOAD_SHARE_TYPE          2
624 #define BROADCAST_TYPE           3
625
626 static const value_string sua_traffic_mode_type_values[] = {
627   { OVER_RIDE_TYPE ,                             "Over-ride" },
628   { LOAD_SHARE_TYPE,                             "Load-share" },
629   { BROADCAST_TYPE,                              "Broadcast" },
630   {0,                           NULL } };
631
632 static void
633 dissect_sua_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
634 {
635   guint32 traffic_mode_type;
636
637   traffic_mode_type = tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET);
638
639   proto_tree_add_uint(parameter_tree, hf_sua_traffic_mode_type, 
640                       parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH,
641                       traffic_mode_type);
642   
643   proto_item_set_text(parameter_item, "Traffic mode type (%s)", val_to_str(traffic_mode_type, sua_traffic_mode_type_values, "unknown"));
644 }
645
646 #define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
647 #define ERROR_CODE_LENGTH 4
648
649 #define INVALID_VERSION_ERROR_CODE                   0x01
650 #define INVALID_INTERFACE_IDENTIFIER_ERROR_CODE      0x02
651 #define UNSUPPORTED_MESSAGE_CLASS_ERROR_CODE         0x03
652 #define UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE          0x04
653 #define UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR_CODE 0x05
654 #define UNEXPECTED_MESSAGE_ERROR_CODE                0x06
655 #define PROTOCOL_ERROR_ERROR_CODE                    0x07
656 #define INVALID_STREAM_IDENTIFIER_ERROR_CODE         0x09
657 #define REFUSED_ERROR_CODE                           0x0d
658 #define ASP_IDENTIFIER_REQUIRED_ERROR_CODE           0x0e
659 #define INVALID_ASP_IDENTIFIER_ERROR_CODE            0x0f
660 #define INVALID_ROUTING_CONTEXT_ERROR_CODE           0x10
661 #define INVALID_PARAMETER_VALUE_ERROR_CODE           0x11
662 #define PARAMETER_FIELD_ERROR_CODE                   0x12
663 #define UNEXPECTED_PARAMETER_ERROR_CODE              0x13
664 #define DESTINATION_STATUS_UNKNOWN_ERROR_CODE        0x14
665 #define INVALID_NETWORK_APPEARANCE_ERROR_CODE        0x15
666 #define MISSING_PARAMETER_VALUE_ERROR_CODE           0x16
667 #define ROUTING_CONTEXT_CHANGE_REFUSED               0x17
668 #define INVALID_LOADSHARING_LABEL_ERROR_CODE         0x18
669
670 static const value_string sua_error_code_values[] = {
671   { INVALID_VERSION_ERROR_CODE,                   "Invalid version" },
672   { INVALID_INTERFACE_IDENTIFIER_ERROR_CODE,      "Ivalid Interface Identifier" },
673   { UNSUPPORTED_MESSAGE_CLASS_ERROR_CODE,         "Unsupported message class" },
674   { UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE,          "Unsupported message type" },
675   { UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR_CODE, "Unsupported traffic handling mode" },
676   { UNEXPECTED_MESSAGE_ERROR_CODE,                "Unexpected message" },
677   { PROTOCOL_ERROR_ERROR_CODE,                    "Protocol error" },
678   { INVALID_STREAM_IDENTIFIER_ERROR_CODE,         "Invalid Stream Identifier" },
679   { REFUSED_ERROR_CODE,                           "Refused - Management Blocking" },
680   { ASP_IDENTIFIER_REQUIRED_ERROR_CODE,           "ASP Identifier Required" },
681   { INVALID_ASP_IDENTIFIER_ERROR_CODE,            "Invalid ASP Identifier" },
682   { INVALID_ROUTING_CONTEXT_ERROR_CODE,           "Invalid Routing Context" },
683   { INVALID_PARAMETER_VALUE_ERROR_CODE,           "Invalid Parameter Value" },
684   { PARAMETER_FIELD_ERROR_CODE,                   "Parameter Field Error" },
685   { UNEXPECTED_PARAMETER_ERROR_CODE,              "Unexpected Parameter" },
686   { DESTINATION_STATUS_UNKNOWN_ERROR_CODE,        "Destination Status Unknown" },
687   { INVALID_NETWORK_APPEARANCE_ERROR_CODE,        "Invalid Netwrok Appearance" },
688   { MISSING_PARAMETER_VALUE_ERROR_CODE,           "Missing Parameter" },
689   { ROUTING_CONTEXT_CHANGE_REFUSED,               "Routing Key Change Refused" },
690   { INVALID_LOADSHARING_LABEL_ERROR_CODE,         "Invalid Loadsharing Label" },
691   { 0,                                            NULL } };
692
693 static void
694 dissect_sua_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
695 {
696   guint32 error_code;
697
698   error_code = tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET);
699   proto_tree_add_uint(parameter_tree, hf_sua_error_code, 
700                       parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH,
701                       error_code);
702   proto_item_set_text(parameter_item, "Error code (%s)", val_to_str(error_code, sua_error_code_values, "unknown"));
703 }
704
705 #define STATUS_TYPE_LENGTH 2
706 #define STATUS_INFO_LENGTH 2
707 #define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
708 #define STATUS_INFO_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
709
710 #define AS_STATE_CHANGE_TYPE       1
711 #define OTHER_TYPE                 2
712
713 static const value_string sua_status_type_values[] = {
714   { AS_STATE_CHANGE_TYPE,            "Application server state change" },
715   { OTHER_TYPE,                      "Other" },
716   { 0,                           NULL } };
717
718 #define RESERVED_INFO              1
719 #define AS_INACTIVE_INFO           2
720 #define AS_ACTIVE_INFO             3
721 #define AS_PENDING_INFO            4
722
723 #define INSUFFICIENT_ASP_RES_INFO  1
724 #define ALTERNATE_ASP_ACTIVE_INFO  2
725 #define ASP_FAILURE                3
726
727 static const value_string sua_status_type_info_values[] = {
728   { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO,             "Reserved" },
729   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO,          "Application server inactive" },
730   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO,            "Application server active" },
731   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO,           "Application server pending" },
732   { OTHER_TYPE           * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
733   { OTHER_TYPE           * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
734   { OTHER_TYPE           * 256 * 256 + ASP_FAILURE,               "ASP Failure" },
735   {0,                           NULL } };
736
737 static void
738 dissect_sua_status_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
739 {
740   guint16 status_type, status_info;
741
742   status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
743   status_info = tvb_get_ntohs(parameter_tvb, STATUS_INFO_OFFSET);
744
745   proto_tree_add_uint(parameter_tree, hf_sua_status_type, 
746                       parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH,
747                       status_type);
748   proto_tree_add_uint_format(parameter_tree, hf_sua_status_info, 
749                                                parameter_tvb, STATUS_INFO_OFFSET, STATUS_INFO_LENGTH,
750                                                status_info, "Status info: %s (%u)",
751                                                val_to_str(status_type * 256 * 256 + status_info, sua_status_type_info_values, "unknown"), status_info);
752
753   proto_item_set_text(parameter_item, "Status type / ID (%s)",
754                       val_to_str(status_type * 256 * 256 + status_info, sua_status_type_info_values, "unknown status information"));
755 }
756
757 #define CONGESTION_LEVEL_LENGTH 4
758 #define CONGESTION_LEVEL_OFFSET PARAMETER_VALUE_OFFSET
759
760 static void
761 dissect_sua_congestion_level_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
762 {
763   guint32 congestion_level;
764
765   congestion_level = tvb_get_ntohl(parameter_tvb, CONGESTION_LEVEL_OFFSET);
766
767   proto_tree_add_uint(parameter_tree, hf_sua_congestion_level, 
768                       parameter_tvb, CONGESTION_LEVEL_OFFSET, CONGESTION_LEVEL_LENGTH,
769                       congestion_level);
770     
771   proto_item_set_text(parameter_item, "Congestion Level: %u", congestion_level);
772
773 }
774
775 #define ASP_IDENTIFIER_LENGTH 4
776 #define ASP_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
777
778 static void
779 dissect_sua_asp_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
780 {
781   guint32 asp_identifier;
782
783   asp_identifier = tvb_get_ntohl(parameter_tvb, ASP_IDENTIFIER_OFFSET);
784
785   proto_tree_add_uint(parameter_tree, hf_sua_asp_identifier, 
786                       parameter_tvb, ASP_IDENTIFIER_OFFSET, ASP_IDENTIFIER_LENGTH,
787                       asp_identifier);
788     
789   proto_item_set_text(parameter_item, "ASP Identifer: %u", asp_identifier);
790 }
791
792 #define AFFECTED_MASK_LENGTH 1
793 #define AFFECTED_DPC_LENGTH  3
794 #define AFFECTED_DESTINATION_LENGTH (AFFECTED_MASK_LENGTH + AFFECTED_DPC_LENGTH)
795
796 #define AFFECTED_MASK_OFFSET 0
797 #define AFFECTED_DPC_OFFSET  1
798
799 static void
800 dissect_sua_affected_destinations_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
801 {
802   guint8  mask;
803   guint16 length, number_of_destinations, destination_number;
804   guint32 dpc;
805   gint destination_offset;
806   proto_item *destination_item;
807   proto_tree *destination_tree;
808
809   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
810   number_of_destinations= (length - PARAMETER_HEADER_LENGTH) / 4;
811
812   destination_offset = PARAMETER_VALUE_OFFSET;
813   for(destination_number=1; destination_number <= number_of_destinations; destination_number++) {
814     mask = tvb_get_guint8(parameter_tvb, destination_offset + AFFECTED_MASK_OFFSET);
815     dpc  = tvb_get_ntoh24(parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET);
816     destination_item = proto_tree_add_text(parameter_tree, parameter_tvb, destination_offset, AFFECTED_DESTINATION_LENGTH, "Affected destination");
817     destination_tree = proto_item_add_subtree(destination_item, ett_sua_affected_destination);
818
819     proto_tree_add_uint(destination_tree, hf_sua_mask, 
820                                           parameter_tvb, destination_offset + AFFECTED_MASK_OFFSET, AFFECTED_MASK_LENGTH,
821                                           mask);
822     proto_tree_add_uint(destination_tree, hf_sua_dpc, 
823                                           parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET, AFFECTED_DPC_LENGTH,
824                                           dpc);
825     destination_offset += AFFECTED_DESTINATION_LENGTH;
826   };
827   proto_item_set_text(parameter_item, "Affected destination (%u destination%s)",
828                                   number_of_destinations, plurality(number_of_destinations, "", "s"));
829
830 }
831
832 #define SS7_HOP_COUNTER_LENGTH 1
833 #define SS7_HOP_COUNTER_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
834
835 static void
836 dissect_sua_ss7_hop_counter_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
837 {
838   guint8 hop_counter;
839  
840   hop_counter = tvb_get_guint8(parameter_tvb,  SS7_HOP_COUNTER_OFFSET);
841     
842   proto_tree_add_bytes(parameter_tree, hf_sua_ss7_hop_counter_reserved, 
843                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,
844                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH));
845                        
846   proto_tree_add_uint(parameter_tree, hf_sua_ss7_hop_counter_counter, 
847                       parameter_tvb, SS7_HOP_COUNTER_OFFSET, SS7_HOP_COUNTER_LENGTH,
848                       hop_counter);
849   
850   proto_item_set_text(parameter_item, "SS7 Hop Counter (%u)", hop_counter);
851 }
852
853 #define ROUTING_INDICATOR_LENGTH  2
854 #define ADDRESS_INDICATOR_LENGTH  2
855
856 #define ROUTING_INDICATOR_OFFSET  PARAMETER_VALUE_OFFSET
857 #define ADDRESS_INDICATOR_OFFSET  (ROUTING_INDICATOR_OFFSET + ROUTING_INDICATOR_LENGTH)
858 #define ADDRESS_PARAMETERS_OFFSET (ADDRESS_INDICATOR_OFFSET + ADDRESS_INDICATOR_LENGTH)
859
860 #define RESERVED_ROUTING_INDICATOR              0
861 #define ROUTE_ON_GT_ROUTING_INDICATOR           1
862 #define ROUTE_ON_SSN_PC_ROUTING_INDICATOR       2
863 #define ROUTE_ON_HOSTNAMEROUTING_INDICATOR      3
864 #define ROUTE_ON_SSN_IP_ROUTING_INDICATOR       4
865
866 static const value_string sua_routing_indicator_values[] = {
867   { RESERVED_ROUTING_INDICATOR,            "Reserved" },
868   { ROUTE_ON_GT_ROUTING_INDICATOR,         "Route on Global Title" },
869   { ROUTE_ON_SSN_PC_ROUTING_INDICATOR,     "Route on SSN + PC" },
870   { ROUTE_ON_HOSTNAMEROUTING_INDICATOR,    "Route on Hostname" },
871   { ROUTE_ON_SSN_IP_ROUTING_INDICATOR,     "Route on SSN + IP Address" },
872   { 0,                                     NULL } };
873
874 #define ADDRESS_RESERVED_BITMASK 0xfff8
875 #define ADDRESS_GT_BITMASK       0x0004
876 #define ADDRESS_PC_BITMASK       0x0002
877 #define ADDRESS_SSN_BITMASK      0x0001
878
879 static void
880 dissect_sua_source_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
881 {
882   guint16 routing_indicator, address_indicator;
883   proto_item *address_indicator_item;
884   proto_tree *address_indicator_tree;
885   
886   routing_indicator = tvb_get_ntohs(parameter_tvb, ROUTING_INDICATOR_OFFSET);
887   address_indicator = tvb_get_ntohs(parameter_tvb, ADDRESS_INDICATOR_OFFSET);
888
889   proto_tree_add_uint(parameter_tree, hf_sua_source_address_routing_indicator, 
890                       parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH,
891                       routing_indicator);
892   
893   address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
894   address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_source_address_indicator);
895   proto_tree_add_uint(address_indicator_tree, hf_sua_source_address_reserved_bits, 
896                       parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH,
897                       address_indicator);
898   proto_tree_add_boolean(address_indicator_tree, hf_sua_source_address_gt_bit, parameter_tvb,
899                                            ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, address_indicator);
900   proto_tree_add_boolean(address_indicator_tree, hf_sua_source_address_pc_bit, parameter_tvb,
901                                            ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, address_indicator);
902   proto_tree_add_boolean(address_indicator_tree, hf_sua_source_address_ssn_bit, parameter_tvb,
903                                            ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, address_indicator);
904
905   proto_item_set_text(parameter_item, "Source Address");
906   
907   /* dissect address parameters */
908   dissect_sua_tlv_list(parameter_tvb, parameter_tree, ADDRESS_PARAMETERS_OFFSET);
909 }
910
911 static void
912 dissect_sua_destination_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
913 {
914   guint16 routing_indicator, address_indicator;
915   proto_item *address_indicator_item;
916   proto_tree *address_indicator_tree;
917   
918   routing_indicator = tvb_get_ntohs(parameter_tvb, ROUTING_INDICATOR_OFFSET);
919   address_indicator = tvb_get_ntohs(parameter_tvb, ADDRESS_INDICATOR_OFFSET);
920
921   proto_tree_add_uint(parameter_tree, hf_sua_destination_address_routing_indicator, 
922                       parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH,
923                       routing_indicator);
924   
925   address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
926   address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_destination_address_indicator);
927   proto_tree_add_uint(address_indicator_tree, hf_sua_destination_address_reserved_bits, 
928                       parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH,
929                       address_indicator);
930   proto_tree_add_boolean(address_indicator_tree, hf_sua_destination_address_gt_bit, parameter_tvb,
931                                            ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, address_indicator);
932   proto_tree_add_boolean(address_indicator_tree, hf_sua_destination_address_pc_bit, parameter_tvb,
933                                            ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, address_indicator);
934   proto_tree_add_boolean(address_indicator_tree, hf_sua_destination_address_ssn_bit, parameter_tvb,
935                                            ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, address_indicator);
936
937   proto_item_set_text(parameter_item, "Destination Address");
938   
939   /* dissect address parameters */
940   dissect_sua_tlv_list(parameter_tvb, parameter_tree, ADDRESS_PARAMETERS_OFFSET);
941 }
942
943 #define SOURCE_REFERENCE_NUMBER_LENGTH 4
944 #define SOURCE_REFERENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
945
946 static void
947 dissect_sua_source_reference_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
948 {
949   guint32 reference;
950
951   reference = tvb_get_ntohl(parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET);
952
953   proto_tree_add_uint(parameter_tree, hf_sua_source_reference_number, 
954                       parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET, SOURCE_REFERENCE_NUMBER_LENGTH,
955                       reference);
956     
957   proto_item_set_text(parameter_item, "Source Reference Number: %u", reference);
958 }
959
960 #define DESTINATION_REFERENCE_NUMBER_LENGTH 4
961 #define DESTINATION_REFERENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
962
963 static void
964 dissect_sua_destination_reference_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
965 {
966   guint32 reference;
967
968   reference = tvb_get_ntohl(parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET);
969
970   proto_tree_add_uint(parameter_tree, hf_sua_destination_reference_number, 
971                       parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET, DESTINATION_REFERENCE_NUMBER_LENGTH,
972                       reference);
973     
974   proto_item_set_text(parameter_item, "Destination Reference Number: %u", reference);
975 }
976
977 #define CAUSE_TYPE_LENGTH 1
978 #define CAUSE_VALUE_LENGTH 1
979
980 #define CAUSE_TYPE_OFFSET  (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
981 #define CAUSE_VALUE_OFFSET (CAUSE_TYPE_OFFSET + CAUSE_TYPE_LENGTH)
982
983 #define RETURN_CAUSE_TYPE    0x1
984 #define REFUSAL_CAUSE_TYPE   0x2
985 #define RELEASE_CAUSE_TYPE   0x3
986 #define RESET_CAUSE_TYPE     0x4
987 #define ERROR_CAUSE_TYPE     0x5
988
989 static const value_string sua_cause_type_values[] = {
990   { RETURN_CAUSE_TYPE,    "Return Cause" },
991   { REFUSAL_CAUSE_TYPE,   "Refusual Cause" },
992   { RELEASE_CAUSE_TYPE,   "Release Cause" },
993   { RESET_CAUSE_TYPE,     "Reset Cause" },
994   { ERROR_CAUSE_TYPE,     "Error cause" },
995   { 0,                    NULL } };
996
997 static void
998 dissect_sua_sccp_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
999 {
1000   guint8 type, value;
1001  
1002   type  = tvb_get_guint8(parameter_tvb,  CAUSE_TYPE_OFFSET);
1003   value = tvb_get_guint8(parameter_tvb,  CAUSE_VALUE_OFFSET);
1004     
1005   proto_tree_add_bytes(parameter_tree, hf_sua_cause_reserved, 
1006                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH,
1007                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH));
1008   proto_tree_add_uint(parameter_tree, hf_sua_cause_type, 
1009                       parameter_tvb, CAUSE_TYPE_OFFSET, CAUSE_TYPE_LENGTH,
1010                       type);
1011   proto_tree_add_uint(parameter_tree, hf_sua_cause_value, 
1012                       parameter_tvb, CAUSE_VALUE_OFFSET, CAUSE_VALUE_LENGTH,
1013                       value);
1014   
1015   proto_item_set_text(parameter_item, "SCCP Cause (%s)", val_to_str(type, sua_cause_type_values, "unknown"));
1016 }
1017
1018 #define SEQUENCE_NUMBER_REC_SEQ_LENGTH  1
1019 #define SEQUENCE_NUMBER_SENT_SEQ_LENGTH 1
1020 #define SEQUENCE_NUMBER_REC_SEQ_OFFSET  (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
1021 #define SEQUENCE_NUMBER_SENT_SEQ_OFFSET (SEQUENCE_NUMBER_REC_SEQ_OFFSET + SEQUENCE_NUMBER_REC_SEQ_LENGTH)
1022
1023 #define SEQ_NUM_MASK       0xFE
1024 #define SPARE_BIT_MASK     0x01
1025 #define MORE_DATA_BIT_MASK 0x01
1026
1027 static const true_false_string sua_more_data_bit_value = {
1028   "More Data",
1029   "Not More Data"
1030 };
1031
1032 static void
1033 dissect_sua_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1034 {
1035   guint8  receive_sequence_number, sent_sequence_number;
1036   proto_item *sent_sequence_number_item;
1037   proto_tree *sent_sequence_number_tree;
1038   proto_item *receive_sequence_number_item;
1039   proto_tree *receive_sequence_number_tree;
1040   
1041   receive_sequence_number = tvb_get_guint8(parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET);
1042   sent_sequence_number    = tvb_get_guint8(parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET);
1043
1044   proto_tree_add_bytes(parameter_tree, hf_sua_sequence_number_reserved, 
1045                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH,
1046                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH));
1047                        
1048   receive_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb,
1049                                                      SEQUENCE_NUMBER_REC_SEQ_OFFSET,
1050                                                      SEQUENCE_NUMBER_REC_SEQ_LENGTH, "Receive Sequence Number");
1051   receive_sequence_number_tree = proto_item_add_subtree(receive_sequence_number_item, ett_sua_sequence_number_rec_number);
1052   proto_tree_add_uint(receive_sequence_number_tree, hf_sua_sequence_number_rec_number, 
1053                       parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH,
1054                       receive_sequence_number);
1055   proto_tree_add_boolean(receive_sequence_number_tree, hf_sua_sequence_number_more_data_bit,
1056                          parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, 
1057                          receive_sequence_number);
1058   
1059   sent_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb,
1060                                                      SEQUENCE_NUMBER_SENT_SEQ_OFFSET,
1061                                                      SEQUENCE_NUMBER_SENT_SEQ_LENGTH, "Sent Sequence Number");
1062   sent_sequence_number_tree = proto_item_add_subtree(sent_sequence_number_item, ett_sua_sequence_number_sent_number);
1063   proto_tree_add_uint(sent_sequence_number_tree, hf_sua_sequence_number_sent_number, 
1064                       parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH,
1065                       sent_sequence_number);
1066   proto_tree_add_boolean(sent_sequence_number_tree, hf_sua_sequence_number_spare_bit,
1067                          parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, 
1068                          sent_sequence_number);
1069
1070   proto_item_set_text(parameter_item, "Sequence Number");
1071 }
1072
1073 #define RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH 1
1074 #define RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1075
1076 static void
1077 dissect_sua_receive_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1078 {
1079   guint8  receive_sequence_number;
1080   proto_item *receive_sequence_number_item;
1081   proto_tree *receive_sequence_number_tree;
1082   
1083   receive_sequence_number = tvb_get_guint8(parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET);
1084   
1085   proto_tree_add_bytes(parameter_tree, hf_sua_receive_sequence_number_reserved, 
1086                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,
1087                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH));
1088   receive_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb,
1089                                                      RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET,
1090                                                      RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, "Receive Sequence Number");
1091   receive_sequence_number_tree = proto_item_add_subtree(receive_sequence_number_item, ett_sua_receive_sequence_number_number);
1092   proto_tree_add_uint(receive_sequence_number_tree, hf_sua_receive_sequence_number_number, 
1093                       parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH,
1094                       receive_sequence_number);
1095   proto_tree_add_boolean(receive_sequence_number_tree, hf_sua_receive_sequence_number_spare_bit,
1096                          parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, 
1097                          receive_sequence_number);
1098
1099   proto_item_set_text(parameter_item, "Receive Sequence Number");
1100 }
1101
1102 #define PROTOCOL_CLASSES_LENGTH        1
1103 #define INTERWORKING_LENGTH            1
1104 #define PROTOCOL_CLASSES_OFFSET        (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
1105 #define INTERWORKING_OFFSET            (PROTOCOL_CLASSES_OFFSET + PROTOCOL_CLASSES_LENGTH)
1106
1107 #define A_BIT_MASK 0x08
1108 #define B_BIT_MASK 0x04
1109 #define C_BIT_MASK 0x02
1110 #define D_BIT_MASK 0x01
1111 #define RESERVED_BITS_MASK 0xF0
1112
1113 static const true_false_string sua_supported_bit_value = {
1114   "Supported",
1115   "Unsupported"
1116 };
1117
1118 #define NO_INTERWORKING      0x0
1119 #define ASP_SS7_INTERWORKING 0x1
1120 #define SG_INTERWORKING      0x2
1121 #define RELAY_INTERWORKING   0x3
1122
1123 static const value_string sua_interworking_values[] = {
1124   { NO_INTERWORKING,        "No Interworking with SS7 Networks" },
1125   { ASP_SS7_INTERWORKING,   "IP-Signalling Endpoint interworking with with SS7 networks" },
1126   { SG_INTERWORKING,        "Signalling Gateway" },
1127   { RELAY_INTERWORKING,     "Relay Node Support" },
1128   { 0,                      NULL } };
1129
1130 static void
1131 dissect_sua_asp_capabilities_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1132 {
1133   guint8  protocol_classes, interworking;
1134   proto_item *protocol_classes_item;
1135   proto_tree *protocol_classes_tree;
1136   
1137   protocol_classes = tvb_get_guint8(parameter_tvb, PROTOCOL_CLASSES_OFFSET);
1138   interworking     = tvb_get_guint8(parameter_tvb, INTERWORKING_OFFSET);
1139   
1140   proto_tree_add_bytes(parameter_tree, hf_sua_asp_capabilities_reserved, 
1141                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH,
1142                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH));
1143   protocol_classes_item = proto_tree_add_text(parameter_tree, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, "Protocol classes");
1144   protocol_classes_tree = proto_item_add_subtree(protocol_classes_item, ett_sua_protcol_classes);
1145   proto_tree_add_uint(protocol_classes_tree, hf_sua_asp_capabilities_reserved_bits, 
1146                       parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH,
1147                       protocol_classes);
1148   proto_tree_add_boolean(protocol_classes_tree, hf_sua_asp_capabilities_a_bit, parameter_tvb,
1149                                            PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, protocol_classes);
1150   proto_tree_add_boolean(protocol_classes_tree, hf_sua_asp_capabilities_b_bit, parameter_tvb,
1151                                            PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, protocol_classes);
1152   proto_tree_add_boolean(protocol_classes_tree, hf_sua_asp_capabilities_c_bit, parameter_tvb,
1153                                            PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, protocol_classes);
1154   proto_tree_add_boolean(protocol_classes_tree, hf_sua_asp_capabilities_d_bit, parameter_tvb,
1155                                            PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, protocol_classes);
1156
1157   proto_tree_add_uint(parameter_tree, hf_sua_asp_capabilities_interworking, 
1158                       parameter_tvb, INTERWORKING_OFFSET, INTERWORKING_LENGTH,
1159                       interworking);
1160   
1161   proto_item_set_text(parameter_item, "ASP Capabilities");
1162 }
1163
1164 #define CREDIT_LENGTH 4
1165 #define CREDIT_OFFSET PARAMETER_VALUE_OFFSET
1166
1167 static void
1168 dissect_sua_credit_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1169 {
1170   guint32 credit;
1171
1172   credit = tvb_get_ntohl(parameter_tvb, CREDIT_OFFSET);
1173
1174   proto_tree_add_uint(parameter_tree, hf_sua_credit, 
1175                       parameter_tvb, CREDIT_OFFSET, CREDIT_LENGTH,
1176                       credit);
1177     
1178   proto_item_set_text(parameter_item, "Credit: %u", credit);
1179 }
1180
1181 #define CAUSE_LENGTH 2
1182 #define USER_LENGTH  2
1183 #define CAUSE_OFFSET PARAMETER_VALUE_OFFSET
1184 #define USER_OFFSET (CAUSE_OFFSET + CAUSE_LENGTH)
1185
1186 #define UNAVAILABLE_CAUSE    0x0
1187 #define UNEQUIPPED_CAUSE     0x2
1188 #define INACCESSABLE_CAUSE   0x3
1189
1190 static const value_string sua_cause_values[] = {
1191   { UNAVAILABLE_CAUSE,    "Remote SCCP unavailable, Reason unknown" },
1192   { UNEQUIPPED_CAUSE,     "Remote SCCP unequipped" },
1193   { INACCESSABLE_CAUSE,   "Remote SCCP inaccessable" },
1194   { 0,                    NULL } };
1195
1196 static void
1197 dissect_sua_user_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1198 {
1199   guint16 cause, user;
1200
1201   cause = tvb_get_ntohs(parameter_tvb, CAUSE_OFFSET);
1202   user  = tvb_get_ntohs(parameter_tvb, USER_OFFSET);
1203
1204   proto_tree_add_uint(parameter_tree, hf_sua_cause, 
1205                       parameter_tvb, CAUSE_OFFSET, CAUSE_LENGTH,
1206                       cause);
1207   proto_tree_add_uint(parameter_tree, hf_sua_user, 
1208                       parameter_tvb, USER_OFFSET, USER_LENGTH,
1209                       user);
1210    
1211   proto_item_set_text(parameter_item, "User / Cause");
1212 }
1213
1214 #define NETWORK_APPEARANCE_LENGTH 4
1215 #define NETWORK_APPEARANCE_OFFSET PARAMETER_VALUE_OFFSET
1216
1217 static void
1218 dissect_sua_network_appearance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1219 {
1220   guint32 appearance;
1221
1222   appearance = tvb_get_ntohl(parameter_tvb, NETWORK_APPEARANCE_OFFSET);
1223
1224   proto_tree_add_uint(parameter_tree, hf_sua_network_appearance, 
1225                       parameter_tvb, NETWORK_APPEARANCE_OFFSET, NETWORK_APPEARANCE_LENGTH,
1226                       appearance);
1227     
1228   proto_item_set_text(parameter_item, "Network Appearance: %u", appearance);
1229 }
1230
1231 #define IDENTIFIER_LENGTH      4
1232 #define IDENTIFIER_OFFSET      PARAMETER_VALUE_OFFSET
1233 #define KEY_PARAMETERS_OFFSET  (IDENTIFIER_OFFSET + IDENTIFIER_LENGTH)
1234
1235 static void
1236 dissect_sua_routing_key_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1237 {
1238   guint32 identifier;
1239   
1240   identifier = tvb_get_ntohl(parameter_tvb, IDENTIFIER_OFFSET);
1241
1242   proto_tree_add_uint(parameter_tree, hf_sua_routing_key_identifier, 
1243                       parameter_tvb, IDENTIFIER_OFFSET, IDENTIFIER_LENGTH,
1244                       identifier);
1245   
1246   proto_item_set_text(parameter_item, "Routing Key");
1247   
1248   dissect_sua_tlv_list(parameter_tvb, parameter_tree, KEY_PARAMETERS_OFFSET);
1249 }
1250
1251 #define LOCAL_ROUTING_KEY_ID_LENGTH         4
1252 #define REGISTRATION_STATUS_LENGTH          4
1253 #define REGISTRATION_ROUTING_CONTEXT_LENGTH 4
1254 #define LOCAL_ROUTING_KEY_OFFSET            PARAMETER_VALUE_OFFSET
1255 #define REGISTRATION_STATUS_OFFSET          (LOCAL_ROUTING_KEY_OFFSET + LOCAL_ROUTING_KEY_ID_LENGTH)
1256 #define REGISTRATION_ROUTING_CONTEXT_OFFSET (REGISTRATION_STATUS_OFFSET + REGISTRATION_STATUS_LENGTH)
1257
1258 #define SUCCESSFULLY_REGISTERED_REGISTRATION_STATUS               0x0
1259 #define UNKNOWN_REGISTRATION_STATUS                               0x1
1260 #define INVALID_DESTINATION_ADDRESSS_REGISTRATION_STATUS          0x2
1261 #define INVALID_NETWORK_APPEARANCE_REGISTRATION_STATUS            0x3
1262 #define INVALID_ROUTING_KEY_REGISTRATION_STATUS                   0x4
1263 #define PERMISSION_DENIED_REGISTRATION_STATUS                     0x5
1264 #define CANNOT_SUPPORT_UNIQUE_ROUTING_REGISTRATION_STATUS         0x6
1265 #define ROUTING_KEY_NOT_PROVISIONED_REGISTRATION_STATUS           0x7
1266 #define INSUFFICIENT_RESOURCES_REGISTRATION_STATUS                0x8
1267 #define UNSUPPORTED_RK_PARAMETER_REGISTRATION_FIELD_STATUS        0x9
1268 #define UNSUPPORTED_INVALID_TRAFFIC_MODE_TYPE_REGISTRATION_STATUS 0xa
1269
1270 static const value_string sua_registration_status_values[] = {
1271   { SUCCESSFULLY_REGISTERED_REGISTRATION_STATUS,               "Successfully Registered" },
1272   { UNKNOWN_REGISTRATION_STATUS,                               "Error - Unknown" },
1273   { INVALID_DESTINATION_ADDRESSS_REGISTRATION_STATUS,          "Error - Invalid Destination Address" },
1274   { INVALID_NETWORK_APPEARANCE_REGISTRATION_STATUS,            "Error - Invalid Network Appearance" },
1275   { INVALID_ROUTING_KEY_REGISTRATION_STATUS,                   "Error - Invalid Routing Key" },
1276   { PERMISSION_DENIED_REGISTRATION_STATUS,                     "Error - Permission Denied" },
1277   { CANNOT_SUPPORT_UNIQUE_ROUTING_REGISTRATION_STATUS,         "Error - Cannot Support Unique Routing" },
1278   { ROUTING_KEY_NOT_PROVISIONED_REGISTRATION_STATUS,           "Error - Routing Key Not Currently Provisioned" },
1279   { INSUFFICIENT_RESOURCES_REGISTRATION_STATUS,                "Error - Insufficient Resources" },
1280   { UNSUPPORTED_RK_PARAMETER_REGISTRATION_FIELD_STATUS,        "Error - Unsupported Routing Key Parameter Field" },
1281   { UNSUPPORTED_INVALID_TRAFFIC_MODE_TYPE_REGISTRATION_STATUS, "Error - Unsupported / Invalid Traffic Mode Type" },
1282   { 0,                                            NULL } };
1283
1284 static void
1285 dissect_sua_registration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1286 {
1287   guint32 local_routing_key_identifier, registration_status, routing_context;
1288
1289   local_routing_key_identifier = tvb_get_ntohl(parameter_tvb, LOCAL_ROUTING_KEY_OFFSET);
1290   registration_status = tvb_get_ntohl(parameter_tvb, REGISTRATION_STATUS_OFFSET);
1291   routing_context = tvb_get_ntohl(parameter_tvb, REGISTRATION_ROUTING_CONTEXT_OFFSET);
1292
1293   proto_tree_add_uint(parameter_tree, hf_sua_registration_result_routing_key_identifier, 
1294                       parameter_tvb, LOCAL_ROUTING_KEY_OFFSET, LOCAL_ROUTING_KEY_ID_LENGTH,
1295                       local_routing_key_identifier);
1296   proto_tree_add_uint(parameter_tree, hf_sua_registration_result_status, 
1297                       parameter_tvb, REGISTRATION_STATUS_OFFSET, REGISTRATION_STATUS_LENGTH,
1298                       registration_status);
1299   proto_tree_add_uint(parameter_tree, hf_sua_registration_result_routing_context, 
1300                       parameter_tvb, REGISTRATION_ROUTING_CONTEXT_OFFSET, REGISTRATION_ROUTING_CONTEXT_LENGTH,
1301                       routing_context);
1302    
1303   proto_item_set_text(parameter_item, "Registration Result: %s", val_to_str(registration_status, sua_registration_status_values, "Unknown"));
1304 }
1305
1306 #define DEREGISTRATION_ROUTING_CONTEXT_LENGTH 4
1307 #define DEREGISTRATION_STATUS_LENGTH          4
1308
1309 #define DEREGISTRATION_ROUTING_CONTEXT_OFFSET PARAMETER_VALUE_OFFSET
1310 #define DEREGISTRATION_STATUS_OFFSET          (DEREGISTRATION_ROUTING_CONTEXT_OFFSET + DEREGISTRATION_ROUTING_CONTEXT_LENGTH)
1311
1312 #define SUCCESSFULLY_DEREGISTERED_DEREGISTRATION_STATUS                0x0
1313 #define UNKNOWN_DEREGISTRATION_STATUS                                  0x1
1314 #define INVALID_ROUTING_CONTEXT_DEREGISTRATION_STATUS                  0x2
1315 #define PERMISSION_DENIED_DEREGISTRATION_STATUS                        0x3
1316 #define NOT_REGISTERED_DEREGISTRATION_STATUS                           0x4
1317 #define ASP_CURRENTLY_ACTIVE_FOR_ROUTING_CONTEXT_DEREGISTRATION_STATUS 0x5
1318
1319 static const value_string sua_deregistration_status_values[] = {
1320   { SUCCESSFULLY_DEREGISTERED_DEREGISTRATION_STATUS,                "Successfully Deregistered" },
1321   { UNKNOWN_DEREGISTRATION_STATUS,                                  "Error - Unknown" },
1322   { INVALID_ROUTING_CONTEXT_DEREGISTRATION_STATUS,                  "Error - Invalid Routing Context" },
1323   { PERMISSION_DENIED_DEREGISTRATION_STATUS,                        "Error - Permission Denied" },
1324   { NOT_REGISTERED_DEREGISTRATION_STATUS,                           "Error - Not Registered" },
1325   { ASP_CURRENTLY_ACTIVE_FOR_ROUTING_CONTEXT_DEREGISTRATION_STATUS, "Error - ASP Currently Active for Routing Context" },
1326   { 0,                                                              NULL } };
1327
1328 static void
1329 dissect_sua_deregistration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1330 {
1331   guint32 routing_context, deregistration_status;
1332
1333   routing_context       = tvb_get_ntohl(parameter_tvb, DEREGISTRATION_ROUTING_CONTEXT_OFFSET);
1334   deregistration_status = tvb_get_ntohl(parameter_tvb, DEREGISTRATION_STATUS_OFFSET);
1335
1336   proto_tree_add_uint(parameter_tree, hf_sua_deregistration_result_routing_context, 
1337                       parameter_tvb, DEREGISTRATION_ROUTING_CONTEXT_OFFSET, DEREGISTRATION_ROUTING_CONTEXT_LENGTH,
1338                       routing_context);
1339   proto_tree_add_uint(parameter_tree, hf_sua_deregistration_result_status, 
1340                       parameter_tvb, REGISTRATION_STATUS_OFFSET, REGISTRATION_STATUS_LENGTH,
1341                       deregistration_status);
1342    
1343   proto_item_set_text(parameter_item, "Deregistration Result: %s", val_to_str(deregistration_status, sua_deregistration_status_values, "Unknown"));
1344 }
1345
1346 #define ADDRESS_RANGE_ADDRESS_PARAMETERS_OFFSET  PARAMETER_VALUE_OFFSET
1347
1348 static void
1349 dissect_sua_address_range_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1350 {
1351   proto_item_set_text(parameter_item, "Address Range");
1352   
1353   dissect_sua_tlv_list(parameter_tvb, parameter_tree, ADDRESS_RANGE_ADDRESS_PARAMETERS_OFFSET);
1354 }
1355
1356 #define CORRELATION_ID_LENGTH 4
1357 #define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
1358
1359 static void
1360 dissect_sua_correlation_id_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1361 {
1362   guint32 correlation_id;
1363
1364   correlation_id = tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET);
1365
1366   proto_tree_add_uint(parameter_tree, hf_sua_correlation_id, 
1367                       parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH,
1368                       correlation_id);
1369     
1370   proto_item_set_text(parameter_item, "Correlation ID: %u", correlation_id);
1371 }
1372
1373 #define IMPORTANCE_LENGTH 1
1374 #define IMPORTANCE_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1375
1376 static void
1377 dissect_sua_importance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1378 {
1379   guint8 importance;
1380  
1381   importance = tvb_get_guint8(parameter_tvb,  IMPORTANCE_OFFSET);
1382     
1383   proto_tree_add_bytes(parameter_tree, hf_sua_importance_reserved, 
1384                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,
1385                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH));
1386   proto_tree_add_uint(parameter_tree, hf_sua_importance, 
1387                       parameter_tvb, IMPORTANCE_OFFSET, IMPORTANCE_LENGTH,
1388                       importance);
1389   
1390   proto_item_set_text(parameter_item, "Importance (%u)", importance);
1391 }
1392
1393 #define MESSAGE_PRIORITY_LENGTH 1
1394 #define MESSAGE_PRIORITY_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1395
1396 static void
1397 dissect_sua_message_priority_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1398 {
1399   guint8 priority;
1400  
1401   priority = tvb_get_guint8(parameter_tvb,  MESSAGE_PRIORITY_OFFSET);
1402   proto_tree_add_bytes(parameter_tree, hf_sua_message_priority_reserved, 
1403                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,
1404                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH));
1405   
1406   proto_tree_add_uint(parameter_tree, hf_sua_message_priority, 
1407                       parameter_tvb, MESSAGE_PRIORITY_OFFSET, MESSAGE_PRIORITY_LENGTH,
1408                       priority);
1409   
1410   proto_item_set_text(parameter_item, "Message Priority (%u)", priority);
1411 }
1412
1413 #define PROTOCOL_CLASS_LENGTH         1
1414 #define PROTOCOL_CLASS_OFFSET         (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1415
1416 #define RETURN_ON_ERROR_BIT_MASK 0x80
1417 #define PROTOCOL_CLASS_MASK      0x7f
1418
1419
1420 static const true_false_string sua_return_on_error_bit_value = {
1421   "Return Message On Error",
1422   "No Special Options"
1423 };
1424
1425 static void
1426 dissect_sua_protocol_class_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1427 {
1428   guint8  protocol_class;
1429   proto_item *protocol_class_item;
1430   proto_tree *protocol_class_tree;
1431   
1432   protocol_class = tvb_get_guint8(parameter_tvb, PROTOCOL_CLASS_OFFSET);
1433   
1434   proto_tree_add_bytes(parameter_tree, hf_sua_protocol_class_reserved, 
1435                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,
1436                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH));
1437
1438   protocol_class_item = proto_tree_add_text(parameter_tree, parameter_tvb, PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH,
1439                                             "Protocol Class");
1440   protocol_class_tree = proto_item_add_subtree(protocol_class_item, ett_sua_return_on_error_bit_and_protocol_class);
1441  
1442   proto_tree_add_boolean(protocol_class_tree, hf_sua_return_on_error_bit, parameter_tvb,
1443                                            PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH, protocol_class);
1444   proto_tree_add_uint(protocol_class_tree, hf_sua_protocol_class, 
1445                       parameter_tvb, PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH,
1446                       protocol_class); 
1447    
1448   proto_item_set_text(parameter_item, "Protocol Class");
1449 }
1450
1451 #define SEQUENCE_CONTROL_LENGTH 4
1452 #define SEQUENCE_CONTROL_OFFSET PARAMETER_VALUE_OFFSET
1453
1454 static void
1455 dissect_sua_sequence_control_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1456 {
1457   guint32 sequence_control;
1458
1459   sequence_control = tvb_get_ntohl(parameter_tvb, SEQUENCE_CONTROL_OFFSET);
1460
1461   proto_tree_add_uint(parameter_tree, hf_sua_sequence_control, 
1462                       parameter_tvb, SEQUENCE_CONTROL_OFFSET, SEQUENCE_CONTROL_LENGTH,
1463                       sequence_control);
1464     
1465   proto_item_set_text(parameter_item, "Sequence Control: %u", sequence_control);
1466 }
1467
1468 #define FIRST_REMAINING_LENGTH        1
1469 #define SEGMENTATION_REFERENCE_LENGTH 3
1470 #define FIRST_REMAINING_OFFSET        PARAMETER_VALUE_OFFSET
1471 #define SEGMENTATION_REFERENCE_OFFSET (FIRST_REMAINING_OFFSET + FIRST_REMAINING_LENGTH)
1472
1473 #define FIRST_BIT_MASK 0x80
1474 #define NUMBER_OF_SEGMENTS_MASK 0x7f
1475
1476 static const true_false_string sua_first_bit_value = {
1477   "First segment",
1478   "Subsequent segment"
1479 };
1480
1481 static void
1482 dissect_sua_segmentation_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1483 {
1484   guint8  first_remaining;
1485   guint32 segmentation_reference;
1486   proto_item *first_remaining_item;
1487   proto_tree *first_remaining_tree;
1488   
1489   first_remaining        = tvb_get_guint8(parameter_tvb, FIRST_REMAINING_OFFSET);
1490   segmentation_reference = tvb_get_ntoh24(parameter_tvb, SEGMENTATION_REFERENCE_OFFSET);
1491   
1492   first_remaining_item = proto_tree_add_text(parameter_tree, parameter_tvb, FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH,
1493                                                                      "First / Remaining");
1494   first_remaining_tree = proto_item_add_subtree(first_remaining_item, ett_sua_first_remaining);
1495   proto_tree_add_boolean(first_remaining_tree, hf_sua_first_bit, parameter_tvb,
1496                                            FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH, first_remaining);
1497   proto_tree_add_uint(first_remaining_tree, hf_sua_number_of_remaining_segments, 
1498                       parameter_tvb, FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH,
1499                       first_remaining);
1500
1501   proto_tree_add_uint(parameter_tree, hf_sua_segmentation_reference, 
1502                       parameter_tvb, SEGMENTATION_REFERENCE_OFFSET, SEGMENTATION_REFERENCE_LENGTH,
1503                       segmentation_reference);
1504   
1505   proto_item_set_text(parameter_item, "Segmentation");
1506 }
1507
1508 #define SMI_LENGTH 1
1509 #define SMI_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1510
1511 static void
1512 dissect_sua_smi_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1513 {
1514   guint8 smi;
1515  
1516   smi = tvb_get_guint8(parameter_tvb,  SMI_OFFSET);
1517     
1518   proto_tree_add_bytes(parameter_tree, hf_sua_smi_reserved, 
1519                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,
1520                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH));
1521   proto_tree_add_uint(parameter_tree, hf_sua_smi, 
1522                       parameter_tvb, SMI_OFFSET, SMI_LENGTH,
1523                       smi);
1524   
1525   proto_item_set_text(parameter_item, "SMI (%u)", smi);
1526 }
1527
1528 #define TID_START_LENGTH 1
1529 #define TID_END_LENGTH 1
1530 #define TID_VALUE_LENGTH 2
1531
1532 #define TID_START_OFFSET PARAMETER_VALUE_OFFSET
1533 #define TID_END_OFFSET   (TID_START_OFFSET + TID_START_LENGTH)
1534 #define TID_VALUE_OFFSET (TID_END_OFFSET + TID_END_LENGTH)
1535
1536 static void
1537 dissect_sua_tid_label_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1538 {
1539   guint8  start, end;
1540   guint16 value;
1541   
1542   start = tvb_get_guint8(parameter_tvb,  TID_START_OFFSET);
1543   end   = tvb_get_guint8(parameter_tvb,  TID_END_OFFSET);
1544   value = tvb_get_ntohs(parameter_tvb,   TID_VALUE_OFFSET);
1545    
1546   proto_tree_add_uint(parameter_tree, hf_sua_tid_label_start, 
1547                       parameter_tvb, TID_START_OFFSET, TID_START_LENGTH,
1548                       start);
1549   proto_tree_add_uint(parameter_tree, hf_sua_tid_label_end, 
1550                       parameter_tvb, TID_END_OFFSET, TID_END_LENGTH,
1551                       end);
1552   proto_tree_add_uint(parameter_tree, hf_sua_tid_label_value, 
1553                       parameter_tvb, TID_VALUE_OFFSET, TID_VALUE_LENGTH,
1554                       value);
1555   
1556   proto_item_set_text(parameter_item, "TID Label");
1557 }
1558
1559 #define DRN_START_LENGTH 1
1560 #define DRN_END_LENGTH 1
1561 #define DRN_VALUE_LENGTH 2
1562
1563 #define DRN_START_OFFSET PARAMETER_VALUE_OFFSET
1564 #define DRN_END_OFFSET   (DRN_START_OFFSET + DRN_START_LENGTH)
1565 #define DRN_VALUE_OFFSET (DRN_END_OFFSET + DRN_END_LENGTH)
1566
1567 static void
1568 dissect_sua_drn_label_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1569 {
1570   guint8  start, end;
1571   guint16 value;
1572   
1573   start = tvb_get_guint8(parameter_tvb,  DRN_START_OFFSET);
1574   end   = tvb_get_guint8(parameter_tvb,  DRN_END_OFFSET);
1575   value = tvb_get_ntohs(parameter_tvb,   DRN_VALUE_OFFSET);
1576    
1577   proto_tree_add_uint(parameter_tree, hf_sua_drn_label_start, 
1578                       parameter_tvb, DRN_START_OFFSET, DRN_START_LENGTH,
1579                       start);
1580   proto_tree_add_uint(parameter_tree, hf_sua_drn_label_end, 
1581                       parameter_tvb, DRN_END_OFFSET, DRN_END_LENGTH,
1582                       end);
1583   proto_tree_add_uint(parameter_tree, hf_sua_drn_label_value, 
1584                       parameter_tvb, DRN_VALUE_OFFSET, DRN_VALUE_LENGTH,
1585                       value);
1586   
1587   proto_item_set_text(parameter_item, "DRN Label");
1588 }
1589
1590 #define NO_OF_DIGITS_LENGTH      1
1591 #define TRANSLATION_TYPE_LENGTH  1
1592 #define NUMBERING_PLAN_LENGTH    1
1593 #define NATURE_OF_ADDRESS_LENGTH 1
1594
1595 #define NO_OF_DIGITS_OFFSET      PARAMETER_VALUE_OFFSET
1596 #define TRANSLATION_TYPE_OFFSET  (NO_OF_DIGITS_OFFSET + NO_OF_DIGITS_LENGTH)
1597 #define NUMBERING_PLAN_OFFSET    (TRANSLATION_TYPE_OFFSET + TRANSLATION_TYPE_LENGTH)
1598 #define NATURE_OF_ADDRESS_OFFSET (NUMBERING_PLAN_OFFSET + NUMBERING_PLAN_LENGTH)
1599 #define GLOBAL_TITLE_OFFSET      (NATURE_OF_ADDRESS_OFFSET + NATURE_OF_ADDRESS_LENGTH)
1600
1601 #define ISDN_TELEPHONY_NUMBERING_PLAN   1
1602 #define GENERIC_NUMBERING_PLAN          2
1603 #define DATA_NUMBERING_PLAN             3
1604 #define TELEX_NUMBERING_PLAN            4
1605 #define MARITIME_MOBILE_NUMBERING_PLAN  5
1606 #define LAND_MOBILE_NUMBERING_PLAN      6
1607 #define ISDN_MOBILE_NUMBERING_PLAN      7
1608 #define PRIVATE_NETWORK_NUMBERING_PLAN 14
1609
1610 static const value_string sua_numbering_plan_values[] = {
1611   { ISDN_TELEPHONY_NUMBERING_PLAN,  "ISDN/Telephony Numbering Plan (Rec. E.161 and E.164)" },
1612   { GENERIC_NUMBERING_PLAN,         "Generic Numbering Plan" },
1613   { DATA_NUMBERING_PLAN,            "Data Numbering Plan (Rec. X.121)" },
1614   { TELEX_NUMBERING_PLAN,           "Telex Numbering Plan (Rec. F.69)" },
1615   { MARITIME_MOBILE_NUMBERING_PLAN, "Maritime Mobile Numbering Plan (Rec. E.210 and E.211)" },
1616   { LAND_MOBILE_NUMBERING_PLAN,     "Land Mobile Numbering Plan (Rec. E.212)" },
1617   { ISDN_MOBILE_NUMBERING_PLAN,     "ISDN/Mobile Numbering Plan (Rec. E.214)" },
1618   { PRIVATE_NETWORK_NUMBERING_PLAN, "Private Network Or Network-Specific Numbering Plan" },
1619   { 0,                                             NULL } };
1620
1621 #define UNKNOWN_NATURE_OF_ADDRESS                       0
1622 #define SUBSCRIBER_NUMBER_NATURE_OF_ADDRESS             1
1623 #define RESERVED_FOR_NATIONAL_USE_NATURE_OF_ADDRESS     2
1624 #define NATIONAL_SIGNIFICANT_NUMBER_NATURE_OF_ADDRESS   3
1625 #define INTERNATION_NUMBER_NATURE_OF_ADDRESS            4
1626
1627 static const value_string sua_nature_of_address_values[] = {
1628   { UNKNOWN_NATURE_OF_ADDRESS,                     "Unknown" },
1629   { SUBSCRIBER_NUMBER_NATURE_OF_ADDRESS,           "Subscriber Number" },
1630   { RESERVED_FOR_NATIONAL_USE_NATURE_OF_ADDRESS,   "Reserved For National Use" },
1631   { NATIONAL_SIGNIFICANT_NUMBER_NATURE_OF_ADDRESS, "Natinal Significant Number" },
1632   { INTERNATION_NUMBER_NATURE_OF_ADDRESS,          "International Number" },
1633   { 0,                                             NULL } };
1634
1635 static void
1636 dissect_sua_global_title_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1637 {
1638   guint8  number_of_digits, translation_type, numbering_plan, nature_of_address;
1639   guint16 length, global_title_length, padding_length;
1640   
1641   length              = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1642   global_title_length = length - (PARAMETER_HEADER_LENGTH + NO_OF_DIGITS_LENGTH
1643                                                           + TRANSLATION_TYPE_LENGTH
1644                                                           + NUMBERING_PLAN_LENGTH
1645                                                           + NATURE_OF_ADDRESS_LENGTH);
1646   padding_length      = nr_of_padding_bytes(length);
1647
1648   number_of_digits  = tvb_get_guint8(parameter_tvb, NO_OF_DIGITS_OFFSET);
1649   translation_type  = tvb_get_guint8(parameter_tvb, TRANSLATION_TYPE_OFFSET);
1650   numbering_plan    = tvb_get_guint8(parameter_tvb, NUMBERING_PLAN_OFFSET);
1651   nature_of_address = tvb_get_guint8(parameter_tvb, NATURE_OF_ADDRESS_OFFSET);
1652
1653   proto_tree_add_uint(parameter_tree, hf_sua_number_of_digits, 
1654                       parameter_tvb, NO_OF_DIGITS_OFFSET, NO_OF_DIGITS_LENGTH,
1655                       number_of_digits);
1656   proto_tree_add_uint(parameter_tree, hf_sua_translation_type, 
1657                       parameter_tvb, TRANSLATION_TYPE_OFFSET, TRANSLATION_TYPE_LENGTH,
1658                       translation_type);
1659   proto_tree_add_uint(parameter_tree, hf_sua_numbering_plan, 
1660                       parameter_tvb, NUMBERING_PLAN_OFFSET, NUMBERING_PLAN_LENGTH,
1661                       numbering_plan);
1662   proto_tree_add_uint(parameter_tree, hf_sua_nature_of_address, 
1663                       parameter_tvb, NATURE_OF_ADDRESS_OFFSET, NATURE_OF_ADDRESS_LENGTH,
1664                       nature_of_address);
1665   proto_tree_add_bytes(parameter_tree, hf_sua_global_title, 
1666                        parameter_tvb, GLOBAL_TITLE_OFFSET, global_title_length,
1667                        tvb_get_ptr(parameter_tvb, GLOBAL_TITLE_OFFSET, global_title_length));
1668
1669   if (padding_length > 0)
1670     proto_tree_add_bytes(parameter_tree, hf_sua_global_title_padding, 
1671                          parameter_tvb, GLOBAL_TITLE_OFFSET + global_title_length, padding_length,
1672                          tvb_get_ptr(parameter_tvb, GLOBAL_TITLE_OFFSET + global_title_length, padding_length));
1673                          
1674   proto_item_set_text(parameter_item, "Global Title");
1675
1676 }
1677
1678 static void
1679 dissect_sua_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1680 {
1681   guint8  mask;
1682   guint32 dpc;
1683
1684   mask = tvb_get_guint8(parameter_tvb, AFFECTED_MASK_OFFSET);
1685   dpc  = tvb_get_ntoh24(parameter_tvb, AFFECTED_DPC_OFFSET);
1686
1687   proto_tree_add_uint(parameter_tree, hf_sua_point_code_mask, 
1688                       parameter_tvb, PARAMETER_VALUE_OFFSET + AFFECTED_MASK_OFFSET, AFFECTED_MASK_LENGTH,
1689                       mask);
1690   proto_tree_add_uint(parameter_tree, hf_sua_point_code_dpc, 
1691                       parameter_tvb, PARAMETER_VALUE_OFFSET + AFFECTED_DPC_OFFSET, AFFECTED_DPC_LENGTH,
1692                       dpc);
1693   proto_item_set_text(parameter_item, "Point Code");
1694
1695 }
1696
1697 #define SSN_LENGTH 1
1698 #define SSN_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1699
1700 static void
1701 dissect_sua_ssn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1702 {
1703   guint8 ssn;
1704  
1705   ssn = tvb_get_guint8(parameter_tvb,  SSN_OFFSET);
1706     
1707   proto_tree_add_bytes(parameter_tree, hf_sua_ssn_reserved, 
1708                        parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,
1709                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH));
1710   proto_tree_add_uint(parameter_tree, hf_sua_ssn_number, 
1711                       parameter_tvb, SSN_OFFSET, SSN_LENGTH,
1712                       ssn);
1713   
1714   proto_item_set_text(parameter_item, "Subsystem number (%u)", ssn);
1715 }
1716
1717 #define IPV4_ADDRESS_LENGTH 4
1718 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1719
1720 static void
1721 dissect_sua_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1722 {
1723   guint32 ipv4_address;
1724
1725   tvb_memcpy(parameter_tvb, (guint8 *)&ipv4_address, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH); 
1726   proto_tree_add_ipv4(parameter_tree, hf_sua_ipv4,
1727                                   parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH,
1728                                   ipv4_address);  
1729   proto_item_set_text(parameter_item, "IPV4 Address");
1730 }
1731
1732 static void
1733 dissect_sua_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1734 {
1735   guint16  length, hostname_length, padding_length;
1736   char *hostname;
1737
1738   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1739   padding_length = nr_of_padding_bytes(length);
1740   hostname_length = length - PARAMETER_HEADER_LENGTH;
1741   hostname = (char *)tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, hostname_length);
1742   
1743   proto_tree_add_string(parameter_tree, hf_sua_hostname, parameter_tvb,
1744                                           PARAMETER_VALUE_OFFSET, hostname_length,
1745                                           hostname);
1746   if (padding_length > 0)
1747     proto_tree_add_bytes(parameter_tree, hf_sua_hostname_padding, 
1748                          parameter_tvb, PARAMETER_VALUE_OFFSET + hostname_length, padding_length,
1749                          tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET + hostname_length, padding_length));
1750
1751   proto_item_set_text(parameter_item, "Hostname (%s)", hostname);
1752 }
1753
1754 #define IPV6_ADDRESS_LENGTH 16
1755 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1756
1757 static void
1758 dissect_sua_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1759 {
1760   proto_tree_add_ipv6(parameter_tree, hf_sua_ipv6,
1761                                   parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH,
1762                                   tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH));
1763   
1764   proto_item_set_text(parameter_item, "IPV6 Address");
1765 }
1766
1767 static void
1768 dissect_sua_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1769 {
1770   guint16 tag, length, parameter_value_length, padding_length;
1771   
1772   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1773   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1774   padding_length = nr_of_padding_bytes(length);
1775
1776   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
1777
1778   proto_tree_add_bytes(parameter_tree, hf_sua_parameter_value, 
1779                        parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length,
1780                        tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length));
1781   
1782   if (padding_length > 0)
1783     proto_tree_add_bytes(parameter_tree, hf_sua_parameter_padding, 
1784                          parameter_tvb, PARAMETER_VALUE_OFFSET + parameter_value_length, padding_length,
1785                          tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET + parameter_value_length, padding_length));
1786
1787   proto_item_set_text(parameter_item, "Parameter with tag %u and %u byte%s value",
1788                                   tag, parameter_value_length, plurality(parameter_value_length, "", "s"));
1789 }
1790
1791 static void
1792 dissect_sua_parameter(tvbuff_t *parameter_tvb, proto_tree *sua_tree)
1793 {
1794   guint16 tag, length, padding_length, total_length;
1795   proto_item *parameter_item;
1796   proto_tree *parameter_tree;
1797
1798   /* extract tag and length from the parameter */
1799   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1800   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1801
1802   /* calculate padding and total length */
1803   padding_length = nr_of_padding_bytes(length);
1804   total_length   = length + padding_length;
1805
1806   /* create proto_tree stuff */
1807   parameter_item   = proto_tree_add_text(sua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, total_length, "Incomplete parameter");
1808   parameter_tree   = proto_item_add_subtree(parameter_item, ett_sua_parameter);
1809
1810   /* add tag and length to the sua tree */
1811   proto_tree_add_uint(parameter_tree, hf_sua_parameter_tag, 
1812                                   parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH,
1813                                   tag);
1814   
1815   proto_tree_add_uint(parameter_tree, hf_sua_parameter_length, 
1816                                   parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH,
1817                                   length);
1818
1819   switch(tag) {
1820   case DATA_PARAMETER_TAG:
1821     dissect_sua_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1822     break;
1823   case INFO_STRING_PARAMETER_TAG:
1824     dissect_sua_info_parameter(parameter_tvb, parameter_tree, parameter_item);
1825     break;
1826   case ROUTING_CONTEXT_PARAMETER_TAG:
1827     dissect_sua_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
1828     break;
1829   case DIAGNOSTIC_INFO_PARAMETER_TAG:
1830     dissect_sua_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
1831     break;
1832   case HEARTBEAT_DATA_PARAMETER_TAG:
1833     dissect_sua_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1834     break;
1835   case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
1836     dissect_sua_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1837     break;
1838   case ERROR_CODE_PARAMETER_TAG:
1839     dissect_sua_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1840     break;
1841   case STATUS_PARAMETER_TAG:
1842     dissect_sua_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1843     break;
1844   case CONGESTION_LEVEL_PARAMETER_TAG:
1845     dissect_sua_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
1846     break;
1847   case ASP_IDENTIFIER_PARAMETER_TAG:
1848     dissect_sua_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1849     break;
1850   case AFFECTED_POINT_CODE_PARAMETER_TAG:
1851     dissect_sua_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
1852     break;
1853   case SS7_HOP_COUNTER_PARAMETER_TAG:
1854     dissect_sua_ss7_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
1855     break;
1856   case SOURCE_ADDRESS_PARAMETER_TAG:
1857     dissect_sua_source_address_parameter(parameter_tvb, parameter_tree, parameter_item);
1858     break;
1859   case DESTINATION_ADDRESS_PARAMETER_TAG:
1860     dissect_sua_destination_address_parameter(parameter_tvb, parameter_tree, parameter_item);
1861     break;
1862   case SOURCE_REFERENCE_NUMBER_PARAMETER_TAG:
1863     dissect_sua_source_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1864     break;
1865   case DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG:
1866     dissect_sua_destination_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1867     break;
1868   case SCCP_CAUSE_PARAMETER_TAG:
1869     dissect_sua_sccp_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
1870     break;
1871   case SEQUENCE_NUMBER_PARAMETER_TAG:
1872     dissect_sua_sequence_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1873     break;
1874   case RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG:
1875     dissect_sua_receive_sequence_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1876     break;
1877   case ASP_CAPABILITIES_PARAMETER_TAG:
1878     dissect_sua_asp_capabilities_parameter(parameter_tvb, parameter_tree, parameter_item);
1879     break;
1880   case CREDIT_PARAMETER_TAG:
1881     dissect_sua_credit_parameter(parameter_tvb, parameter_tree, parameter_item);
1882     break;
1883   case USER_CAUSE_PARAMETER_TAG:
1884     dissect_sua_user_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
1885     break;
1886   case NETWORK_APPEARANCE_PARAMETER_TAG:
1887     dissect_sua_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
1888     break;
1889   case ROUTING_KEY_PARAMETER_TAG:
1890     dissect_sua_routing_key_parameter(parameter_tvb, parameter_tree, parameter_item);
1891     break;
1892   case REGISTRATION_RESULT_PARAMETER_TAG:
1893     dissect_sua_registration_result_parameter(parameter_tvb, parameter_tree, parameter_item);
1894     break;
1895   case DEREGISTRATION_RESULT_PARAMETER_TAG:
1896     dissect_sua_deregistration_result_parameter(parameter_tvb, parameter_tree, parameter_item);
1897     break;
1898   case ADDRESS_RANGE_PARAMETER_TAG:
1899     dissect_sua_address_range_parameter(parameter_tvb, parameter_tree, parameter_item);
1900     break;
1901   case CORRELATION_ID_PARAMETER_TAG:
1902     dissect_sua_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
1903     break;
1904   case IMPORTANCE_PARAMETER_TAG:
1905     dissect_sua_importance_parameter(parameter_tvb, parameter_tree, parameter_item);
1906     break;
1907   case MESSAGE_PRIORITY_PARAMETER_TAG:
1908     dissect_sua_message_priority_parameter(parameter_tvb, parameter_tree, parameter_item);
1909     break;
1910   case PROTOCOL_CLASS_PARAMETER_TAG:
1911     dissect_sua_protocol_class_parameter(parameter_tvb, parameter_tree, parameter_item);
1912     break;
1913   case SEQUENCE_CONTROL_PARAMETER_TAG:
1914     dissect_sua_sequence_control_parameter(parameter_tvb, parameter_tree, parameter_item);
1915     break;
1916   case SEGMENTATION_PARAMETER_TAG:
1917     dissect_sua_segmentation_parameter(parameter_tvb, parameter_tree, parameter_item);
1918     break;
1919   case SMI_PARAMETER_TAG:
1920     dissect_sua_smi_parameter(parameter_tvb, parameter_tree, parameter_item);
1921     break;
1922   case TID_LABEL_PARAMETER_TAG:
1923     dissect_sua_tid_label_parameter(parameter_tvb, parameter_tree, parameter_item);
1924     break;
1925   case DRN_LABEL_PARAMETER_TAG:
1926     dissect_sua_drn_label_parameter(parameter_tvb, parameter_tree, parameter_item);
1927     break;
1928   case GLOBAL_TITLE_PARAMETER_TAG:
1929     dissect_sua_global_title_parameter(parameter_tvb, parameter_tree, parameter_item);
1930     break;
1931   case POINT_CODE_PARAMETER_TAG:
1932     dissect_sua_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1933     break;
1934   case SUBSYSTEM_NUMBER_PARAMETER_TAG:
1935     dissect_sua_ssn_parameter(parameter_tvb, parameter_tree, parameter_item);
1936     break;
1937   case IPV4_ADDRESS_PARAMETER_TAG:
1938     dissect_sua_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
1939     break;
1940   case HOSTNAME_PARAMETER_TAG:
1941     dissect_sua_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
1942     break;
1943   case IPV6_ADDRESS_PARAMETER_TAG:
1944     dissect_sua_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
1945     break;
1946   default:
1947     dissect_sua_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1948     break;
1949   };
1950 }
1951
1952 static void
1953 dissect_sua_tlv_list(tvbuff_t *tlv_tvb, proto_tree *sua_tree, gint initial_offset)
1954 {
1955   gint offset, length, padding_length, total_length;
1956   tvbuff_t *parameter_tvb;
1957   
1958   offset = initial_offset;
1959   
1960   while(tvb_reported_length_remaining(tlv_tvb, offset)) {
1961     length         = tvb_get_ntohs(tlv_tvb, offset + PARAMETER_LENGTH_OFFSET);
1962     padding_length = nr_of_padding_bytes(length);
1963     total_length   = length + padding_length;
1964     /* create a tvb for the parameter including the padding bytes */
1965     parameter_tvb    = tvb_new_subset(tlv_tvb, offset, total_length, total_length);
1966     dissect_sua_parameter(parameter_tvb, sua_tree); 
1967     /* get rid of the handled parameter */
1968     offset += total_length;
1969   }
1970 }
1971
1972 static void
1973 dissect_sua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *sua_tree)
1974 {
1975   tvbuff_t *common_header_tvb;
1976
1977   common_header_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_OFFSET, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
1978   dissect_sua_common_header(common_header_tvb, pinfo, sua_tree);
1979   
1980   if (sua_tree)
1981     dissect_sua_tlv_list(message_tvb, sua_tree, COMMON_HEADER_LENGTH);
1982 }
1983
1984 /* Support of Siemens Light Version starts here */
1985 #define SUAL_VERSION_LENGTH          1
1986 #define SUAL_SPARE_1_LENGTH          1
1987 #define SUAL_MESSAGE_TYPE_LENGTH     2
1988 #define SUAL_SUBSYSTEM_NUMBER_LENGTH 2
1989 #define SUAL_SPARE_2_LENGTH          2
1990 #define SUAL_MESSAGE_LENGTH_LENGTH   4
1991 #define SUAL_COMMON_HEADER_LENGTH   (SUAL_VERSION_LENGTH + SUAL_SPARE_1_LENGTH + SUAL_MESSAGE_TYPE_LENGTH + \
1992                                      SUAL_SUBSYSTEM_NUMBER_LENGTH + SUAL_SPARE_2_LENGTH + SUAL_MESSAGE_LENGTH_LENGTH)
1993
1994 #define SUAL_VERSION_OFFSET          0
1995 #define SUAL_SPARE_1_OFFSET          (SUAL_VERSION_OFFSET + SUAL_VERSION_LENGTH)
1996 #define SUAL_MESSAGE_TYPE_OFFSET     (SUAL_SPARE_1_OFFSET + SUAL_SPARE_1_LENGTH)
1997 #define SUAL_SUBSYSTEM_NUMBER_OFFSET (SUAL_MESSAGE_TYPE_OFFSET + SUAL_MESSAGE_TYPE_LENGTH)
1998 #define SUAL_SPARE_2_OFFSET          (SUAL_SUBSYSTEM_NUMBER_OFFSET + SUAL_SUBSYSTEM_NUMBER_LENGTH)
1999 #define SUAL_MESSAGE_LENGTH_OFFSET   (SUAL_SPARE_2_OFFSET + SUAL_SPARE_2_LENGTH)
2000
2001 /* SUAL message type coding */
2002 #define SUAL_MSG_CLDT                     0x0501
2003 #define SUAL_MSG_CORE                     0x0701
2004 #define SUAL_MSG_COAK_CC                    0x0702
2005 #define SUAL_MSG_COAK_CREF                0x0712
2006 #define SUAL_MSG_RELRE                    0x0703
2007 #define SUAL_MSG_RELCO                    0x0704
2008 #define SUAL_MSG_CODT                     0x0707
2009 #define SUAL_MSG_ERR                      0x0000
2010
2011 static const value_string sua_light_message_type_values[] = {
2012   {  SUAL_MSG_CLDT,              "Connectionless Data Transfer (CLDT)"},
2013   {  SUAL_MSG_CORE,              "Connection Request (CORE)"},
2014   {  SUAL_MSG_COAK_CC,           "Connection Acknowledge (COAK_CC)"},
2015   {  SUAL_MSG_COAK_CREF,         "Connection Acknowledge (COAK_CREF)"},
2016   {  SUAL_MSG_RELRE,             "Release Request (RELRE)"},
2017   {  SUAL_MSG_RELCO,             "Release Complete (RELCO)"},
2018   {  SUAL_MSG_CODT,              "Connection Oriented Data Transfer (CODT)"},
2019   {  SUAL_MSG_ERR,               "Error (ERR)"},
2020   {  0,                          NULL}};
2021
2022 static const value_string sua_light_message_type_acro_values[] = {
2023   {  SUAL_MSG_CLDT,              "CLDT"},
2024   {  SUAL_MSG_CORE,              "CORE"},
2025   {  SUAL_MSG_COAK_CC,           "COAK_CC"},
2026   {  SUAL_MSG_COAK_CREF,         "COAK_CREF"},
2027   {  SUAL_MSG_RELRE,             "RELRE"},
2028   {  SUAL_MSG_RELCO,             "RELCO"},
2029   {  SUAL_MSG_CODT,              "CODT"},
2030   {  SUAL_MSG_ERR,               "ERR"},
2031   {  0,                          NULL}};
2032
2033
2034 /* SUAL Error Codes */
2035 #define SUAL_ERR_INVVERS                0x0001
2036 #define SUAL_ERR_INVSTRID               0x0005
2037 #define SUAL_ERR_INVMSGTYP      0x0006
2038
2039 static const value_string sua_light_error_code_values[] = {
2040   {  SUAL_ERR_INVVERS,          "Invalid Protocol Version"},    
2041   {  SUAL_ERR_INVSTRID,         "Invalid Stream Identifier"},   
2042   {  SUAL_ERR_INVMSGTYP,        "Invalid Message Type"},
2043   {  0,                          NULL}};
2044
2045 static void
2046 dissect_sua_light_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, 
2047                                 proto_tree *sual_tree, guint16  *subsystem_number)
2048 {
2049   guint8  version, spare_1;
2050   guint16 message_type, spare_2; 
2051   guint32 message_length;
2052
2053   /* Extract the common header */
2054   version           = tvb_get_guint8(common_header_tvb, SUAL_VERSION_OFFSET);
2055   spare_1           = tvb_get_guint8(common_header_tvb, SUAL_SPARE_1_OFFSET);
2056   message_type      = tvb_get_ntohs(common_header_tvb,  SUAL_MESSAGE_TYPE_OFFSET);
2057   *subsystem_number = tvb_get_ntohs(common_header_tvb,  SUAL_SUBSYSTEM_NUMBER_OFFSET);
2058   spare_2           = tvb_get_ntohs(common_header_tvb,  SUAL_SPARE_2_OFFSET);
2059   message_length    = tvb_get_ntohl(common_header_tvb,  SUAL_MESSAGE_LENGTH_OFFSET);
2060
2061   if (check_col(pinfo->cinfo, COL_INFO)) {
2062     col_append_str(pinfo->cinfo, COL_INFO, val_to_str(message_type, sua_light_message_type_acro_values, "Unknown"));
2063     col_append_str(pinfo->cinfo, COL_INFO, " ");
2064   };
2065
2066   if (sual_tree) {
2067     /* add the components of the common header to the protocol tree */
2068     proto_tree_add_uint(sual_tree, hf_sua_light_version, common_header_tvb, SUAL_VERSION_OFFSET, SUAL_VERSION_LENGTH, version);
2069     proto_tree_add_uint(sual_tree, hf_sua_light_spare_1, common_header_tvb, SUAL_SPARE_1_OFFSET, SUAL_SPARE_1_LENGTH, spare_1);
2070     proto_tree_add_uint(sual_tree, hf_sua_light_message_type, common_header_tvb, SUAL_MESSAGE_TYPE_OFFSET, SUAL_MESSAGE_TYPE_LENGTH,message_type);
2071     proto_tree_add_uint(sual_tree, hf_sua_light_subsystem_number, common_header_tvb, SUAL_SUBSYSTEM_NUMBER_OFFSET, SUAL_SUBSYSTEM_NUMBER_LENGTH, *subsystem_number);
2072     proto_tree_add_uint(sual_tree, hf_sua_light_spare_2, common_header_tvb, SUAL_SPARE_2_OFFSET, SUAL_SPARE_2_LENGTH, spare_2);
2073     proto_tree_add_uint(sual_tree, hf_sua_light_message_length, common_header_tvb, SUAL_MESSAGE_LENGTH_OFFSET, SUAL_MESSAGE_LENGTH_LENGTH, message_length);
2074   };
2075 }
2076
2077 static void
2078 dissect_sua_light_payload(tvbuff_t *payload_tvb, packet_info *pinfo,
2079                           guint16 subsystem_number, proto_tree *sual_tree, proto_tree *tree)
2080 {
2081   guint         payload_length = tvb_reported_length(payload_tvb);
2082         
2083   /* do lookup with the subdissector table */
2084   if ( ! dissector_try_port (sua_light_dissector_table, subsystem_number, payload_tvb, pinfo, tree))
2085   {
2086      if (sual_tree)
2087        proto_tree_add_text(sual_tree, payload_tvb, 0, -1, "Payload: %u byte%s", payload_length, plurality(payload_length, "", "s"));
2088   }
2089 }
2090
2091 static void
2092 dissect_sua_light_error_payload(tvbuff_t *payload_tvb, proto_tree *sual_tree)
2093 {
2094     if (sual_tree) 
2095        proto_tree_add_item(sual_tree, hf_sua_light_error_code, payload_tvb, 0, 2, FALSE); 
2096 }
2097
2098 static void
2099 dissect_sua_light_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *sual_tree, proto_tree *tree)
2100 {
2101   gint     offset, payload_length;
2102   guint16  subsystem_number;
2103   guint16  message_type;
2104   tvbuff_t *common_header_tvb;
2105   tvbuff_t *payload_tvb;
2106
2107   offset = 0;
2108   /* extract and process the common header */
2109   common_header_tvb = tvb_new_subset(message_tvb, offset, SUAL_COMMON_HEADER_LENGTH, SUAL_COMMON_HEADER_LENGTH);
2110   message_type      = tvb_get_ntohs(common_header_tvb, SUAL_MESSAGE_TYPE_OFFSET);
2111   dissect_sua_light_common_header(common_header_tvb, pinfo, sual_tree, &subsystem_number);
2112   offset           += SUAL_COMMON_HEADER_LENGTH;
2113   payload_length    = tvb_length(message_tvb) - SUAL_COMMON_HEADER_LENGTH;
2114   if (payload_length != 0)
2115   {
2116      payload_tvb = tvb_new_subset(message_tvb, offset, payload_length, payload_length);
2117      if (message_type != SUAL_MSG_ERR)
2118         dissect_sua_light_payload(payload_tvb, pinfo, subsystem_number, sual_tree, tree);
2119      else
2120         dissect_sua_light_error_payload(payload_tvb, sual_tree);   
2121   }
2122 }
2123
2124 static void
2125 dissect_sua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
2126 {
2127   proto_item *sua_item;
2128   proto_tree *sua_tree;
2129
2130   /* make entry in the Protocol column on summary display */
2131   switch(sua_version) {
2132     case IETF_VERSION08:
2133       if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
2134         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SUA");
2135       break;
2136     case SIEMENS_VERSION: 
2137       if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
2138         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SUA-Light");
2139       break;
2140   }
2141   
2142   /* In the interest of speed, if "tree" is NULL, don't do any work not
2143      necessary to generate protocol tree items. */
2144   if (tree) {
2145     /* create the sua protocol tree */
2146     sua_item = proto_tree_add_item(tree, proto_sua, message_tvb, 0, -1, FALSE);
2147     sua_tree = proto_item_add_subtree(sua_item, ett_sua);
2148   } else {
2149     sua_tree = NULL;
2150   };
2151   
2152   /* dissect the message */
2153   switch(sua_version) {
2154     case IETF_VERSION08:
2155         dissect_sua_message(message_tvb, pinfo, sua_tree);
2156         break;
2157     case SIEMENS_VERSION:
2158         dissect_sua_light_message(message_tvb, pinfo, sua_tree, tree);
2159         break;
2160   }
2161 }
2162
2163 /* Register the protocol with Ethereal */
2164 void
2165 proto_register_sua(void)
2166 {                 
2167
2168   /* Setup list of header fields */
2169   static hf_register_info hf[] = {
2170     { &hf_sua_version,
2171       { "Version", "sua.version",
2172               FT_UINT8, BASE_DEC, VALS(sua_protocol_version_values), 0x0,          
2173               "", HFILL }
2174     },
2175     { &hf_sua_reserved,
2176       { "Reserved", "sua.reserved",
2177                FT_BYTES, BASE_NONE, NULL, 0x0,          
2178                "", HFILL }
2179     }, 
2180     { &hf_sua_message_class,
2181       { "Message Class", "sua.message_class",
2182                FT_UINT8, BASE_DEC, VALS(sua_message_class_values), 0x0,          
2183                "", HFILL }
2184     },
2185     { &hf_sua_message_type,
2186       { "Message Type", "sua.message_type",
2187         FT_UINT8, BASE_DEC, NULL, 0x0,          
2188               "", HFILL }
2189     },
2190     { &hf_sua_message_length,
2191       { "Message Length", "sua.message_length",
2192               FT_UINT32, BASE_DEC, NULL, 0x0,          
2193               "", HFILL }
2194     }, 
2195     { &hf_sua_parameter_tag,
2196       { "Parameter Tag", "sua.parameter_tag",
2197         FT_UINT16, BASE_HEX, VALS(sua_parameter_tag_values), 0x0,          
2198             "", HFILL }
2199     },
2200     { &hf_sua_parameter_length,
2201       { "Parameter Length", "sua.parameter_length",
2202               FT_UINT16, BASE_DEC, NULL, 0x0,          
2203               "", HFILL }
2204     }, 
2205     { &hf_sua_parameter_value,
2206       { "Parameter Value", "sua.parameter_value",
2207               FT_BYTES, BASE_NONE, NULL, 0x0,          
2208               "", HFILL }
2209     },   
2210     { &hf_sua_parameter_padding,
2211       { "Padding", "sua.parameter_padding",
2212               FT_BYTES, BASE_NONE, NULL, 0x0,          
2213               "", HFILL }
2214     },   
2215     { &hf_sua_data_padding,
2216       { "Padding", "sua.data.padding",
2217               FT_BYTES, BASE_NONE, NULL, 0x0,          
2218               "", HFILL }
2219     },   
2220     { &hf_sua_info_string,
2221       { "Info string", "sua.info_string.string",
2222               FT_STRING, BASE_NONE, NULL, 0x0,          
2223               "", HFILL }
2224     }, 
2225     { &hf_sua_info_string_padding,
2226       { "Padding", "sua.info_string.padding",
2227               FT_BYTES, BASE_NONE, NULL, 0x0,          
2228               "", HFILL }
2229     },   
2230     { &hf_sua_routing_context,
2231       { "Routing context", "sua.routing_context.context",
2232         FT_UINT32, BASE_DEC, NULL, 0x0,          
2233               "", HFILL }
2234     },
2235     { &hf_sua_diagnostic_information_info,
2236       { "Diagnostic Information", "sua.diagnostic_information.info",
2237               FT_BYTES, BASE_NONE, NULL, 0x0,          
2238               "", HFILL }
2239     },   
2240     { &hf_sua_diagnostic_information_padding,
2241       { "Padding", "sua.diagnostic_information.padding",
2242               FT_BYTES, BASE_NONE, NULL, 0x0,          
2243               "", HFILL }
2244     },   
2245     { &hf_sua_heartbeat_data,
2246       { "Heratbeat Data", "sua.heartbeat.data",
2247               FT_BYTES, BASE_NONE, NULL, 0x0,          
2248               "", HFILL }
2249     },   
2250     { &hf_sua_heartbeat_padding,
2251       { "Padding", "sua.heartbeat.padding",
2252               FT_BYTES, BASE_NONE, NULL, 0x0,          
2253               "", HFILL }
2254     },   
2255     { &hf_sua_traffic_mode_type,
2256       { "Traffic mode Type", "sua.traffic_mode_type.type",
2257               FT_UINT32, BASE_DEC, VALS(sua_traffic_mode_type_values), 0x0,          
2258               "", HFILL }
2259     },
2260     { &hf_sua_error_code,
2261       { "Error code", "sua.error_code.code",
2262               FT_UINT32, BASE_DEC, VALS(sua_error_code_values), 0x0,          
2263               "", HFILL }
2264     },
2265     { &hf_sua_status_type,
2266       { "Status type", "sua.status.type",
2267             FT_UINT16, BASE_DEC, VALS(sua_status_type_values), 0x0,          
2268             "", HFILL }
2269     }, 
2270     { &hf_sua_status_info,
2271       { "Status info", "sua.status.info",
2272           FT_UINT16, BASE_DEC, NULL, 0x0,          
2273           "", HFILL }
2274     }, 
2275     { &hf_sua_congestion_level,
2276       { "Congestion Level", "sua.congestion_level.level",
2277               FT_UINT32, BASE_DEC, NULL, 0x0,          
2278               "", HFILL }
2279     },
2280     { &hf_sua_asp_identifier,
2281       { "ASP Identifier", "sua.asp_identifier.id",
2282               FT_UINT32, BASE_DEC, NULL, 0x0,          
2283               "", HFILL }
2284     },
2285     { &hf_sua_mask,
2286       { "Mask", "sua.affected_point_code.mask",
2287               FT_UINT8, BASE_HEX, NULL, 0x0,          
2288               "", HFILL }
2289     }, 
2290     { &hf_sua_dpc,
2291       { "Affected DPC", "sua.affected_pointcode.dpc",
2292               FT_UINT24, BASE_DEC, NULL, 0x0,          
2293               "", HFILL }
2294     }, 
2295     { &hf_sua_ss7_hop_counter_counter,
2296       { "SS7 Hop Counter", "sua.ss7_hop_counter.counter",
2297                FT_UINT8, BASE_DEC, NULL, 0x0,          
2298                "", HFILL }
2299     }, 
2300     { &hf_sua_ss7_hop_counter_reserved,
2301       { "Reserved", "sua.ss7_hop_counter.reserved",
2302               FT_BYTES, BASE_NONE, NULL, 0x0,          
2303               "", HFILL }
2304     },   
2305     { &hf_sua_source_address_routing_indicator,
2306       { "Routing Indicator", "sua.source_address.routing_indicator",
2307               FT_UINT16, BASE_DEC, VALS(sua_routing_indicator_values), 0x0,          
2308               "", HFILL }
2309     },
2310     { &hf_sua_source_address_reserved_bits,
2311       { "Reserved Bits", "sua.source_address.reserved_bits",
2312               FT_UINT16, BASE_DEC, NULL, ADDRESS_RESERVED_BITMASK,          
2313               "", HFILL }
2314     },
2315     { &hf_sua_source_address_gt_bit,
2316       { "Include GT", "sua.source_address.gt_bit",
2317               FT_BOOLEAN, 16, NULL, ADDRESS_GT_BITMASK,          
2318               "", HFILL }
2319     },
2320     { &hf_sua_source_address_pc_bit,
2321       { "Include PC", "sua.source_address.pc_bit",
2322               FT_BOOLEAN, 16, NULL, ADDRESS_PC_BITMASK,          
2323               "", HFILL }
2324     },
2325     { &hf_sua_source_address_ssn_bit,
2326       { "Include SSN", "sua.source_address.ssn_bit",
2327               FT_BOOLEAN, 16, NULL, ADDRESS_SSN_BITMASK,          
2328               "", HFILL }
2329     },
2330     { &hf_sua_destination_address_routing_indicator,
2331       { "Routing Indicator", "sua.destination_address.routing_indicator",
2332               FT_UINT16, BASE_DEC, VALS(sua_routing_indicator_values), 0x0,          
2333               "", HFILL }
2334     },
2335     { &hf_sua_destination_address_reserved_bits,
2336       { "Reserved Bits", "sua.destination_address.reserved_bits",
2337               FT_UINT16, BASE_DEC, NULL, ADDRESS_RESERVED_BITMASK,          
2338               "", HFILL }
2339     },
2340     { &hf_sua_destination_address_gt_bit,
2341       { "Include GT", "sua.destination_address.gt_bit",
2342               FT_BOOLEAN, 16, NULL, ADDRESS_GT_BITMASK,          
2343               "", HFILL }
2344     },
2345     { &hf_sua_destination_address_pc_bit,
2346       { "Include PC", "sua.destination_address.pc_bit",
2347               FT_BOOLEAN, 16, NULL, ADDRESS_PC_BITMASK,          
2348               "", HFILL }
2349     },
2350     { &hf_sua_destination_address_ssn_bit,
2351       { "Include SSN", "sua.destination_address.ssn_bit",
2352               FT_BOOLEAN, 16, NULL, ADDRESS_SSN_BITMASK,          
2353               "", HFILL }
2354     },
2355     { &hf_sua_source_reference_number,
2356       { "Source Reference Number", "sua.source_reference_number.number",
2357               FT_UINT32, BASE_DEC, NULL, 0x0,          
2358               "", HFILL }
2359     },
2360     { &hf_sua_destination_reference_number,
2361       { "Destination Reference Number", "sua.destination_reference_number",
2362               FT_UINT32, BASE_DEC, NULL, 0x0,          
2363               "", HFILL }
2364     },
2365     { &hf_sua_cause_reserved,
2366       { "Reserved", "sua.sccp_cause.reserved",
2367                FT_BYTES, BASE_NONE, NULL, 0x0,          
2368                "", HFILL }
2369     }, 
2370     { &hf_sua_cause_type,
2371       { "Cause Type", "sua.sccp_cause.type",
2372                FT_UINT8, BASE_HEX, VALS(sua_cause_type_values), 0x0,          
2373                "", HFILL }
2374     }, 
2375     { &hf_sua_cause_value,
2376       { "Cause Value", "sua.sccp_cause.value",
2377                FT_UINT8, BASE_HEX, NULL, 0x0,          
2378                "", HFILL }
2379     }, 
2380     { &hf_sua_sequence_number_reserved,
2381       { "Reserved", "sua.sequence_number.reserved",
2382               FT_BYTES, BASE_NONE, NULL, 0x0,          
2383               "", HFILL }
2384     },    
2385     { &hf_sua_sequence_number_rec_number,
2386       { "Receive Sequence Number P(R)", "sua.sequence_number.receive_sequence_number",
2387               FT_UINT8, BASE_DEC, NULL, SEQ_NUM_MASK,          
2388               "", HFILL }
2389     },
2390     { &hf_sua_sequence_number_more_data_bit,
2391       { "More Data Bit", "sua.sequence_number.more_data_bit",
2392               FT_BOOLEAN, 8, TFS(&sua_more_data_bit_value), MORE_DATA_BIT_MASK,          
2393               "", HFILL }
2394     },
2395     { &hf_sua_sequence_number_sent_number,
2396       { "Sent Sequence Number P(S)", "sua.sequence_number.sent_sequence_number",
2397               FT_UINT8, BASE_DEC, NULL, SEQ_NUM_MASK,          
2398               "", HFILL }
2399     },
2400     { &hf_sua_sequence_number_spare_bit,
2401       { "Spare Bit", "sua.sequence_number.spare_bit",
2402               FT_BOOLEAN, 8, NULL, SPARE_BIT_MASK,          
2403               "", HFILL }
2404     },
2405     { &hf_sua_receive_sequence_number_reserved,
2406       { "Reserved", "sua.receive_sequence_number.reserved",
2407               FT_BYTES, BASE_NONE, NULL, 0x0,          
2408               "", HFILL }
2409     },    
2410     { &hf_sua_receive_sequence_number_number,
2411       { "Receive Sequence Number P(R)", "sua.receive_sequence_number.number",
2412               FT_UINT8, BASE_DEC, NULL, SEQ_NUM_MASK,          
2413               "", HFILL }
2414     },
2415     { &hf_sua_receive_sequence_number_spare_bit,
2416       { "Spare Bit", "sua.receive_sequence_number.spare_bit",
2417               FT_BOOLEAN, 8, NULL, SPARE_BIT_MASK,          
2418               "", HFILL }
2419     },
2420     { &hf_sua_asp_capabilities_reserved,
2421       { "Reserved", "sua.asp_capabilities.reserved",
2422               FT_BYTES, BASE_NONE, NULL, 0x0,          
2423               "", HFILL }
2424     },    
2425     { &hf_sua_asp_capabilities_reserved_bits,
2426       { "Reserved Bits", "sua.asp_capabilities.reserved_bits",
2427               FT_UINT8, BASE_HEX, NULL, RESERVED_BITS_MASK,          
2428               "", HFILL }
2429     },
2430     { &hf_sua_asp_capabilities_a_bit,
2431       { "Protocol Class 3", "sua.asp_capabilities.a_bit",
2432               FT_BOOLEAN, 8, TFS(&sua_supported_bit_value), A_BIT_MASK,          
2433               "", HFILL }
2434     },
2435     { &hf_sua_asp_capabilities_b_bit,
2436       { "Protocol Class 2", "sua.asp_capabilities.b_bit",
2437               FT_BOOLEAN, 8, TFS(&sua_supported_bit_value), B_BIT_MASK,          
2438               "", HFILL }
2439     },
2440     { &hf_sua_asp_capabilities_c_bit,
2441       { "Protocol Class 1", "sua.asp_capabilities.c_bit",
2442               FT_BOOLEAN, 8, TFS(&sua_supported_bit_value), C_BIT_MASK,          
2443               "", HFILL }
2444     },
2445     { &hf_sua_asp_capabilities_d_bit,
2446       { "Protocol Class 0", "sua.asp_capabilities.d_bit",
2447               FT_BOOLEAN, 8, TFS(&sua_supported_bit_value), D_BIT_MASK,          
2448               "", HFILL }
2449     },
2450     { &hf_sua_asp_capabilities_interworking,
2451       { "Interworking", "sua.asp_capabilities.interworking",
2452               FT_UINT8, BASE_HEX, VALS(sua_interworking_values), 0x0,          
2453               "", HFILL }
2454     },
2455     { &hf_sua_credit,
2456       { "Credit", "sua.credit.credit",
2457               FT_UINT32, BASE_DEC, NULL, 0x0,          
2458               "", HFILL }
2459     },
2460     { &hf_sua_cause,
2461       { "Cause", "sua.cause_user.cause",
2462               FT_UINT16, BASE_DEC, VALS(sua_cause_values), 0x0,          
2463               "", HFILL }
2464     },
2465     { &hf_sua_user,
2466       { "User", "sua.cause_user.user",
2467               FT_UINT16, BASE_DEC, NULL, 0x0,          
2468               "", HFILL }
2469     },
2470     { &hf_sua_network_appearance,
2471       { "Network Appearance", "sua.network_appearance.appearance",
2472               FT_UINT32, BASE_DEC, NULL, 0x0,          
2473               "", HFILL }
2474     },
2475     { &hf_sua_routing_key_identifier,
2476       { "Local Routing Key Identifier", "sua.routing_key.identifier",
2477               FT_UINT32, BASE_HEX, NULL, 0x0,          
2478               "", HFILL }
2479     },
2480     { &hf_sua_registration_result_routing_key_identifier,
2481       { "Local Routing Key Identifier", "sua.registration_result.local_routing_key_identifier",
2482             FT_UINT32, BASE_DEC, NULL, 0x0,          
2483             "", HFILL }
2484     }, 
2485     { &hf_sua_registration_result_status,
2486       { "Registration Status", "sua.registration_result.registration_status",
2487             FT_UINT32, BASE_DEC, VALS(sua_registration_status_values), 0x0,          
2488             "", HFILL }
2489     }, 
2490     { &hf_sua_registration_result_routing_context,
2491       { "Routing Context", "sua.registration_result.routing_context",
2492             FT_UINT32, BASE_DEC, NULL, 0x0,          
2493             "", HFILL }
2494     }, 
2495     { &hf_sua_deregistration_result_status,
2496       { "Deregistration Status", "sua.deregistration_result.deregistration_status",
2497             FT_UINT32, BASE_DEC, VALS(sua_deregistration_status_values), 0x0,          
2498             "", HFILL }
2499     }, 
2500     { &hf_sua_deregistration_result_routing_context,
2501       { "Routing Context", "sua.deregistration_result.routing_context",
2502             FT_UINT32, BASE_DEC, NULL, 0x0,          
2503             "", HFILL }
2504     }, 
2505     { &hf_sua_correlation_id,
2506       { "Correlation ID", "sua.correlation_id.identifier",
2507               FT_UINT32, BASE_DEC, NULL, 0x0,          
2508               "", HFILL }
2509     },
2510     { &hf_sua_importance_reserved,
2511       { "Reserved", "sua.importance.reserved",
2512                FT_BYTES, BASE_NONE, NULL, 0x0,          
2513                "", HFILL }
2514     }, 
2515     { &hf_sua_importance,
2516       { "Importance", "sua.importance.inportance",
2517                FT_UINT8, BASE_DEC, NULL, 0x0,          
2518                "", HFILL }
2519     }, 
2520     { &hf_sua_message_priority_reserved,
2521       { "Reserved", "sua.message_priority.reserved",
2522                FT_BYTES, BASE_NONE, NULL, 0x0,          
2523                "", HFILL }
2524     }, 
2525     { &hf_sua_message_priority,
2526       { "Message Priority", "sua.message_priority.priority",
2527                FT_UINT8, BASE_DEC, NULL, 0x0,          
2528                "", HFILL }
2529     }, 
2530     { &hf_sua_protocol_class_reserved,
2531       { "Reserved", "sua.protcol_class.reserved",
2532               FT_BYTES, BASE_HEX, NULL, 0x0,          
2533               "", HFILL }
2534     },
2535     {&hf_sua_return_on_error_bit,
2536      { "Return On Error Bit", "sua.protocol_class.return_on_error_bit",
2537        FT_BOOLEAN, 8, TFS(&sua_return_on_error_bit_value), RETURN_ON_ERROR_BIT_MASK,          
2538        "", HFILL }
2539     },
2540     {&hf_sua_protocol_class,
2541      { "Protocol Class", "sua.protocol_class.class",
2542        FT_UINT8, BASE_DEC, NULL, PROTOCOL_CLASS_MASK,          
2543        "", HFILL }
2544     },
2545     { &hf_sua_sequence_control,
2546       { "Sequence Control", "sua.sequence_control.sequence_control",
2547               FT_UINT32, BASE_DEC, NULL, 0x0,          
2548               "", HFILL }
2549     },
2550     {&hf_sua_first_bit,
2551      { "First Segment Bit", "sua.segmentation.first_bit",
2552        FT_BOOLEAN, 8, TFS(&sua_first_bit_value), FIRST_BIT_MASK,          
2553        "", HFILL }
2554     },
2555     {&hf_sua_number_of_remaining_segments,
2556      { "Number of Remaining Segments", "sua.segmentation.number_of_remaining_segments",
2557        FT_UINT8, BASE_DEC, NULL, NUMBER_OF_SEGMENTS_MASK,          
2558        "", HFILL }
2559     },
2560     { &hf_sua_segmentation_reference,
2561       { "Segmentation Reference", "sua.segmentation.reference",
2562               FT_UINT24, BASE_DEC, NULL, 0x0,          
2563               "", HFILL }
2564     },
2565     { &hf_sua_smi_reserved,
2566       { "Reserved", "sua.smi.reserved",
2567                FT_BYTES, BASE_DEC, NULL, 0x0,          
2568                "", HFILL }
2569     }, 
2570     { &hf_sua_smi,
2571       { "SMI", "sua.smi.smi",
2572                FT_UINT8, BASE_DEC, NULL, 0x0,          
2573                "", HFILL }
2574     }, 
2575     { &hf_sua_tid_label_start,
2576       { "Start", "sua.tid_label.start",
2577                FT_UINT8, BASE_DEC, NULL, 0x0,          
2578                "", HFILL }
2579     }, 
2580     { &hf_sua_tid_label_end,
2581       { "End", "sua.tid_label.end",
2582                FT_UINT8, BASE_DEC, NULL, 0x0,          
2583                "", HFILL }
2584     }, 
2585     { &hf_sua_tid_label_value,
2586       { "Label Value", "sua.tid_label.value",
2587                FT_UINT16, BASE_HEX, NULL, 0x0,          
2588                "", HFILL }
2589     }, 
2590     { &hf_sua_drn_label_start,
2591       { "Start", "sua.drn_label.start",
2592                FT_UINT8, BASE_DEC, NULL, 0x0,          
2593                "", HFILL }
2594     }, 
2595     { &hf_sua_drn_label_end,
2596       { "End", "sua.drn_label.end",
2597                FT_UINT8, BASE_DEC, NULL, 0x0,          
2598                "", HFILL }
2599     }, 
2600     { &hf_sua_drn_label_value,
2601       { "Label Value", "sua.drn_label.value",
2602                FT_UINT16, BASE_HEX, NULL, 0x0,          
2603                "", HFILL }
2604     }, 
2605     { &hf_sua_number_of_digits,
2606       { "Number of Digits", "sua.global_title.number_of_digits",
2607               FT_UINT8, BASE_DEC, NULL, 0x0,          
2608               "", HFILL }
2609     },    
2610     { &hf_sua_translation_type,
2611       { "Translation Type", "sua.global_title.translation_type",
2612               FT_UINT8, BASE_HEX, NULL, 0x0,          
2613               "", HFILL }
2614     },    
2615     { &hf_sua_numbering_plan,
2616       { "Numbering Plan", "sua.global_title.numbering_plan",
2617               FT_UINT8, BASE_HEX, VALS(sua_numbering_plan_values), 0x0,          
2618               "", HFILL }
2619     },    
2620     { &hf_sua_nature_of_address,
2621       { "Nature of Address", "sua.global_title.nature_of_address",
2622               FT_UINT8, BASE_HEX, VALS(sua_nature_of_address_values), 0x0,          
2623               "", HFILL }
2624     },    
2625     { &hf_sua_nature_of_address,
2626       { "Nature Of Address", "sua.global_title.nature_of_address",
2627               FT_UINT8, BASE_HEX, VALS(sua_nature_of_address_values), 0x0,          
2628               "", HFILL }
2629     },    
2630     { &hf_sua_global_title,
2631       { "Global Title", "sua.global_title.signals",
2632               FT_BYTES, BASE_NONE, NULL, 0x0,          
2633               "", HFILL }
2634     },    
2635     { &hf_sua_global_title_padding,
2636       { "Padding", "sua.global_title.padding",
2637               FT_BYTES, BASE_NONE, NULL, 0x0,          
2638               "", HFILL }
2639     },    
2640     { &hf_sua_point_code_mask,
2641       { "Mask", "sua.point_code.mask",
2642               FT_UINT8, BASE_HEX, NULL, 0x0,          
2643               "", HFILL }
2644     },    
2645     { &hf_sua_point_code_dpc,
2646       { "Point Code", "sua.point_code.pc",
2647               FT_UINT24, BASE_DEC, NULL, 0x0,          
2648               "", HFILL }
2649     },    
2650     { &hf_sua_ssn_reserved,
2651       { "Reserved", "sua.ssn.reserved",
2652               FT_BYTES, BASE_NONE, NULL, 0x0,          
2653               "", HFILL }
2654     },    
2655     { &hf_sua_ssn_number,
2656       { "Subsystem Number", "sua.ssn.number",
2657               FT_UINT8, BASE_DEC, NULL, 0x0,          
2658               "", HFILL }
2659     },    
2660     {&hf_sua_ipv4,
2661      { "IP Version 4 address", "sua.ipv4.address",
2662        FT_IPv4, BASE_NONE, NULL, 0x0,
2663        "", HFILL }
2664     },
2665     {&hf_sua_hostname,
2666      { "Hostname", "sua.hostname.name",
2667        FT_STRING, BASE_NONE, NULL, 0x0,          
2668        "", HFILL }
2669     }, 
2670     {&hf_sua_hostname_padding,
2671      { "Padding", "sua.hostname.padding",
2672        FT_BYTES, BASE_NONE, NULL, 0x0,          
2673        "", HFILL }
2674     }, 
2675     {&hf_sua_ipv6,
2676      { "IP Version 6 address", "sua.ipv6.address",
2677        FT_IPv6, BASE_NONE, NULL, 0x0,
2678        "", HFILL }
2679     },
2680     { &hf_sua_light_version,
2681       { "Version", "sua.light.version",
2682               FT_UINT8, BASE_DEC, NULL, 0x0,          
2683               "", HFILL }
2684     },
2685     { &hf_sua_light_spare_1,
2686       { "Spare", "sua.light.spare_1",
2687               FT_UINT8, BASE_HEX, NULL, 0x0,          
2688               "", HFILL }
2689     }, 
2690     { &hf_sua_light_message_type,
2691       { "Message Type", "sua.light.message_type",
2692               FT_UINT16, BASE_DEC, VALS(sua_light_message_type_values), 0x0,          
2693               "", HFILL }
2694     },
2695     { &hf_sua_light_subsystem_number,
2696       { "Subsystem number", "sua.light.subsystem_number",
2697               FT_UINT16, BASE_DEC, NULL, 0x0,          
2698               "", HFILL }
2699     },
2700     { &hf_sua_light_spare_2,
2701       { "Spare", "sua.light.spare_2",
2702               FT_UINT16, BASE_DEC, NULL, 0x0,          
2703               "", HFILL }
2704     },
2705     { &hf_sua_light_message_length,
2706       { "Message length", "sua.light.message_length",
2707         FT_UINT32, BASE_DEC, NULL, 0x0,          
2708                "", HFILL }
2709     },
2710     { &hf_sua_light_error_code,
2711       { "Error Code", "sua.light.error_code",
2712         FT_UINT16, BASE_HEX, VALS(&sua_light_error_code_values), 0x0,
2713               "", HFILL }
2714     }
2715   };
2716   
2717   /* Setup protocol subtree array */
2718   static gint *ett[] = {
2719     &ett_sua,
2720     &ett_sua_parameter,
2721     &ett_sua_source_address_indicator,
2722     &ett_sua_destination_address_indicator,
2723     &ett_sua_affected_destination,
2724     &ett_sua_sequence_number_rec_number,
2725     &ett_sua_sequence_number_sent_number,
2726     &ett_sua_receive_sequence_number_number,
2727     &ett_sua_protcol_classes,
2728     &ett_sua_first_remaining,
2729     &ett_sua_return_on_error_bit_and_protocol_class
2730   };
2731   
2732   static enum_val_t sua_options[] = {
2733     { "Internet draft 8 version",        IETF_VERSION08 },
2734     { "SUA light (Siemens proprietary)", SIEMENS_VERSION },
2735     { NULL, 0 }
2736   };
2737
2738   
2739   /* Register the protocol name and description */
2740   proto_sua = proto_register_protocol("SS7 SCCP-User Adaptation Layer", "SUA", "sua");
2741   
2742   /* Required function calls to register the header fields and subtrees used */
2743   proto_register_field_array(proto_sua, hf, array_length(hf));
2744   proto_register_subtree_array(ett, array_length(ett));
2745     
2746   sua_module = prefs_register_protocol(proto_sua, NULL);
2747   sua_light_dissector_table = register_dissector_table("sual.subsystem_number",
2748                                 "SUA Light subsystem number", FT_UINT16,
2749                                 BASE_DEC);
2750
2751   prefs_register_enum_preference(sua_module,
2752                                  "sua_version",
2753                                  "SUA Version",
2754                                  "SUA Version",
2755                                  &sua_version,
2756                                  sua_options, FALSE);
2757 };
2758
2759 void
2760 proto_reg_handoff_sua(void)
2761 {
2762   dissector_handle_t sua_handle;
2763
2764   sua_handle = create_dissector_handle(dissect_sua, proto_sua);
2765   dissector_add("sctp.ppi",  SUA_PAYLOAD_PROTO_ID, sua_handle);
2766   dissector_add("sctp.port", SCTP_PORT_SUA,        sua_handle);
2767 }