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