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