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