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